Skip to content
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

docs[snippets]: add stripe webhook integration #347

Merged
merged 7 commits into from
May 18, 2024
Merged
4 changes: 4 additions & 0 deletions .vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ const sidebarsSnippets = (): DefaultTheme.SidebarItem[] => [
text: 'htmx',
link: '/snippets/htmx',
},
{
text: 'Stripe Webhook',
link: '/snippets/stripe-webhook'
}
],
},
]
Expand Down
90 changes: 90 additions & 0 deletions snippets/stripe-webhook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Stripe Webhook Integration

This introduces how to create an API with Hono to receive Stripe Webhook events.

yusukebe marked this conversation as resolved.
Show resolved Hide resolved
## Preparation

Please install the official Stripe SDK at first:

```bash
npm install stripe
```

And put the following values on the `.dev.vars` file to insert the Stripe API keys:

```
STRIPE_API_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
```

You can learn about the Stripe API keys by the following documents:

- Secret Key: https://docs.stripe.com/keys
- Webhook secret: https://docs.stripe.com/webhooks

## How to protect the API for Stripe Webhook events

The API that processes webhook events is publicly accessible.Therefore, a mechanism is needed to protect it from attacks such as malicious third parties spoofing Stripe's webhook event objects and sending requests. In Stripe's case, you can protect the API by issuing a webhook secret and verifying each request.

Learn more: https://docs.stripe.com/webhooks?lang=node#verify-official-libraries

## Implementing the Webhook API by hosting environment or framework
To perform signature verification with Stripe, the raw request body is needed.
When using a framework, you need to ensure that the original body is not modified. If any changes are made to the raw request body, the verification will fail.

In the case of Hono, we can get the raw request body by the `context.req.text()` method. So we can create the webhook API like the following example:

```ts
import Stripe from 'stripe';
import { Hono } from 'hono';
import { env } from 'hono/adapter';

const app = new Hono();

app.post("/webhook", async (context) => {
const { STRIPE_SECRET_API_KEY, STRIPE_WEBHOOK_SECRET } = env(context);
const stripe = new Stripe(STRIPE_SECRET_API_KEY);
const event = await context.req.json();
const signature = context.req.header('stripe-signature');
try {
if (!signature) {
return context.text("", 400);
}
const body = await context.req.text();
const event = await stripe.webhooks.constructEventAsync(
body,
signature,
STRIPE_WEBHOOK_SECRET
);
switch(event.type) {
case "payment_intent.created": {
console.log(event.data.object);
break
}
default:
break
}
return context.text("", 200);
} catch (err) {
const errorMessage = `⚠️ Webhook signature verification failed. ${err instanceof Error ? err.message : "Internal server error"}`;
console.log(errorMessage);
return context.text(errorMessage, 400);
}
});

export default app;
```


## Lear more

- Details on Stripe Webhooks:
https://docs.stripe.com/webhooks
- Implementing for payment processing:
https://docs.stripe.com/payments/handling-payment-events
- Implementing for subscriptions:
https://docs.stripe.com/billing/subscriptions/webhooks
- List of webhook events sent by Stripe:
https://docs.stripe.com/api/events
- Sample template for Cloudflare:
https://github.com/stripe-samples/stripe-node-cloudflare-worker-template/