The Two-Layer System You Need to Understand
Visa doesn't work the way most developers think. There isn't one API call that moves money. There are two distinct phases, and they happen at different times:
- Authorization — happens in real time. The cardholder taps or enters their card, and within seconds, the issuing bank approves or declines. Money is held, not moved.
- Settlement (Base II) — happens later, usually in batches. This is when money actually moves between banks through VisaNet. It can take 1-3 business days.
This matters because your app might show "payment successful" after authorization, but the merchant doesn't have the money yet. And sometimes, a transaction that was authorized never settles — or settles for a different amount (think restaurant tips or hotel holds).
Real-world gotcha: I've seen cases where a Visa authorization was approved, then reversed, but a Base II settlement still came through days later. The customer got charged twice. Your reconciliation system needs to handle this.
Choosing Your Integration Path
You have three main options, and the right one depends on your scale and compliance appetite:
1. Payment Service Provider (PSP)
Stripe, Adyen, Braintree — they handle the Visa integration for you. You call their API, they talk to Visa. This is the right choice for 90% of companies.
// Stripe example — this is all you need
const paymentIntent = await stripe.paymentIntents.create({
amount: 2000, // $20.00 in cents
currency: 'usd',
payment_method_types: ['card'],
});
Pros: fast to integrate, PCI compliance is mostly handled, fraud tools included. Cons: per-transaction fees add up at scale, less control over the authorization flow.
2. Payment Processor Direct Integration
Companies like Worldpay, FIS, or Fiserv give you closer access to the card networks. You get more control over authorization parameters, but you take on more PCI scope.
3. Direct Visa Integration (VisaNet)
Only for large issuers and processors. You're talking ISO 8583 message formats, dedicated network connections, and a certification process that takes months. Unless you're building a bank, skip this.
The Authorization Flow in Detail
Here's what actually happens when a user pays with their Visa card in your app:
Stripe, Adyen
Approve/Decline
- Your app collects card details (or a token) and sends them to your PSP
- The PSP formats an authorization request and routes it to the acquirer
- The acquirer sends it through VisaNet to the issuing bank
- The issuer checks: valid card? Sufficient funds? Fraud signals? Then approves or declines
- The response travels back the same path with a response code
The whole thing takes 1-3 seconds. The response code tells you what happened:
// Common Visa response codes
00 — Approved
05 — Do not honor (generic decline)
14 — Invalid card number
51 — Insufficient funds
61 — Exceeds withdrawal limit
65 — Exceeds withdrawal frequency
Tip: Don't show raw response codes to users. Map them to friendly messages. "Insufficient funds" becomes "Your card was declined. Please try a different payment method." Never reveal the specific reason — it's a security risk.
Tokenization — Stop Storing Card Numbers
If you're storing raw card numbers, stop. Visa Token Service (VTS) replaces the actual PAN (Primary Account Number) with a token that's useless if stolen.
There are two types of tokens you'll encounter:
- PSP tokens — Stripe's
pm_xxxor Adyen'sstoredPaymentMethod. These are proprietary to the PSP. - Network tokens — issued by Visa directly. These survive if you switch PSPs, and they get better authorization rates (issuers trust them more).
Network tokens also handle card-on-file updates automatically. When a customer's card expires and their bank issues a new one, the network token stays valid. No more failed recurring payments because of expired cards.
Handling Refunds and Disputes
Refunds in the Visa world aren't instant. Here's the timeline:
- Void — if the transaction hasn't settled yet, you can void the authorization. The hold drops off the customer's account in 1-3 days. This is free.
- Refund — if the transaction has settled, you issue a refund. This creates a new transaction going the other direction. Takes 5-10 business days to appear on the customer's statement.
- Chargeback — the customer disputes the charge with their bank. You have a limited window (usually 30 days) to respond with evidence. Chargebacks cost you a fee regardless of outcome.
PCI DSS — The Compliance Reality
If you touch card data, you need PCI DSS compliance. The level depends on how you integrate:
- SAQ A — you use a hosted payment page (Stripe Checkout, Adyen Drop-in). Easiest. ~20 questions.
- SAQ A-EP — you use client-side tokenization (Stripe Elements). Card data hits your frontend but not your server. ~140 questions.
- SAQ D — card data touches your server. Full audit. 300+ requirements. Avoid this unless you have a dedicated security team.
Five Things I Learned the Hard Way
- Always implement idempotency keys. Network timeouts happen. Without idempotency, a retry can charge the customer twice.
- Build reconciliation from day one. Compare your records against the PSP's settlement reports daily. Discrepancies compound fast.
- Test with real card networks in sandbox. Stripe's test mode doesn't simulate all Visa-specific behaviors. Use their "test clocks" for subscription edge cases.
- Handle partial authorizations. Some issuers approve a lower amount than requested. Your app needs to handle this gracefully — either accept the partial amount or void and ask for a different card.
- Monitor authorization rates. A drop in auth rate is the canary in the coal mine. It could mean your MCC is wrong, your fraud rules are too aggressive, or an issuer is blocking you.
Getting Started
If you're building a new payment integration, start with a PSP like Stripe or Adyen. Get your basic flow working — authorization, capture, refund. Then layer on complexity: webhooks for async events, reconciliation for settlement, and monitoring for auth rates.
The payment space rewards boring, reliable engineering over clever hacks. Build it right the first time, because debugging payment issues in production — with real money on the line — is not where you want to be learning.
References
- Visa Developer Center — Visa Direct Documentation
- Visa Core Rules and Visa Product and Service Rules
- PCI Security Standards Council — Document Library
- Stripe Documentation — Payment Intents API
- ISO 8583 — Financial Transaction Card Originated Messages
Disclaimer: This article reflects the author's personal experience and opinions. Product names, logos, and brands are property of their respective owners. Pricing and features mentioned are subject to change — always verify with official documentation.