Skip to main content
Stripe is Droplinked’s default card-payment processor. It powers three flows:
  1. Merchant onboarding — Connect (Standard accounts) so merchants receive funds in their own Stripe account
  2. Customer paymentsPaymentIntent 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 (Stripe Connect Standard)

The platform creates a Standard Connect account for each merchant and returns a hosted onboarding link.
1

Look up shop + user

Resolve the user’s email and the shop’s existing expressStripeAccountId (if any).
2

Reject if already onboarded

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

Create the Stripe account

stripe.accounts.create({ type: 'standard', email }). 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.

Webhook: account.updated

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 connectedpayment_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

All webhook handlers (account update, payment-intent succeeded, charge refunded, etc.) use stripe.webhooks.constructEvent to validate the Stripe-Signature header against the endpoint secret. A failed verification returns 400 and is never processed. For replay safety and the broader webhook test matrix, see Checkout stability.

Flow diagram — customer payment

Troubleshooting