├── .gitignore ├── src ├── config.js ├── public │ └── index.html └── index.js ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## nodejs 2 | node_modules 3 | 4 | ## environment variables 5 | .env 6 | 7 | ## ngrok 8 | ngrok -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | const { config } = require("dotenv"); 2 | config(); 3 | 4 | const COINBASE_API_KEY = process.env.COINBASE_API_KEY; 5 | const COINBASE_WEBHOOK_SECRET = process.env.COINBASE_WEBHOOK_SECRET; 6 | const DOMAIN = process.env.DOMAIN; 7 | 8 | module.exports = { 9 | COINBASE_API_KEY, 10 | COINBASE_WEBHOOK_SECRET, 11 | DOMAIN 12 | }; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-coinbase-commerce", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node src/index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "coinbase-commerce-node": "^1.0.4", 14 | "cors": "^2.8.5", 15 | "dotenv": "^10.0.0", 16 | "express": "^4.17.1", 17 | "morgan": "^1.10.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Coinbase Commerce Express 2 | 3 | A simple example of an application that recives cryptocurrencies payments using express and Coibase commerce. 4 | 5 | ### Environment varibles 6 | 7 | In order to work properly, this application needs the following environment variables: 8 | 9 | ``` 10 | COINBASE_API_KEY= 11 | COINBASE_WEBHOOK_SECRET= 12 | DOMAIN= 13 | ``` 14 | 15 | You can get the api key and webhook secret from your dashboard accounts: https://commerce.coinbase.com/dashboard/settings 16 | 17 | and in order to use a https domain you can use Heroku or ngrok -------------------------------------------------------------------------------- /src/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | My Crypto Store 8 | 9 | 10 | 11 |

My awesome sound effect

12 | 13 | 14 |

15 | 16 | 17 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const cors = require("cors"); 3 | const path = require("path"); 4 | const morgan = require("morgan"); 5 | 6 | const { Client, resources, Webhook } = require("coinbase-commerce-node"); 7 | const { 8 | COINBASE_API_KEY, 9 | COINBASE_WEBHOOK_SECRET, 10 | DOMAIN, 11 | } = require("./config"); 12 | 13 | const { Charge } = resources; 14 | Client.init(COINBASE_API_KEY); 15 | 16 | const app = express(); 17 | 18 | app.use(cors()); 19 | app.use(morgan("dev")); 20 | 21 | // add verify in order to process rawBody 22 | app.use( 23 | express.json({ 24 | verify: (req, res, buf) => { 25 | req.rawBody = buf; 26 | }, 27 | }) 28 | ); 29 | 30 | app.get("/create-charge", async (req, res) => { 31 | const chargeData = { 32 | name: "Sound Effect", 33 | description: "An awesome science fiction sound effect", 34 | local_price: { 35 | amount: 0.2, 36 | currency: "USD", 37 | }, 38 | pricing_type: "fixed_price", 39 | metadata: { 40 | customer_id: "id_1005", 41 | customer_name: "Satoshi Nakamoto", 42 | }, 43 | redirect_url: `${DOMAIN}/success-payment`, 44 | cancel_url: `${DOMAIN}/cancel-payment`, 45 | }; 46 | 47 | const charge = await Charge.create(chargeData); 48 | 49 | console.log(charge); 50 | 51 | res.send(charge); 52 | }); 53 | 54 | app.post("/payment-handler", (req, res) => { 55 | const rawBody = req.rawBody; 56 | const signature = req.headers["x-cc-webhook-signature"]; 57 | const webhookSecret = COINBASE_WEBHOOK_SECRET; 58 | 59 | let event; 60 | 61 | try { 62 | event = Webhook.verifyEventBody(rawBody, signature, webhookSecret); 63 | // console.log(event); 64 | 65 | if (event.type === "charge:pending") { 66 | // received order 67 | // user paid, but transaction not confirm on blockchain yet 68 | console.log("pending payment"); 69 | } 70 | 71 | if (event.type === "charge:confirmed") { 72 | // fulfill order 73 | // charge confirmed 74 | console.log("charge confirme"); 75 | } 76 | 77 | if (event.type === "charge:failed") { 78 | // cancel order 79 | // charge failed or expired 80 | console.log("charge failed"); 81 | } 82 | 83 | res.send(`success ${event.id}`); 84 | } catch (error) { 85 | console.log(error); 86 | res.status(400).send("failure"); 87 | } 88 | }); 89 | 90 | app.get("/success-payment", (req, res) => { 91 | res.send("success payment"); 92 | }); 93 | 94 | app.get("/cancel-payment", (req, res) => { 95 | res.send("cancel payment"); 96 | }); 97 | 98 | app.use(express.static(path.join(__dirname, "public"))); 99 | 100 | const PORT = process.env.PORT || 3000; 101 | 102 | app.listen(PORT); 103 | console.log("Server on port", PORT); 104 | --------------------------------------------------------------------------------