Checkout & payments
Payment gateway sandbox round-trip verification
Generated from docs/plan/core/payment-gateway-sandbox-round-trip-verification/PLAN.md in the project's planning notes, which are not part of the public repository. Nothing described below is implemented — it is the written plan for it.
An idea, not a commitment. It has a written plan but no place in the build order and no date. What is committed.
Payment integrations (Stripe, PayPal, Klarna) are theoretically correct but never verified against real gateways. This core work adds round-trip sandbox tests confirming session creation, webhook handling, and state transitions work end-to-end.
The problem
Payment integrations are implemented correctly by design, but we’ve never actually run a transaction against Stripe, PayPal, and Klarna in their sandboxes. A missed detail (wrong timestamp format, forgotten signature validation) might silently break in production.
What it does
- Stripe sandbox round-trip: create order, POST /api/payments/start, get redirect URL, simulate Stripe webhook, confirm order becomes ‘paid’
- PayPal sandbox round-trip: same flow, confirm PayPal session creation and webhook state changes work
- Klarna sandbox round-trip: same flow, confirm Klarna authorization and capture sequence works
- Idempotency: replay each webhook, confirm state does not change (no double-charge)
- Error cases: webhook with wrong signature, wrong amount, out-of-order events — confirm all are handled safely
- Test data retention: keep test orders in a ‘sandbox-test’ category so they don’t pollute reports
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- Live production testing — that’s certification (production-payment-gateway-certification).
- Automated CI/CD integration — tests run manually before each release (can be automated later).
Data model
No new schema. Test orders have a flag/category for identification: sandbox_test=true or similar.
API
- POST /api/tests/payment-gateway/{provider} — run round-trip test against provider’s sandbox, return results
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Test panel under Payments; buttons for ‘Test Stripe’, ‘Test PayPal’, ‘Test Klarna’. Results show pass/fail for each step (session creation, webhook delivery, state transition). Log is accessible for debugging.
The seam — why this is core
Core owns the test harness and validation logic. Providers’ sandboxes are external (third-party). Tests are part of the smoke-test suite.
Payment correctness is non-negotiable. Unverified integrations are a trust issue.
Dependencies
- adyen-payment-gateway, bnpl, apple-pay-google-pay-setup, paypal-suite-expansion — each provider can be tested
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- Run ‘Test Stripe’: creates order, calls Stripe API, receives session URL, simulates charge.succeeded webhook, order becomes ‘paid’ ✓
- Run ‘Test PayPal’: same flow ✓
- Run ‘Test Klarna’: same flow ✓
- Replay webhook: same event id sent twice; order state unchanged on second delivery ✓
- Wrong signature: webhook rejected with 401 ✓
- Wrong amount: webhook rejected as suspicious, audit-logged ✓
- Test orders marked ‘sandbox_test’; don’t appear in production reports or inventory calculations
Risks
False sense of correctness: passing sandbox tests doesn’t mean production is safe. A detail unique to production (certificate expiry, webhook rate limiting, DNS issues) could still break. Sandbox mirrors production but is not identical. Test flakiness: if sandbox is slow or has outages, tests fail intermittently, crying wolf. Tests should have generous timeouts and clear failure messages. Credential rotation: test sandbox credentials must be rotated regularly; a leaked sandbox credential is less severe than production, but still a risk.
Commercial context
| Suggested price | Core |
| Rival anchor | Magento: PayPal and Braintree sandbox-verified in production for a decade. |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and CONTRIBUTING.md for how to work on this repository.