PAYMENT GATEWAY

By Himanshu Shekhar | 12 Sep 2022 | (0 Reviews)

Suggest Improvement on Payment Gateway Integration Basics β€” Click here



Module 00 : Payment Gateway Introduction & Foundation

This module provides a complete foundation of payment gateway systems, how online payments work, the payment ecosystem, and key terminology. Understanding payment gateways is essential for developers, security testers, and merchants to ensure secure and reliable financial transactions.


0.1 What is a Payment Gateway?

A Payment Gateway is a technology service that securely transmits payment information between a customer, the merchant's website, and the bank (or payment processor). It acts as a digital β€œpoint‑of‑sale” terminal for online transactions, encrypting sensitive card data and ensuring secure communication.

In simple words, when a customer enters their credit card details on a shopping website, the payment gateway collects that information, sends it to the acquiring bank in a secure format, and returns a response (approved or declined) so the merchant can either confirm or cancel the order.

πŸ” Key Functions
  • Encryption: Protects cardholder data using TLS/SSL and often PCI‑compliant tokenisation.
  • Routing: Directs the transaction to the appropriate card network (Visa, Mastercard, etc.).
  • Authorization: Requests approval from the issuing bank.
  • Notification: Sends approval/decline back to the merchant website.
  • Settlement: Transfers funds from the customer’s bank to the merchant’s account.
🧠 Real World Examples
  • Stripe, PayPal, Razorpay, Square, Authorize.Net
  • Paytm Payment Gateway, CC Avenue, PayU
  • Amazon Pay, Google Pay for merchants
πŸ’‘ Payment gateways are not banks – they facilitate the connection between merchants, customers, and financial institutions.
βœ… Key Takeaway: The payment gateway is the critical middleman that securely moves money from customer to merchant online.

0.2 How Online Payments Work (Step‑by‑Step)

An online payment involves multiple parties and a series of secure messages. Below is the typical flow for a card‑based transaction. Understanding each step helps identify where security breaches can happen.

  1. Customer initiates purchase: Adds items to cart and clicks β€œCheckout”.
  2. Enters payment details: Fills in card number, expiry, CVV, and billing address on the merchant’s site.
  3. Browser sends encrypted data: Data is encrypted using TLS and sent to the merchant’s server (or directly to the gateway via API).
  4. Merchant forwards to payment gateway: The merchant’s server sends the payment data to the gateway (Stripe, Razorpay, etc.).
  5. Gateway validates and routes: The gateway checks for fraud, tokenises the card if needed, and sends the request to the acquiring bank / processor.
  6. Processor contacts card network: Acquirer sends the request to the card network (Visa/Mastercard).
  7. Card network forwards to issuing bank: The customer’s bank receives the request, checks funds/validity, and records the transaction.
  8. Authorization response travels back: Approve/decline message goes back through the chain (issuer β†’ network β†’ acquirer β†’ gateway β†’ merchant).
  9. Merchant displays result: The website shows β€œPayment Successful” or β€œDeclined”.
  10. Settlement (later): Funds move from issuing bank to acquiring bank to merchant account (usually after 2‑3 days).
πŸ’‘ Diagram in text:
Customer β†’ Merchant β†’ Gateway β†’ Acquirer β†’ Card Network β†’ Issuer β†’ (response reverse)
⚠️ Each step is a potential security gap – encryption, firewalls, PCI DSS compliance, and tokenisation are essential.
βœ… Key Takeaway: Online payments involve a chain of trust – if any link is broken, fraud can occur.

0.3 Payment Gateway vs Payment Processor (Key Differences)

Though often used interchangeably, a payment gateway and a payment processor serve different roles. A gateway transmits payment data; a processor settles the funds.

AspectPayment GatewayPayment Processor
Role--Authorisation & communicationSettlement & fund movement
Action--Encrypts and routes transactionTransfers money between banks
When used--During checkout (real‑time)After approval (batch settlement)
Example companies--Stripe, Braintree, Razorpay (they often act as both)First Data, Worldpay, Fiserv

Many modern providers (like Stripe, Razorpay) offer both gateway and processing services, so the distinction blurs.

βœ… Key Takeaway: Gateway = secure message delivery; Processor = actual money movement.

0.4 Payment Ecosystem – Who is Involved?

The payment ecosystem includes several entities, each with specific responsibilities. Understanding them helps identify attack surfaces and compliance requirements.

πŸ”Ή Core Players
  • Customer (Cardholder): The person buying a product/service.
  • Merchant: The business selling products.
  • Issuing Bank: The customer’s bank that issued the credit/debit card.
  • Acquiring Bank (Acquirer): The merchant’s bank that receives the money.
  • Card Networks (Schemes): Visa, Mastercard, American Express, RuPay, etc. – set rules and route transactions.
  • Payment Gateway: Technology interface for transmitting data.
  • Payment Processor: Entity that handles settlement and sometimes gateway services.
πŸ”Έ Additional Entities
  • Payment Service Provider (PSP): All‑in‑one gateway + merchant account (e.g., Stripe).
  • Independent Sales Organisation (ISO): Reseller of merchant services.
  • Payment Facilitator (PayFac): Sub‑merchant onboarding (e.g., Square).
  • Third‑Party Security Assessors (QSA): Auditors for PCI compliance.
πŸ’‘ For security testing, focus on the gateway, processor, merchant server, and issuer – they are the most targeted.
βœ… Key Takeaway: A single transaction touches many entities – each is a potential vulnerability point.

0.5 Merchant Accounts & Settlements

A merchant account is a special bank account that allows businesses to accept credit/debit card payments. Settlement is the process of moving funds from the customer’s bank to the merchant’s account.

πŸ“Œ Types of Merchant Accounts
  • Dedicated Merchant Account: Owned by one business – better rates, longer approval.
  • Aggregated Account (PayFac): Shared account (Stripe, Square) – fast setup, higher fees.
  • Third‑Party Processor: A service that provides both gateway and merchant account.
πŸ’° Settlement Flow
  1. Transaction authorised – customer’s funds are reserved.
  2. Capture – merchant initiates capture (or auto‑capture after shipping).
  3. Batch settlement – at end of day, all captured transactions are sent as a batch.
  4. Funding – funds appear in merchant account after 1‑3 business days (including fees deduction).
⚠️ Settlement delays create risk – chargebacks can happen after funds are already transferred.
βœ… Key Takeaway: Merchant accounts are the destination of funds – compromising them leads to direct financial loss.

0.6 Payment Flow Architecture (API‑based & Hosted)

Payment gateways offer different integration methods. The architecture affects security responsibilities and PCI DSS scope.

🏷️ Hosted / Redirect

Customer is redirected to the gateway’s payment page (e.g., PayPal).

  • βœ… Minimal PCI burden (merchant never touches card data).
  • ❌ Less customisation.
  • ❌ Customer leaves your site.
🧩 JavaScript / Tokenisation (iFrame)

Gateway provides a JavaScript library that collects card data directly (Stripe Elements, Razorpay).

  • βœ… Card data never touches your server.
  • βœ… High customisation.
  • ❌ Requires handling webhooks.
βš™οΈ Direct API (Server‑to‑Server)

Merchant collects card data and sends it to gateway via API.

  • ❌ High PCI compliance burden (SAQ D).
  • βœ… Complete control.
  • ❌ Risk of storing/transmitting card data insecurely.

Modern best practice is tokenisation / iFrame – it balances security and user experience.

πŸ’‘ Most penetration tests on payment gateways focus on API integration (webhooks, signature validation) and client‑side tokenisation.
βœ… Key Takeaway: The integration method determines your PCI DSS scope and security responsibilities.

0.7 Types of Online Payments (Use Cases)

Payment gateways support different transaction types depending on the business model.

TypeDescriptionExample
One‑time payment--Single charge for a product/service.Buying a laptop.
Recurring (Subscription)--Charged automatically at intervals.Netflix, Spotify.
Authorisation & Capture--Authorise amount then capture later (e.g., after shipping).Hotel booking, pre‑order.
MOTO (Mail Order / Telephone Order)--Card details taken over phone/email.Call‑centre orders.
Tokenised payments--Use a token instead of card number for repeat purchases.Saved cards in Uber.
Refunds / Voids--Reverse a transaction (full or partial).Customer returns item.
🚨 Recurring payments require extra security – stored tokens must be protected, and customers need easy cancellation.
βœ… Key Takeaway: Different transaction types have different security requirements (e.g., CVV is often not stored for recurring).

0.8 UPI, Cards, Wallets & Net Banking (Popular Methods)

Modern gateways support multiple payment instruments. Each has a different security model.

MethodHow It WorksAuthenticationSecurity Note
Credit/Debit CardCard number, expiry, CVV, sometimes 3D Secure (OTP).OTP or passwordHigh fraud risk if card details leaked.
UPI (Unified Payments Interface)Virtual ID (user@bank) + UPI PIN or biometric.Mobile‑based PIN / device bindingRelatively secure, but device cloning is a risk.
Digital Wallets (PayTM, Google Pay, Apple Pay)Stored payment methods, tokenised transactions.Biometrics, PIN, device unlockTokenisation reduces exposure of actual card details.
Net BankingRedirect to bank login page, authenticate with credentials + OTP.Password + OTP / hardware tokenVulnerable to phishing and MITM if not properly validated.
Buy Now, Pay Later (BNPL)Short‑term credit (Klarna, Afterpay).Soft credit check + identity verificationRisk of identity theft.
πŸ’‘ UPI has become the dominant payment method in India due to its ease and direct bank integration.
βœ… Key Takeaway: Different payment instruments have different attack surfaces – test each integration separately.

