forked from stripe-archive/stripe-webhook-monitor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
97 lines (86 loc) · 3.09 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"use strict";
const config = require("./config.js");
const boxen = require("boxen");
const stripe = require("stripe")(config.stripe.secretKey);
const express = require("express");
const socketio = require("socket.io");
const http = require("http");
const bodyParser = require("body-parser");
const path = require("path");
const chalk = require("chalk");
/*
We use two different Express servers for security reasons: our webhooks
endpoint needs to be publicly accessible, but we don't want our monitoring
dashboard to be publicly accessible since it may contain sensitive data.
*/
// The first Express server will serve Stripe Monitor (on a different port).
const monitor = express();
const monitorServer = http.Server(monitor);
// We'll set up Socket.io to notify us of new events
const io = socketio(monitorServer);
let recentEvents = [];
// Serve static files and start the server
monitor.use(express.static(path.join(__dirname, "public")));
monitorServer.listen(config.port, () => {
console.log(`Stripe Monitor is up: http://localhost:${config.port}`);
});
// Provides environment details: the Dashboard URL will vary based on whether we're in test or live mode
monitor.get("/environment", async (req, res) => {
let dashboardUrl = "https://dashboard.stripe.com/";
if (config.stripe.secretKey.startsWith("sk_test")) {
dashboardUrl += "test/";
}
res.send({ dashboardUrl });
});
// Provides the 20 most recent events (useful when the app first loads)
monitor.get("/recent-events", async (req, res) => {
let response = await stripe.events.list({ limit: 20 });
recentEvents = response.data;
res.send(recentEvents);
});
// The second Express server will receive webhooks
const webhooks = express();
const webhooksPort = config.port + 1;
webhooks.use(bodyParser.json());
webhooks.listen(webhooksPort, () => {
console.log(`Listening for webhooks: http://localhost:${webhooksPort}`);
});
// Provides an endpoint to receive webhooks
webhooks.post("/", async (req, res) => {
let event = req.body;
// Send a notification that we have a new event
// Here we're using Socket.io, but server-sent events or another mechanism can be used.
io.emit("event", event);
// Stripe needs to receive a 200 status from any webhooks endpoint
res.sendStatus(200);
});
// Use ngrok to provide a public URL for receiving webhooks
if (config.ngrok.enabled) {
const ngrok = require("ngrok");
const boxen = require("boxen");
ngrok.connect(
{
addr: webhooksPort,
subdomain: config.ngrok.subdomain,
authtoken: config.ngrok.authtoken
},
function(err, url) {
if (err) {
console.log(err);
if (err.code === "ECONNREFUSED") {
console.log(
chalk.red(`Connection refused at ${err.address}:${err.port}`)
);
process.exit(1);
}
console.log(chalk.yellow(`ngrok reported an error: ${err.msg}`));
console.log(
boxen(err.details.err.trim(), {
padding: { top: 0, right: 2, bottom: 0, left: 2 }
})
);
}
console.log(` └ Public URL for receiving Stripe webhooks: ${url}`);
}
);
}