Switching our payment gateway

Published on Jan 13, 2025

Among the things I’ve been doing for quite some time, perhaps the most significant in terms of experiences has been my own application, billit.io. The challenges I faced, as well as the fact that I constantly had to make decisions and test solutions, were crucial factors in my development.

More experienced individuals in the field generally agree that among the most critical aspects of an application are the entry point (Login/Signup) and payments in a web application.

At Billit, we used one of the most well-known payment gateways in our country for years, until they suddenly and significantly increased their fees, and their support became very poor. Their attitude was more or less, "We know you won’t leave easily, so just be patient."
And we were, but even patience has its limits.

The more popular services, like Stripe, Recurly, Paddle, etc., which manage subscriptions and are primarily used by SaaS applications, solve a range of issues for you. However, something else very important also happens at the same time: you build your entire business literally on a third-party service. Subscriptions, coupons, transaction history—all of it resides there. So, if that service, for any reason, decides to stop working with you, you’re left in limbo. How easily can you switch? And what happens to the stored cards—are they transferable, or do you ask all your customers to re-enter them to continue their subscriptions?

As with all things, the decisions you make depend on the business itself. As a small web app/side project, we made decisions with the primary goal of remaining flexible if things went wrong again.

And to avoid misunderstandings, if a web app is just starting out, having its billing/subscription management sorted is extremely important, and the time saved is genuinely critical. In such cases, relying on a provider like Stripe to handle everything correctly and securely might be the only way forward, allowing you to focus on the rest—your actual service. Though, the truth is, I almost always see these apps later avoiding revisiting this area because it’s never the “right time.”

Our Options

Laravel Cashier

As a Laravel app, this seemed like the easiest solution. However, given our setup, I felt that we’d simply be adding another dependency on top of Stripe’s dependency, which didn’t make much sense—especially since we weren’t even using Stripe’s subscription features.

That said, we tried it out, renamed entire tables and models so they could coexist, only to realize it didn’t suit us. I had to perform a rather painful rollback.

Additionally, with this solution, if something goes wrong with Stripe, we’d only have one easy alternative—Paddle—by switching packages and making a few other changes. These two options (Stripe and Paddle) were so different that they even required separate packages.

Laravel Spark

This has a lot in common with Cashier but offers additional conveniences and a ready-made UI. Generally, for an MVP relying solely on card payments and subscriptions, it’s ideal. However, we weren’t that kind of project; we also handle bank transfers, which complicated things.

Stripe
For our new provider, we ultimately chose Stripe and connected directly to it. However, we didn’t use any of its subscription management features. It’s simply our payment gateway.

We decide when and who gets charged, we determine when to give a trial and what kind of gift to offer (if any), whether to change a subscription, or validate a coupon. Sure the customer’s card is stored securely in Stripe's servers and the final charge/3ds flows are on their side.

But that’s it.

It took a few days to integrate Stripe, and the result?

  • All new subscriptions are processed via Stripe.
  • All old subscriptions are renewed through the old gateway unless the customer re-enters their card details, in which case they’re automatically moved to Stripe.

Of course, some might wonder: why are both the old and new systems running in parallel? Couldn’t the cards be transferred to the new provider?

The answer is yes; there’s a process that makes this possible. Stripe has detailed documentation and procedures for how this can be done. I believe it’s the duty of every serious payment gateway to respect its clients by minimizing inconvenience for their customers.

In our case, I mentioned the process to them but nothing came of it, so unfortunately we had to ask all of our clients to put their credit cards again to our system.

Implementing Stripe, our experience

I wanted to mention that I earned a stripe certification that was extremely enlightening and I highly recommend it to anyone planning to work with Stripe.

Its documentation is very comprehensive but can easily confuse you, as it often presents multiple ways to solve a need. At times, you’re left wondering whether the solution you’ve chosen is the best and most flexible. This is especially true when you need to implement 3DS flows as well, which make things much more complicated. This complexity by the way is why the philosophy behind Cashier packages changed at some point, opting for direct redirects to the provider to avoid dealing with these challenges during implementation and maintenance.

Another strong and very helpful feature is Stripe’s Discord channel.

Overall, while the experience is harder than it once was, it remains top-notch, with excellent CLI tooling for local development and a super-comprehensive dashboard and logs for any debugging needs.