0.9 Sandbox vs Production Environment (Testing vs Live)

Every payment gateway provides a sandbox (test) environment that mimics the live system but uses test credentials, test card numbers, and does not move real money.

🟒 Sandbox (Test)
  • Use test API keys.
  • Simulate all transaction responses (approve, decline, error).
  • No real money deducted.
  • Use test card numbers (e.g., 4242 4242 4242 4242 for Stripe).
  • Safe for development and automated testing.
πŸ”΄ Production (Live)
  • Use live API keys (must be kept secret).
  • Real money moves.
  • Requires PCI DSS compliance.
  • Logging must avoid PAN.
  • Webhook URLs must be secure (HTTPS, signature validation).
⚠️ Never use live keys during development or testing – you could accidentally charge real customers.
βœ… Key Takeaway: Always test thoroughly in sandbox before switching to production – and rotate keys after go‑live.

0.10 Common Payment Terminology – Glossary

Familiarise yourself with these terms – they appear in every payment integration and security assessment.

  • PAN: Primary Account Number (full card number).
  • CVV/CVC: Card verification value (3 or 4 digits).
  • Tokenisation: Replace PAN with a non‑sensitive token.
  • 3D Secure: Extra authentication step (OTP/password) for cards.
  • PCI DSS: Payment Card Industry Data Security Standard.
  • Acquirer: Merchant’s bank.
  • Issuer: Customer’s bank.
  • Authorisation: Freezing funds (not yet transferred).
  • Capture: Transferring authorised funds.
  • Settlement: Final movement of funds.
  • Chargeback: Customer disputes a transaction.
  • Refund: Return of funds to customer (reverse transaction).
  • Webhook: HTTP callback from gateway to merchant for async events.
  • Recurring Billing: Scheduled automatic payments.
  • MOTO: Mail Order / Telephone Order (card not present).
  • ISO 8583: Standard for financial transaction messages.
πŸ’‘ For penetration testers, focus on tokenisation, webhook security, and 3D Secure bypass tests.
βœ… Key Takeaway: Mastering the terminology allows you to read API documentation and identify weak spots faster.

πŸŽ“ Module 00 : Payment Gateway Introduction & Foundation – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 01 : Payment Gateway Core APIs

This module dives deep into the core APIs of payment gateways – REST fundamentals, authentication, webhooks, signature verification, and transaction management. Mastering these APIs is essential for developers integrating payment systems and for security testers auditing payment flows.


1.1 REST API Fundamentals

Most modern payment gateways (Stripe, Razorpay, PayPal) expose a RESTful API that allows merchants to programmatically create payments, refunds, manage customers, and handle webhooks.

πŸ”Ή Core REST Concepts
  • Resources: Objects like payments, refunds, customers, subscriptions.
  • HTTP Methods: GET (retrieve), POST (create), PUT/PATCH (update), DELETE.
  • Statelessness: Each request contains all necessary information; server does not store client context.
  • JSON: Most gateways use JSON for requests and responses.
πŸ”Έ Typical Payment API Endpoints
  • POST /v1/payments – Create a payment.
  • GET /v1/payments/{id} – Retrieve a payment.
  • POST /v1/payments/{id}/refunds – Refund a payment.
  • GET /v1/refunds/{id} – Check refund status.
  • POST /v1/webhooks – Configure webhook endpoints.
πŸ’‘ REST APIs are preferred over SOAP because they are lightweight, use standard HTTP, and are easier to test.
βœ… Key Takeaway: Understanding REST methods and status codes (200, 400, 401, 500) is critical for debugging and security testing.

1.2 API Authentication & Tokens

Payment gateways require authentication to ensure only authorised merchants can access APIs. Common methods include API keys, OAuth2, and JWT (JSON Web Tokens).

MethodHow it worksSecurity LevelExamples
API Key (Basic Auth)--Key sent as username:password in Authorization header. Medium – risk if sent over HTTP (must use TLS). Stripe (sk_live_...), Razorpay (rzp_live_...).
Bearer Token (OAuth2)--Short-lived token obtained via client credentials or user authorisation. High – tokens can be scoped and rotated. PayPal, Braintree.
JWT (JSON Web Tokens)--Signed token containing claims; verified by gateway. High if signature algorithm is strong (HS256/RS256). Some custom integrations.
# Example: API Key in curl
curl -X GET https://api.paymentgateway.com/v1/payments \
  -H "Authorization: Basic base64(publishable_key:secret_key)"

# Bearer token
curl -X GET https://api.paymentgateway.com/v1/payments \
  -H "Authorization: Bearer sk_live_abc123"
⚠️ Never hard‑code API keys in client‑side code (mobile apps, frontend JavaScript). Use environment variables and server‑side proxies.
βœ… Key Takeaway: Strong authentication prevents unauthorised API calls – always use TLS and rotate keys periodically.

1.3 API Keys & Secret Keys (Publishable vs Secret)

Payment gateways typically provide two types of keys: a publishable key (client‑side) and a secret key (server‑side). Mixing them up leads to security breaches.

πŸ”‘ Publishable Key
  • Used in client‑side code (web/mobile).
  • Can only create tokens (PCI‑safe) – cannot charge or refund.
  • Example: pk_live_4eC39HqLyjWDarjtT (Stripe).
  • Safe to embed in HTML/JavaScript.
🀫 Secret Key
  • Never exposed to the client – kept on the server.
  • Can perform any operation (create payment, refund, manage webhooks).
  • Example: sk_live_4eC39HqLyjWDarjtT (Stripe).
  • Compromise = full account takeover.
# Correct usage (server‑side Node.js)
const stripe = require('stripe')('sk_live_...'); // secret key

# Incorrect (exposing secret key in frontend JS)
const stripe = Stripe('sk_live_...'); // DANGEROUS!
🚨 Critical: If a secret key is leaked, rotate it immediately and revoke the old one. Monitor for unauthorised charges.
βœ… Key Takeaway: Keep secret keys out of version control, use environment variables, and restrict IPs where possible.

1.4 JSON Requests & Responses

Payment APIs use JSON (JavaScript Object Notation) for data exchange. Understanding the structure helps in integration and security testing.

πŸ“€ Create Payment Request (example – Razorpay style)
POST /v1/payments HTTP/1.1
Host: api.razorpay.com
Authorization: Basic base64(key:secret)
Content-Type: application/json

{
    "amount": 1000,          // β‚Ή10.00 (in paise)
    "currency": "INR",
    "receipt": "order_123",
    "payment_capture": 1,
    "notes": {
        "customer_email": "user@example.com"
    }
}
πŸ“₯ Success Response
{
    "id": "pay_abc123",
    "entity": "payment",
    "amount": 1000,
    "currency": "INR",
    "status": "captured",
    "method": "card",
    "created_at": 1612345678
}
πŸ’‘ Always validate the response structure – amount, currency, status, and signature (if present) before updating your database.
βœ… Key Takeaway: JSON schemas are often versioned – always refer to the latest API documentation.

1.5 Webhooks & Event Handling

Webhooks are asynchronous HTTP callbacks that notify your server when an event occurs (e.g., payment success, refund processed). They are essential for real‑time order updates, especially when the user is not on the website.

πŸ“‘ How a Webhook Works
  1. Merchant registers a webhook URL (e.g., https://shop.com/webhook) in the gateway dashboard.
  2. When a payment succeeds, the gateway sends a POST request to that URL with a JSON payload.
  3. Your server processes the payload and updates the order status.
πŸ” Security for Webhooks
  • Signature verification: Gateways sign webhook payloads with a secret. Verify the signature before processing (prevents fake events).
  • Idempotency: Webhooks may be retried – ensure your handler can process duplicates safely.
  • Authentication: Require a custom header or use the signature for authentication.
  • Logging: Log all incoming webhooks for auditing and debugging.
# Example webhook receiver (Node.js/Express)
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
    const sig = req.headers['x-razorpay-signature'];
    const webhookSecret = process.env.WEBHOOK_SECRET;
    try {
        const event = razorpay.validateWebhookSignature(req.body, sig, webhookSecret);
        if (event.event === 'payment.captured') {
            // Update order
        }
        res.status(200).send('OK');
    } catch (err) {
        res.status(400).send('Invalid signature');
    }
});
⚠️ Failing to verify webhook signatures makes your server vulnerable to forged payment success events.
βœ… Key Takeaway: Treat webhooks as untrusted – verify signatures, check idempotency, and never rely solely on webhook for critical logic (use API fallback).

1.6 Callback URLs & Redirects (Synchronous)

While webhooks are asynchronous, many gateways also support redirect‑based callbacks for hosted payment pages. After payment, the customer is redirected back to your site with payment status in the URL (GET parameters).

