Yesterday I started the PayPal integration into Mavenseed.

By lunch I was done with digital payments, and in the afternoon I moved to implementing PayPal for recurring subscriptions.

It all starts with a switch.

This just reloads the page with a gateway param in the URL.
We then load the appropriate partial based on the gateway. The Stripe partial loads Elements, while the Braintree partial loads the Braintree hosted Dropin.
Really nothing much has changed in the order controller.

Since everything is done with service classes, we just add the paypal token (braintree nonce) and pass it off to the checkout service.
The checkout service acts as a gateway service and will spin off the appropriate service class depending on the chosen gateway.

Gist: https://gist.github.com/bearded-avenger/6d277d887275e7cf621206a4bfc7f35b
From within the order or subscription service class, we call yet other service classes that make the actual API calls.

P.S - Keys are encrypted before stored in the off chance that one day the db is leaked. Mavenseed is a multi-tenant SaaS app so we have to store them somewhere.
The paypal sub service is complex, but everything is handled in service classes, so the errors bubble down nicely, and are easily testable with mock data.

We'll find out if this actually works soon as I move to finish off this implementation today.

Gist: https://gist.github.com/bearded-avenger/68fa43fcdee3e6c641df3d9048dbb872
The limitations of Braintree are still present even after five years, which is pretty frustrating.

They offer no way to create plans through their API.

This is going to be a friction point for our users, because we have a UI for this in the app.

https://developers.braintreepayments.com/reference/request/plan/all/ruby
To add to that, Braintree does not offer percentage based coupons, nor do they allow upgrading a subscription to a different interval (mth -> qtr).

Despite the above, Braintree remains the most friendly developer way to implement PayPal into a SaaS app. https://twitter.com/nphaskins/status/1042082965159858176
Perhaps the biggest frustration with Braintree is the fact that they do not return times with their subscription objects.

That's kind of important.

2.6.2 :151 > http://object.next _billing_date
=> "2020-10-24"
2.6.2 :152 > object.paid_through_date
=> "2020-10-23"
PayPal cancelling ✅

Fun fact: you cannot reactivate a cancelled Braintree subscription like you can with Stripe before period end.

You must create a new subscription entirely.
OK so webhooks are completed.

Pretty simple controller here that takes the event and verifies that it came from Braintree.

We then fire off the appropriately named service file to run that logic.

Gist: https://gist.github.com/bearded-avenger/22f930351f4da6e5c3d46b9a3fee6c6e
Another fun fact with Braintree is that they do not send an event id with their webhooks, which means there's no good way to ensure idempotency.

The best we can do is log them, along with the payload from the hook, which support can use to troubleshoot if necessary.
For all intents and purposes the PayPal integration is completed. That covers digital payments and recurring subscriptions.

Let's talk about a few more limitations with Braintree and how you can overcome them.

To start, you can't update a subscription to a different plan.
Well, you technically can update a subscription from a monthly-plan-a to mothly-plan-b, but if the monthly-plan-b is at a higher cost, the subscription won't update!

I don't understand the use case behind this, but it makes upgrading worthless.

https://developers.braintreepayments.com/reference/request/subscription/update/ruby
So the only option here is to offer the user the option to cancel outright before they can switch to a new plan.

You could calc the prorate yourself, and maybe create a dynamic coupon on Braintree....but...oops...their API doesn't support creating coupons.
Once cancelled, there's no "reactivate" before the period end like Stripe. You have to create a new subscription entirely.

This means that the user could still have access but would want to start a subscription again, there's no way but to create a new one.

Thanks Braintree. 🖕
Just like with Stripe subscriptions, I've built a way for customers to be able to automatically detect if the PayPal subscription is out of sync with the vendor.

If it's out of sync, it offers a one click method to sync everything back up.
You can follow @nphaskins.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: