-
Notifications
You must be signed in to change notification settings - Fork 751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added typescript webhook example #749
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.env | ||
express-ts.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import Stripe from 'stripe'; | ||
import express from 'express'; | ||
import bodyParser from 'body-parser'; | ||
import dotenv from 'dotenv'; | ||
|
||
dotenv.config(); | ||
|
||
const stripe: Stripe = new Stripe(process.env.STRIPE_API_KEY!, { | ||
apiVersion: '2019-12-03', | ||
typescript: true, | ||
}); | ||
|
||
/** | ||
* You'll need to make sure this is externally accessible. ngrok (https://ngrok.com/) | ||
* makes this really easy. | ||
* | ||
* Alternatively, you could use the stripe-cli in forward mode: https://github.com/stripe/stripe-cli | ||
* | ||
* To run this file, just provide your Secret API Key and Webhook Secret in a .env file in this directory like so: | ||
* | ||
* STRIPE_API_KEY=sk_test_XXX | ||
* WEBHOOK_SECRET=whsec_XXX | ||
* | ||
* Then run "npm run tsc", which will convert this TypeScript file to JS and then run it. | ||
* | ||
* For use with the stripe-cli, run the following: | ||
* | ||
* 1. "stripe listen --forward-to localhost:3000/webhooks" | ||
* 2. Copy the provided webhook signing secret to your .env file | ||
* 3. In a new terminal window: "npm run tsc" | ||
* 4. In yet another new terminal window: "stripe trigger payment_intents.succeeded" | ||
*/ | ||
|
||
const webhookSecret: string = process.env.WEBHOOK_SECRET!; | ||
const app: express.Application = express(); | ||
|
||
// Only use the raw body parser for webhooks | ||
app.use( | ||
( | ||
req: express.Request, | ||
res: express.Response, | ||
next: express.NextFunction | ||
): void => { | ||
if (req.originalUrl === '/webhooks') { | ||
next(); | ||
} else { | ||
bodyParser.json()(req, res, next); | ||
} | ||
} | ||
); | ||
|
||
// Stripe requires the raw body to construct the event | ||
app.post( | ||
'/webhooks', | ||
bodyParser.raw({type: 'application/json'}), | ||
(req: express.Request, res: express.Response): express.Response | void => { | ||
const sig: string = req.headers['stripe-signature'] as string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is fixed; you no longer need to cast! |
||
|
||
let event: Stripe.Event; | ||
|
||
try { | ||
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret); | ||
} catch (err) { | ||
// On error, return the error message | ||
return res.status(400).send(`Webhook Error: ${err.message}`); | ||
} | ||
|
||
// Do something with event | ||
console.log('Success:', event.id); | ||
|
||
// Cast event data to Stripe object | ||
switch (event.type) { | ||
case 'payment_intent.succeeded': | ||
const pi = event.data.object as Stripe.PaymentIntent; | ||
console.log(`PaymentIntent status: ${pi.status}`); | ||
break; | ||
} | ||
|
||
// Return a response to acknowledge receipt of the event | ||
return res.json({received: true}); | ||
} | ||
); | ||
|
||
app.listen( | ||
3000, | ||
(): void => { | ||
console.log('Example app listening on port 3000!'); | ||
} | ||
); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this our best-practice? Does line 55 not work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line 55 does work, but I've seen people get tripped up by how express' middleware works. Having this block here will hopefully nip that confusion in the bud (and makes it so all other routes use the json body parser).