πŸ”„ Typical Redirect Flow
  1. Customer clicks β€œPay” and is sent to gateway’s hosted page.
  2. After payment, gateway redirects to return_url (e.g., https://shop.com/return) with parameters like payment_id, order_id, status.
  3. Merchant validates the data (often using a signature) and updates the order.
⚠️ Security Risks with Redirects
  • Parameter tampering: A user might modify URL parameters (e.g., change status to success).
  • Missing signature: Without signature validation, anyone can fake a success callback.
  • Open redirect: If the merchant does not validate return_url, attackers can redirect customers to phishing sites.
# Example vulnerable redirect handling (DO NOT DO THIS)
if ($_GET['status'] == 'success') {
    $order->paid = true;               // Attacker can craft ?status=success
}
🚨 Never trust redirect parameters alone. Always verify the payment status by calling the gateway’s API or using a signature.
βœ… Key Takeaway: Use webhooks for reliable server‑side updates; redirects are for user experience only – they are not secure evidence.

1.7 Signature Verification (Integrity & Authenticity)

Payment gateways sign webhook payloads and sometimes redirect parameters using a secret key. Verifying the signature proves the data was sent by the gateway and not tampered with.

πŸ” How Signature Verification Works
  1. The gateway generates a hash (HMAC) of the payload using a secret key (webhook secret).
  2. The hash is sent in a header (e.g., X-Razorpay-Signature).
  3. Your server computes the same hash using the payload and its copy of the secret.
  4. If they match, the payload is genuine.
# Python example (Razorpay)
import razorpay
client = razorpay.Client(auth=("key", "secret"))
webhook_secret = "your_webhook_secret"
payload = request.get_data()
signature = request.headers.get('X-Razorpay-Signature')

try:
    client.utility.verify_webhook_signature(payload, signature, webhook_secret)
    # Payment is legitimate
except razorpay.errors.SignatureVerificationError:
    # Reject request
πŸ’‘ Different gateways use different signature algorithms – always follow the official documentation.
βœ… Key Takeaway: Signature verification is the most critical security control for webhooks and callbacks – never skip it.

1.8 Payment Verification Workflow (Best Practices)

A secure payment verification workflow combines synchronous callbacks, webhooks, and API fallbacks to ensure no failed payment is marked successful and no successful payment is lost.

βœ… Recommended Workflow
  1. Create order – Store order details, generate unique order ID.
  2. Initiate payment – Call gateway API to create a payment session (or redirect to hosted page).
  3. After redirect (if used) – Extract payment ID from URL parameters; do NOT rely on status parameter.
  4. Query payment status via API – Call GET /v1/payments/{id} to get authoritative status.
  5. Update order – Only after API confirms captured or paid.
  6. Handle webhooks – Listen to payment.captured events to cover cases where user closes the browser before redirect.
  7. Idempotent processing – Use order ID as idempotency key to prevent double processing.
⚠️ Never rely solely on client‑side notifications or redirect parameters – always verify with server‑to‑server API.
βœ… Key Takeaway: A hybrid approach (webhook + API poll) eliminates single points of failure.

1.9 Transaction Status APIs (GET Payment)

The status API allows you to query a specific transaction by its ID. It returns the most up‑to‑date information including status, amount, method, and failure reason.

Common Status Values
StatusMeaning
createdPayment object created but not yet authorised.
authorized--_:Funds reserved, not captured yet.
captured--_:Funds transferred to merchant – success.
failed--_:Payment declined (insufficient funds, expired card, etc.).
refunded--_:Full refund processed.
# Example GET status API (Stripe)
curl https://api.stripe.com/v1/payments/py_abc123 \
  -u sk_live_...:

# Response
{
  "id": "py_abc123",
  "object": "payment_intent",
  "amount": 2000,
  "status": "succeeded"
}
πŸ’‘ Some gateways provide a β€œretrieve” endpoint for both payments and refunds – always check the documentation.
βœ… Key Takeaway: Use status APIs as the source of truth – they are more reliable than webhooks or redirect parameters.

1.10 Refund APIs (Processing Returns)

Refund APIs allow merchants to return funds to customers partially or fully. They are critical for customer satisfaction but also a vector for fraud if not properly secured.

πŸ“¦ Typical Refund Request
POST /v1/payments/pay_abc123/refunds
Authorization: Basic base64(key:secret)
Content-Type: application/json

{
    "amount": 500,          // refund amount in minor units (paise/cents)
    "reason": "customer_request",
    "notes": {
        "order_id": "order_xyz"
    }
}
πŸ“₯ Refund Response
{
    "id": "ref_abc123",
    "payment_id": "pay_abc123",
    "amount": 500,
    "status": "processed",
    "created_at": 1612345678
}
πŸ”’ Security Considerations
  • Authentication: Only authorised users (admin) should be able to initiate refunds.
  • Idempotency: Use unique refund IDs or idempotency keys to prevent double refunds.
  • Audit logs: Record who initiated refund and why.
  • Partial refunds: Some gateways allow multiple partial refunds – track remaining amount.
  • Webhooks: Listen to refund.created / refund.updated events to sync status.
🚨 A compromised secret key can be used to issue mass refunds, draining merchant funds – protect keys fiercely.
βœ… Key Takeaway: Refund APIs must be protected with strong authentication, idempotency keys, and thorough logging.

πŸŽ“ Module 01 : Payment Gateway Core APIs – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 02 : Payment Gateway Security & Compliance

This module covers the essential security controls and compliance requirements for payment gateway integrations. Topics include HTTPS, PCI-DSS, API key management, webhook security, fraud detection, rate limiting, and secure logging. Implementing these measures protects both merchants and customers from financial fraud and data breaches.


2.1 HTTPS & SSL Certificates (Encryption in Transit)

All communication between the merchant server, payment gateway, and customer browser must be encrypted using TLS (Transport Layer Security). HTTPS protects payment card data, API keys, and webhook payloads from eavesdropping and tampering.

πŸ” Why HTTPS is Mandatory
  • Prevents man‑in‑the‑middle (MITM) attacks.
  • PCI-DSS requirement (all cardholder data transmission).
  • Protects API credentials in transit.
  • User trust – browsers show β€œSecure” lock icon.
⚠️ Common HTTPS Misconfigurations
  • Mixed content (HTTP resources on HTTPS page).
  • Weak cipher suites (RC4, 3DES, export ciphers).
  • Expired or self‑signed certificates.
  • Missing HTTP Strict Transport Security (HSTS).
πŸ›‘οΈ Best Practices
  • Use TLS 1.2 or TLS 1.3 only – disable SSLv2, SSLv3, TLS 1.0, TLS 1.1.
  • Obtain certificates from trusted Certificate Authorities (CA).
  • Enable HSTS (Strict-Transport-Security) to enforce HTTPS for all subdomains.
  • Regularly test with SSL Labs (https://www.ssllabs.com/ssltest/).
# Example HSTS header (Apache)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
🚨 Without HTTPS, an attacker on the same Wi-Fi can intercept API keys and payment data – a critical compliance failure.
βœ… Key Takeaway: HTTPS is the foundation of payment security – all endpoints, including webhooks and redirect URLs, must use TLS.

2.2 PCI-DSS Compliance (Payment Card Industry Data Security Standard)

PCI-DSS is a set of security standards enforced by major card brands (Visa, Mastercard, etc.). Any business that stores, processes, or transmits cardholder data must comply. Non‑compliance can result in heavy fines, increased transaction fees, and loss of ability to accept credit cards.

πŸ“œ Key PCI-DSS Requirements (v3.2.1)
Requirement Description
Build & Maintain Secure Network Configure firewalls properly, use secure system configurations, and avoid default usernames/passwords.
Protect Cardholder Data Encrypt cardholder data during transmission using TLS/HTTPS and never store sensitive authentication data such as CVV or track data.
Maintain Vulnerability Management Regularly update systems, apply security patches, and use anti-malware or endpoint protection solutions.
Implement Strong Access Control Restrict access to cardholder data based on business need-to-know and enforce strong authentication mechanisms.
Monitor & Test Networks Enable logging, monitor network activity, use intrusion detection systems, and perform regular penetration testing.
Maintain Information Security Policy Create documented security policies, conduct risk assessments, and train employees on security best practices.
🎯 SAQ (Self‑Assessment Questionnaire) Types
  • SAQ A: Redirect / iFrame (tokenisation) – lowest burden.
  • SAQ A-EP: Partially hosted e‑commerce.
  • SAQ D: Store or process card data directly – highest burden.
⚠️ Storing CVV or full track data is strictly forbidden by PCI-DSS – even temporarily.
βœ… Key Takeaway: Use tokenisation / iFrame to reduce PCI scope; never build a custom payment form without professional security review.

2.3 Secure API Key Management (Secrets Protection)

API keys (especially secret keys) are the digital keys to your payment account. A leaked secret key allows an attacker to create charges, refunds, and even modify webhook endpoints.

πŸ”‘ Do’s and Don’ts
βœ… Best Practices
  • Store keys in environment variables, never in code.
  • Use dedicated secrets manager (AWS Secrets Manager, HashiCorp Vault, Doppler).
  • Rotate keys regularly (e.g., every 90 days).
  • Create separate keys for development and production.
  • Restrict key permissions (e.g., read‑only API keys for monitoring).
❌ Never Do This
  • Hard‑code keys in source code (especially public repos).
  • Commit keys to GitHub, GitLab, Bitbucket.
  • Send keys via email, Slack, or chat.
  • Embed keys in client‑side JavaScript (publishable key is fine).
πŸ› οΈ Detection & Response
  • Use git hooks (e.g., git‑secrets) to prevent accidental commits.
  • Enable key rotation API – gateways allow instant revocation.
  • Monitor API activity for unexpected geographic locations or IPs.
# .env file example (never commit)
STRIPE_SECRET_KEY=sk_live_...
RAZORPAY_KEY_ID=rzp_live_...  
🚨 If you accidentally commit a secret key, assume it is compromised – rotate it immediately.
βœ… Key Takeaway: Secret keys must be treated like passwords – protect at all costs.

2.4 Payment Tampering Prevention (Amount, Currency, ID Manipulation)

Attackers often try to modify payment parameters – amount, currency, merchant ID, or order reference – to pay less, receive money, or bypass checks. Preventing tampering requires server‑side validation and cryptographic signatures.

🎯 Common Tampering Attacks
  • Amount manipulation: Change amount from $100 to $1 in request.
  • Currency change: Switch from USD to INR to reduce value.
  • ID substitution: Replace merchant ID to pay a different seller.
  • Callback spoofing: Fake success notification.
πŸ›‘οΈ Prevention Techniques
  • Server‑side amount validation: Never trust client‑side price – recalculate from order data.
  • Signed payloads: Use HMAC signatures for all callbacks and webhooks.
  • Idempotency keys: Prevent replay of successful requests.
  • Strict input validation: Reject unexpected fields or data types.
# Example: Server‑side amount validation (Node.js)
function createPayment(orderId) {
    const order = db.getOrder(orderId);
    const total = order.totalPrice; // recalculated from DB, not from client
    return gateway.payments.create({ amount: total, currency: 'INR' });
}
⚠️ PCI‑DSS requires that merchant servers never trust client‑provided transaction amounts without verification.
βœ… Key Takeaway: Always derive payment amounts from server‑side order data – treat all client input as untrusted.

2.5 Webhook Security (Signature Verification & Idempotency)

Webhooks are critical for asynchronous payment status updates, but they are also a prime attack vector. Without proper security, attackers can send fake β€œpayment succeeded” events and trick your system into fulfilling orders without actual payment.

πŸ”’ Essential Webhook Security Controls
Control Why It Matters
Signature Verification Ensures the webhook request genuinely came from the payment gateway and was not modified or sent by an attacker.
Idempotency Keys Prevents duplicate transaction processing when gateways retry webhook delivery multiple times.
HTTPS Only Encrypts webhook payloads during transmission. Most payment gateways require secure HTTPS endpoints.
IP Whitelisting (Optional) Restricts webhook requests to trusted payment gateway IP addresses for additional security protection.
Authentication via Custom Header Adds an extra security layer using secret API keys or tokens inside request headers.
# Example: Webhook signature verification (Stripe in Node.js)
const stripe = require('stripe')('sk_...');
const endpointSecret = 'whsec_...';

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
    const sig = req.headers['stripe-signature'];
    let event;
    try {
        event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
    } catch (err) {
        return res.status(400).send(`Webhook Error: ${err.message}`);
    }
    // Handle event (payment_intent.succeeded, etc.)
    res.json({received: true});
});
🚨 Failing to verify webhook signatures is equivalent to leaving your cash register unlocked – anyone can mark orders as paid.
βœ… Key Takeaway: Always verify webhook signatures using the gateway’s official library or documented algorithm.

