Stripe And Webhook Cookbook
Use this page when moving from Stripe adapter wiring to production webhook behavior.
Prerequisites
Section titled “Prerequisites”- Stripe Provider is complete.
STRIPE_SECRET_KEYandSTRIPE_WEBHOOK_SECRETare configured in the host environment.- The Stripe provider is registered through
createMikaProviderRegistry([stripeProvider]). - The webhook route renders on demand with
export const prerender = false.
- Install Stripe and create the SDK client in a server-only module.
- Pass that client and
STRIPE_WEBHOOK_SECRETtocreateMikaStripeProvider(). - Register the provider through
createMikaProviderRegistry([stripeProvider]). - Copy or implement
src/pages/api/mika-webhook/[provider].ts. - Preserve the original
Requestso Mika can read the raw body for provider verification. - Confirm checkout success by calling Mika checkout status; do not trust the success URL alone.
- Monitor webhook replay, failure, and deduplication records through host ops/admin surfaces.
Webhook Endpoint Shape
Section titled “Webhook Endpoint Shape”import { createMika } from "@bnomei/emdash-mika/astro";import { createProviderName } from "@bnomei/emdash-mika/types";import type { APIRoute } from "astro";
export const prerender = false;
export const POST: APIRoute = async ({ params, request, url }) => { const provider = params.provider; if (!provider) return new Response("Missing provider.", { status: 400 });
const Mika = createMika({ request, url }, { includeWebhook: true }); const result = await Mika.webhook.receive({ provider: createProviderName(provider), });
return Response.json(result, { status: result.status });};The copied template endpoint adds diagnostics such as payload hash and signature-header presence, but verification still happens inside the provider adapter using the raw body from ctx.request.
Stripe Verification Requirements
Section titled “Stripe Verification Requirements”createMikaStripeProvider() verifies webhooks when the host supplied:
- a Stripe-shaped client with
stripe.webhooks.constructEvent; webhookSecret;- the original raw request body;
- the incoming
Stripe-Signatureheader.
The adapter returns a payloadHash as sha256:<hex> plus parsed provider event data. Mika’s backend uses provider evidence for deduplication and workflow handling. Stripe payment failures, expired checkout sessions, refunds, partial refunds, and uncollectible invoices are normalized into Mika payment events instead of being treated as unknown webhooks.
Idempotency And Returns
Section titled “Idempotency And Returns”Checkout start should receive a host idempotency key when the caller may retry the same request. Mika stores checkout idempotency metadata and rejects same-key different-input replay.
The success URL is not proof of payment. The copied success page reads checkoutId and optional token, then calls Mika.checkout.status(...) and renders the provider-backed status.
The cancel page can call Mika checkout cancel for abandonment UX, but it is not proof that payment failed or never completed. Release expired stock reservations from maintenance.
Verify
Section titled “Verify”- Stripe sends
Stripe-Signatureto the webhook endpoint. - The endpoint passes the original
RequesttocreateMika({ request, url }, { includeWebhook: true }). - A valid webhook returns a Mika result envelope with the provider event normalized or queued.
- Checkout success renders status from
Mika.checkout.status(...), not from the return URL alone.
External References
Section titled “External References”- Stripe webhook signature verification for
Stripe-Signature, raw body, andconstructEvent()requirements. - Stripe webhooks for endpoint setup, retries, and event delivery behavior.
Source Anchors
Section titled “Source Anchors”- ⓟ
../emdash-mika/src/stripe.ts - ⓟ
../emdash-mika/src/provider.ts - ⓟ
../emdash-mika/src/api/backend.ts - ⓐ
../emdash-mika/src/templates/astro/pages/api/mika-webhook/[provider].ts - ⓐ
../emdash-mika/src/templates/astro/pages/checkout/success.astro - ⓐ
../emdash-mika/src/templates/astro/pages/checkout/cancel.astro