So, at The Food Corridor, we’ve been using Stripe happily since we launched in June of 2016. As a developer, I’d used Stripe before in a couple of different ways, but this has definitely been my most sustained use of the payment service. (If you don’t know what Stripe is, it is an API that makes charging customers as easy as an API call. More here.)
I wanted to outline some of the things I’ve learned from months of using Stripe.
- Stripe supports pulling money directly from bank accounts, via ACH, but it really isn’t the same ACH as your bank lets you do. This is because Stripe isn’t a bank. The biggest thing to be aware of here is that Stripe ACH takes 7 days to arrive in your bank account. Another issue is that you have to do verification. They have two ways of doing verification–micro deposits and Plaid. Plaid is instant, but only supports major banks, which was a non starter for us (updated 9/8: Plaid supports around 1000 banks now). The code for micro deposits is straightforward, but be prepared for some customer support issues. Stripe deposits two amounts and withdraws just one amount, which was confusing for some of our users. It also takes a couple of days, so if your users are hot to spend money, Stripe ACH may not be a fit. The win? Definitely cheaper. (And I didn’t find any other service that would support both credit card and ACH transactions that was developer friendly.)
- Don’t forget to set up your webhooks out of the gate. Stripe mentions this, but I glossed over it in the early days, and missed some events that were important. (The most relevant is that ACH is asynchronous, so when an ACH transfer fails, it is reported via webhook. If bank account verification doesn’t work, you’ll get a different kind of webhook. Review the docs and set up webhooks for all the ACH events.) If you don’t have time for a full featured webhook processing implementation, Zapier can just send the webhook data to your email. This can be a great stopgap solution. Or you can use stripe_event.
- Per support, if a webhook post fails (because your app is down, for example), they are retried once an hour for 72 hours.
- Speaking of stopgap solutions, the Stripe Dashboard is fantastic for manual processes. Just because you can automate everything via an API, doesn’t mean you should. There can be some complicated edge cases with payment processing, especially around refunds, but they can easily be handled with a google doc of instructions and the Stripe Dashboard. I have found only one use case that the API can handle that the dashboard cannot (a partial refund of an ACH transaction).
- I have found Stripe support to be excellent, quick and knowledgeable.
- Occasionally customer charges will be declined because of bank fraud triggers. Expect to occasionally ask your customers to call their bank. (I think this has happend about once every third month).
- Disputes are a total pain, because the process is opaque and slow (expect a resolution in about two months and know you are not in possession of the payment during that time).
- Make sure to capture the payment id anytime you charge a card or run ACH. It will make future automation a lot easier.
- Monthly plans are complicated, so if you can lean on Stripe for management, even if you are doing manual plan management (applying coupons, adding, or removing users from plans via the dashboard), do that.
- The first payment you charge takes 7 days to move from stripe to your bank account. This is for fraud protection. Payments thereafter typically take 2 days (but it depends on your country and industry).
And here are some special tips if you are using Stripe Connect (their marketplace product).
- Read the docs!
- Remember that first payment timeline? It applies to every one of the connected accounts. Think about charging your own credit card as soon as you connect an account to help with customer cash flow.
- Consider whether you want to use managed vs standalone accounts. Managed accounts are a lot more work but allow you to have a seamless UX that you control. Standalone accounts, which we use, are far quicker to setup. I think this depends on the number of sellers you have in your marketplace.
- You also want to think about whether to place the charges on the platform account or on the connected accounts. A major factor there is who bears the Stripe fees, the platform or the sellers. We charged on the platform account because we wanted all our data in one place. If you are selling plans, you can’t charge on the platform and use Stripe plans.
- If you are charging on the platform account, and are using standalone accounts (where the sellers have to set up a stripe account) your sellers won’t see charge descriptions unless you manually copy the description over. The code looks like:
# this will let the sellers know what invoice the charge was for
transfer_id = charge.transfer
transfer = Stripe::Transfer.retrieve(transfer_id, expand: ['destination_
payment'])
payment_id = transfer.destination_payment
payment = Stripe::Charge.retrieve(payment_id, {stripe_account: destinati
on_account_id})
payment.description = description
payment.save
Happy charging!