2.6 Fraud Detection Basics (Rules & Machine Learning)

Payment fraud includes card testing, unauthorised transactions, friendly fraud (chargebacks), and account takeover. Gateways offer built‑in fraud detection, but merchants should add extra layers.

πŸ“Š Common Fraud Indicators
  • Multiple failed payment attempts in short time (card testing).
  • Orders from high‑risk countries or anonymous proxies (VPN / Tor).
  • Unusually large order amounts or high velocity.
  • Mismatch between billing and shipping address (for physical goods).
  • Suspicious email addresses (temporary, misspelt).
πŸ›‘οΈ Fraud Prevention Techniques
  • 3D Secure (3DS2): Transfers liability to issuer – reduces chargeback risk.
  • Velocity checks: Limit number of attempts from same IP or card.
  • AVS (Address Verification Service): Match billing address with cardholder’s bank.
  • CVV check: Require CVV for card‑not‑present transactions.
  • Machine learning models: Stripe Radar, Braintree Advanced Fraud Protection.
  • Manual review queue: Flag high‑risk orders for human verification.
πŸ’‘ Many gateways provide webhook events for payment.fraud_risk – can auto‑cancel or hold orders.
βœ… Key Takeaway: Fraud detection is a balance between security (blocking fraud) and user experience (avoid false positives).

2.7 Rate Limiting & Abuse Prevention (Throttling)

Attackers may abuse payment APIs by submitting many requests – to test stolen cards, brute‑force discounts, or cause denial of service. Rate limiting prevents such abuse.

🎯 What to Rate Limit
  • Create payment endpoint: Limit by IP, session, or user account.
  • Refund API: Stricter limits – typically admin‑only with low threshold.
  • Webhook receiver: Not usually rate‑limited, but ensure idempotency.
  • Login / OTP generation: Critical for preventing credential stuffing.
πŸ”§ Implementation Strategies
  • Sliding window counters: Redis + time‑buckets.
  • Token bucket: Allows bursts then throttles.
  • Per‑user/account limits: Prevent one account from flooding.
  • Penalty box: Temporary blocks (e.g., 1 hour) after exceeding limits.
# Example: Express‑rate‑limit (Node.js)
const rateLimit = require('express-rate-limit');
const createPaymentLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 10, // limit each IP to 10 requests
    message: 'Too many payment attempts, try later'
});
app.post('/api/payments', createPaymentLimiter, paymentHandler);
⚠️ Rate limiting should be applied at the API gateway or reverse proxy layer for effectiveness.
βœ… Key Takeaway: Rate limiting protects against brute‑force and DDoS attacks – essential for payment APIs.

2.8 Secure Transaction Logging (Audit Trails)

Comprehensive logging is required by PCI-DSS and helps during incident investigations. However, logs must never contain sensitive cardholder data (PAN, CVV, track data).

πŸ“ What to Log (and what NOT to log)
βœ… Log these (safe)
  • Payment ID, order ID, amount, currency, status.
  • Timestamp, IP address (may be limited due to PII laws).
  • User ID / session ID (if not personal).
  • API endpoint called, response status code.
  • Webhook received events (with payload but not secrets).
❌ Never log these
  • Full PAN (card number) – hashing or truncation allowed.
  • CVV / CVC – PCI forbids storage even in logs.
  • Expiry date (can be kept separately with PAN hashed).
  • Track data from magnetic stripe.
  • API secret keys, signatures, or authentication tokens.
πŸ”’ Best Practices
  • Use centralized logging (ELK, Splunk, Datadog) with strict access controls.
  • Enable log rotation and retention policies (e.g., 1 year for PCI).
  • Mask or truncate PAN – only last 4 digits can be stored.
  • Integrate with SIEM for real‑time alerts.
  • Regularly audit log access – who can read them.
# Example: Logging a payment event (JSON format)
{
    "timestamp": "2025-01-15T10:30:00Z",
    "event": "payment.created",
    "payment_id": "pay_abc123",
    "order_id": "order_xyz",
    "amount": 1000,
    "currency": "INR",
    "status": "created",
    "ip": "203.0.113.45",
    "user_id": "user_789",
    "panic": null
}
🚨 Accidentally logging CVV or full PAN leads to PCI compliance failure and potential data breach.
βœ… Key Takeaway: Logs are your eyes during an attack – keep them secure, complete, but free of sensitive card data.

πŸŽ“ Module 02 : Payment Gateway Security & Compliance – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 03 : Stripe Payment Gateway

This module provides a comprehensive guide to integrating Stripe, one of the most popular payment gateways. You'll learn about account setup, dashboard navigation, API keys, Checkout, Payment Intents, webhooks, refunds, and subscriptions – with practical examples and security best practices.


3.1 Stripe Account Setup (Production & Test Mode)

Stripe offers both Test Mode (sandbox) and Live Mode (production). Always start with Test Mode to integrate and test without moving real money.

πŸ“ Step‑by‑Step Setup
  1. Go to https://dashboard.stripe.com/register and sign up.
  2. Verify your email address.
  3. Complete business details (country, type, product description).
  4. Toggle between Test Mode and Live Mode using the switcher in the dashboard.
  5. In Test Mode, you can use test card numbers (e.g., 4242 4242 4242 4242) to simulate payments.
πŸ’‘ Stripe’s test environment is fully functional – you can create payments, webhooks, refunds, and subscriptions.
βœ… Key Takeaway: Always start in Test Mode. Switch to Live Mode only after thorough testing.

3.2 Stripe Dashboard Overview (Key Sections)

The Stripe Dashboard is your central control panel for managing payments, customers, disputes, and settings.

Section Purpose
Payments View all transactions and filter payments by status such as succeeded, pending, failed, or refunded.
Customers Manage customer profiles, billing details, and saved payment methods.
Subscriptions Handle recurring billing, subscription plans, renewals, and automated payment cycles.
Disputes Monitor chargebacks, manage disputes, and submit evidence for representment.
Webhooks Configure webhook endpoints to receive real-time asynchronous payment events and notifications.
Developers Access API keys, integration logs, SDK documentation, and event monitoring tools.
πŸ”§ Key Developer Tools
  • API Keys: Publishable key (pk_test_...) and secret key (sk_test_...).
  • Webhooks: Add endpoints, view recent deliveries, and retry failed events.
  • Logs: Detailed request/response logs for debugging.
  • Events: All webhook‑triggered events listed with payloads.
