BillingWebhookKit

Next.js payment webhook entitlement test matrix

Before a webhook grants paid access, prove every provider event maps to one boring decision: grant, renew, pause, revoke, ignore, or quarantine.

Generate an entitlement matrix Build a webhook test plan

Why entitlement tests fail late

Most checkout bugs are not just signature bugs. The route verifies a valid event, then grants access on the wrong status, runs fulfillment twice after duplicate replay, revokes too early after cancellation, or forgets the refund path. A matrix makes those product decisions visible before live checkout traffic arrives.

Minimum Next.js matrix

Event class Trusted fields Expected entitlement decision Regression test
Paid checkout event_name, provider object ID, paid status, currency, product or price ID, customer ID Grant access once and attach the provider object to the user record. Signed fixture returns 2xx and writes exactly one entitlement.
Renewal or payment success Subscription ID, invoice/payment ID, current period, paid status Extend access once for the paid period without recreating the user. Duplicate replay keeps one extension for the same invoice/payment.
Cancellation Subscription ID, cancellation mode, period end, provider status Schedule revocation at period end, or revoke immediately only when the provider semantics require it. Cancellation fixture does not erase paid access before the expected date.
Failed payment Subscription ID, invoice/payment ID, attempt status, grace period policy Mark billing risk, notify support or the user, and keep access according to the grace policy. Failed payment fixture never grants new paid access.
Refund or chargeback Payment ID, refund ID, amount, reason, original order or invoice Record rollback evidence, revoke or flag access according to refund policy, and avoid duplicate support actions. Refund replay produces one rollback record and one access decision.
Unknown event Provider event ID, type, raw payload hash Return a safe 2xx or quarantine according to policy, but never grant access by default. Unknown signed fixture writes no entitlement.

Handler order

Keep the webhook route deterministic. Read the exact raw body, verify the provider signature, parse JSON, build an idempotency key, validate provider object fields, then evaluate the entitlement matrix.

export async function POST(request: Request) {
  const rawBody = await request.text();
  const signature = request.headers.get("x-signature");

  await verifyProviderSignature(rawBody, signature);
  const event = JSON.parse(rawBody);
  const key = buildWebhookIdempotencyKey(event);

  await runOnce(key, async () => {
    const decision = decideEntitlement(event);
    await applyEntitlementDecision(decision);
  });

  return new Response("ok", { status: 200 });
}

Provider examples

Lemon Squeezy

Start with order_created, subscription payment success, cancellation, license key, and refund flows. Keep x-signature checks before paid-state decisions.

Stripe

Cover checkout.session.completed, invoice.paid, customer.subscription.deleted, and refund or dispute events. Match entitlements to price IDs, not UI labels.

Paddle

Cover transaction.completed, subscription lifecycle events, pause/cancel states, and adjustments. Verify Paddle-Signature against request.text().

CI gate

Run valid signature, mutated body, duplicate replay, unpaid status, refund rollback, and unknown event tests before exposing a public buy link.

FAQ

What should an entitlement test matrix cover for payment webhooks?

Cover paid checkout, renewal, cancellation, refund, failed payment, duplicate replay, unknown events, and the exact access decision expected for each event.

Where should entitlement logic run in a Next.js payment webhook?

Run entitlement decisions only after raw-body signature verification, idempotency checks, provider object validation, and paid-state checks have passed.

Use the free tools before buying the Pro Kit

The browser-only tools generate an entitlement matrix and launch plan for free. The CNY 69 Pro Kit is for teams that want copy-ready fixtures, tests, and review evidence in one package.