Accepting PayPal payments with Stripe

Introduction

Earlier this year Stripe quietly rolled out PayPal support for both one-off payments and subscription charges. Given an estimated 400+ million people have a PayPal account, adding it as a payment option to your existing Stripe integration should be a no-brainer if your account is eligible. Back in July this year I enabled PayPal for fitIQ membership subscriptions, and while there was pleasantly little involved from both the Stripe and the PayPal sides, there were a few noteworthy things I thought worth sharing.

Screenshot taken from https://stripe.com/docs/payments/paypal

Eligibility

At present Stripe only supports PayPal integration for businesses based in Europe (including the UK, despite its non EU status). I don't know why, and it seems like a great shame, but hopefully something Stripe/PayPal will address in future. Your customers can be anywhere in the world, but your business must be based in Europe.

Enabling PayPal

There isn't a great deal to actually enabling PayPal; it acts almost like any other payment Wallet you can choose to accept. Head to your payment methods page, select the appropriate configuration from the dropdown (I only have a ‘Default’ option and suspect you do too) and look for PayPal under the Wallets section:

Make sure you're in test mode, and simply click ‘Turn on’:

As far as test mode goes, that's pretty much it. The only caveat is that if you're currently hardcoding payment_method_types when initiating a checkout flow, you'll need to make sure you add paypal to the list:

const session = await stripe.checkout.sessions.create({
  payment_method_types: ['card', 'paypal'],
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: {
        name: 'T-shirt',
      },
      unit_amount: 2000,
    },
    quantity: 1,
  }],
  mode: 'payment',
  success_url: 'https://example.com/success',
  cancel_url: 'https://example.com/cancel',
})

It's worth noting that in payment and subscription modes you can omit the payment_method_types parameter altogether and Stripe will use your enabled payment methods instead, which saves you configuring the same thing in two places. You should see a PayPal option the next time you initiate a Stripe checkout in a supported currency:

Configuring webhooks

When choosing Paypal to place a test order, you'll be redirected to a test Stripe page prompting you to make sure you've got webhooks configured correctly, since PayPal payments are processed asynchronously (in my experience this means within seconds rather than minutes or worse, but your mileage may vary). If you've got webhooks configured already it's likely that your existing code will work fine even if you're not explicitly handling the payment_intent.succeeded and payment_intent.failed events cited in the instructions below - I'm only handling customer.subscription.* and checkout.session.completed and PayPal transactions are handled fine.

If you're not handling webhooks at all, you should get them set up and make sure they at least cover the events mentioned below. Check out Stripe's required use of webhooks best practice and their much longer guide on the subject to get started.

Automatically transferring PayPal revenue to Stripe

In test mode when you click ‘Turn on’ to enable PayPal, that's it. In live mode, you'll see this:

The first choice you have to make is where the revenue you make through PayPal sales should end up. If you're using Stripe as your primary payment processor, there's absolutely no reason to choose anything other than the default option of ‘Settle PayPal revenue to Stripe balance’:

With this configuration any money made through PayPal is automatically transferred out into your Stripe account, neatly sidestepping any concerns of PayPal freezing your account with a load of money in it. I don't know if automatically means immediately because I've never paid close enough attention, but it's quick enough that I've never had to go and check, and when I have my PayPal balance has always been zero.

With that done you'll either need to sign into an existing PayPal business account or create a new one. If creating a new account you may have to jump through a few hoops and wait for verification (I don't remember either way, but I do have a few signup-related emails from when I set it up), but it's all fairly painless. Once the flow is complete PayPal will let you know and prompt you to head back to Stripe: you can ignore the link to ‘Set up automatic transfer’, since Stripe will configure that for you:

‘Go back to Stripe Payments’ will land you back on your list of Stripe payment methods again, but hopefully this time PayPal will be active. Don't panic if it still says ‘Turn on’ - simply click it again and rather than re-initiate the PayPal flow again it should immediately become active and present you with something like this:

Configuration wise, that's it. You can now accept PayPal payments! All of your existing products will continue to work across any currencies you've got enabled which are supported by the PayPal integration. In my case, fitIQ memberships are available in USD, GBP and EUR, and the PayPal integration works for all three.

Viewing PayPal payments in Stripe

PayPal payments show up in the Stripe dashboard just like any other payment, until you drill into the details. You won't get a risk evaluation as they're only supported for card-based payments, but other than that the payment looks like pretty much any other:

Viewing PayPal payments in PayPal

Apart from double-checking the first PayPal payment I ever received for fitIQ and again when writing this article, I haven't bothered checking up on my PayPal account. For what it's worth, here's the payment shown above but viewed in PayPal instead, with some further breakdown and customer details chopped off the bottom:

If you weren't using PayPal before, I can't see any particularly good reason to bother checking up on your PayPal account unless something goes wrong. You can do everything you need to from Stripe, including issuing refunds for PayPal transactions.

Fees

You might have guessed that there's a catch somewhere, and if it's anywhere, it's in the fees. Both Stripe and PayPal take their cut, and although Stripe's appears to be much lower than usual at the price points fitIQ operates at, PayPal's is much higher. Here are two equivalent transactions a day apart with a very similar USD to GBP exchange rate. Stripe-only first:

And here's the equivalent via PayPal:

Fees account for roughly 4.1% of the Stripe transaction and 6.6% of the Stripe+PayPal one. I don't expect these to be the same for you, but for a $30 purchase price in October 2023 they give you a rough idea of what to expect.

Summary

Customers are apparently 54% more willing to buy when a business accepts PayPal. I'd say a few minutes of configuration coupled with a small increase in fees seems like a pretty fair trade for 400+ million wallets you didn't have access to before. The number one aim during checkout is conversion, and the easiest way to lose someone's interest is to not offer them their preferred or most accessible payment method. Just because you might not even notice PayPal as an option the next time you purchase something online, doesn't mean someone else isn't actively looking for it.

If you enjoyed this article, please consider sharing it on X, Bluesky, or your platform of choice - it helps a lot. I’m all ears for any feedback, corrections or errors, so please if you have any. Thanks!