πŸ’‘ The dashboard also includes a Test Clock for simulating subscription renewals.
βœ… Key Takeaway: Spend time exploring the dashboard – it’s essential for monitoring and debugging.

3.3 Stripe API Keys (Publishable vs Secret)

Stripe provides two types of keys: publishable key (client‑side) and secret key (server‑side). Never expose the secret key in client‑side code.

πŸ”‘ Publishable Key (pk_...)
  • Used in frontend JavaScript (Stripe.js, Elements).
  • Can create tokens and payment methods – cannot charge or refund.
  • Safe to embed in HTML/JS.
  • Example: pk_test_4eC39HqLyjWDarjtT
🀫 Secret Key (sk_...)
  • Used on the server to perform any API action (create payment, refund, manage subscriptions).
  • Must be kept secret – never commit to version control.
  • Rotate if compromised.
  • Example: sk_test_4eC39HqLyjWDarjtT
# Storing keys in .env (Node.js)
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...

# Using keys
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
🚨 Critical: If your secret key is leaked, rotate it immediately from the dashboard and revoke the old key.
βœ… Key Takeaway: Always store secret keys in environment variables; never hard‑code them.

3.4 Stripe Checkout Integration (Pre‑built Payment Page)

Stripe Checkout is a hosted payment page that handles card collection, 3D Secure, and payment confirmation. It reduces PCI compliance burden and is the quickest way to start accepting payments.

πŸ›’ Integration Steps (Server‑side)
  1. Create a Checkout Session on your server.
  2. Redirect the customer to the session URL.
  3. Stripe handles the rest – customer pays, and you receive webhooks.
# Node.js (Express) example
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/create-checkout-session', async (req, res) => {
    const session = await stripe.checkout.sessions.create({
        payment_method_types: ['card'],
        line_items: [{
            price_data: {
                currency: 'usd',
                product_data: { name: 'T-shirt' },
                unit_amount: 2000, // $20.00
            },
            quantity: 1,
        }],
        mode: 'payment',
        success_url: 'https://your-site.com/success?session_id={CHECKOUT_SESSION_ID}',
        cancel_url: 'https://your-site.com/cancel',
    });
    res.json({ id: session.id });
});

On the frontend, redirect the customer using session.id with Stripe.js:

<script src="https://js.stripe.com/v3/"></script>
<script>
    const stripe = Stripe('pk_test_...');
    stripe.redirectToCheckout({ sessionId: '{{session.id}}' });
</script>
πŸ’‘ Checkout supports one‑time payments, subscriptions, and even donations.
βœ… Key Takeaway: Checkout is the simplest integration – handles UI, validation, and PCI compliance.

3.5 Stripe Payment Intents API (Manual Payment Flow)

Payment Intents API gives you full control over the payment lifecycle – from authorisation to capture. It is used for custom checkout forms, delayed capture, or when you need to handle 3D Secure yourself.

πŸ“¦ Payment Intent Steps
  1. Create a PaymentIntent on the server with amount and currency.
  2. Return the client secret to the frontend.
  3. Confirm the payment on the client side (Stripe.js).
  4. Listen to webhook events (payment_intent.succeeded) to update order status.
# Create PaymentIntent (Node.js)
const paymentIntent = await stripe.paymentIntents.create({
    amount: 2000,
    currency: 'usd',
    payment_method_types: ['card'],
});

// Response includes client_secret (for frontend)
{ id: 'pi_123', client_secret: 'pi_123_secret_abc' }
# Frontend confirmation (Stripe Elements)
const { error, paymentIntent } = await stripe.confirmCardPayment(clientSecret, {
    payment_method: { card: cardElement }
});
πŸ”§ Advanced Options
  • Capture method: manual (authorise only, capture later).
  • Payment method types: Add card, link, us_bank_account.
  • Statement descriptor: Custom text on customer’s bank statement.
  • Metadata: Store custom data (order ID, user ID).
⚠️ Payment Intents require proper error handling – network failures, card declines, 3D Secure challenges.
βœ… Key Takeaway: Use Payment Intents when you need custom UI or authorisation‑only flows.

3.6 Stripe Webhooks (Asynchronous Event Handling)

Stripe sends webhooks for asynchronous events like payment success, refund completion, subscription renewal, and failed payments. Webhooks are critical for reliable order processing.

πŸ“‘ Common Webhook Events
EventWhen triggered
payment_intent.succeededPayment succeeded (captured).
payment_intent.payment_failedPayment failed – decline, insufficient funds.
charge.refundedRefund processed.
checkout.session.completedCheckout session completed.
invoice.payment_succeededSubscription invoice paid.
πŸ”’ Webhook Security
  • Stripe signs each webhook with a secret (whsec_...).
  • Verify signature using Stripe library – reject unsigned requests.
  • Use HTTPS for webhook endpoint.
  • Respond with 200 OK within 10 seconds; otherwise Stripe retries.
  • Implement idempotency – process each event only once (use event.id).
# Webhook handler (Node.js)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const endpointSecret = 'whsec_...';

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
    const sig = req.headers['stripe-signature'];
    let event;
    try {
        event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
    } catch (err) {
        return res.status(400).send(`Webhook Error: ${err.message}`);
    }
    switch (event.type) {
        case 'payment_intent.succeeded':
            const paymentIntent = event.data.object;
            // Update order status in your DB
            break;
        default:
            console.log(`Unhandled event type ${event.type}`);
    }
    res.status(200).end();
});
🚨 Never skip signature verification – otherwise attackers can fake payment success.
βœ… Key Takeaway: Webhooks are the most reliable way to get payment status – always use them.

3.7 Stripe Refunds & Subscriptions (Recurring Billing)

Stripe supports full and partial refunds via API or dashboard. Subscriptions allow recurring billing with flexible plans, trial periods, and automatic invoicing.

πŸ’° Processing Refunds
# Full refund of a payment intent
const refund = await stripe.refunds.create({
    payment_intent: 'pi_123',
});

# Partial refund
const refund = await stripe.refunds.create({
    charge: 'ch_123',
    amount: 500, // refund $5.00
});
  • Refunds are synchronous – they happen immediately (but bank processing may take days).
  • You can refund up to the original captured amount.
  • Webhook event: charge.refunded.
πŸ”„ Setting Up Subscriptions
  1. Create a Product and Price (one‑time, recurring).
  2. Create a Customer (if not exists).
  3. Create a Subscription with the price ID and customer ID.
  4. Stripe handles recurring charges, prorations, and invoice emails.
# Create a subscription (Node.js)
const subscription = await stripe.subscriptions.create({
    customer: 'cus_123',
    items: [{ price: 'price_1ABC123' }],
    expand: ['latest_invoice.payment_intent'],
});
πŸ’‘ You can offer trial periods (trial_period_days) and enable automatic tax calculation.
⚠️ For subscriptions, handle webhook events like invoice.payment_succeeded and customer.subscription.deleted.
βœ… Key Takeaway: Stripe’s subscription API is powerful – test in sandbox before going live.

πŸŽ“ Module 03 : Stripe Payment Gateway – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 04 : PayPal Payment Gateway

This module provides a comprehensive guide to integrating PayPal, one of the world’s most recognised payment platforms. You will learn about account setup, API credentials, Checkout, Instant Payment Notifications (IPN), webhooks, and subscriptions – with real‑world examples and security considerations.


4.1 PayPal Business Setup (Sandbox & Live)

To integrate PayPal, you need a Business Account. PayPal provides a Sandbox environment for testing with fake money and a Live environment for real transactions.

πŸ“ Step‑by‑Step Setup
  1. Go to https://www.paypal.com/business/signup and sign up for a Business account.
  2. Verify your email address and provide basic business information.
  3. Access the Developer Dashboard at https://developer.paypal.com.
  4. Create Sandbox test accounts (buyer and seller) under Sandbox β†’ Accounts.
  5. Toggle between Sandbox and Live mode in your API credentials.
πŸ’‘ Sandbox accounts come with fake balances – you can simulate successful payments, declines, and even disputes.
βœ… Key Takeaway: Always develop and test in Sandbox; switch to Live only after thorough verification.

4.2 PayPal Developer Console – Key Sections

The PayPal Developer Dashboard is your central hub for managing apps, API credentials, webhooks, and testing tools.

Section Purpose
My Apps & Credentials--_:Create REST API apps, get Client ID and Secret.
Sandbox Accounts--_:Create and manage test buyers/sellers with pre‑loaded balances.
Webhooks--_:Register HTTPS endpoints for real‑time event notifications.
IPN Simulator--_:Test Instant Payment Notifications manually.
Transactions Search (Sandbox)--_:View test payments and refunds.
πŸ’‘ PayPal also provides a REST API Explorer for testing endpoints directly from the browser.
βœ… Key Takeaway: The Developer Console is essential for configuration and debugging – explore every tab.

4.3 PayPal API Credentials (Client ID & Secret)

PayPal uses OAuth2 for API authentication. You receive a Client ID (public) and a Secret (confidential). Never expose the secret on the client side.

πŸ”‘ Client ID (Public)
  • Used in frontend JavaScript (PayPal Buttons).
  • Can be safely embedded in HTML.
  • Example: Adf3jkl...abc
🀫 Secret (Confidential)
  • Used for server‑to‑server API calls (e.g., capturing payment, refund).
  • Never expose in client‑side code.
  • Store in environment variables.
  • Rotate if compromised.
# Store credentials in .env (Node.js)
PAYPAL_CLIENT_ID=Adf3jkl...
PAYPAL_SECRET=EdfG45...

# Use with PayPal SDK
const paypal = require('@paypal/checkout-server-sdk');
const environment = new paypal.core.SandboxEnvironment(process.env.PAYPAL_CLIENT_ID, process.env.PAYPAL_SECRET);
const client = new paypal.core.PayPalHttpClient(environment);
🚨 Leaking your Secret allows attackers to create/capture payments and refunds – protect it like a password.
βœ… Key Takeaway: Always keep secrets in environment variables and restrict API permissions where possible.

4.4 PayPal Checkout Integration (Hosted & Custom)

PayPal offers two main integration methods: the hosted smart buttons (JavaScript) and the server‑side Orders API for full control. Both support cards, PayPal balance, and local payment methods.

πŸ›’ Smart Buttons (Hosted – Easiest)
<div id="paypal-button-container"></div>
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&currency=USD"></script>
<script>
    paypal.Buttons({
        createOrder: function(data, actions) {
            return actions.order.create({
                purchase_units: [{
                    amount: { value: '10.00' }
                }]
            });
        },
        onApprove: function(data, actions) {
            return actions.order.capture().then(function(details) {
                alert('Transaction completed by ' + details.payer.name.given_name);
                // Send the order ID to your server for verification
            });
        }
    }).render('#paypal-button-container');
</script>
βš™οΈ Server‑Side Orders API (More Control)
# Node.js – Create order
const request = new paypal.orders.OrdersCreateRequest();
request.requestBody({
    intent: 'CAPTURE',
    purchase_units: [{ amount: { currency_code: 'USD', value: '10.00' } }]
});
const order = await client.execute(request);
// Return order.id to frontend
res.json({ id: order.result.id });
πŸ’‘ PayPal Checkout handles 3D Secure, card errors, and alternative payment methods automatically.
βœ… Key Takeaway: The hosted button method is the quickest and most secure – card data never touches your server.

4.5 PayPal IPN & Webhooks (Asynchronous Notifications)

PayPal provides two asynchronous notification mechanisms: Instant Payment Notification (IPN) (legacy, POST form‑encoded) and Webhooks (modern, JSON). Both are used to update order statuses in real time.

πŸ“‘ Webhook Events (Recommended)
EventWhen triggered
PAYMENT.CAPTURE.COMPLETED--_:Payment captured successfully. PAYMENT.CAPTURE.DENIED--_:Payment declined.
PAYMENT.CAPTURE.REFUNDED--_:Refund processed.
BILLING.SUBSCRIPTION.ACTIVATED--_:Subscription activated.
πŸ”’ Security – Verifying IPN Messages
# Node.js IPN verification (legacy)
const ipn = require('paypal-ipn');
ipn.verify(req.body, function callback(err, msg) {
    if (err) { /* invalid */ }
    else { /* valid – process */ }
});
⚠️ IPN messages can be spoofed – always verify them by sending back to PayPal (or use webhooks with signature).
βœ… Key Takeaway: Prefer webhooks over IPN – they are easier to verify and secure.

4.6 PayPal Subscriptions (Billing Plans & Agreements)

PayPal Subscriptions allow merchants to charge customers on a recurring basis (weekly, monthly, yearly) with trial periods, proration, and automatic retry of failed payments.

πŸ”„ Subscription Steps
  1. Create a Product (if not exists).
  2. Create a Billing Plan (duration, frequency, pricing).
  3. Create a Subscription (assign plan to customer).
  4. Redirect customer to PayPal to approve.
  5. Listen to webhook events (e.g., BILLING.SUBSCRIPTION.ACTIVATED).
# Create Billing Plan (Node.js)
const request = new paypal.billingPlans.BillingPlansCreateRequest();
request.requestBody({
    name: 'Monthly Membership',
    description: 'Recurring monthly subscription',
    type: 'INFINITE',
    payment_definitions: [{
        name: 'Monthly Payment',
        type: 'REGULAR',
        frequency_interval: '1',
        frequency: 'MONTH',
        amount: { currency: 'USD', value: '9.99' },
        cycles: '0' // infinite
    }],
    merchant_preferences: {
        return_url: 'https://shop.com/success',
        cancel_url: 'https://shop.com/cancel'
    }
});
πŸ’‘ PayPal automatically handles failed payments retries and sends emails to customers.
⚠️ Test subscriptions in Sandbox using a test buyer account – you can simulate retries using the IPN simulator.
βœ… Key Takeaway: Subscriptions reduce manual billing effort – always test all lifecycle events (trial, renewal, cancellation).

πŸŽ“ Module 04 : PayPal Payment Gateway – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 05 : Razorpay Payment Gateway

This module provides a comprehensive guide to integrating Razorpay, a leading Indian payment gateway. You will learn about account setup, test/live modes, Orders API, Checkout integration, webhooks, and refunds – with practical examples and security considerations.


5.1 Razorpay Account Setup (Dashboard & API Access)

To start accepting payments with Razorpay, you need to create a merchant account and obtain API keys. Razorpay offers a free test environment for integration and a production environment for live transactions.

πŸ“ Step‑by‑Step Setup
  1. Go to https://dashboard.razorpay.com/signup and sign up.
  2. Verify your email and provide basic business details (company type, PAN, GST optional for test).
  3. Once logged in, navigate to Settings β†’ API Keys to generate your Key ID and Key Secret.
  4. For production, you will also need to submit KYC documents and activate your account.
πŸ’‘ Razorpay provides a fully functional test mode – you can simulate payments, refunds, and webhooks without real money.
βœ… Key Takeaway: Sign up and generate API keys in test mode first; upgrade to live only after successful integration.

5.2 Razorpay Test & Live Mode (Sandbox vs Production)

Razorpay separates test and live environments using different API keys. Switching between them is manual – you must change keys in your code.

🟒 Test Mode (Sandbox)
  • Use test Key ID: rzp_test_XXXXXX
  • Test cards: 4111 1111 1111 1111 (visa success), 4242 4242 4242 4242 (3D secure)
  • No real money moves; all transactions are simulation.
  • Webhook URLs can be local (using ngrok) – HTTPS not strictly required.
πŸ”΄ Live Mode (Production)
  • Use live Key ID: rzp_live_XXXXXX
  • Real money transactions; requires compliance (PCI DSS not needed if using Checkout).
  • Webhook URLs must be HTTPS and publicly accessible.
  • Need KYC and business verification before activation.
⚠️ Never commit test or live keys to version control – use environment variables.
βœ… Key Takeaway: Always test thoroughly in test mode; switch to live only when all scenarios work correctly.

5.3 Razorpay Orders API (Create & Fetch Orders)

Razorpay uses an Order object to represent a payment request. You create an order on your server, then pass the order ID to the frontend Checkout.

πŸ“¦ Create Order – API Reference
POST https://api.razorpay.com/v1/orders
Authorization: Basic base64(key_id:key_secret)
Content-Type: application/json

{
    "amount": 50000,           // β‚Ή500.00 (in paise)
    "currency": "INR",
    "receipt": "order_rcptid_11",
    "notes": {
        "order_id": "order_123",
        "customer_email": "user@example.com"
    }
}
πŸ“₯ Sample Response
{
    "id": "order_Examp1e12345",
    "entity": "order",
    "amount": 50000,
    "amount_paid": 0,
    "status": "created",
    "created_at": 1650000000
}
πŸ”§ Code Example (Node.js with Razorpay NPM)
const Razorpay = require('razorpay');
const instance = new Razorpay({
    key_id: process.env.RAZORPAY_KEY_ID,
    key_secret: process.env.RAZORPAY_KEY_SECRET
});

async function createOrder(amount, receipt) {
    const options = {
        amount: amount * 100, // convert to paise
        currency: 'INR',
        receipt: receipt,
        notes: { version: '1.0' }
    };
    const order = await instance.orders.create(options);
    return order;
}
πŸ’‘ Amount is always in the smallest currency unit (paise for INR). Never manipulate amount on the client.
βœ… Key Takeaway: Create orders server‑side; the frontend only needs the order ID.

5.4 Razorpay Checkout Integration (JavaScript SDK)

Razorpay Checkout is a hosted payment page that handles cards, UPI, net banking, wallets, and EMI. It is the simplest and most secure way to accept payments – card data never touches your server.

