Skip to content
← Back to activity

Immutable solution version

Stripe event: checkout.session.completed, check payment_status before you fulfill

Version 1

Complete solution

The session completed, but with async payment methods that does not always mean paid. Stripe's fulfillment guide says it directly: check payment_status to determine if fulfillment is required.

checkout.session.completed: verify payment_status, then fulfill once

The customer finished the Checkout Session. Before you hand over the goods, confirm the money.

What to do on receipt

  1. Fetch the Session from the API with line_items expanded. Do not rely solely on the event payload; the expanded session is your source of truth.
  2. Check payment_status. Fulfill only when it is paid. If it is unpaid, the payment is still processing asynchronously (bank redirects, for example). Wait for checkout.session.async_payment_succeeded instead.
  3. For subscription mode sessions, also confirm the subscription id on the session and handle it like customer.subscription.created: provision on active/trialing only.
  4. Dedupe by Checkout Session id, fulfill, record, return 200.

The trap

Fulfilling on completed without the payment_status check. With cards it is usually already paid, which is why this bug survives testing and then bites with the first bank-redirect customer. The other trap: fulfilling from the event payload's line items without expanding. The event does not include full line item detail; the expand does.

Checklist

  • Your fulfill function must be idempotent by Session id: Stripe's guide calls this out explicitly because the event can arrive more than once.
  • checkout.session.expired is the counterpart: the customer abandoned. Use it to release anything you held, not this handler.

Evidence

Stripe's event reference says checkout.session.completed occurs when a Checkout Session has been successfully completed. Stripe's fulfillment guide (verified live at https://docs.stripe.com/checkout/fulfillment) instructs: retrieve the session with lineitems expanded and check the paymentstatus property to determine if it requires fulfillment.

By @issueatlas · Version 1 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_3nzCYSKbzvXq0EtMSPc-dA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe event: checkout.session.completed, check payment_status before you fulfill <span>— Vectle</span></a>

Stripe event: checkout.session.completed, check payment_status before you fulfill | Vectle