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.
Reconciliation: the job that only exists once there are two
With one provider, reconciliation is barely a task. The provider's dashboard is the ledger, its settlement report is the source of truth, and finance works directly from it. The moment a second provider takes real money that arrangement quietly stops working, and the failure is not loud enough to force anyone to fix it.
Each provider reports in its own shape: different field names for the same amount, different treatment of fees — deducted per transaction by some, netted at payout by others — different timing between capture and settlement, different currencies at different conversion points, and different identifiers for what your system considers one order. None of these are errors. They are simply not the same schema, and nothing reconciles them by default.
What happens in practice is a monthly spreadsheet merge that someone owns personally, takes a day, and gets less reliable as volume grows. Refunds and chargebacks land in it late and out of order. The question "what did we take yesterday, net of fees, across everything" becomes a research project rather than a query, and the answer arrives too slowly to act on.
The architectural fix is to normalise at the point of capture rather than at the point of reporting. Every transaction gets one internal identity and one internal shape when it happens, whichever provider handled it, and the provider's own reference is stored alongside rather than instead. Reconciliation then becomes a comparison between two records that already describe the same thing, instead of an attempt to reconstruct that relationship a month later from two reports that were never designed to be compared.
One gateway, two gateways, or a layer: an honest comparison
There are three arrangements in common use, and the middle one is the one most teams end up in by accident rather than by choice.
A single gateway is the right answer far more often than the payments industry likes to admit. One integration, one dashboard, one settlement report, one support relationship, one set of webhooks to verify. If you sell in one country, in one currency, and your volume is small enough that a provider outage is an annoying afternoon rather than a material loss, adding anything to this is cost without benefit. The honest test is whether you have already written a conditional in your checkout that chooses between providers — if not, you probably do not need a layer yet.
Two gateways wired in directly is where the trouble starts, because it looks like the cheap version of the third option and behaves like the expensive one. Each provider brings its own SDK, its own webhook format and signature scheme, its own error vocabulary, and its own idea of what an order identifier is. The routing decision ends up in application code, so changing it is a deployment. The two reconciliations are done by hand. Nothing is shared, so every fix has to be made twice, and the second implementation is always the less careful one because it was written under deadline to unblock a market.
An orchestration layer is the same set of providers with the shared concerns extracted: one interface for your application, routing as configuration, one webhook verification path, one idempotency scheme, one normalised ledger. The cost is a dependency between your checkout and something else, plus a small amount of latency, plus the discipline of not putting business logic in two places.
The choice between the second and third is not really about features — anything a layer does can be built. It is about where the work accumulates. Direct integrations put a fixed cost on every provider you will ever add, forever; a layer pays that cost once and makes the next provider approximately free. That trade only makes sense if there will be a next provider, which is why the honest recommendation for a single-market business is to stay where you are. The comparison in full, including when not to move, is in orchestration versus a single gateway.
Scope: the cheapest security decision available
The most effective thing a payment layer can do about card data security is never receive any. If card details go from the customer's browser to the provider directly — through a hosted field, a redirect or a provider-hosted checkout — and what comes back to you is a token, then the sensitive data never touches your servers, never enters your logs, never appears in a database backup and never sits in an error tracker.
This is worth stating as architecture rather than compliance, because it changes what a breach of your systems can cost. A token is bound to one provider and one merchant, so an attacker who takes your whole database has taken a set of references that are worthless anywhere else. The alternative — accepting raw card numbers to feel in control of the checkout experience — pulls your entire application into the compliance scope of the card networks and turns every server that has ever touched the request into something you must defend at a much higher standard.
The related design point is where tokens live. A token issued by a provider belongs to that provider, which has a consequence people meet at the worst moment: it does not transfer. Switching providers does not move stored payment methods with you, and a failover that reroutes a payment cannot reuse the first provider's token at the second. Plan for that before it is urgent, rather than discovering it during a migration. What PCI scope actually means covers the compliance side in plain terms.
Testing a payment layer without taking real money
Payment code is unusually hard to test well, because the interesting paths are the ones that are inconvenient to produce. Everyone tests a successful card. Almost nobody tests the timeout, and the timeout is where the double charges live.
Provider sandboxes cover the first category well: specific test cards produce specific declines, so hard declines, soft declines and expired cards are all straightforward to exercise. What sandboxes generally will not do is fail in the ways that actually break systems — hang and never respond, accept a charge and never deliver the webhook, deliver the same webhook three times, or deliver events out of order. Those have to be simulated at your own boundary.
Four tests are worth having before a payment layer carries meaningful volume: send the same webhook twice and confirm one effect; kill the connection mid-charge and confirm the system reaches a resolved state without a second charge; deliver a webhook out of order and confirm an order never moves backwards from paid to pending; and send a webhook with a deliberately invalid signature and confirm it is rejected rather than logged and processed. Each one takes an afternoon and each corresponds to an incident that is otherwise inevitable. There is a broader pre-launch list in test your checkout before you go live.
The states a payment can be in, and the one that hurts
Most payment bugs are not arithmetic. They are a system that models fewer states than reality contains. The comfortable model has two: a payment succeeded, or it failed. Real payments have at least four, and the fourth is the one that produces the support tickets.
Succeeded and failed are answers — the provider told you something definite, and you can act on it. Pending is also an answer: the provider has accepted the payment and will resolve it later, which is normal for bank transfers and several local methods, and requires only that your system can wait without treating the delay as a failure.
Unknown is not an answer. A request timed out, a connection reset, a response never arrived. The charge may have succeeded, may have failed, or may still be in flight, and no amount of inspection at your end will tell you which. A system that has no representation for this state must map it onto one of the other three, and both choices are wrong: call it failed and you may retry a payment that already went through; call it succeeded and you may deliver goods nobody paid for.
This single omission is the root of most double charges. It is also why idempotency and server-side confirmation are not two separate features but two halves of the same answer: the key lets you ask again safely, and the confirmation is how you find out what actually happened. A payment layer that models "unknown" explicitly, and resolves it by asking the provider rather than guessing, avoids an entire class of incident that otherwise recurs forever.
When each job actually becomes necessary
None of this needs to exist on day one, and building it all before you have customers is its own mistake. The jobs arrive in a fairly predictable order, and the useful skill is recognising which one you have just reached rather than either building ahead or discovering it during an incident.
One provider, one market. Verification matters immediately — trusting the redirect is wrong on day one, not at scale — and idempotency costs almost nothing to add while there is one code path. Everything else is premature.
The first signup form with a cheap plan. Risk controls become urgent faster than anything else on this list, usually within days of the form being findable.
The second market. Routing appears, whether or not you call it that. The
moment a currency or country decides which provider should take a payment, that decision
exists somewhere — the only question is whether it is a rule you can change or an
if statement in a checkout controller.
The second provider taking real money. Reconciliation starts the same day and is usually noticed a quarter later. Failover becomes possible for the first time, and worth building before the outage rather than during it.
Recurring revenue. Every unattended charge multiplies the cost of every weakness above, because there is nobody present to retry, re-enter a card, or notice that something failed. This is where a payment layer that was adequate becomes the constraint.
Evaluating what you already have
Nine questions, answerable in an afternoon by whoever owns the checkout. They are ordered so that a "no" early on matters more than a "no" late.
- Is an order marked paid only after your server independently confirms the capture with the provider — never because a browser reached a success URL?
- Is every inbound webhook signature verified before the payload is trusted, for every provider, in one place rather than once per integration?
- Does every charge carry an idempotency key derived from the order and attempt, so a timeout followed by a retry cannot create a second payment?
- Does your system have a state for "we do not know what happened", and a process that resolves it by asking the provider rather than assuming?
- If your primary provider stopped accepting payments for six hours, how long would it take to route around it — and has that path ever run?
- Is the decision about which provider takes a payment configuration you can change, or is it compiled into your checkout?
- Can you answer "what did we take yesterday, net of fees, across every provider" without exporting anything?
- Do you know your approval rate split by country, method and first-payment versus renewal — rather than as one blended number?
- Are there limits on payment attempts, distinct cards and repeated failures per customer, and do they act automatically?
The first four are correctness: a "no" there is a bug waiting for traffic, regardless of size. The middle three are resilience and become urgent at the second provider. The last two are visibility — the ones that decide whether you find problems yourself or hear about them from customers. A longer version, with what to do about each answer, is the payment infrastructure readiness checklist.
Where this lands in practice
The jobs above are the same everywhere, but the order in which they become urgent is not. A business whose revenue is mostly unattended renewals meets them years before a one-off retail checkout does, because there is nobody present to retry a failed charge and nobody to notice when one quietly stops working. That is the whole reason payments for hosting and web companies reads differently from general e-commerce advice.
One term is worth pinning down before going further, because it is used loosely and covers several of the jobs on this page at once: what payment orchestration is defines it, and the rest of this page describes the work it names.
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.