So, if you want to handle ACH transactions with Stripe, you can. Some limits to include the length of time for the transaction (5 business days on top of stripes 2 business day transfer duration) and support only for US accounts, but the API is nice and the price is pretty nice too (0.8% up to $5).
But if you are trying to do recurring billing with Stripe and ACH and you want to let your customer change their default charge source between credit card and bank accounts as a payment source (or even two different bank accounts), you’re going to run into a roadblock. While Stripe will happily accept new credit information with the exact same card number, expiration date and CVC code, and just create a new source for each entry, it is not so forgiving with bank accounts. Instead, you’ll get this error message: "A bank account with that routing number and account number already exists for this customer."
if you try to change the default source to an existing bank account record in Stripe.
I found some code with this error message, but it actually isn’t complete. It’s not best to examine the error message and switch on that, but I didn’t see a specific exception class for this type of exception.
For a complete solution, you need to check the stripe tokens routing number and last 4 digits of the account number. If a user has two different bank accounts that match both in the last 4 of the account number and the routing number, well then, I think you are out of luck.
Here’s the complete ruby code, making sure to match the current request’s routing id number just in case your user wants to switch between multiple bank accounts for their default charge.
def update_customer_from_token(customer,stripe_token)
# takes the stripe customer object and the new token
# from the stripe indicating the changed payment method
success = false
Stripe.api_key = ENV["stripe_secret_key"]
begin
new_pmt_obj = customer.sources.create({:source => stripe_token})
customer.default_source = new_pmt_obj.id
customer.save
success = true
rescue Stripe::InvalidRequestError => e
# special case where the bank account already exists, let's use that.
if e.message == 'A bank account with that routing number and account number already exists for this customer.'
tokobj = Stripe::Token.retrieve(stripe_token)
customer.sources.each do | src |
begin
if src.object == 'bank_account' && src.routing_number == tokobj.bank_account.routing_number && src.last4 == tokobj.bank_account.last
customer.default_source = src.id
customer.save
success = true
break
end
rescue => e
Rails.logger.error(STRIPE_ERROR_PREFIX+" 4 unable to update customer for "+customer.inspect+", "+e.inspect)
end
end
else
Rails.logger.error(STRIPE_ERROR_PREFIX+" 3 unable to update customer for "+customer.inspect+", "+e.inspect)
end
rescue Stripe::CardError => e
Rails.logger.error(STRIPE_ERROR_PREFIX+" 1 unable to update customer for "+customer.inspect+", "+e.inspect)
rescue => e
Rails.logger.error(STRIPE_ERROR_PREFIX+" 2 unable to update customer for "+customer.inspect+", "+e.inspect)
end
success
end
Or, you could just let the user choose from a drop down list of their existing sources which one they want to be the default. That might be a cleaner solution.