Skip to main content
Stripe is Droplinked’s default card-payment processor. It powers three flows:
  1. Merchant onboarding — Connect, plus an OAuth onramp for merchants who already have a Stripe account
  2. Customer payments — PaymentIntent per order, attached to the merchant’s connected account or to the platform’s primary account when the merchant isn’t connected
  3. Subscription billing — Stripe Checkout sessions for Droplinked’s own SaaS plans

Configuration

Use test-mode keys (sk_test_...) for the dev environment. Stripe issues a separate webhook signing secret per endpoint per environment.

Merchant onboarding

There are three Stripe onramps, and they do not all produce the same kind of account. Because the account type determines merchant of record, chargeback liability and payout ownership, here is the precise mapping:
The generated OpenAPI summary for GET /stripe/account-onboarding describes it as creating an “Express” account. That summary is wrong — the implementation calls accounts.create({ type: 'standard' }). Accounts from that route are Standard.
Who is merchant of record, and who answers a chargeback, follows the account the charge landed in — see Merchant PSP onboarding for the full table.
1

Look up shop + user

Resolve the user’s email and the shop’s existing connected-account id (if any).
2

Reject if already onboarded

If the shop already has a connected account, throws BadRequestException (“already onboarded”).
3

Create the Stripe account

stripe.accounts.create({ type, email }) — standard on the legacy route, express on the Connect-module route. Save the new account ID against the shop.
4

Return the onboarding link

stripe.accountLinks.create() with a return URL appropriate for the environment. Return the URL to the merchant.
A connected account is not automatically a chargeable one. Until Stripe enables charges, the checkout intent resolver reports PSP_ACCOUNT_NOT_READY / STRIPE_CHARGES_DISABLED and the card slot is withheld. Resolve availability at request time.

Webhook: account.updated

Mounted at POST /stripe/account-onboarding/webhook. The platform listens for account.updated events. When charges_enabled and payouts_enabled are both true, the shop’s Stripe status is flipped to active.
The handler:
  1. Fetches the account-update endpoint secret from config
  2. Constructs the event with stripe.webhooks.constructEvent(body, sig, secret) — verifying authenticity
  3. If the event is account.updated and both capabilities are enabled, marks the shop active
  4. Returns true on success; throws BadRequestException on verification failure
Always use the raw request body when verifying webhooks. Re-parsed JSON breaks the signature.

Customer payments

Per-order payments use the standard PaymentIntent flow. See Order lifecycle for how this integrates with the order-confirmation saga.

Connected-account vs platform charges

  • Merchant connected — payment_intent.create({ on_behalf_of, transfer_data }) so funds settle into the merchant’s Stripe account; platform retains an application fee
  • Merchant not connected — Payment captured into the platform’s primary Stripe account; merchant payout reconciled out-of-band

Subscription billing

Droplinked’s own SaaS plans bill through Stripe Checkout (subscription mode). The subscription gateway is exposed as integration-service endpoints called server-to-server from the backend.

Create a subscription checkout session

Returns { checkoutUrl, sessionId }. Redirect the merchant to checkoutUrl.
Stripe metadata values must be strings — the gateway drops null/undefined entries before sending.

Webhook signature verification

Droplinked mounts four Stripe webhook routes: All of them use stripe.webhooks.constructEvent to validate the Stripe-Signature header against the endpoint secret, over the raw request body. A failed verification returns 400 and is never processed. A missing signing secret returns 503, not 400, so Stripe retries rather than dropping a genuine event — it re-delivers for up to three days. Full contract, including every non-Stripe source: Webhooks. For replay safety and the broader webhook test matrix, see Checkout stability.

Flow diagram — customer payment

Troubleshooting