Properly handle stripe hook with sig verification
							parent
							
								
									e2e0fa2a00
								
							
						
					
					
						commit
						bf6c35ea50
					
				
							
								
								
									
										10
									
								
								app.js
								
								
								
								
							
							
						
						
									
										10
									
								
								app.js
								
								
								
								
							|  | @ -272,7 +272,6 @@ app.enable('trust proxy'); | ||||||
| app.use(helmet()); | app.use(helmet()); | ||||||
| app.set('port', process.env.PORT || 1111); | app.set('port', process.env.PORT || 1111); | ||||||
| app.use(logger('dev')); | app.use(logger('dev')); | ||||||
| app.use(bodyParser.json()); |  | ||||||
| app.use(bodyParser.urlencoded({ extended: false })); | app.use(bodyParser.urlencoded({ extended: false })); | ||||||
| app.use(cookieParser(config.secretCookie)); | app.use(cookieParser(config.secretCookie)); | ||||||
| app.use(session({ | app.use(session({ | ||||||
|  | @ -287,6 +286,15 @@ app.use(session({ | ||||||
|     store: store |     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
 | // Set locales from session
 | ||||||
| app.use(i18n.init); | app.use(i18n.init); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,5 +3,6 @@ | ||||||
|     "publicKey": "pk_test_this_is_not_real", |     "publicKey": "pk_test_this_is_not_real", | ||||||
|     "stripeCurrency": "usd", |     "stripeCurrency": "usd", | ||||||
|     "stripeDescription": "expressCart payment", |     "stripeDescription": "expressCart payment", | ||||||
|     "stripeLogoURL": "http://localhost:1111/images/stripelogo.png" |     "stripeLogoURL": "http://localhost:1111/images/stripelogo.png", | ||||||
|  |     "stripeWebhookSecret": "" | ||||||
| } | } | ||||||
|  | @ -16,6 +16,9 @@ | ||||||
|         "stripeLogoURL": { |         "stripeLogoURL": { | ||||||
|             "type": "string", |             "type": "string", | ||||||
|             "format": "uri-template" |             "format": "uri-template" | ||||||
|  |         }, | ||||||
|  |         "stripeWebhookSecret": { | ||||||
|  |             "type": "string" | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     "required": [ |     "required": [ | ||||||
|  |  | ||||||
|  | @ -7614,7 +7614,8 @@ | ||||||
|     "qs": { |     "qs": { | ||||||
|       "version": "6.5.2", |       "version": "6.5.2", | ||||||
|       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", |       "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": { |     "quick-lru": { | ||||||
|       "version": "1.1.0", |       "version": "1.1.0", | ||||||
|  | @ -8726,13 +8727,18 @@ | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "stripe": { |     "stripe": { | ||||||
|       "version": "5.10.0", |       "version": "7.12.0", | ||||||
|       "resolved": "https://registry.npmjs.org/stripe/-/stripe-5.10.0.tgz", |       "resolved": "https://registry.npmjs.org/stripe/-/stripe-7.12.0.tgz", | ||||||
|       "integrity": "sha512-AUDmXfNAAY/oOfW87HPO4bDzNWJp8iQd0blVWwwEgPxO1DmEC//foI0C9rhr2ZNsuF6kLypPfNtGB9Uf+RCQzQ==", |       "integrity": "sha512-h/NMB7E+0WgDuEOdfrS9giYmTfQRvOoKHdYaKzo9V0hxilXopVJd3ZZQ47193rAOHjIhmuCDtQRb3gEEm24gKg==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "lodash.isplainobject": "^4.0.6", |         "qs": "^6.6.0" | ||||||
|         "qs": "~6.5.1", |       }, | ||||||
|         "safe-buffer": "^5.1.1" |       "dependencies": { | ||||||
|  |         "qs": { | ||||||
|  |           "version": "6.9.0", | ||||||
|  |           "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.0.tgz", | ||||||
|  |           "integrity": "sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA==" | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "superagent": { |     "superagent": { | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ | ||||||
|     "sanitize-html": "^1.20.1", |     "sanitize-html": "^1.20.1", | ||||||
|     "sitemap": "^1.6.0", |     "sitemap": "^1.6.0", | ||||||
|     "strip-bom": "^3.0.0", |     "strip-bom": "^3.0.0", | ||||||
|     "stripe": "^5.10.0", |     "stripe": "^7.12.0", | ||||||
|     "uglifycss": "0.0.27" |     "uglifycss": "0.0.27" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|  |  | ||||||
|  | @ -115,13 +115,27 @@ router.post('/checkout_action', (req, res, next) => { | ||||||
| // Subscription hook from Stripe
 | // Subscription hook from Stripe
 | ||||||
| router.all('/subscription_update', async (req, res, next) => { | router.all('/subscription_update', async (req, res, next) => { | ||||||
|     const db = req.app.db; |     const db = req.app.db; | ||||||
|  |     const stripeSigSecret = common.getPaymentConfig().stripeWebhookSecret; | ||||||
|  |     const stripeSig = req.headers['stripe-signature']; | ||||||
| 
 | 
 | ||||||
|     if(!req.body.data.object.customer){ |     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' }); |             return res.status(400).json({ message: 'Customer not found' }); | ||||||
|         } |         } | ||||||
|  |     }else{ | ||||||
|  |         hook = req.body; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     const order = await db.orders.findOne({ |     const order = await db.orders.findOne({ | ||||||
|         orderCustomer: req.body.data.object.customer, |         orderCustomer: hook.data.object.customer, | ||||||
|         orderType: 'Subscription' |         orderType: 'Subscription' | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | @ -130,7 +144,7 @@ router.all('/subscription_update', async (req, res, next) => { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let orderStatus = 'Paid'; |     let orderStatus = 'Paid'; | ||||||
|     if(req.body.type === 'invoice.payment_failed'){ |     if(hook.type === 'invoice.payment_failed'){ | ||||||
|         orderStatus = 'Declined'; |         orderStatus = 'Declined'; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue