A payment is not a redirect: designing a trustworthy webhook workflow

A payment is not a redirect: designing a trustworthy webhook workflow
AI-generated illustrative photograph

A buyer pays, closes the tab and later asks where the purchase went. Another buyer returns to the success page twice. Neither browser action should decide whether an order is paid. A checkout interface is a conversation with the customer; the payment ledger is a separate server responsibility. This distinction matters for domain sales because the next action may transfer an asset that cannot simply be put back into a shopping cart. START WITH ONE ORDER, NOT ONE BUTTON Before opening checkout, create an internal order with a stable identifier, buyer, item, expected amount and currency. Think of this as a sealed envelope describing the transaction you intend to accept. When a payment notification arrives, the application should compare it with that envelope. A valid notification for a different order is still the wrong notification. A payment in dollars must not satisfy an order recorded in euros merely because the digits match. For a practical example, imagine an order for a domain priced at €500. Store the amount as 50000 euro cents, not a formatted string containing a currency symbol. Record any discount and the final payable amount at order creation. A later catalogue price change should not silently rewrite an existing checkout. Decide explicitly how a customer can cancel the old order and create a new one. AUTHENTICITY BEFORE BUSINESS LOGIC Stripe documents signature verification using the original request body, the signature header and the endpoint signing secret. Its official libraries provide this check. Keep the endpoint secret in server configuration, separate test and live environments, and never put it in frontend code. A useful implementation review follows the request from the network entrance to the handler. Where is its body read? Which middleware parses it? Does any proxy rewrite it? The team should be able to point to the exact verification boundary. Do not diagnose failures by printing secrets into logs. Instead, record a request identifier, the relevant environment and a sanitised failure category. Treat authentication failures differently from temporary database outages: they need different responses and different alerts. RECEIPT IS NOT COMPLETION Stripe notes that notifications can be repeated and arrive out of order. Its fulfilment guidance distinguishes delayed payment outcomes. Those are transport and payment realities, not evidence that the customer pressed the wrong button. Design an inbox for accepted notifications and a separate order transition. A unique event identifier helps stop one delivery being handled twice, but the business operation also needs a guard: an order already fulfilled must not transfer its domain again. Consider two workers reaching the same order simultaneously. A database constraint or transaction should arbitrate the transition, rather than a browser variable or an optimistic “already checked” condition. Use states that colleagues can explain: awaiting payment, payment confirmed, fulfilment pending, fulfilled, and needs review. A failed or expired attempt belongs to its own history. It should not overwrite a newer successful payment simply because an older message arrived later. WHAT TO TEST BEFORE LAUNCH Make a small table of expected outcomes. An invalid signature must not alter an order. A duplicate valid event must not create a second transfer. A valid payment with an unexpected amount, currency or session reference must enter review rather than silently pass. A payment confirmed while the buyer’s browser is closed should still appear in the account. A database interruption should leave enough information to recover safely. Test delayed success and delayed failure separately. Then test the unglamorous case: the notification is accepted, but the fulfilment worker stops halfway through. Recovery should continue from persisted state, not rely on someone remembering what happened. Never use a production asset transfer merely to demonstrate a green success screen. MAKE UNCERTAINTY VISIBLE The customer needs a clear distinction between “payment confirmed” and “transfer completed”. Show the order number and the next step; avoid claiming success while the server is still waiting. For staff, build a review queue with reason codes and a reconciliation action that retrieves the authoritative payment record. This is our operational recommendation, not a claim that installing a webhook alone prevents every incident. A domain project starts with a suitable name, but reliable checkout becomes part of the brand experience. Explore names in the DomainEvery catalogue: https://domainevery.com/en/domains, and budget for payment verification, recovery and fulfilment alongside the website design. SOURCES Stripe: webhooks: https://docs.stripe.com/webhooks Stripe: endpoint management and signature troubleshooting: https://docs.stripe.com/events/manage-webhook-endpoints Stripe: hosted Checkout fulfilment: https://docs.stripe.com/checkout/fulfillment.md?payment-ui=stripe-hosted