πŸ›’ Integration Steps
  1. Include the Razorpay Checkout script on your payment page.
  2. Create an order on your server (as shown in 5.3) and pass the order ID to the frontend.
  3. Initialise the Razorpay Checkout object with the order ID and user details.
  4. Handle success (payment capture) via a callback, then verify the payment status on your server.
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
    const options = {
        key: "{{RAZORPAY_KEY_ID}}",        // Your test/live key ID
        amount: 50000,                    // in paise
        currency: "INR",
        name: "Acme Corp",
        description: "Test Transaction",
        order_id: "{{order_id}}",          // Order ID from server
        handler: function (response) {
            // Send payment_id and order_id to your server for verification
            fetch('/verify-payment', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    razorpay_payment_id: response.razorpay_payment_id,
                    razorpay_order_id: response.razorpay_order_id,
                    razorpay_signature: response.razorpay_signature
                })
            });
        },
        prefill: {
            name: "Customer Name",
            email: "customer@example.com",
            contact: "9999999999"
        },
        theme: { color: "#F37254" }
    };
    const rzp = new Razorpay(options);
    document.getElementById('pay-btn').onclick = function() { rzp.open(); };
</script>
🚨 Critical: Always verify payment signature on your server – never trust the client callback alone.
βœ… Key Takeaway: Checkout is PCI‑SAQ A compliant – your server never sees card details.

5.5 Razorpay Webhooks (Payment & Refund Events)

Razorpay sends webhooks (HTTP callbacks) for important events like payment capture, refund processed, and subscription renewal. Webhooks are the most reliable way to update order status asynchronously.

πŸ“‘ Common Webhook Events
EventDescription
payment.captured--_:Payment successfully captured.
payment.failed--_:Payment failed due to insufficient funds, expired card, etc.
refund.created--_:Refund initiated.
refund.processed--_:Refund completed.
πŸ”’ Webhook Signature Verification

Razorpay signs each webhook with a secret. You must verify the signature before processing.

// Node.js example using Razorpay utility
const crypto = require('crypto');
const webhookSecret = process.env.RAZORPAY_WEBHOOK_SECRET;

app.post('/razorpay-webhook', express.raw({type: 'application/json'}), (req, res) => {
    const signature = req.headers['x-razorpay-signature'];
    const body = req.body.toString('utf8');
    const expectedSignature = crypto.createHmac('sha256', webhookSecret).update(body).digest('hex');
    if (signature !== expectedSignature) {
        return res.status(400).send('Invalid signature');
    }
    const event = JSON.parse(body);
    switch (event.event) {
        case 'payment.captured':
            // Update order in database
            break;
    }
    res.status(200).end();
});
⚠️ Never skip signature verification – otherwise attackers can forge payment success events.
βœ… Key Takeaway: Use webhooks for idempotent, reliable order updates – they work even if the user closes the browser.

5.6 Razorpay Refund APIs (Full & Partial)

Razorpay allows you to refund a payment fully or partially via API. Refunds can be initiated from the dashboard or programmatically. Always ensure refunds are authorised (e.g., admin action) to prevent abuse.

πŸ’° Refund Request (Full Refund)
POST https://api.razorpay.com/v1/payments/{payment_id}/refund
Authorization: Basic base64(key_id:key_secret)
Content-Type: application/json

{
    "amount": 50000,           // amount in paise – optional, full if omitted
    "notes": {
        "reason": "customer_request",
        "order_id": "order_123"
    }
}
πŸ“₯ Sample Response
{
    "id": "ref_Examp1e123",
    "entity": "refund",
    "amount": 50000,
    "status": "processed",
    "payment_id": "pay_Examp1e456",
    "created_at": 1650000000
}
πŸ”§ Code Example (Node.js)
// Refund a payment (partial or full)
async function refundPayment(paymentId, amountInPaise = null) {
    const options = {};
    if (amountInPaise) options.amount = amountInPaise;
    const refund = await instance.payments.refund(paymentId, options);
    return refund;
}
πŸ’‘ Refunds may take 2‑5 days to reflect in the customer’s bank account, but Razorpay updates status immediately.
🚨 Security Note: Refund APIs should be protected – restrict access to admin roles and use idempotency keys.
βœ… Key Takeaway: Programmatic refunds are powerful – log all refunds and require strong authentication.

πŸŽ“ Module 05 : Razorpay Payment Gateway – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 06 : Paytm Payment Gateway

This module covers the integration of Paytm, one of India’s leading payment gateways. You will learn about merchant account setup, MID & merchant keys, integration workflow, callback verification, checksum‑based β€œwebhooks”, and refund/status APIs – with practical examples and security best practices.


6.1 Paytm Merchant Account Setup

To accept payments via Paytm, you need to register as a merchant on Paytm’s business portal. Paytm provides separate test (staging) and production environments.

πŸ“ Step‑by‑Step Setup
  1. Go to https://business.paytm.com and click β€œSign Up”.
  2. Fill in business details (type, PAN, GST, bank account).
  3. Complete KYC process – may require document submission.
  4. Once approved, you will receive a Merchant ID (MID) and access to the dashboard.
  5. For testing, also request staging credentials from Paytm support or use the sandbox portal.
πŸ’‘ Paytm’s staging environment is available at https://dashboard.paytm.com/merchant using test MID.
βœ… Key Takeaway: Start with staging credentials; move to production only after successful testing.

6.2 Paytm MID & Merchant Keys

Paytm uses a combination of Merchant ID (MID), Merchant Key, and Industry Type to identify and authenticate merchants. These are used to generate checksums for request and response validation.

πŸ†” Merchant ID (MID)
  • Unique identifier for your business.
  • Typically 7‑digit numeric or alphanumeric.
  • Example: 1234567
πŸ”‘ Merchant Key
  • Secret key used for checksum generation.
  • Never expose in client‑side code.
  • Store in environment variables.
🏒 Industry Type
  • Retail, e‑commerce, education, travel, etc.
  • Determines transaction parameters.
  • Obtained from Paytm dashboard.
πŸ”§ Securing Keys
# Store in .env file (never commit)
PAYTM_MID=1234567
PAYTM_MERCHANT_KEY=your_merchant_key
PAYTM_INDUSTRY_TYPE=RETAIL

# In code (Node.js)
const paytmConfig = {
    mid: process.env.PAYTM_MID,
    merchantKey: process.env.PAYTM_MERCHANT_KEY,
    website: 'WEBSTAGING',  // or 'WEBPRO' for production
    industryType: process.env.PAYTM_INDUSTRY_TYPE
};
🚨 Leaking your Merchant Key allows attackers to generate valid checksums – treat it like a password.
βœ… Key Takeaway: Keep Merchant Key secret and never hard‑code it in source code.

6.3 Paytm Integration Workflow (Checksum‑Based)

Paytm uses a redirect‑based flow. The merchant generates a checksum for the transaction, redirects the customer to Paytm’s hosted page, and Paytm sends the response to a callback URL.

πŸ”„ Steps
  1. Initiate Transaction: Merchant creates an order, collects customer details.
  2. Generate Checksum: Using Merchant Key, generate a checksum for the transaction parameters (order ID, amount, etc.).
  3. Redirect to Paytm: Send the checksum and parameters to Paytm’s payment page (staging or production URL).
  4. Customer Pays: Customer completes payment on Paytm (cards, UPI, wallet, net banking).
  5. Callback Response: Paytm redirects back to your callback_url with a response checksum.
  6. Verify Checksum: Merchant re‑computes the checksum and verifies it – only then updates order status.
  7. Transaction Status API (optional): For additional confirmation, call Paytm’s order status API.
πŸ’‘ Paytm’s callback URL must be HTTPS in production; staging can use HTTP.
βœ… Key Takeaway: Checksum verification is the only way to ensure callback authenticity – never skip it.

6.4 Paytm Callback Verification (Checksum Validation)

Paytm sends transaction response via a GET/POST callback to your specified URL. The response contains a checksum. You must re‑generate the checksum and compare it to verify the integrity and authenticity.

πŸ” Checksum Generation & Verification

Paytm provides libraries in multiple languages. Below is a PHP example using their library.

// PHP callback handler (using Paytm's lib)
require_once("encdec_paytm.php");
$paytmChecksum = $_POST["CHECKSUMHASH"];
$paytmParams = $_POST;
unset($paytmParams["CHECKSUMHASH"]);
$isValidChecksum = verifychecksum_e($paytmParams, PAYTM_MERCHANT_KEY, $paytmChecksum);

if ($isValidChecksum && $_POST['STATUS'] == 'TXN_SUCCESS') {
    // Update order status
    $orderId = $_POST['ORDERID'];
    $txnAmount = $_POST['TXNAMOUNT'];
    // Additional verification via TxnStatus API recommended
}
πŸ“₯ Sample Callback Response Parameters
ParameterDescription
ORDERID--Merchant’s order ID.
STATUS--_:TXN_SUCCESS, TXN_FAILURE, PENDING.
TXNAMOUNT--_:Transaction amount.
BANKTXNID--_:Paytm transaction ID.
RESPCODE--_:Response code (01 = success).
CHECKSUMHASH--_:Checksum for verification.
🚨 Never trust callback parameters without checksum validation – an attacker can forge a fake success response.
βœ… Key Takeaway: Always verify checksum and optionally confirm via transaction status API before granting benefits.

6.5 Paytm Webhooks (Checksum‑Based Callbacks)

Paytm does not use standard JSON webhooks like Stripe. Instead, it relies on the same redirect‑based callback mechanism. After payment, Paytm hits your callback_url with POST parameters and a checksum. This is the equivalent of a webhook.

πŸ“‘ Handling β€œWebhook” Callbacks
  • Set your callback_url in the Paytm dashboard (Test/Live).
  • This URL must be publicly accessible (HTTPS in production).
  • Paytm sends both success and failure notifications to the same URL.
  • Your server must respond with 200 OK (any other status may be retried, but Paytm retries are limited).
  • Implement idempotency using your own order ID – the same callback may be sent twice.
πŸ”’ Security – No IP whitelisting needed (checksum is enough)

Because all responses are signed with your Merchant Key, you don’t need to whitelist Paytm IP addresses. Checksum verification alone guarantees authenticity.

πŸ’‘ Unlike Stripe, Paytm does not have a separate webhook subscription system – all responses come through the callback URL.
βœ… Key Takeaway: Treat the callback URL as your webhook endpoint – verify checksum and avoid processing duplicates.

6.6 Paytm Refund & Status APIs (Transaction Management)

Paytm provides APIs to check transaction status and initiate refunds. These are server‑to‑server REST calls using the same checksum mechanism.

πŸ“Š Transaction Status API

After receiving a callback, it’s recommended to double‑check the status using the Order Status API.

POST https://securegw.paytm.in/merchant-status/getTxnStatus
Parameters (JSON):
{
    "MID": "your_mid",
    "ORDERID": "order_123",
    "CHECKSUMHASH": "generated_checksum"
}

Response includes STATUS, TXNAMOUNT, BANKTXNID, etc.

πŸ’° Refund API
POST https://securegw.paytm.in/refund/apply
Parameters (JSON):
{
    "MID": "your_mid",
    "ORDERID": "order_123",
    "TXNID": "paytm_txn_id",
    "REFUNDAMOUNT": "500.00",
    "CHECKSUMHASH": "generated_checksum"
}
πŸ’‘ Refunds can be partial and initiated up to 180 days after the original transaction.
⚠️ Always use idempotency keys when calling refund API – otherwise duplicate calls may refund twice.
βœ… Key Takeaway: Transaction status API adds an extra layer of verification; refund APIs should be protected with admin authentication.

πŸŽ“ Module 06 : Paytm Payment Gateway – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’


Module 07 : PhonePe Payment Gateway

This module covers the integration of PhonePe, a popular Indian UPI‑based payment gateway. You will learn about merchant setup, API authentication (checksum/salt), UPI integration, payment status verification, and callback/refund handling – with practical examples and security best practices.


7.1 PhonePe Merchant Setup (Test & Production)

To start accepting payments via PhonePe, you need to register as a merchant on the PhonePe business portal. PhonePe provides separate test (sandbox) and production environments.

πŸ“ Step‑by‑Step Setup
  1. Go to https://www.phonepe.com/business and click β€œSign Up”.
  2. Fill in business details (company name, PAN, GST, bank account).
  3. Complete KYC verification (may take a few days).
  4. Once approved, login to the PhonePe Merchant Dashboard.
  5. Obtain your Merchant ID and Salt Key (for checksum generation).
  6. For testing, request sandbox credentials or use PhonePe’s test environment (test.phonepe.com).
πŸ’‘ PhonePe’s sandbox environment is available at https://test.phonepe.com with test merchant IDs.
βœ… Key Takeaway: Always start with sandbox credentials; switch to production only after full validation.

7.2 PhonePe API Authentication (Checksum & Salt)

PhonePe uses a checksum‑based authentication mechanism similar to Paytm. Each API request must include a X-VERIFY header containing a SHA‑256 hash generated using your Merchant ID, the request payload, and a Salt Key.

πŸ” How Checksum Works
  • Concatenate payload + /pg/v1/pay (API endpoint) + saltKey
  • Compute SHA‑256 hash β†’ append ###1 (suffix for the salt version).
  • Example header: X-VERIFY: sha256_hash###1
// Node.js example
const crypto = require('crypto');
const payload = JSON.stringify({ merchantId: 'MERCHANTUID', ... });
const endpoint = '/pg/v1/pay';
const saltKey = process.env.PHONEPE_SALT_KEY;
const string = payload + endpoint + saltKey;
const sha256 = crypto.createHash('sha256').update(string).digest('hex');
const xVerify = sha256 + '###1';
πŸ”‘ Required Credentials
πŸ†” Merchant ID
  • Unique identifier for your business.
  • Example: MERCHANTUID
πŸ§‚ Salt Key
  • Secret key used for checksum generation.
  • Never expose in client‑side code.
  • Store in environment variables.
🚨 Leaking your Salt Key allows attackers to forge valid API requests – protect it like a password.
βœ… Key Takeaway: Checksum ensures request integrity; always verify the response checksum as well.

7.3 PhonePe UPI Integration (PG Pay API)

PhonePe offers a redirect‑based UPI integration using the /pg/v1/pay endpoint. The merchant creates a payment request, redirects the customer to PhonePe’s hosted page, and handles the callback.

πŸ”„ Integration Flow
  1. Create Payment Request: On your server, call POST https://api.phonepe.com/apis/hermes/pg/v1/pay (sandbox: test.phonepe.com).
  2. Get Redirect URL: PhonePe returns a data.instrumentResponse.redirectInfo.url.
  3. Redirect Customer: Send the customer to that URL (PhonePe’s payment page).
  4. Customer Pays: Customer completes payment on PhonePe (UPI, cards, wallet).
  5. Callback Response: PhonePe redirects to your redirectUrl (merchant provided) with a transaction ID.
  6. Verify Checksum & Status: Verify the callback checksum, then call status API if needed.
πŸ“¦ Sample Payment Request (Node.js)
const payload = {
    merchantId: 'MERCHANTUID',
    merchantTransactionId: 'TXN123',
    merchantUserId: 'USER456',
    amount: 10000, // β‚Ή100.00 in paise
    redirectUrl: 'https://your-site.com/phonepe-callback',
    redirectMode: 'REDIRECT',
    paymentInstrument: { type: 'PAY_PAGE' }
};
const base64Payload = Buffer.from(JSON.stringify(payload)).toString('base64');
const checksum = crypto.createHash('sha256').update(base64Payload + '/pg/v1/pay' + saltKey).digest('hex') + '###1';
const response = await axios.post(`${baseUrl}/pg/v1/pay`, { request: base64Payload }, {
    headers: { 'Content-Type': 'application/json', 'X-VERIFY': checksum }
});
πŸ’‘ PhonePe supports multiple payment instruments: UPI, cards, net banking, and wallets.
βœ… Key Takeaway: The redirect method keeps your server PCI‑compliant – card data never touches your server.

7.4 Payment Status Verification (Transaction Status API)

After receiving a callback, it is strongly recommended to verify the transaction status using PhonePe’s status API. This provides an extra layer of security and confirmation.

πŸ“‘ Status API Endpoint

GET /pg/v1/status/{merchantId}/{merchantTransactionId}

πŸ” Request Example
const endpoint = `/pg/v1/status/${merchantId}/${merchantTransactionId}`;
const checksum = crypto.createHash('sha256').update(endpoint + saltKey).digest('hex') + '###1';
const response = await axios.get(`${baseUrl}${endpoint}`, {
    headers: { 'Content-Type': 'application/json', 'X-VERIFY': checksum }
});
πŸ“₯ Sample Status Response
{
    "success": true,
    "code": "PAYMENT_SUCCESS",
    "message": "Transaction successful",
    "data": {
        "merchantId": "MERCHANTUID",
        "merchantTransactionId": "TXN123",
        "transactionId": "PhonePeTxnId",
        "amount": 10000,
        "state": "COMPLETED",
        "paymentInstrument": { "type": "UPI", "utr": "1234567890" }
    }
}
⚠️ Do not rely solely on callback – always call status API before updating order status.
βœ… Key Takeaway: Status API provides authoritative final status and protects against callback spoofing.

7.5 Callback & Refund Handling

PhonePe sends payment responses to your redirectUrl via GET (or POST, depending on configuration). You must verify the checksum and process the transaction. Refunds are initiated via API and must be verified similarly.

πŸ“₯ Callback Handling
// Node.js callback handler (GET)
app.get('/phonepe-callback', async (req, res) => {
    const { merchantId, transactionId, amount, checksumHash } = req.query;
    // Recompute checksum for the response
    const payload = `merchantId=${merchantId}&transactionId=${transactionId}&amount=${amount}`;
    const computedHash = crypto.createHash('sha256').update(payload + saltKey).digest('hex') + '###1';
    if (computedHash !== checksumHash) {
        return res.status(400).send('Invalid checksum');
    }
    // Call status API for final confirmation
    const status = await getTransactionStatus(merchantId, transactionId);
    if (status.data.state === 'COMPLETED') {
        // Update order
    }
    res.send('OK');
});
πŸ’° Refund API

POST /pg/v1/refund (requires checksum similar to pay API).

// Refund request payload
{
    "merchantId": "MERCHANTUID",
    "merchantTransactionId": "REFUND123",
    "originalTransactionId": "PhonePeTxnId",
    "amount": 5000,
    "callbackUrl": "https://your-site.com/refund-callback"
}
πŸ’‘ Refunds are processed within 5‑7 days; PhonePe sends a separate callback for refund status.
🚨 Security Note: Refund APIs must be protected with strong authentication – only admin users should initiate refunds.
βœ… Key Takeaway: Implement idempotency for refunds and log all refund activities for audit.

πŸŽ“ Module 07 : PhonePe Payment Gateway – Completed

You have successfully completed this module of Payment Gateway Integration Basics.

Keep building your expertise step by step β€” Learn Next Module β†’