Integrating the Stripe payment gateway into checkout (Project Aurora)
Turn a spoken assignment into a structured brief ready to hand off.
Sample of a real output
Summary
Mark from the Payments team dictated a brief for wiring the Stripe payment gateway into the checkout of the Project Aurora e-shop. The goal is to replace the current manual invoicing with online card payments, with support for Apple Pay and Google Pay. The deadline for the production rollout is July 15, with an MVP on the staging environment by the end of June.
Detailed minutes
What needs to be built
The goal is to add card payments via Stripe to Project Aurora's existing checkout. After filling the cart, the customer picks a payment method and pays right on the page, without being redirected to an external gateway. Mark stressed that the payment form should be embedded via Stripe Elements so it stays within the e-shop's design.
Besides the standard card, Apple Pay and Google Pay should be supported, because according to the analytics, mobile orders make up more than half of the traffic. Cash and invoice payments remain available as alternatives; Stripe is just a third option on top.
Technical requirements and safeguards
Reliable payment confirmation is critical. The order status must never change based on the response from the browser, but exclusively via a Stripe webhook on the backend (the payment_intent.succeeded event). Mark explicitly warned against a situation where the customer pays but the connection drops and the order stays stuck as unpaid.
Every call must be idempotent (running it again won't create a second payment) via an idempotency key. Webhooks must be verified by signature so they can't be spoofed. In case of a Stripe outage, a fallback is required — the checkout must not go down entirely; the card option is just hidden and the remaining payment methods are offered.
Tasks
- Create a backend endpoint for creating a PaymentIntent with Stripe (amount, currency, idempotency key).
- Integrate Stripe Elements into the frontend checkout (card, Apple Pay, Google Pay) in the e-shop's design.
- Implement a webhook handler for payment_intent.succeeded and payment_intent.payment_failed with signature verification.
- Add a fallback: when Stripe is unavailable, hide card payment and offer cash and invoice.
- Prepare test scenarios (success, card failure, webhook outage, duplicate payment) on the staging environment.
Decisions
- The payment form will be embedded via Stripe Elements directly into the checkout, with no redirect to an external page. 💬 from transcript: „"I want it inside, in the same design, not bouncing the person off to some third-party page."“
- Payment confirmation is handled by the server-side payment_intent.succeeded webhook, not by the client response. 💬 from transcript: „"The source of truth is the webhook on the backend, full stop."“
- Apple Pay and Google Pay are part of the first MVP, not a later phase. 💬 from transcript: „"Treat Apple Pay and Google Pay as part of the baseline, not a bonus for later."“
Key insights
- The order status is driven exclusively by the server-side webhook, not by the browser response — this protects against losing a payment when the connection drops. 💬 from transcript: „"Never, and I mean never, confirm an order based on what comes back to the browser. Only based on the webhook on the server."“
- Mobile orders make up over 50% of traffic, which is why Apple Pay and Google Pay are part of the MVP, not a second phase. 💬 from transcript: „"More than half of people buy from their phone, so Apple Pay and Google Pay have to be there right away, not sometime later."“
- If Stripe goes down, the whole checkout must not break — only card payment is hidden, and cash and invoice remain. 💬 from transcript: „"If Stripe goes down, don't let the whole checkout crash. Just hide the card option and people pay another way."“
Data
- July 15 date Production rollout Deadline for launching the payment gateway in live operation.
- end of June date MVP on staging A working integration ready for testing.
- high priority Task priority Mark flagged card payments as blocking for the summer campaign.
- over 50 % Share of mobile orders The reason for including Apple Pay and Google Pay in the MVP.
Unclear / risks
- It is not specified whether saving cards for recurring payments (saved cards) should be supported, or only one-off payments.
- Mark did not mention a specific threshold for automatic refunds — this needs to be finalized with the support team.
- It was not stated which currencies will be accepted (only CZK, or also EUR for international customers).
Brief for implementer
Implementation brief — Integrating the Stripe payment gateway (Project Aurora)
Goal
Add card payments via Stripe to the existing checkout of the Project Aurora e-shop, including Apple Pay and Google Pay, as a third payment method alongside cash and invoice.
Scope
- Payment form embedded via Stripe Elements directly into the checkout (no redirect to an external gateway).
- Support for payment methods: card, Apple Pay, Google Pay.
- Server-side payment confirmation via webhooks (source of truth = backend, not the browser).
- Fallback when Stripe is unavailable (graceful degradation without bringing down the whole checkout).
Out of scope
- Saving cards for recurring payments (saved cards) — not handled for now, pending a decision.
- Refunds via the admin UI — for the MVP, refunds via the Stripe Dashboard are sufficient.
Functional requirements
- Creating a payment
- The backend endpoint creates a
PaymentIntent(amount, currency,idempotency_key). - The frontend requests the
client_secretand renders Stripe Elements.
- The backend endpoint creates a
- Payment confirmation
- The order status is changed exclusively by the
payment_intent.succeededwebhook. - The client response is only used to show the "thank you" screen, never to confirm the order.
- The order status is changed exclusively by the
- Payment failure
payment_intent.payment_failedwebhook → the order stays in the "awaiting payment" state, and the customer gets the option to try again.
- Fallback
- When Stripe is unavailable, card payment is hidden and cash + invoice are shown. The checkout must not go down entirely.
Non-functional requirements
- Idempotency: every
PaymentIntentcall uses an idempotency key (resubmitting won't create a second payment). - Webhook security: signature verification (
Stripe-Signature), rejection of unverified requests. - Secrets: Stripe API keys exclusively in GCP Secret Manager, never in code or in a
.envfile in git. - Logging: every payment failure and every incoming webhook goes to structured logging (Cloud Logging).
Acceptance criteria
- The customer pays by card and the order is marked as paid only after the
payment_intent.succeededwebhook is received. - Apple Pay and Google Pay show up on supported devices and work end-to-end.
- If the connection drops after payment (browser closed), the order is still marked as paid thanks to the webhook.
- Submitting a payment twice does not create two payments (verified via the idempotency key).
- A spoofed webhook without a valid signature is rejected (HTTP 400).
- During a simulated Stripe outage, the checkout doesn't break — card payment simply disappears.
Deadlines
- MVP on staging: end of June
- Production: July 15
Open questions
- Saving cards for recurring payments — yes/no?
- Currencies: only CZK, or also EUR?
- Threshold for automatic refunds?
Transcript sample
Okay, let's move on to payments. I want us to finally get card payments via Stripe into the Aurora checkout. Right now people pay either in cash on delivery or by invoice, and that's slowing us down.
The important thing is that it stays inside, in the same design. No bouncing off to a third-party page. We'll embed it via their Elements so it looks like part of the e-shop.
And now the most important part. Never, and I mean never, confirm an order based on what comes back to the browser. Only based on the webhook on the server. We've already had a case where a person paid, their connection dropped, and the order was left hanging as unpaid. That must not happen again.
Treat Apple Pay and Google Pay as part of the baseline, not a bonus for later. More than half of people buy from their phone, so it has to be there right away.
And one more thing. If Stripe goes down, don't let the whole checkout crash. Just hide the card option and people pay another way. I don't want to lose an entire sale because of a gateway outage.
Ultimately I want it live by July 15, because of the summer campaign. On staging, let's have it working by the end of June so Lucy has enough time to click through it properly.