Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Implementing API Billing with Stripe (daily.co)
180 points by kwindla on April 2, 2019 | hide | past | favorite | 82 comments


   A good first question to ask about a data model is, "where does the data live?"

   In general, we think it's a good idea to make Stripe the "one true source" for as much of your customer and billing data as possible.
Our company went the opposite way, we have our own model and we abstract stripe as a payment option supported. Recently with the same model we were able to add Paypal and other country specific payment methods.


I've done it both ways.

My last company processed >$100MM/yr of tshirts, split between Stripe and PayPal. Stripe was wonderful; PayPal was hell. It required a lot of engineering effort to build and maintain the system, even as simple purchases (no subscriptions). But if you're selling impulse buys online, PayPal is required.

Current company is B2B SaaS, smaller team, and I said "no freaking way" to PayPal. Built the subscription system around Stripe. Lack of PayPal has probably cost a few sales but our pace of development is much faster, and the new features we're able to roll out (like a referral program) move the needle more.

If you go the "straddle multiple billing systems" route, expect to dedicate one fulltime engineer to billing for the life of the project. That may be reasonable for a team of 10, but it's death for a team of 2.


Out of interest, why did you go down the avenue of hacking together your own system to handle subscriptions? Surely you've limited yourself like you've said you have to build out every time you want to attach another payment method like paypal - Is this not more expensive than looking into a Merchant of Record handling these complexities for you?


There must be some sort of miscommunication here. My (SaaS) subscription system is vanilla Stripe without abstraction. My (single-purchase, tshirt) system was an abstraction across Stripe and PayPal.

I can only imagine the elevated pain of abstracting across multiple subscription systems. Ouch.


My bad must have been a miscommunication here. I was about to expand on those key differences between payment gateways vs Merchant of Records. http://bit.ly/2Us1OWM - Could still be an interesting read as it explores those key elements of what you have to juggle.


As a solo developer on a project which needs flexible payment options (also t-shirts) that's why I need to pick a payment solution that supports paypal besides other methods.

Paddle looks like the service I need on the long run:

https://paddle.com/solutions/saas/


How did you go about implementing a referral program in Stripe?


I have a polymorphic ledger table of Credit, Spend, Payout.

I scan recent invoice history periodically to keep Credits up to date. Payouts are via PayPal masspay. Spends (using credit balance to offset their SaaS bill) are created on the invoice.created webhook, which adds a corresponding negative line item to the invoice.

I considered doing everything in Stripe - you can add pending invoice items instead of credits and payouts, then 'spends' are just the natural processing of bills - but it would have been very difficult to get analytics (eg, total outstanding payout liability).


Why though? I am using Braintree for cards and paypal and it's a breeze.


+1 I recent saw a couple of cases of small companies who chose to depend on Stripe for managing their payment data to save cost on initial development. As a result, their operations staff struggled between Stripe's admin panel and their internal tools even to answer simple user questions.

Eventually, when they decided to streamline their payment and billing operations on their own tools, due to historical data on Stripe servers, they built a custom presentation layer on top of Stripe APIs. They ended up spending pretty much the same time and effort as they would have done by managing the business flows on their own systems and storing all the data on their DBs and using Stripe just for processing payments. Worse yet, they still depend on Stripe for stuff like reporting.


Agreed.

> In general, we think it's a good idea to make Stripe the "one true source" for as much of your customer and billing data as possible.

Customer and billing data are mission critical and as such having a third party payment processor as "one true source" seems suicidal, frankly.

We have Stripe handle the actual payments and nothing else.


"Suicidal" might be a little strong. :-)

Like most things in engineering, you can move the tradeoffs around to optimize for different use cases.

The "one true source" approach allows you to avoid writing logic to keep data in sync between your customer records and Stripe's systems. It also implicitly pushes you to think about how to store enough data in Stripe that the Stripe dashboards become your interactive way of managing and viewing customers. Those are both big enough wins that I do think it's the right approach to take for lots of folks who are just spinning up charging for a product, and for relatively simple recurring revenue use cases.

If you need to use multiple payment processors, or you need to have a complex view of your customer and lifecycle, then it's not the right approach.


What happens if you lose access to Stripe or they shut down?

Engineering is one thing but it must never trump strategic business thinking. Sometimes the cleverer engineering option is a business death trap.

Any solution that puts your balls into someone else's hands is suicidal.


> a third party payment processor as "one true source" seems suicidal

for small product/shop/site with no strong core competence in billing it may be wise versa..


Yea. Customer and billing isn't something good to hand over to another system you don't control. As a payment processor and API though, Stripe is great


(Please don’t use two-space indentation preformatting for quotes. Use a `>` prefix possibly combined with asterisks for italics.)


Couldn't agree more. Reading over it's tied to Stripe and their implementation, not even any sort of abstracted interfaces. Vendor lock-in isn't a good plan and to your point, make it easier to add another payment system when needed. Good choice


> Vendor lock-in isn't a good plan

I'll take vendor lockin over being locked into a bunch of homebrew garbage that some former developer managed to sucker the entire company into creating because of "vendor lockin". So many times engineers come up with fears about "vendor lockin" and forget how easy it is to lock the company into an unsupported, half-baked homebuilt product that has nothing to do with the company's core business.

I've seen it with reporting and analytics, I've seen it with frameworks, I've seen it with deployment systems, build systems and configuration management systems. I've seen it with payment systems, crappy half-baked hybrid cloud implementations, database provisioning systems and more. All in the name of "avoid vendor lock-in".

Being locked into your own garbage-tier product that has nothing to do with your business sucks. If stripe kicks the bucket, you won't be the only person in that boat and there will be a path forward. Know what is worse? How about when the only developer who can support your crappy half-baked payment system leaves the company? Which stack overflow article will show how to get out of that mess? Talk about vendor lockin! You locked yourself into your own mess!


Spoken like someone who hasn't had a vendor disappear and have your entire implementation on their platform vanish.


Considering how Stripe caused an abrupt vendor disappearance when buying Index, resulting in a tidalwave of broken integrations (as Stripe closed Index with no notice, and stopped responding to clients), I wouldn't trust them to support a platform for any period of time to ensure a smooth transition.

Stripe might leave the servers online in a half broken state for a few weeks, but they will not answer tickets or phone calls about critical issues if they've decided to can a product.

https://www.pymnts.com/news/partnerships-acquisitions/2018/s...


I think it really depends on the situation. Low level functionality (eg payments api) is more generic than high level functionality (billing cycles, dashboards, handling failed payments, etc) and therefore more likely to have a solution which will completely solve your problem.


Question: did you plan the abstraction by looking at multiple providers first then figuring out the abstraction that would work well for all of them or did you just look at Stripe and luckily come up with an abstraction that also worked for other providers?

I'm encouraged by your success of this model. I'm currently struggling with the 'billing system as source of truth' model.


We used other payment gateways before Stripe.

We built the abstraction around the requirements for our business model, although after some iterations it became similar to the model used by Stripe (customers, sources, plans...). We support saved payment options and on them we do recurring billing and one-stop payments.

A user for us can have multiple sources and a source is a saved external card or payment method, in the case of Stripe a source is a combination of the Stripe customer id and Stripe source token.

Most payment gateways support some kind of token that represents a saved card or similar on which you can do a charge.


There is a very nice implementation of this called KillBill: it's a self-hosted invoicing system that can connect to many payment providers like Stripe/Paypal/...

It's really nice to be in control of the invoicing, without having to implement it ourselves, and of course not depend on only one provider. It also has support for taxes with plugins.


Stripe's "getting started" documentation, as well as this article, show us how easy it is to get started with Stripe - if you ignore the existence of taxation.

The article is completely missing any mention of tax, be it sales tax or VAT. This is my biggest complaint of Stripe.

For a lot of us, we live in countries where we simply _have_ to start collecting and remitting tax from the very first customer.


That's what I'm stuck with as well. Paddle.com has this covered really well, but they have a long way to go in terms of API quality and breadth.

Stripe has indicated that they're working on it, but no timeline yet: https://www.indiehackers.com/forum/stripe-onboarding-integra...


Couldn't agree more, cool to see they indicate that they're working on it but then as I'm sure you're aware of there is so much more needed than just the dealing of tax, how do you deal with the likes of managing your chargebacks? Support? - This post expands on how Paddle helps here: http://bit.ly/2Us1OWM


I've seen way too many "just copy these 5 lines" and you are good to go. With payments this is never that simple.


Makes sense - I guess it's just an unclear emphasis on their offering which essentially is taking that work off your hands. What would you prefer to see?


A checklist of cases that I might not thought of. I would group example code around different use case and not around API endpoints.

For example Braintree is good in that sense: https://developers.braintreepayments.com/guides/recurring-bi...

I know it's not a payment gateway's responsibility, but some further handholding on tax and VAT, invoicing issues would be handy.


Agreed. It's much more like "just handle these 50 edge cases and you're good to go."


I've just finished a Stripe integration[0]. Given Stripe's developer first reputation I thought this would an easy job that wouldn't take more than a couple of days. Boy was I wrong! In the end, it took me about 3 weeks.

Small disclaimer here, I was implementing Stripe Billing, not Stripe Payments. The Billing suite is a lot more complicated compared to the Payment suite.

Nonetheless I took me a really long time to figure out all the special cases such as: renewing a card, switching to a different payment method, up/downgrading a plan, multiple currencies, etc.

At some point you'll be almost finished with the integration and only then do you find the need to implement webhooks for certain asynchronous payment methods (especially needed when you are in Europe). Once implemented, webhooks give you endless new workflows to handle, and many race conditions between your frontend and backend. So it constantly feels like one step forward and two steps back.

I don't think it's Stripe's fault though that my implementation took so long. Stripe's documentation is pretty solid. It's just that billing touches just about every part of your stack (frontend, backend, database, testing, tooling, accounting) and it's painful if you find out you have a bug that caused you to over/undercharge a customer. You need to take your time to get it right.

[0] shameless plug: https://www.mailhardener.com


I'm a Stripe fan, so my perspective on this is that Stripe has done an incredible job making "easy things easy," and a pretty good job making "hard things possible."

There are things I'd love to see added to the Stripe Billing APIs (some of which I mentioned in the article), but I have a really healthy respect for the amount of good work that's gone into the design of an API that, as you say, touches just about every part of a potential customer/payments workflow.

Stripe's API has consistent naming, a clean design of the core data objects, consistent data formatting and request patterns, good dashboard tools for seeing what's happened in requests and webhooks, and great documentation. All of which are non-trivial, and basically none of which any of the other "name brand" APIs I've used in the last year or so do. :-)


Yes and no. Some parts of the documentation can be clarified in my opinion.

For example: if you change the default payment method of a Customer, the default payment method of all this customer's Subscriptions is not changed. The documentation is not clear about that.

Also, if you remove a payment method from a customer, the subscriptions seems unaffected. If you're not careful you might still end up charging this customers card when the subscription auto-renews.

I'm still a fan of Stripe though. I have my fair share of experience implementing other PSP's and they were an unbelievable PITA. As far is my experience goes, Stripe is miles ahead of their (european) competitors.


You're right, their documentation is great and the API is nice to work with, but you are forced to do things their way. I was recently working with Billing and ran into a pretty big issue: A customer on a recurring plan upgrades to a more expensive plan. As long as the customer has a valid source on file, the upgrade is processed. Stripe's default is to adjust the payment to be collected and charge it on the next invoice, which comes at the end of the billing period. If you want to charge the difference immediately, you can by manually forcing an invoice. The problem is that the invoice doesn't close for 24 hours and you can't force it to close any faster. If the customer's payment source is declined when the invoice closes, you just gave them 24 hours access to your premium upgrade which you now have to detect and rescind after being alerted via a webhook. There's nothing in the documentation that warns about this or offers a solution, and worse yet, rolling the user back to their previous plan is not an option. For some use cases, it might not be a big deal, but for most businesses that is a nightmare. The easy stuff is indeed easy, but once you start to wander off of The Path, things can get very difficult.


Our experience is that manual invoices are charged right away. I wonder what's different about our setups? The only thing I can think of off the top of my head is webhooks that aren't responding, which would delay the invoice closing. But I think that would make the delay 72 hours, rather than 24.


I misspoke, it's 1 hour, not 24. Can be found here [0]. Regardless, the upgrade happens _before_ the customer is charged, so unless you put a hold on your system and wait for that invoice to close, you're still giving them access before they've paid (Stripe's system will shown them as having the new upgraded plan before the invoice closes). And with the charge re-tries and back-off they use, if your webhooks aren't listening and reacting, you've still opened up your product to a user who hasn't paid for up to days at a time. I would be very interested to know how you got yours to close instantly, if it is doing that.

[0] https://stripe.com/docs/billing/invoices/subscription#genera...


If you want to skip the 1 hour delay, you can manually finalize the invoice:

https://stripe.com/docs/api/invoices/finalize


You're right, it's not synchronous! I looked back at our development notes and it seems like we were seeing about 15 minutes, generally, between creation of the manual invoice and finalization/payment. But that was using our test, not production Stripe API keys, and was a fairly small set of anecdata. I don't have better data because we ended up not rolling out any features that required manual invoice generation.


Why can't you just charge the card directly?


That defeats the entire purpose of using the Billing product. Best I could come up with is to auth the source for the amount and see if it is accepted, then let it die by not capturing. But then you have customers who complain about being double charged.


Stripe's generally consistent, except for three different ways to enter a name:

     name
     account_holder_name
     first_name + last_name
And four different structures for addresses:

     address_line1
     address.line1
     legal_entity.line1 (a personal address, old as of new version)
     legal_entity.personal_address.line1 (personal address when the prior is a business, old as of new version)


It didn't take me nearly as long to implement Stripe Billing (a couple of days) but that's because all they can do is sign up for my one subscription plan, cancel, and update their card.

There are surprising edge cases that crop up. For example, canceling a subscription and then restarting it is actually somewhat painful.

But yes, their documentation is stellar!


I found Stripe usage quite complicated. It felt like they were handling very complex use cases at the expense of simpler ones (which are probably the majority).

It's one of those things where once you're already "in the know", the simple use cases are in fact simple to implement. But sifting through the massive and complex API set, with outdated and partial documentation/examples all over the internet, it's very difficult to get into. Every single example starts with "this is not production ready..." And the official docs are difficult to piece together into an "E2E best practices" setup.

Not saying there is a better solution, just that as a competent dev with a simple use case, I found Stripe overly complex.


They often offer either the simple option or the custom-built option basically:

- Stripe Checkout (https://stripe.com/docs/checkout) vs implementing your custom credit card form and using the API directly (https://stripe.com/docs/charges)

- Standard, Express, Custom options for Stripe Connect (e.g. take money from someone and give it to someone else): https://stripe.com/docs/connect/accounts


Hi from Stripe!

We are currently working on a new version of our Checkout product[0] and would love feedback. We are working on making the simplest drop-in integration to get up and running on Stripe, and we support Stripe Billing! Send me any thoughts you have (matt at stripe).

[0] https://stripe.com/docs/payments/checkout


Unrelated: can you guys please provide a native way to pause subscriptions? I find all the recommended methods in your docs hellish.


Thanks for sharing.

I’m curious why there is an even number of cents requirement on stripe’s end?

I’m also not a fan of the quantity 1 line item rollup, although I understand the workaround. For the customer receiving the invoice, it makes it harder to breakdown the invoice in an automated way, since the detail info is moved to a text block.


> I’m curious why there is an even number of cents requirement on stripe’s end?

Likely to prevent floating point screwups.


This was a really interesting article, thanks for writing!

At my last startup, we used our DB as the single source of truth. I think using Stripe as the source of truth like you suggest would have alleviated a lot of our issues keeping things in sync.

My biggest pain point though was around managing features on the client side. We had a bunch of different plans from lots of iterating (and customers coming from different sources that had similar but slightly different experiences), so it became hard to decide "should I allow the user to see this feature/do this action?". I haven't yet seen a great way to handle that. The plans literal here looks like a great starting point though!


Yeah, I definitely feel your pain regarding iterating on plans and features.

Stripe explicitly makes it hard to modify most aspects of Stripe-level plans after they are created, which definitely is the right call because user expectations about recurring payments need to remain stable. But that means you have to build your own plan->feature mapping to manage a proliferation of plans, if you do any experimenting with or evolution of your pricing.


Agreed, making the plans hard to modify definitely makes sense, but then I feel like I need another abstraction on top of Stripe. Have you come across any good ways for handling this?


No, haven't seen anything. Everything looks like a hammer, of course, but to me this just feels like a general software engineering thing, if that makes sense -- building an abstraction on top of a library service. Our plan is to evolve the plans literal in our code into this abstraction (it already kind of is). Next step is probably to add something a little like feature flags, but we're still thinking this through.


Is there any downside to just using the payments api and not use any of the other stripe features? Subscriptions can be implemented manually right?


Yes, subscriptions can be implemented manually. We did that two years ago before Stripe had the full “Billing” API.

One big win you get with Billing, though, is automatic generation of invoices each subscription period. It’s nice not to have to write that code, and the automatic invoices tie in nicely to a few other things Stripe can do better than we can, like automatic retries of payments that fail.


At the cost of how much complexity? Is it worth it if you want to stay maximally flexible in how you charge?


Stripe was much more complicated than it seemed. At the end i used Chargebee which did a lot of the work.

A lot of things were abstracted away and i got a much better admin panel and can change payment processors anytime.


I so wish Stripe would stop ignoring a number of countries and make their billing available there (Poland is an example). I am stuck with Braintree and it is not a happy ride.


Poland is currently in private beta. You can request invite here: https://stripe.com/global#PL


Huh? I signed up several times already, and never heard from Stripe… Well, signed up again. Anything to get the option of switching from Braintree.


And here's your startup idea: Build a complete and configurable front-end to Stripe Billing that does all the hard work behind the scenes and lets existing Stripe users "upgrade" to billing without the implementation pain.

I've researched something like this some months ago and couldn't find anything that had the quality and features we needed. I'm sure lots of companies would pay for a solution like this (my company included).


I had a similar impression when I was implementing Stripe for my business. It seems like there's a lot of boilerplate and heavy-lifting that I would have preferred to just abstract away using some existing service instead of spending the hours on getting it working in a way others probably already have.

Would you be open to sharing your thoughts on how you'd like something like this to work? I might be interested in giving it a shot. My email address is hello@wyatt.engineer


You put in all the effort to put up a cypher to unlock your email address on your profile and then just give away the gold in one fell swoop ;)


I have something just about ready to launch that tries to do this. My goal is to make creating web apps as simple as blogging is when you use WordPress.

https://userappstore.com/public/2-powered-by-dashboard.png

https://github.com/userappstore/dashboard

I am putting the finishing polish and fixes on a platform and marketplace using this software, just working on the final integration tests that verify it all works together.


I know it's not specific to Stripe, but it seems there are products out there like ChargeBee that cover a lot of the use case.


That sounds a bit like Drew Wilson's Plasso, which was recently acquired by GoDaddy and promptly shut down.

https://web.archive.org/web/20181206180323/https://plasso.co...


> Usage data needs to be sent to Stripe continuously. There's no way to submit usage data to Stripe after the end of a billing period.

I don't understand how this is supposed to work when you're sending in aggregated data. How can you know before the period has ended?


Maybe noob questions, but how to do tests with stripe API? For example, how to write a test for plan upgrade? From what I remember there can be set testing env in stripe but the shortest subscription time was 1 day, so how to use it in automatic tests?


We disable live API interaction w/ stripe in our tests and use hardcoded response values. You can use a library to do this or patch the stripe sdk - depending on the language/framework you are using.


You should never write tests against a live API. Always mock APIs and handle what happens when e.g. they send a 501 response, etc. Stripe has testing libraries in Ruby and other languages which are very easy to use.


Just create a stub with the possible responses.


I built a prototype for health care last week. Daily is awesome. Keep it up!


Stripe is touted as 'developer-friendly', but it's not all it's cracked up to be. I think PayPal is underrated here.

- Stripe's list of prohibited businesses is much larger than PayPal's. They are not business-friendly.

- PayPal is available in over 200 countries. You can accept payments in many countries Stripe is not available in.

- On PayPal you can start accepting payments immediately, no need to submit complex business docs.

- PayPal is easier to setup (Paypal.me link, buttons, send via email etc.) and has lower fees for small transactions.

- People might be more comfortable buying from a relatively unknown site when they are using trusted 3rd party provider like PayPal.


I'm eternally amazed at the rate of speed at which any HN comment section derails into off-topic nonsense. What does this have to do with the linked article? Is it possible to do what's described in the article with PayPal?


This is unnecessarily complicated. That's why I handle all subscriptions with PayPal.


How does PayPal handle granular billing like this?


Simple. Send the customer to PayPal with a subscription request, the amount and customer id. They activate the subscription and pay. Get that id back via IPN after each new subscription. Deliver the service. Done!


How does that match the use case here, with billing per minute? If the user has to confirm each subscription, you can't efficiently create new subscriptions for e.g. each call. You also can't know beforehand how much you'll need to bill. If you're at the end of the month sending a single "here's everything" request, I fail to see how that's different from what's described in the article.


Paypal has APIs that support that. Example: https://developer.paypal.com/docs/classic/express-checkout/e...


Doesn't appear to have a non-deprecated replacement new users could use though?


Exactly my point. PayPal also makes it extremely simple for fixed amount monthly subscriptions - which is my use case. I do use Stripe, but not for subscriptions. This is the reason why.


PayPal subscriptions are fixed amounts.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: