STRIPE_SHOP - BevvyTech/BrewskiDocs GitHub Wiki
Here’s a full implementation brief in a code-block style, suitable to hand to an LLM or engineer. It describes what to build, how the flows should behave, and which Stripe concepts & APIs to use (you can map to your local Stripe API docs).
## Payment Flow & Order Lifecycle — Implementation Brief
### Objectives
- Use **Stripe Connect** to orchestrate payments, commissions, and payouts.
- Support a **pre-authorization (manual capture)** model: hold funds when customer places an order, but capture only after merchant acceptance.
- Deduct a **configurable platform fee** (e.g. 2% + £10) at the time of capture.
- Maintain order status transitions in our system (e.g. `review` → `accepted` → `paid` / `cancelled`).
- Use Stripe webhooks to confirm capture or cancellation and update our database reliably.
---
### Key Concepts & Stripe APIs
| Concept | Description / Use |
|---|----------------------|
| **PaymentIntent with manual capture** | Create a `PaymentIntent` with `capture_method = "manual"` so that Stripe authorises (places a hold) but doesn’t immediately take the funds. |
| **application_fee_amount + transfer_data.destination** | Use `application_fee_amount` to specify your platform’s commission, and `transfer_data.destination` to route the remainder to the merchant’s Stripe connected account. |
| **Capture / Cancel** | When merchant accepts: call `stripe.paymentIntents.capture(id)`. When merchant rejects: call `stripe.paymentIntents.cancel(id)`. |
| **Webhooks** | Listen for `payment_intent.succeeded` (capture completed), `payment_intent.canceled` (authorization voided / cancelled). Verify signatures. |
| **Order status transitions** | Map Stripe state changes to your internal order statuses. Use idempotent updates. |
---
### Flow Outline
1. **Order placement (customer action)**
- Customer submits order.
- Backend computes commission: `commission = round(order_total * percent_fee + fixed_fee)`.
- Create a Stripe `PaymentIntent`:
- `amount = order_total`
- `currency = …`
- `capture_method = "manual"`
- `application_fee_amount = commission`
- `transfer_data.destination = merchant_stripe_account_id`
- Add metadata: `order_id`, maybe `merchant_id`.
- Store in your database:
- `order.status = "review"`
- `order.stripe_payment_intent_id = <the id>`
2. **Merchant decision**
- If merchant **accepts**:
- Backend calls `stripe.paymentIntents.capture(intent_id)`.
- Update `order.status = "accepted"`.
- If merchant **rejects** or order expires:
- Backend calls `stripe.paymentIntents.cancel(intent_id)`.
- Update `order.status = "cancelled"`.
3. **Stripe webhooks**
- Set up webhook endpoints and subscribe to relevant events:
- `payment_intent.succeeded` → map to `order.status = "paid"`.
- `payment_intent.canceled` → map to `order.status = "cancelled"`.
- Verify webhook signatures using your Stripe webhook secret.
- Handle idempotency (don’t double-apply status changes).
4. **Configuration & dynamic fees**
- Store `percent_fee` and `fixed_fee` in config or a table, so you can change them without code changes.
- Always compute commission at the moment you create the PaymentIntent.
---
### Status Transitions (simplified)
pending / draft → review (when order placed, before capture) review → accepted → trigger capture → Stripe → on success → paid review → cancelled (if merchant rejects or timeouts) → cancel intent
Stripe may automatically cancel uncaptured PaymentIntents after 7 days (or card-specific hold expiry) — typical behaviour in Stripe’s manual capture model.
(Stripe docs: *“you can place a hold … later capture”* for eligible payment methods) :contentReference[oaicite:0]{index=0}
---
### Implementation Checklist for LLM / Engineer
- Initialize Stripe SDK with API version pinned (e.g. “2024-09-30” or your version).
- Build function to **create PaymentIntent** with `capture_method = "manual"`, `application_fee_amount`, and `transfer_data.destination`.
- Build **capture** and **cancel** functions calling Stripe’s API.
- Store / update order statuses in your database according to outcomes.
- Build webhook listener to handle `payment_intent.succeeded` and `payment_intent.canceled`.
- Validate webhook signatures.
- Ensure idempotency and safe error handling.
- Expose merchant action triggers (accept / reject) to call the capture / cancel logic.
- Allow commission parameters to be loaded dynamically.
- Use Stripe test mode to test end-to-end: auth, capture, cancel, webhooks.
---
### Notes / Refs for Offline Use
- Stripe supports **manual capture** flows (authorisation then capture) via `capture_method = "manual"`. :contentReference[oaicite:1]{index=1}
- The “Capture a charge” API (for older Charge objects) shows concept of capturing a previously authorised charge. :contentReference[oaicite:2]{index=2}
- Stripe automatically expires/voids authorizations you never capture after a time window. :contentReference[oaicite:3]{index=3}
---
This brief gives a self-contained specification of what needs to be implemented (without prescribing your internal API design). Use it to guide your LLM / engineer to build the correct pre-authorization + capture + commission split flow with Stripe Connect.