Hacker News new | ask | show | jobs
Ask HN: How do I integrate subscription billing to my SaaS
5 points by user3487 4201 days ago
Hi,

I'm building a web and mobile based SaaS which has a subscription tier. It would be preferable to keep the billing outside the application (API) so that the product can stand on it's own, i.e. separation of concern. How is this managed the best? Is it even possible too keep them as separated as I wish for?

I am thinking about just adding a "Stripe customer id" field to the account model, but I was hoping to not integrate Stripe directly. The plan is to use Stripe for the payments as I understand that they have a fantastic API.

Thanks!

6 comments

Stripe. Just how you think you'd do it, with a CustomerID field in the user (or company) table.

Don't sweat the possibility that you'll have to change payment providers one day. You probably will, and it won't be anywhere near as much effort as you think.

I once switched a couple of my services from Amazon Payments over to Stripe in the course of an afternoon, fixing up the fields, adding a PaymentProviderID column to the table, and rewiring the backend. It was in no way painful. Certainly less effort than it would have been to build in an abstraction layer ahead of time that would have been any help at all during the conversion process.

This is a great example of "you aren't going to need it" combined with "you're just going to build the wrong thing" combined with "quit fannying about building crap you don't need and actually ship your product". To pull off the perfect abstraction layer, you'd need to know not only the system you were integrating, but also enough about the next system that you wouldn't have to do all those things I describe above anyway. It'll take you just as much time to do the work up front as it would to do it when you actually need it, but in the meantime you won't have a shipped product.

In short, don't sweat it.

I would avoid integrating directly with stripe, since if any trouble ever happens with your account (chargebacks, etc), and they terminate it, you need to change all your code before you can resume accepting payments. For this reason I recommend using an abstraction layer to buffer for payment gateways. One good option is Chargebee, which integrates with 12+ different gateways. This way, the same code can control different payment options, and you are not limited to one gateway.
Thank you, that is great information to have in mind! As I wrote in another answer, the subscription will most likely end up as a separate service so it wouldn't be a problem for customers to access the application if I get trouble with Stripe, at least. I would imagine that having a third party gateway would add to the expenses. I am not really too interested in that in the beginning.

Could you educate me when a chargeback would occur using Stripe?

We create a Stripe customer at the same time the customer registers. At that same time we assign them to a "free" plan at Stripe. Then once they decide on which plan and to stay on and be a subscriber we update their plan to the new plan. Stripe then charges them for it and sets the recurrence etc.

You can also setup the plans to have a grace period before they are charged with Stripe.

As for how we actually implement it, we create a small service around subscriptions and it is called by our create steps which then hides the calls to Stripe. This way if we ever went away from Stripe it would only require some small changes in the subscription service.

Also, we store the Stripe customer id and card id in our subscription record, and we do it using a generic data structure where we list vendor, vendor customerId and vendor cardId etc. This way nothing is labeled Stripe, except the vendor value itself would be Stripe in our case.

Lastly we also have a web hook active so we can get notifications from Stripe and update records appropriately. Again, a small separate service that handles only the web hooks.

Thank you for the magnificent answer. It seems like a good idea to create a separate service to handle the registration. My app is backed by a REST API (I know, I am so trendy), so it would just be to call that one and a call to Stripe's API and be done.

One thing I realized now, reading your answer, is that the customer's plans should be changed depending by the user's usage (think storage space). Should I be running a cron job once or twice a day to check the usage, compare it to their subscription plan and update it at Stripe? Of course notify them by email, and maybe give them a day to re-do and not give them unexpected charges.

So if your plans vary based on usage patterns and that carries additional charges, then yes, you'll have to run some sort of scheduled job to check for users getting close to plan thresholds. IMO you don't want to auto upgrade people, but rather warn them at say 80%, then 90% and give them the option to upgrade or be frozen at their current use level. This prevents chargebacks and complaints for auto upgrades they didn't want to have happen. Seems you already are on that path.

But on the other hand (thinking storage space), if your model is such that they pay $9.99/month with up to 5gb and for every gb over 5 they pay $0.99 say. Then you can auto charge the incremental fees and just make sure you are sending the clients an email and keeping them in the loop. I have not done this with Stripe myself so I am not sure the best way to set it up, but my initial guess would say you leave their base plan alone (unless they upgrade/downgrade it) and just add a surcharge to their account at Stripe if they go over their allotted storage space. One way I can think of off the top of my head is to change their account balance to be -$.99, or whatever their overage is, so that Stripe can bill that plus their next monthly service. But I am sure there is likely a more elegant solution.

Someone else mentioned Chargebee, which is a great service, but we chose not to go the route of like a Chargebee because paying additional fees on top of Stripe just didn't fit our model initially, and we feel our chargeback risk is very low. But if you have a higher risk business with a greater potential for chargebacks and disputes then it is best to insulate your self as best you can, and Chargebee helps you do that. In our case, we actually can process charges through Stripe or Balanced payments (although 100% is going through Stripe right now), which is why we did the vendor based model as I described above, that was our insurance in case we every had problems with one provider.

This is amazing, thank you again! It seems that the way you have decided to solve this is both scalable and modular, so it's very likely that I will adopt it. I will talk with my business people about the best solution for us on handling tier upgrades, notification etc. Right now you have assured me I can let the subscription integration wait, so I'll continue focusing on the actual product and implement the subscription later.
Awesome, glad I could help some, good luck!
Even though you should use stripe (we all love it), you should not directly code for stripe only. Here is how:

- Create an abstract "Ecommerce" module in your app and let it configure different payment gateways. In your case, start with stripe as the only payment gate way to choose from. But doing it this way now lets your app easily plug into other payment APIs in future as needed.

- For the user model, instead of having "Stripe customer id" as a field, I suggest having a user meta table with key/value pairs. So in the usermeta table, you can have {'stripe_customer_id': 'xyz'} for a particular user. This way, you can use other payment gateways and not really limiting to Stripe.

- manage the subscriptions/cancellations/refunds in your app instead of stripe. This way, your app has all records of transactions.

Thank you for the answer!

Mr. @davismwfl gave me some really good directions on my problem in his answers, do you agree on that way? Is there a reason you suggest managing the subscriptions directly in the app instead of in Stripe? And does it count as "my app" if I manage it in a separate service, as @davismwfl solution?

Codegeek is right on with this, the description I gave is in line with the same thing he is stating. Our data store is mongo so we use documents for the subscription details but if I was in an rdbms it would likely be a key/value pair as described.

The detail about storing all your subscription details locally is valid. We do it but also put the details in Stripe as that is what enables the recurring billing. That is also what I was pointing out in the web hooks as we store all the Stripe history from the web hooks. Works great.

https://stripe.com is the best. You can also use BrainTree.
Thank you. I'm planning to use Stripe for payment service. The thing I am looking for is the practical implementation of adding a user to my application, and creating a subscription account at the same time without mixing Stripe code into my product. Do you have any experience with that to share?
Braintree?