Stripe Connect
Setup guide and operations for the stripe_connect payments provider. The shared API
(initiate_payment, webhooks, hooks, saved methods) is documented in
Payments.
For marketplace platforms – connect your users as Stripe Express accounts, collect platform fees, and transfer funds.
Uses the same Stripe account as the regular Stripe provider – no separate Stripe account needed – but it is its own instance with its own env vars:
"stripe_connect": { "type": "stripe_connect", "refresh_url": "/connect/onboard/refresh", "return_url": "/connect/onboard/return"}KIRAK_PAYMENT_STRIPE_CONNECT_SECRET_KEY=sk_test_...KIRAK_PAYMENT_STRIPE_CONNECT_WEBHOOK_SECRET=whsec_...KIRAK_PAYMENT_STRIPE_CONNECT_PLATFORM_WEBHOOK_SECRET=whsec_...The Connect methods (onboard_merchant, connect_checkout, …) use the first
stripe_connect-type instance, or the one named by "provider" in the params.
Stripe treats a connected-accounts event and a platform-account event as two
different webhook subscriptions, each with its own signing secret, even when
both point at the same URL. Set up two endpoints in the Stripe Dashboard
(Developers -> Webhooks), both at
https://your-domain.com/payments/webhook/stripe_connect:
- A connected-accounts endpoint, with Listen to events on Connected
accounts checked, for the merchants’ own accounts:
account.updated,account.application.deauthorized. Copy its signing secret intoKIRAK_PAYMENT_STRIPE_CONNECT_WEBHOOK_SECRET. - A platform-account endpoint (the box unchecked).
connect_checkoutsessions are destination charges created on the platform account, and saved methods and off-session charges live there too (see “Off-session Charges” below), so all of their events arrive here:checkout.session.completed,checkout.session.async_payment_succeeded,checkout.session.async_payment_failed,charge.refunded,payment_intent.succeeded,payment_intent.payment_failed,payment_method.detached,payment_method.updated,payment_method.automatically_updated,customer.updated. Copy its signing secret intoKIRAK_PAYMENT_STRIPE_CONNECT_PLATFORM_WEBHOOK_SECRET.
handle_webhook verifies an incoming request against
KIRAK_PAYMENT_STRIPE_CONNECT_WEBHOOK_SECRET first, then against
KIRAK_PAYMENT_STRIPE_CONNECT_PLATFORM_WEBHOOK_SECRET (if configured) when
the first check fails, so both endpoints can deliver to the same route.
platform_webhook_secret is optional only for an app that uses merchant
onboarding alone; connect_checkout, saved payment methods and off-session
charges all report through the platform-account endpoint.
When a stripe and a stripe_connect instance share one Stripe account,
both receive the platform’s setup sessions and PaymentIntents. Kirak stamps
metadata.kirak_instance (the instance name) on the setup sessions, saving
checkouts and off-session PaymentIntents it creates, and an instance skips
any tagged for another instance, so a method is saved once and an off-session
charge is settled by the instance that made it.
Known limitation: Connect checkout sessions hardcode
payment_method_types: ["card"] (the regular Stripe provider does not), so
Apple Pay/Google Pay/ACH/SEPA are not offered even where Stripe would
otherwise auto-enable them. Not yet configurable.
Onboard a Merchant
Section titled “Onboard a Merchant”result = await kirak.payments.onboard_merchant({ "user_id": "42", "email": "merchant@example.com",})# result["data"]["onboarding_url"] -> redirect merchant here to complete Stripe onboardingRegenerate Onboarding Link
Section titled “Regenerate Onboarding Link”result = await kirak.payments.create_onboarding_link({ "user_id": "42",})Check Merchant Status
Section titled “Check Merchant Status”result = await kirak.payments.get_merchant_status({ "user_id": "42",})# result["data"]["charges_enabled"] -> bool# result["data"]["payouts_enabled"] -> boolCreate Connect Checkout
Section titled “Create Connect Checkout”Charge a customer through a connected merchant account:
result = await kirak.payments.connect_checkout({ "user_id": "42", # customer user ID "merchant_user_id": "99", # connected merchant user ID "amount": 1999, "currency": "USD", "name": "Service",})Platform fee is read from merchant_accounts.platform_fee_percent (your model).
Off-session Charges
Section titled “Off-session Charges”Charge a saved payment method (see
Saved Payment Methods and Off-Session Charges)
as a destination charge, with the platform fee and transfer going to the same
connected merchant as connect_checkout:
result = await kirak.payments.charge_off_session({ "user_id": "42", # customer user ID "merchant_user_id": "99", # connected merchant user ID "payment_method_id": 7, "amount": 10000, "currency": "USD", "name": "Order", "idempotency_key": "order-42-retry-1",})The saved method and customer live on the platform account, same as the
regular Stripe provider – only the charge itself is routed to the merchant.
merchant_user_id or stripe_account_id is required; an unresolved or not
yet activated merchant raises before any transaction row is written.
Update Merchant Fee
Section titled “Update Merchant Fee”await kirak.payments.update_merchant_fee({ "user_id": "99", "is_paid_user": True, # True -> 5% fee, False -> 10% fee (configurable)})Webhook events
Section titled “Webhook events”Both Stripe Dashboard endpoints (see “Setup” above) deliver to the built-in route
POST /payments/webhook/stripe_connect. after_webhook receives these provider-neutral
event names (see Webhook Hooks):
data["event"] |
Gateway events |
|---|---|
payment_completed |
checkout.session.completed (only when paid), checkout.session.async_payment_succeeded, payment_intent.succeeded (off-session charges only) |
payment_failed |
checkout.session.async_payment_failed, payment_intent.payment_failed (off-session, declined) |
refund_completed |
charge.refunded |
merchant_account_updated |
account.updated |
merchant_deauthorized |
account.application.deauthorized |
payment_method_saved |
checkout.session.completed of a setup session |
payment_method_removed |
payment_method.detached |
payment_action_required |
payment_intent.payment_failed with authentication_required (off-session) |
A redelivered event is skipped by its event id, recorded per instance (see Repeated deliveries).