← all case studies
stripe-go + stripe-node

Mock the Stripe API locally — with the real stripe-go and stripe-node SDKs

stripe-go and stripe-node run against a local mock — webhooks verify through the SDKs’ own constructEvent.

Set up

One service block in stunt.yaml, then stunt up. The webhook_url is your test process — that's where signed deliveries land.

services:
  stripe:
    adapter: ./adapters/stripe-style
    config:
      webhook_url: http://localhost:9090/stripe
stunt catalog add stripe-style
stunt up
# stripe-go: stripe.SetBackend(stripe.APIBackend, stripe.GetBackendWithConfig(stripe.APIBackend, &stripe.BackendConfig{URL: stripe.String(base)}))
# stripe-node: new Stripe(key, { host, port, protocol: "http" })

What the suite proves

Asserted by the conformance suites in stunt's CI — not marketing copy. Every check below is a passing assertion:

  • 01Customer create + get round-trip — the SDK POSTs form-encoded Rails-style bracket bodies (metadata[source]=…); the mock parses them into nested structures like production
  • 02PaymentIntent create + confirm walks the real state machine to succeeded
  • 03The SDK iterator auto-walks has_more / starting_after across pages — a raw page pins that limit is honored
  • 04A webhook endpoint registers through the API; the signed delivery verifies through webhook.ConstructEvent / constructEventAsync — the HMAC checks out and event.data.object parses
  • 05A tampered payload fails the same verifier

Bugs the harness caught

PaymentIntent amount arrived as a JSON string

The mock echoed the form-encoded amount ("4200") verbatim. Real Stripe returns money fields as JSON numbers — and stripe-go’s typed deserializer rejects the response outright. Every existing test unmarshalled into a map, so nothing caught it. The conformance suite failed on its first run.

ConstructEvent only worked after the mock delivered real event objects

Receivers that call constructEvent need the actual Stripe event envelope — id, object, type, data — on the wire, byte-for-byte what gets MAC’d. The mock now delivers exactly that, which is what the SDK verifies here.

The whole flow — create, pay, paginate, receive, verify — runs offline in milliseconds, and the same suite runs in stunt’s CI so the contract can’t drift.