Things to plan for
- Confirm with your Stripe account team that third-party payment processing (custom payment methods and payment records) is enabled for your account, and that your Stripe business entity country is supported.
- The collection surface for these payments is Primer Checkout. Stripe Checkout and Stripe’s hosted invoice page do not apply to payments processed outside Stripe.
- Stripe’s automatic recovery emails do not apply either; customer communications are yours, as covered below.
- Refunds are executed through Primer and reported to Stripe. Disputes are managed with the processor that handled the payment, supported by Primer’s Dispute Webhooks.
- Only subscription invoices can be collected this way. One-off invoices can still be created in Stripe but not collected through Primer.
- Stripe Billing fees apply to billing volume including payments processed outside Stripe. Confirm the treatment on your plan with Stripe.
How it works
When using Stripe Billing with Primer, the plan catalogue and live subscription state is kept in Stripe Billing and the payment processing layer is kept on Primer. Stripe supports this natively for payments processed outside Stripe, built on two objects:- Custom payment methods. A Stripe object that references a payment method held outside Stripe. The Primer token reference is stored in its metadata, and it works with automatically charged subscriptions, so Stripe continues to drive the billing cycle and signals when to collect.
- Payment records. How each Primer-processed outcome is reported back to Stripe, keeping invoices and subscription states accurate.
Prerequisites
- A Primer account with at least one processor connected and a Workflow configured. See Connect a processor.
- A Primer API key with the
client_tokens:writeandtransactions:authorizescopes. See Authentication. - A Stripe account with Stripe Billing and third-party payment processing enabled. Request access from your Stripe account team, and confirm that your business country is supported.
Configure Stripe
In the Stripe Dashboard:- Create a custom payment method type to represent payment methods processed by Primer. Store its ID in your configuration, because custom payment method types can’t be retrieved through the Stripe API.
- Register a webhook endpoint and subscribe it to
invoice.payment_attempt_required,invoice.updated, andinvoice.payment_failed. - Configure your retry schedule, either in your revenue recovery retry settings or with Billing automations. See Renewals and decline-aware retries.
Sign-Up and first payment
Figure 1. Sign-Up and first payment: Stripe raises the invoice, Primer collects, the result is reported back. The customer and subscription are created first because the chargeable amount comes from Stripe’s invoice (tax, proration). The customer then pays through Primer Checkout, the payment method is vaulted, and a custom payment method carrying the Primer token reference is attached to the customer and set as the subscription default. Reporting the payment marks the invoice paid and activates the subscription.Create the subscription in Stripe
Create the customer and subscription in Stripe as you do today, withpayment_behavior set to default_incomplete. Expand latest_invoice to get the amount to charge, which includes tax, discounts, and proration.
Create the subscription
incomplete, with an open invoice. Keep the subscription ID, the invoice ID, and the invoice’s amount_due and currency for the next step.
Collect the first payment with Primer
Create a client session for the invoice amount withvaultOnSuccess enabled, then render Primer Checkout with the returned client token.
Create a client session
Stripe and Primer both express amounts in minor units, so you can pass
amount_due unchanged. Stripe returns currency codes in lowercase, and Primer expects uppercase ISO 4217 codes.Link the payment method and report the payment
When the first payment succeeds, retrieve the customer’s vaulted payment method token from Primer withGET /payment-instruments. Then, in Stripe:
- Create a custom payment method that stores the Primer token in its metadata.
- Attach it to the customer and set it as the subscription’s default payment method.
- Report the payment and attach the payment record to the invoice.
Link and report the first payment
active.
Good to know
- The first payment is initiated by your backend with no webhook prompt. Renewal webhooks begin from the first renewal onward.
- Report the first payment within 23 hours of creating the subscription, or the subscription expires as incomplete.
- If the first payment fails, there will be an open invoice for the customer, and you should retry charging the customer.
- For every invoice, Stripe creates a default PaymentIntent and cancels it when you report a payment record. The canceled PaymentIntent appears next to your reported payment and doesn’t affect the invoice or subscription status. Webhooks events for these events can be ignored entirely
Renewals and decline-aware retries
Figure 2. Renewals: every attempt is executed by Primer and every retry is gated by your decline classification. Retry scheduling uses Stripe Billing Automations, configured in your Dashboard. Because the decline detail comes from the processor through Primer, your backend supplies that context: before reporting a failed attempt, it stamps the invoice metadata with the decline classification derived from Primer’s decline code.Why this matters for retriesStripe Billing schedules each retry, and your backend decides whether to execute it, informed by the decline code Primer returns. Hard declines can be stopped after a single attempt; soft declines follow the retry policy you configure in Stripe.
- Hard declines (stolen card, closed account): the automation cancels the subscription or marks the invoice as
uncollectible. - Soft declines (insufficient funds, temporary issuer errors): the automation attaches your retry policy, for example day 2, day 5, day 8. Each scheduled attempt arrives as a webhook, and execution still sits with you and Primer, so later attempts can be routed to a different processor.
Key design pointStripe’s Smart Retries is not currently supported for custom payment methods (a Stripe limitation), so retries follow a prescribed policy, set globally or on an automation (the automation takes precedence where it applies). Combined with the decline classification above, issuers and schemes only see attempts with a realistic chance of succeeding.
Handle renewals
When Stripe finalises a renewal invoice, it sendsinvoice.payment_attempt_required. Your webhook handler creates a merchant-initiated payment through Primer with the vaulted token and paymentType set to SUBSCRIPTION, then reports the outcome to Stripe.
Handle invoice.payment_attempt_required
If Primer returns the payment as
PENDING, wait for the PAYMENT.STATUS webhook with the final status before you report the outcome to Stripe. See Configure webhooks.Report retries against the payment record
When you report a failed attempt, the invoice stays open and the subscription moves topast_due. Stripe then schedules the next attempt according to your retry settings, and sends a new invoice.payment_attempt_required event for each one.
Report every retry against the existing payment record with reportPaymentAttempt, rather than creating a new record with reportPayment. This keeps a single payment with a consolidated attempt history on the invoice.
Report the outcome of an attempt
Detect the final attempt
With standard retry settings, failures arrive asinvoice.payment_failed. When automations control retries, next_payment_attempt is updated through invoice.updated, so handle both events. There is no dedicated event for an exhausted schedule so you should treat a failure-related invoice update with no remaining next_payment_attempt, together with the resulting subscription state, as the final signal.
Dunning and payment method recovery
Failed-payment emails and card-update prompts are owned by your systems, driven by the same webhooks. When a stored credential is no longer usable after a hard decline, recovery is a customer-present journey: bring the customer back, take a fresh payment through Primer Checkout, vault the new token, and attach a new custom payment method in Stripe. Stripe’s customer portal continues to work for plan changes and cancellations on these subscriptions. With automations enabled, read the next scheduled attempt time frominvoice.updated events.
Update the customer’s payment method
- Bring the customer back to a payment page and collect the new payment method with Primer Checkout, with
vaultOnSuccessenabled. - Create a new custom payment method with the new Primer token, and set it as the subscription’s default payment method.
- If an invoice is still open, charge it through Primer and report the attempt against its payment record.
Refunds
Refund the payment through Primer, with the API or the Dashboard. Then report the refund to the payment record in Stripe, and create a credit note to adjust the invoice. Both full and partial refunds are supported.Report a refund to Stripe