Skip to content
Create account or Sign in
The Stripe Docs logo
/
Ask AI
Create accountSign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
Overview
Billing
OverviewAbout the Billing APIs
Subscriptions
    Overview
    How subscriptions work
    Get started
    Quickstart
    Plan an integration
    Build an integration
    Use cases
      Integrate a SaaS business
      Integrate a sales-led B2B business
      Integrate with third-party payment processing
    About subscriptions
    Enable billing mode
    Configure subscription events
    Entitlements
    Subscription invoices
    Subscription schedules
    Recurring pricing models
    Set up subscriptions
    Configure collection methods
    Embed a pricing table
    Set billing cycles
    Manage subscriptions
    Migrate subscriptions to Stripe
    Set product or subscription quantities
    Mixed interval subscriptions
    Backdate subscriptions
    Set trial periods
    Handle subscriptions with deferred payment
    Apply coupons
    Modify subscriptions
    Manage subscription payment methods
    Analytics
    Manage subscriptions on iOS
Invoicing
Usage-based billing
Quotes
Customer management
Billing with other products
Revenue recovery
Automations
Test your integration
Tax
Overview
Use Stripe tax
Manage compliance
Reporting
Overview
Select a report
Configure reports
Reports for multiple accounts
Reports API
Revenue recognition
Data
Overview
Query business data
Sigma
Data Pipeline
Import external data
United States
English (United States)
HomeRevenueSubscriptionsUse cases

Integrate with third-party payment processors

Learn how to use Stripe subscriptions and invoices with third party payment processors.

To process payments for your Billing subscriptions and invoices with a third-party processor, you have the following options:

Use Stripe Billing to manage subscription payments made with off-Stripe payment processors. With this integration, you can:

  • Make requests for payments linked to a subscription with your off-Stripe payment processor
  • Create and manage charge automatically subscriptions with off-Stripe payments using custom payment methods that reference off-Stripe payment methods
  • Create payment records to capture payment details of off-Stripe transactions, such as payment type and reference ID
  • Use webhooks and record off-Stripe payment results to manage the subscription lifecycle

If you set up this integration, you no longer need to mark invoices as paid out-of-band or rely on the send_invoice method to accept off-Stripe payments.

Note

When integrating with a third-party payment processor, you’re responsible for complying with applicable legal requirements, including your agreement with your PSP, applicable laws, and so on.

Additionally, you’re responsible for limiting your integration to supported locations.

Limitations

Make sure that the following limitations don’t conflict with your use case:

  • You must build and maintain direct integrations with non-Stripe payment processors.
  • If your integration uses the Payment Element or a custom non-Stripe checkout flow, you can use Billing with non-Stripe payment processors. However, you can’t use Billing with Checkout, because Checkout can’t capture details for off-Stripe payments.
  • Customers can view and cancel subscriptions paid outside of Stripe in the customer portal. However, subscription updates (such as plan changes) aren’t supported for custom payment methods through the portal. To make changes, use the Subscriptions API directly instead of the Customer Portal API.
  • In the customer portal, your customers can switch from an off-Stripe (custom) payment method to one processed by Stripe, but cannot switch back to an off-Stripe payment method after they’ve transitioned.
  • You can’t manage disputes of off-Stripe payments in Stripe.
  • Off-Stripe payments have limited support for revenue recovery. They support automations and scheduled retries on failed payments, and are included in revenue recovery analytics. However, they don’t support revenue recovery emails or Smart Retries.
  • Off-Stripe payments are only available to businesses in the specified countries, and you can only use them with payment processors operating in certain countries.

Integration flow

You can integrate your custom payment page or Payment Element with Stripe Billing to process payments off-Stripe. This payment flow relies on two Stripe concepts that enable off-Stripe payments:

  • Custom payment methods: Enables you to create a reference to a non-Stripe payment method (such as a non-Stripe card or bank account) as a Stripe object. Custom payment methods used with the charge_automatically collection method allow you to receive webhooks for future subscription charges, and to apply off-Stripe payments to associated invoices.
  • Payment records: Records indicating successful off-Stripe payments to Stripe, along with associated structured metadata such as payment type, date, and external payment ID.

Prerequisites

To use Stripe Billing with off-Stripe payment processors, you must:

  • Set up a subscription integration for your off-Stripe payments.
  • Renew subscriptions after you set up a subscription integration.

To set up your off-Stripe subscriptions:

  1. Configure a custom payment method type in the Dashboard.
  2. Register customer information needed for subscriptions.
  3. Collect payment information for payment methods not supported on Stripe.
  4. Create subscriptions with payment information and payment records that occurred off-Stripe.
  5. Record payments regardless of where they were processed.

Configure custom payment method types

In the Dashboard, create the custom payment method type your customers will pay with. Custom payment method types allow you to specify branding for the custom payment methods you define for each customer. For example, if you’re using SamplePay as another processor, you might want to create a SamplePayCard to represent cards that you process with SamplePay.

Go to Custom payment method types in the Dashboard. At the end of these steps, you’ll have one or more custom payment method types defined that you can offer your customers when they checkout.

  1. Create a custom payment method type.
  2. Set the display name and logo for the custom payment method type.

Warning

Make sure your custom payment method aligns with our marks policy on the usage of display name and logo.

  1. Click Create to make a new payment method type, SamplePayCard, which you can then use to set up a custom payment method.
  2. You can see the created custom payment method type details in the Dashboard.
  3. Custom payment method types aren’t retrievable through the API. We recommend storing the ID in your database and retrieving it during payment method creation.
  4. After you configure custom payment methods, you can add them in either the Payment Element or directly to your custom payment page.

Collect customer information and create subscription
Server

Collect customer information (email address, billing address, and shipping address) and the price your customer selected. Then make a request to the server to create a new Stripe Customer and Subscription.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/subscriptions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d customer=
"{{CUSTOMER_ID}}"
\ -d "items[0][price]"=
"{{PRICE_ID}}"
\ -d payment_behavior=default_incomplete \ -d "payment_settings[save_default_payment_method]"=on_subscription \ -d "expand[0]"=latest_invoice

At this point the subscription is incomplete with an open invoice.

Collect payment
Client and Server

Redirect the customer to your payment form to collect payment. Collect payment details for the payment method selected, and send a request to your server to initiate a payment session:

client.js
const response = await fetch('/create_payment_session', { method: 'POST', data: { // If needed, include an identifier for the processor selected by the customer } }); // Redirect customer to processor to complete payment window.location.href = response.redirectUrl;

Create a server-side handler to start a new payment session on your third-party processor. Then, send a return URL to redirect your customer to where they can complete payment.

create_payment_session.js
Node.js
Ruby
Python
PHP
Java
Go
.NET
No results
app.post('/create_payment_session', async (req, res) => {
const paymentSession = processorSdk.createPaymentSession({ amount: invoice.amount_due, currency: invoice.currency, return_url: '/payment_session_completed' });
return { redirectUrl: paymentSession.redirectUrl }; });

Record payment
Server

After the customer completes their checkout session on the payment processor, create a record of payment on Stripe:

payment_session_completed.js
Node.js
Ruby
Python
PHP
Java
Go
.NET
No results
const stripe = new Stripe(
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
, { apiVersion: '2025-10-29.clover' }); app.post('/payment_session_completed', async (req, res) => { // `paymentReference` refers to the response object provided by your third-party processor // to indicate completion of payment. The exact contents vary based on the third-party processor. const paymentMethod = await stripe.paymentMethods.create({ type: 'custom', custom: { // Set to the ID of the custom payment method type created in Step 1 type:
'{{CUSTOM_PAYMENT_METHOD_TYPE_ID}}'
, }, metadata: { // Store any information specific to your third-party processor // that's needed to perform off-session payments {{PROCESSOR_AGREEMENT_ID_KEY}}: '{{PROCESSOR_AGREEMENT_ID}}', } });

Note

When setting up your custom payment method and integration, don’t save any sensitive payment credentials with Stripe, including PANs.

Attaching a payment record to the invoice marks it as paid and transitions the associated subscription to active. You must report a payment within 23 hours of creating the subscription, or the subscription transitions to incomplete_expired and you need to recreate it.

Configure the webhook handler

To process future payments for a charge_automatically subscription, configure a handler to receive webhook events. Specifically, you’ll handle the invoice.payment_attempt_required webhook, which Stripe sends when a new invoice is finalized and requires payment through your custom payment method:

webhook.js
Node.js
Ruby
Python
PHP
Java
Go
.NET
No results
const stripe = new Stripe(
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
, { apiVersion: '2025-10-29.clover' }); app.post('/webhook', async (request, response) => { const payload = request.body; const sig = request.headers['stripe-signature']; let event; try { event = stripe.webhooks.constructEvent(payload, sig, endpointSecret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } switch (event.type) { case 'invoice.payment_attempt_required': const invoiceId = event.data.object.id;

Retry failed payments

When a failed payment is reported, the invoice remains open. If the Subscription was created in an incomplete status, it remains incomplete until successful payment is reported, or it expires.

If the Subscription was previously active, it transitions to past_due. If retries are configured, then the Subscription moves into dunning and we send subsequent invoice.payment_attempt_required webhook events when retries are attempted.

You can configure retries using custom retry schedules or automations. We don’t support Smart Retries.

For custom retry schedules, if you exhaust all retries, the invoice and subscription might transition depending on your configured retry settings. You can also manually cancel the subscription earlier if you can’t collect payment.

To handle payment retries, extend the handler implemented in the Configure webhook handler section:

webhook.js
Node.js
Ruby
Python
PHP
Java
Go
.NET
No results
async function processOffSessionPayment(invoice) { const customPaymentMethod = await stripe.paymentMethods.retrieve(invoice.defaultPaymentMethod); // No changes needed, collect payment as before from the third-party processor const paymentResult = await processorSdk.collectPayment({ amount: invoice.amount_remaining, agreement_id: customPaymentMethod.metadata['{{PROCESSOR_AGREEMENT_ID_KEY}}'] }); // Query for any existing payment records, which indicate a prior payment attempt const invoicePayments = await stripe.invoicePayments.list({ invoice: invoice.id, payment: { type: 'payment_record' } }); if (invoicePayments.data.length) {

Handle canceled payments

You can report canceled payments to Stripe when using the asynchronous payment flow. Use this option when a payment is initiated but later canceled.

To report a canceled payment, first create a payment record indicating the payment is initiated (as shown in Record payment).

When the payment is canceled, report the cancellation to Stripe:

payment_session_canceled.js
Node.js
Ruby
Python
PHP
Java
Go
.NET
No results
const stripe = new Stripe(
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
, { apiVersion: '2025-10-29.clover' }); app.post('/payment_session_canceled', async (req, res) => { await stripe.paymentRecords.reportPaymentAttemptCanceled(paymentRecord.id, { canceled_at: Date.now() }); });

Handle refunds

When your third-party processor processes a refund, you can report it to Stripe to maintain accurate payment records. You can report both full and partial refunds, but only after the original payment is successfully recorded in Stripe.

To report a refund, you need to provide the refund reference from your third-party processor, which must be unique for each Payment Record. For a partial refund, specify the amount parameter.

To maintain accurate accounting data, log refunds on issued invoices by using Credit Notes to adjust the invoice amounts.

payment_refunded.js
Node.js
Ruby
Python
PHP
Java
Go
.NET
No results
const stripe = new Stripe(
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
, { apiVersion: '2025-10-29.clover' }); app.post('/payment_refunded', async (req, res) => { const paymentRecordRefund = await stripe.paymentRecords.reportRefund(paymentRecord.id, { // `refundReference` refers to the response object provided by your third-party processor // when the refund is issued. The exact contents vary based on the third-party processor. processor_details: { type: 'custom', custom: { refund_reference: refundReference.id } }, outcome: 'refunded', refunded: { refunded_at: Date.now() } }); const invoicePayments = await stripe.invoicePayments.list({ payment: { type: 'payment_record', payment_record: paymentRecordId } }); // Create a credit note to reflect the refund on the invoice await stripe.creditNotes.create({ invoice: invoicePayments.data[0].invoice, refunds: [{ type: 'payment_record_refund', // amount_refunded is an optional field. If not provided, the credit note is created for the full amount of the PaymentRecord refund. amount_refunded: paymentRecordRefund.refund_details[0].amount_refunded.value, payment_record_refund: { payment_record: paymentRecordRefund.id, refund_group: refundReference.id } } ] }); });

Fees for using third-party payment processors

Billing volume from third-party processors is considered part of your total billing volume, which includes transactions both on and off Stripe that use Stripe Billing functionality. The standard fee structure applies based on your billing contract, either pay-as-you-go or a subscription plan. For more information, see Billing pricing and how Stripe charges for Billing.

In addition, one-off invoices that are paid through a third-party payment processor are monetized under Invoicing pricing. Invoices marked as paid out-of-band aren’t charged as usual.

Supported countries

This feature is available to businesses located in:

Countries where businesses can be located

Australia
Austria
Belgium
Brazil
Bulgaria
Canada
Croatia
Cyprus
Czech Republic
Denmark
Estonia
Finland
France
Germany
Greece
Hong Kong
Hungary
India
Ireland
Italy
Japan
Latvia
Liechtenstein
Lithuania
Luxembourg
Malta
Mexico
Netherlands
New Zealand
Norway
Poland
Portugal
Romania
Singapore
Slovakia
Slovenia
Spain
Sweden
Switzerland
Thailand
United Arab Emirates
United Kingdom
United States

This feature is available to use with payment processors located in:

Countries where payment processors can be located

Albania
Algeria
Angola
Antigua & Barbuda
Argentina
Armenia
Australia
Austria
Azerbaijan
Bahamas
Bahrain
Bangladesh
Belgium
Benin
Bhutan
Bolivia
Bosnia & Herzegovina
Botswana
Brazil
Brunei
Bulgaria
Cambodia
Canada
Chile
China
Colombia
Costa Rica
Côte d’Ivoire
Croatia
Cyprus
Czech Republic
Denmark
Dominican Republic
Ecuador
Egypt
El Salvador
Estonia
Ethiopia
Finland
France
Germany
Ghana
Greece
Guatemala
Guyana
Hong Kong
Hungary
India
Indonesia
Ireland
Italy
Jamaica
Japan
Jordan
Kazakhstan
Kuwait
Laos
Latvia
Liechtenstein
Lithuania
Luxembourg
Macao SAR China
Madagascar
Malaysia
Malta
Mauritius
Mexico
Moldova
Monaco
Mongolia
Morocco
Mozambique
Namibia
Netherlands
New Zealand
Niger
Nigeria
North Macedonia
Norway
Oman
Pakistan
Panama
Paraguay
Peru
Philippines
Poland
Portugal
Qatar
Romania
Rwanda
San Marino
Saudi Arabia
Senegal
Serbia
Singapore
Slovakia
Slovenia
South Africa
South Korea
Spain
Sweden
Switzerland
Taiwan
Thailand
Trinidad & Tobago
Tunisia
Turkey
United Arab Emirates
United Kingdom
United States
Uruguay
Uzbekistan
Vietnam
Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc