
Implementing API Billing with Stripe - kwindla
https://www.daily.co/blog/implementing-api-billing-with-stripe
======
base

       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.

~~~
stickfigure
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.

~~~
noah96
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?

~~~
stickfigure
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.

~~~
noah96
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](http://bit.ly/2Us1OWM) \- Could still be an
interesting read as it explores those key elements of what you have to juggle.

------
stevoski
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.

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

~~~
noah96
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?

~~~
kowdermeister
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...](https://developers.braintreepayments.com/guides/recurring-
billing/overview)

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

------
LeonM
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](https://www.mailhardener.com)

~~~
kwindla
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. :-)

~~~
chrsstrm
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.

~~~
kwindla
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.

~~~
chrsstrm
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...](https://stripe.com/docs/billing/invoices/subscription#generating-
invoices)

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

[https://stripe.com/docs/api/invoices/finalize](https://stripe.com/docs/api/invoices/finalize)

------
eleclady
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.

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

\- Stripe Checkout
([https://stripe.com/docs/checkout](https://stripe.com/docs/checkout)) vs
implementing your custom credit card form and using the API directly
([https://stripe.com/docs/charges](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](https://stripe.com/docs/connect/accounts)

~~~
mduvall
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](https://stripe.com/docs/payments/checkout)

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

------
sbr464
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.

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

Likely to prevent floating point screwups.

------
servercobra
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!

~~~
kwindla
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.

~~~
servercobra
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?

~~~
kwindla
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.

~~~
nicodjimenez
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?

~~~
kwindla
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.

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

------
homero
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.

------
jwr
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.

~~~
strzalek
Poland is currently in private beta. You can request invite here:
[https://stripe.com/global#PL](https://stripe.com/global#PL)

~~~
jwr
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.

------
rsp1984
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).

~~~
warent
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

~~~
arthurcolle
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 ;)

------
Kiro
> 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?

------
pplonski86
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?

~~~
harrisonjackson
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.

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

------
klaudius
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.

~~~
femiagbabiaka
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?

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

~~~
detaro
How does PayPal handle granular billing like this?

~~~
eruci
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!

~~~
detaro
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.

~~~
base
Paypal has APIs that support that. Example:
[https://developer.paypal.com/docs/classic/express-
checkout/e...](https://developer.paypal.com/docs/classic/express-
checkout/ec_set_up_reference_transactions/)

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

