Being a Stripe Verified Partner, Growthmill often receives requests from our clients asking about the possibility of adding a surcharge on credit card transactions to recoup the processing fees associated with offering card payments for their digital transactions.
There are a couple considerations to adding surcharges on credit card payments processed by Stripe
Growthmill cannot provide legal or accounting advice on whether or not adding surcharges to credit card transactions complies with local regulations. We're just engineers! A basic Google Search indicates some grey areas that become more grey if you offer customers the ability to use a payment method without a convenience fee, like ACH / Bank Debit. Bankrate offers some good background on the regulatory assessment of adding surcharges or convenience fees.
Adding ACH is a good way to offer customers an alternative to a credit card surcharge. The good news is with Stripe's Financial Connections and the Stripe Payment Element, paying with ACH is as low friction as a credit card. Gone are the days of microdeposits and async payment method verification.
Stripe offers lots of out-of-the-box functionality, low-code tools and the Stripe Dashboard is a power interface for managing payments but surcharging is not part of Stripe's automation. A custom solution is required.
If you're familiar with how Stripe's payment intents work, adding a surcharge can be done relatively easily. Below we describe how to add convenience fees for Subscription Payments (Recurring Billing)
Set up a system to listen for the invoice events, specifically the invoice.upcoming webhook. This event triggers when an invoice is about to be finalized.
Retrieve customer information and check if the default payment method is a credit card. (Tips&Tricks: Use expand parameter to get all the info via one api call.) Retrieve the customer and check if type parameter has the value card. You can use the provided API call to get this information.
curl https://api.stripe.com/v1/customers/{{customer_id - cus_***}} \
-u "{{STRIPE_SECRET_KEY}}" \
-d "expand[]"="invoice_settings.default_payment_method"
Response:
{
...
"metadata": {},
"type": "card",
...
}
If default_payment_method doesn't exist on the previous expanded customer call, next in the hierarchy is a subscription. To check default payment method on the subscription you should call:
curl https://api.stripe.com/v1/subscriptions/{{subscription_id - sub_***}}} \
-u "{{STRIPE_SECRET_KEY}}" \
-d "expand[]"=default_payment_method
If the customer has Credit Card as a default payment method you can add invoice item as long as invoice is not finalized. When the invoice is in status open you cannot add/remove invoice items.
If the invoice is not finalized you can add new invoice item with convenience fee. You can use amount_due from the invoice.upcoming webhook for calculation: fee = amount_due * 0.03
curl https://api.stripe.com/v1/invoiceitems \
-u "{{STRIPE_SECRET_KEY}}" \
-d customer={{customer_id - cus_***}} \
-d subscription={{subscription_id - sub_***}} \
-d "description={{Description you want to be shown on the invoice - e.g. “Convenience fee”}}" \
-d currency=usd \
-d amount={{fee}}
Continuously monitor for changes in the customer's payment method. If the customer switches from a credit card to another payment method, promptly remove the convenience fee from the invoice. You should listen for customer.updated webhook and check the value of the default_payment_method
{
...
"invoice_settings": {
"custom_fields": null,
"default_payment_method": "pm_1OgQ3BCr7IltEAncvw832wRU",
"footer": null,
"rendering_options": null
},
"livemode": false,
...
}
After finding payment method id in the previous call (pm_***) you need to call payment method retrieval api and check if type field is not card .Check code below.
curl https://api.stripe.com/v1/payment_methods/{{payment_method_id - pm_***}} \
-u "{{STRIPE_SECRET_KEY}}" \
Response:
{
...
"metadata": {},
"type": "us_bank_account",
...
}
There are two scenarios when we want to remove the fee depending on the invoice state. For both scenarios, first you need to find an invoice item id for the fee charge that you want to remove.
1. Removing the fee from the upcoming invoice
You can search for invoice items as stated below. Those will search all the invoice items and return 10 most recent ones. From the returned invoice items, you will need to find one for the convenience fee where invoice is null. This is because the invoice is still not created.
curl -G https://api.stripe.com/v1/invoiceitems \
-u "{{STRIPE_SECRET_KEY}}" \
-d customer={{customer_id - cus_***}} \
-d limit=10
Response:
{
"object": "list",
"data": [
{
"id": "ii_1OgUTSCr7IltEAnc0SQvYoIu",
"object": "invoiceitem",
"amount": 837,
"currency": "usd",
"customer": "cus_PVUfGWnVWlEglO",
"date": 1707148366,
"description": "Convenience fee",
...
"invoice": null,
...
}
2. Removing the fee from the existing invoice in draft state
You can search for invoice items as stated below. Those will search all the invoice items for the given invoice. From the returned invoice items, you will need to find one for the convenience fee.
curl -G https://api.stripe.com/v1/invoiceitems \
-u "{{STRIPE_SECRET_KEY}}" \
-d invoice={{invoice_id - in_***}}
Response:
{
...
"customer": "cus_PVUfGWnVWlEglO",
"date": 1707148366,
"description": "Convenience fee",
...
"invoice":"in_1OgV0QCr7IltEAncTiLghjzE",
...
}
After finding the particular invoice item you can delete it via command:
curl -X DELETE https://api.stripe.com/v1/invoiceitems/ii_1OgR9RCr7IltEAnc4dC4HNHz \
-u "{{STRIPE_SECRET_KEY}}"
Growthmill has 9 certified Stripe professionals experienced in Stripe Payments, Elements, Billing, Migrations, Issuing, Connect, Identity and Tax. We provide advisory services, hand-on-keyboard work or a hyrbid approach, where we provide code samples engineering teams can pickup and incorporate into existing code bases.
Reach out today to talk to one of our professionals about helping with a Stripe.