The part of your product that turns intent into money
Payment infrastructure is the layer that takes a customer's intent to pay and turns it into money you can rely on — choosing a provider, handling the attempt, confirming what happened, and recording it exactly once. For most SaaS products it starts as twenty lines against one provider's SDK and stays that way until the first time it is not enough. This page is about what it eventually has to do, and how to tell which parts you actually need.
Billing decides what to charge. Payments decide how to take it.
Almost every confused payments project starts by treating these as one system. They are two, they fail differently, and vendors on both sides of the line are happy to let you assume otherwise.
A billing engine answers what does this customer owe? — plans and price books, metered usage, seats, proration when someone upgrades mid-cycle, invoices, dunning schedules, sales tax and VAT. When it breaks you invoice the wrong amount.
Payment infrastructure answers how do we actually collect it, and how do we know we did? — which provider takes this payment, what happens when that provider is unavailable, how a retry avoids charging twice, how the result is verified, and how five providers become one set of numbers. When it breaks you lose the sale, or take it twice, or ship something nobody paid for.
Knowing which of the two is hurting is most of the diagnosis. If your revenue numbers are wrong, look at billing. If money is arriving late, twice, or not at all, look here.
PaymentHood sits on the payments side of that line, and only there. It does not meter usage, run plans or proration, issue invoices, manage dunning, or calculate tax — you keep whatever you already use for those. What it changes is that how you take the money stops being hard-wired to a single provider.
Five jobs the payment layer has to do
One provider gives you the first for free and leaves you the other four. That asymmetry is why payment code grows.
Routing
Deciding which provider takes this payment, from currency, country, method and amount. With one provider there is no decision — which is exactly what limits you at the second market.
Failover
Completing the payment when the first attempt fails for a technical reason, without treating a declined card as an outage and without charging anyone twice.
Idempotency
One payment attempt keeps one identity, so a timeout, a double-click or a retry returns the original result instead of creating a second charge.
Verification
Believing the provider, not the browser. Signed webhooks checked properly, and an order marked paid only when your server confirms the capture.
Reconciliation
Several providers, several settlement formats, one ledger — so finance answers "what did we take yesterday" with a query rather than a spreadsheet merge.
Risk controls
Rules that stop the traffic you do not want: velocity limits, repeated failures from one customer, distinct cards in a window, blocked regions.
Routing: the first thing one provider cannot do
A single-provider integration has no routing decision to make, and for one country in one currency that is a feature. It stops being one the moment your customers are somewhere your provider is weak — a currency it will not settle, a method it does not offer, an acquirer with no local presence and therefore a worse approval rate on exactly the cards you want to accept.
The mistake is treating that as a provider-selection problem and re-running the evaluation. It is a structural problem: any single provider is the wrong answer somewhere. Routing turns "which provider" from a decision baked into your checkout into a rule you can change, which is what makes accepting payments across several markets a configuration exercise instead of a rebuild per country.
Failover and idempotency: two halves of one problem
These are usually planned as separate tickets and that is the error. Failover without idempotency is not a safety feature — it is an automated way to charge customers twice, because the failure it most often reacts to is a timeout, and a timeout means you do not know whether the first charge succeeded.
The requirement that falls out of that: the identity of a payment attempt has to live above the providers, not inside one of them, because a provider's own idempotency key is meaningless to the next provider. This is the single most common gap in a home-built payment layer, and it is unpacked properly in how payment failover is actually built.
Verification: the two habits that separate robust from lucky
First, never mark an order paid because a browser arrived at your success URL. That redirect is attacker-controllable and it is also just unreliable — customers close tabs. The payment is real when your server asks the provider and the provider confirms the capture, which is why orders get stuck between paid and pending in systems that trust the redirect.
Second, verify every webhook signature. Each provider signs differently — an HMAC digest in a header here, a form-encoded signature plus a source-IP check there — and an unverified callback endpoint is an open invitation to forge a "payment succeeded" event and take goods without paying. Implemented once centrally this is a solved problem; implemented per provider by whoever added that provider, it is a lottery. The mechanics are in webhooks for payment events.
Risk: the rules that pay for themselves early
Most SaaS products do not have a fraud problem until they have a signup form and a $1 plan, and then they have one immediately. The traffic is not trying to buy your product — it is validating stolen cards against anything that will take a small charge, which leaves you with the declines, the fees and eventually the account review. What stops it is dull and effective: limits on attempts per customer per window, limits on distinct cards, and a rule that reacts to repeated provider rejections rather than waiting for a human. Card testing on signup forms covers what the pattern looks like and which controls actually bite.
Build or buy
Building this is entirely possible and teams do it well. What they underestimate is the ratio: routing, the interesting part, is perhaps a fifth of the work. The rest is idempotency, per-provider error classification, a signature scheme for each provider, state machines that agree with each other, reconciliation, and then maintaining all of it as every provider changes their API on their own schedule.
The honest test is not technical. Build it when your routing logic is genuinely unusual, or when payments are the product. Buy it when payments are critical to the business but are not the business — the comparison in orchestration versus a single gateway is the same decision framed by cost rather than by capability, and the limits of a single payment processor covers what you are carrying while you decide.
One trend raises the stakes on all of it. Software that pays on a user's behalf retries instantly and identically rather than hesitating the way a person does, which turns a tolerable weakness in a payment layer into a visible one — the risks of letting AI agents make payments.
How PaymentHood fits
PaymentHood is the payments half of the boundary above, delivered as one integration. Your product talks to one API — or a free plugin if you are on WooCommerce, WHMCS or Joomla — and 30+ providers sit behind it, with routing, failover, idempotency, webhook verification and reconciliation handled once rather than once per provider. Every provider account stays contracted in your own name and funds settle directly to you; PaymentHood is not a processor, an acquirer or a merchant of record, and takes no percentage and no per-transaction fee at any volume.
What it does not do is the other half. No metering, no plans, no proration, no invoices, no dunning, no tax. Keep your billing engine. This layer goes underneath it.
Put the payment layer somewhere you can change it
Create a free account, connect the providers you already use, and take a payment. Your billing stack does not move.
Route Across
One integration, every provider
Global, regional and crypto providers, activated from a dashboard rather than added in code.