Properly handle stripe hook with sig verification

master
Mark Moffat 2019-11-07 20:13:38 +10:30
parent e2e0fa2a00
commit bf6c35ea50
6 changed files with 46 additions and 14 deletions

10
app.js
View File

@ -272,7 +272,6 @@ app.enable('trust proxy');
app.use(helmet());
app.set('port', process.env.PORT || 1111);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser(config.secretCookie));
app.use(session({
@ -287,6 +286,15 @@ app.use(session({
store: store
}));
app.use(bodyParser.json({
// Only on Stripe URL's which need the rawBody
verify: (req, res, buf) => {
if(req.originalUrl === '/stripe/subscription_update'){
req.rawBody = buf.toString();
}
}
}));
// Set locales from session
app.use(i18n.init);

View File

@ -3,5 +3,6 @@
"publicKey": "pk_test_this_is_not_real",
"stripeCurrency": "usd",
"stripeDescription": "expressCart payment",
"stripeLogoURL": "http://localhost:1111/images/stripelogo.png"
"stripeLogoURL": "http://localhost:1111/images/stripelogo.png",
"stripeWebhookSecret": ""
}

View File

@ -16,6 +16,9 @@
"stripeLogoURL": {
"type": "string",
"format": "uri-template"
},
"stripeWebhookSecret": {
"type": "string"
}
},
"required": [

20
package-lock.json generated
View File

@ -7614,7 +7614,8 @@
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"dev": true
},
"quick-lru": {
"version": "1.1.0",
@ -8726,13 +8727,18 @@
"dev": true
},
"stripe": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-5.10.0.tgz",
"integrity": "sha512-AUDmXfNAAY/oOfW87HPO4bDzNWJp8iQd0blVWwwEgPxO1DmEC//foI0C9rhr2ZNsuF6kLypPfNtGB9Uf+RCQzQ==",
"version": "7.12.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-7.12.0.tgz",
"integrity": "sha512-h/NMB7E+0WgDuEOdfrS9giYmTfQRvOoKHdYaKzo9V0hxilXopVJd3ZZQ47193rAOHjIhmuCDtQRb3gEEm24gKg==",
"requires": {
"lodash.isplainobject": "^4.0.6",
"qs": "~6.5.1",
"safe-buffer": "^5.1.1"
"qs": "^6.6.0"
},
"dependencies": {
"qs": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.0.tgz",
"integrity": "sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA=="
}
}
},
"superagent": {

View File

@ -50,7 +50,7 @@
"sanitize-html": "^1.20.1",
"sitemap": "^1.6.0",
"strip-bom": "^3.0.0",
"stripe": "^5.10.0",
"stripe": "^7.12.0",
"uglifycss": "0.0.27"
},
"devDependencies": {

View File

@ -115,13 +115,27 @@ router.post('/checkout_action', (req, res, next) => {
// Subscription hook from Stripe
router.all('/subscription_update', async (req, res, next) => {
const db = req.app.db;
const stripeSigSecret = common.getPaymentConfig().stripeWebhookSecret;
const stripeSig = req.headers['stripe-signature'];
if(!req.body.data.object.customer){
return res.status(400).json({ message: 'Customer not found' });
let hook;
if(stripeSigSecret){
try{
hook = await stripe.webhooks.constructEvent(req.rawBody, stripeSig, stripeSigSecret);
console.info('Stripe Webhook received');
}catch(err){
return res.status(400).send(`Webhook Error: ${err.message}`);
}
if(!hook.data.object.customer){
return res.status(400).json({ message: 'Customer not found' });
}
}else{
hook = req.body;
}
const order = await db.orders.findOne({
orderCustomer: req.body.data.object.customer,
orderCustomer: hook.data.object.customer,
orderType: 'Subscription'
});
@ -130,7 +144,7 @@ router.all('/subscription_update', async (req, res, next) => {
}
let orderStatus = 'Paid';
if(req.body.type === 'invoice.payment_failed'){
if(hook.type === 'invoice.payment_failed'){
orderStatus = 'Declined';
}