- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
What Happens After You Click "Pay": How a Payment Gateway Really Works
About Post
You type your card number, tap "Pay", a spinner turns for a couple of seconds, and a green tick appears. It feels like one step.
It's actually a relay race between at least five parties, two of which you've probably never heard of, and the money hasn't even moved yet when you see that tick.
If you build anything that takes payments (rent, bookings, subscriptions, donations), knowing this relay changes how you write the code. So let's follow one payment from the button to the bank.
Meet the cast
- The customer (cardholder), with a card from their bank.
- The issuer: the customer's bank. It decides yes or no.
- The merchant: you, or your client.
- The acquirer: the merchant's bank, which receives card payments on the merchant's behalf.
- The card network: Visa, Mastercard and friends, routing messages between acquirers and issuers.
- The payment gateway: the service your code actually talks to. It wraps everything above in an API, and often acts as the acquirer side too.
Your app only ever speaks to the gateway. Everything else happens behind it.
Leg 1: tokenization, or "never touch the card"
The first rule of modern payments: the card number should never reach your server.
Instead, the card form is provided by the gateway: a hosted payment page you redirect to, or fields embedded in your page that are really served from the gateway's domain. The customer types the card details into the gateway's fields. The gateway stores them and hands your frontend a token: a meaningless reference like tok_8fa2... that only that gateway, for your account, can turn back into a card.
Think of a coat check. You hand over the coat and get a numbered ticket. The ticket is useless to a thief who doesn't also have access to that cloakroom.
This matters because of PCI DSS, the security standard for anyone handling card data. If raw card numbers pass through your servers, your whole system is in scope for it: audits, controls, paperwork. If they only ever touch the gateway's fields, your scope shrinks dramatically. Hosted fields aren't a design preference; they're the cheapest security decision you'll ever make.
Leg 2: authorization, the "yes, probably"
Your server sends the token and the amount to the gateway. The gateway passes an authorization request through the acquirer and card network to the issuer, which checks a few things in a fraction of a second: is the card valid, is there enough available balance or credit, does this look like fraud?
Sometimes the issuer wants proof it's really the cardholder, which is where 3-D Secure comes in: the "confirm in your banking app" or one-time code step. Your integration has to handle that extra round trip, which is why modern gateway APIs model a payment as something with states rather than a single call that returns success or failure.
If approved, the issuer places a hold on the amount. The customer sees it as pending. No money has moved. The issuer has only promised it.
Leg 3: capture, the "yes, take it"
Capture tells the gateway to actually collect the authorized amount. Most online shops authorize and capture in one go, and you never notice two steps.
Splitting them is useful when the final amount or the delivery isn't certain yet. Hotels and car rentals are the classic example: authorize at booking, capture at checkout. You can usually capture less than you authorized, but not more. And authorizations don't last forever: if you don't capture within the window your gateway and the card network allow, the hold drops and you have to authorize again.
Leg 4: settlement, the slow part
Captured payments are batched and settled between the banks, and the money lands in the merchant's account later, typically after a few business days, minus fees. This is why "payment succeeded" and "money in the bank" are two different events, and why finance teams reconcile payouts against transactions rather than trusting the app's dashboard.
Leg 5: webhooks, the source of truth
Here's the part that bites developers. After 3-D Secure or a hosted payment page, the customer is redirected back to your site with something like ?status=success. It's tempting to mark the invoice as paid right there.
Don't. Customers close tabs, lose signal, or never get redirected back at all. And a redirect URL is something anyone can type.
The golden rule: the redirect is for the user interface. The webhook is for your database. Mark things as paid when the gateway tells you so, server to server, with a verified signature.
A webhook is the gateway calling your endpoint: "payment succeeded", "payment failed", "refund completed", "dispute opened". Treat these events with care:
- Verify the signature on every webhook, so nobody can fake a "payment succeeded".
- Expect duplicates. Gateways retry until you respond with success, so the same event can arrive twice. Store the event ID with a unique constraint.
- Expect odd ordering. Events can arrive out of order. When in doubt, fetch the payment's current state from the gateway's API.
- Respond fast, process later. Save the event, return 200, and do the real work in a queued job.
Leg 6: refunds and disputes
A refund isn't "undoing" the payment. It's a new transaction in the opposite direction, linked to the original, and it can be partial. It also takes time to show up on the customer's statement, which is worth telling them in the UI so they don't contact support the next morning.
A dispute (chargeback) is different: the customer asks their bank to reverse the charge. The money is pulled back while the case is reviewed, and the merchant submits evidence. Your system should record disputes as their own state, not quietly flip a payment back to "unpaid".
What this means for your code
| Payment fact | Design decision |
|---|---|
| Card data is toxic | Hosted page or hosted fields; store only tokens and references |
| Payments have states | Model pending, requires_action, authorized, captured, refunded, disputed |
| Clients retry | Idempotency keys on payment creation |
| Redirects lie | Webhooks update the database |
| Events repeat | Unique event IDs, idempotent handlers |
| Money settles later | Reconcile payouts, don't assume |
Also store amounts as integers in the smallest currency unit (or as exact decimals), never as floats, and always store the currency next to the amount.
The two-second summary
Token instead of card. Authorization is a promise. Capture is the claim. Settlement is the money. Webhooks are the truth. Refunds are new transactions.
Next time you see that green tick, you'll know it's the start of the process, not the end.
Which part of payment integrations caught you out first: webhooks, 3-D Secure, refunds, or reconciliation?

Be first to comment it...