Before you start
- ✓The list of Stripe features each app or plugin genuinely needs
- ✓A way to issue and withdraw a key for each merchant
- ✓Separate live and test platform keys, kept on the server only
- ✓Apps and plugins whose Stripe library can be pointed at a different address
Why put a gateway in front of Stripe
Apps, plugins and partner integrations all need Stripe, but none should hold your platform's secret key or decide which merchant gets paid. A reverse proxy (a gateway that relays requests) lets them use Stripe's standard libraries while the gateway decides the account, the fee and what's allowed. We built one for Paypolli.
Only pass on what's approved
We list each Stripe request clients may make, such as creating a payment, and whether it needs the merchant's account and your fee adding. Anything else goes nowhere. The list comes from reviewing what each client actually needs.
Give each client its own key
Each merchant integration gets its own gateway key, mapped to the merchant's Stripe account, fee, fee type and live or test. Your Stripe secret stays hidden, and blocking a merchant is a straight refusal at the gateway, not a key rotation.
Change every request, in a fixed order
- Remove any merchant account the client named itself.
- Replace the client's key with your platform key, live or test.
- Add the merchant's account from your own records, where needed.
- Add your fee, the merchant and the recipient to payment requests.
A rewritten request's declared size must be updated to match, or Stripe rejects it.
Point the clients at the gateway
Most Stripe libraries can be pointed at a different address, so client code barely changes. We did the same in a modified version of WooCommerce's Stripe plugin, so every call, including Apple Pay domain registration, went through the gateway.
Webhooks come from Stripe to you, so they skip the gateway: check they're genuine at your own endpoints.
What usually goes wrong
From our own projects, not the manual.
A client could name someone else's account
Proxies pass request headers on by default, so a client could name a merchant account of its own choosing. Always remove it first, then set it from your own records, and make sure a failure to remove it blocks the request.
Rewritten requests were rejected by Stripe
After the fee was added to a request, its declared length no longer matched its content. Update the length whenever the request body changes.
Don't let the gateway leak what it protects
Logging incoming keys, or a key check that never actually rejects anything, undoes the point of the gateway. Log which key was used, never the key itself, and test that bad keys fail.
A plugin fork needed every call rerouted
Pointing a payment plugin at the gateway meant overriding its Stripe address and replacing its secret key with the platform key, including side calls such as Apple Pay domain registration.
Do it yourself, or get help?
If your developers are comfortable with ASP.NET Core and your clients' Stripe libraries can be pointed at a different address, a gateway with a handful of approved requests and changes is a few days' work. If it will carry live money for many merchants, get it reviewed: request handling and key checks are exactly where a small mistake lets one merchant act as another.
Get a developer on it