Set up a subscription with PayPal
Learn how to create and charge for a subscription with PayPal.
Caution
To start accepting PayPal subscriptions on Stripe, you need to enable PayPal recurring payments from the Dashboard.
Use this guide to set up a subscription using PayPal as a payment method.
Create a product and priceDashboard
Products represent the item or service you’re selling. Prices define how much and how frequently you charge for a product. This includes how much the product costs, what currency you accept, and whether it’s a one-time or recurring charge. If you only have a few products and prices, create and manage them in the Dashboard.
This guide uses a stock photo service as an example and charges customers a 15 EUR monthly subscription. To model this:
- Navigate to the Add a product page.
- Enter a Name for the product.
- Enter 15 for the price.
- Select EUR as the currency.
- Click Save product.
After you create the product and the price, record the price ID so you can use it in subsequent steps. The pricing page displays the ID and it looks similar to this: price_
.
Create or retrieve a Customer before setupServer-side
To reuse a PayPal payment method for future payments, attach it to a Customer.
Create a Customer object when a customer creates an account on your business. Associating the ID of the Customer object with your own internal representation of a customer lets you retrieve and use the stored payment method details later. If the customer hasn’t created an account, you can still create a Customer object now and associate it with your internal representation of the customer’s account later.
Create a SetupIntentServer-side
A SetupIntent is an object that represents your intent and tracks the steps to set up your customer’s payment method for future payments.
Create a SetupIntent on your server with payment_method_types set to paypal
and specify the Customer’s id.
The SetupIntent object contains a client_secret, a unique key that you need to pass to Stripe on the client side to redirect your buyer to PayPal and authorize the mandate.
Redirect your customerClient-side
When a customer attempts to set up their PayPal account for future payments, we recommend you use Stripe.js to confirm the SetupIntent. Stripe.js is our foundational JavaScript library for building payment flows. It will automatically handle complexities like the redirect described below, and enables you to easily extend your integration to other payment methods in the future.
Include the Stripe.js script on your checkout page by adding it to the head of your HTML file.
<head> <title>Checkout</title> <script src="https://js.stripe.com/v3/"></script> </head>
Create an instance of Stripe.js with the following JavaScript on your checkout page.
// Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe(
, {} );'pk_test_TYooMQauvdEDq54NiTphI7jx'
To confirm the setup on the client side, pass the client secret of the SetupIntent object that you created in Step 3.
The client secret is different from your API keys that authenticate Stripe API requests. It should still be handled carefully because it can complete the charge. Do not log it, embed it in URLs, or expose it to anyone but the customer.
Confirm PayPal Setup
To authorize you to use their PayPal account for future payments, your customer will be redirected to a PayPal billing agreement page, which they will need to approve before being redirected back to your website. Use stripe.confirmPayPalSetup to handle the redirect away from your page and to complete the setup. Add a return_
to this function to indicate where Stripe should redirect the user to after they approve the billing agreement on PayPal’s website.
// Redirects away from the client const {error} = await stripe.confirmPayPalSetup( '{{SETUP_INTENT_CLIENT_SECRET}}', { return_url: 'https://example.com/setup/complete', mandate_data: { customer_acceptance: { type: 'online', online: { infer_from_client: true } } }, } ); if (error) { // Inform the customer that there was an error. }
You can find the Payment Method owner’s email, payer ID, and Billing Agreement ID on the resulting Mandate under the payment_method_details property. You can also find the buyer’s email and payer ID in the paypal property on the PaymentMethod.
Field | Value |
---|---|
verified_ | The email address of the payer on their PayPal account. |
payer_ | A unique ID of the payer’s PayPal account. |
billing_ | The PayPal Billing Agreement ID (BAID). This is an ID generated by PayPal which represents the mandate between the business and the customer. |
Monitor webhooksServer-side
Use a method such as webhooks to confirm the billing agreement was authorized successfully by your customer, instead of relying on your customer to return to the payment status page. When a customer successfully authorizes the billing agreement, the SetupIntent emits the setup_intent.succeeded webhook event. If a customer doesn’t successfully authorize the billing agreement, the SetupIntent will emit the setup_intent.setup_failed webhook event and returns to a status of requires_
. When a customer revokes the billing agreement from their PayPal account, the mandate.updated is emitted.
Create the subscriptionServer-side
Create a subscription with the price and customer:
Creating subscriptions automatically charges customers because the default payment method is set. After a successful payment, the status in the Stripe Dashboard changes to Active. The price you created earlier determines subsequent billings.
Manage subscription statusClient-side
If the initial payment succeeds, the state of the subscription is active
and no further action is needed. When payments fail, the status is changed to the Subscription status configured in your automatic collection settings. Notify the customer on failure and charge them with a different payment method.
Update a subscriptionServer-side
When you update a subscription, you need to specify off_
. Otherwise, any new payment requires a user redirection to PayPal for confirmation. For example, if you want to change the quantity of an item included in the subscription you can use:
Test the integration
Test your PayPal integration with your test API keys by viewing the redirect page. You can test the successful payment case by authenticating the payment on the redirect page. The PaymentIntent will transition from requires_
to succeeded
.
To test the case where the user fails to authenticate, use your test API keys and view the redirect page. On the redirect page, click Fail test payment. The PaymentIntent will transition from requires_
to requires_
.