DEV Community

Aditi Holkar
Aditi Holkar

Posted on

How to Integrate a Payment Gateway into Your Web App: A Practical Guide

Adding online payments to a web application can make it easier for customers to purchase products, subscribe to services, book appointments, or pay invoices. But payment integration involves more than adding a payment button to a website.

A reliable integration needs a payment gateway, backend APIs, secure authentication, payment status handling, webhooks, and proper error management.

This guide explains the basic process of integrating a payment gateway into a web application, using Razorpay as an example.

1. Understand How Payment Gateway Integration Works

A typical payment flow looks like this:

Customer → Web App → Backend → Payment Gateway → Bank/Payment Network

The customer starts the payment from your website. Your backend creates the payment order through the gateway. The customer then completes the payment using a supported payment method.

After the transaction, your application needs to confirm whether the payment was successful before providing the product or service.

A simplified flow is:

  1. Customer selects a product or service.
  2. Your backend creates an order.
  3. The payment gateway generates the required payment details.
  4. Checkout opens for the customer.
  5. Customer completes the payment.
  6. The gateway returns payment information.
  7. Your backend verifies the payment.
  8. A webhook can update your system about payment events.
  9. Your database records the final payment status.
  10. The application confirms the order.

2. Choose the Right Payment Gateway

Before starting development, compare payment gateways based on factors such as:

  • Supported payment methods
  • Transaction fees
  • API documentation
  • Developer tools
  • Settlement process
  • Refund support
  • International payment support
  • Webhook capabilities
  • Security requirements
  • Customer support

For an Indian web application, gateways such as Razorpay can support common payment methods including UPI, cards, net banking, and wallets, depending on the account and applicable availability.

The important thing is to choose a gateway that fits your application's payment requirements rather than selecting one based only on pricing.

3. Create a Merchant Account

Once you select a gateway, create a merchant account and complete the required verification process.

For Razorpay, developers can use the available test environment to build and test the integration before processing live transactions.

You will generally receive API credentials that allow your backend to communicate with the payment gateway.

Keep these credentials secure.

Never expose secret API keys in frontend JavaScript, HTML, mobile applications, or public repositories.

4. Set Up Your Backend

The backend should handle sensitive payment operations.

For example, your backend might have an endpoint such as:

POST /api/create-payment-order

When the customer clicks "Pay Now", the frontend sends the order information to your backend.

The backend then:

  1. Validates the order.
  2. Calculates the amount.
  3. Creates an order with the payment gateway.
  4. Stores the order information in your database.
  5. Returns the required payment details to the frontend.

The amount should ideally be calculated and validated on the server rather than trusting a price sent directly by the browser.

This prevents customers from manipulating the amount through frontend code.

5. Create a Payment Order

The backend communicates with the gateway API to create a payment order.

For example, suppose a customer is purchasing a product worth ₹2,500.

Your application can create an internal order such as:

Order ID: ORD-1050
Amount: ₹2,500
Currency: INR
Status: Pending

The payment gateway can then create its own corresponding payment order.

Keeping both your internal order ID and the gateway's order ID is useful for tracking and reconciliation.

6. Open the Payment Checkout

After creating the payment order, your frontend can use the payment gateway's checkout mechanism.

The customer may see options such as:

  • UPI
  • Credit card
  • Debit card
  • Net banking
  • Wallets

The exact options depend on the gateway, merchant configuration, customer location, and other factors.

The frontend should not decide whether the transaction is finally successful. It should only handle the customer-facing checkout experience.

7. Verify the Payment on the Server

One of the most important steps is payment verification.

After checkout, the frontend may receive payment information. That information should be sent to your backend for verification.

Your backend can then validate the payment using the gateway's server-side mechanisms.

For Razorpay integrations, signature verification is an important part of confirming that the payment response has not been tampered with.

The general flow is:

Checkout → Payment response → Backend → Signature verification → Payment status

Only after successful verification should your application update the order as paid.

8. Use Webhooks

Payment processing is asynchronous, so your application should also use webhooks.

A webhook allows the payment gateway to send an event directly to your server.

For example:

Razorpay → Webhook → Your Backend

The webhook can notify your application about events such as payment status changes, refunds, settlements, and other payment-related activities.

This is useful when the customer completes a transaction but the browser closes before your frontend receives the final response.

Your webhook endpoint might look conceptually like:

POST /api/payment/webhook

The endpoint receives the event, verifies its authenticity, and updates your database.

9. Make Webhooks Idempotent

Your webhook handler should be designed to handle duplicate events safely.

For example, suppose your system receives the same payment event twice.

Without proper handling, the application might:

  • Mark an order as paid twice
  • Send two confirmation emails
  • Add inventory twice
  • Credit a customer account twice

Store a unique event identifier and check whether the event has already been processed.

A simple approach is:

Receive event → Validate event → Check event ID → Process once → Store event ID

This is called idempotent processing and is essential for reliable payment systems.

10. Handle Payment Failures

Not every payment attempt will succeed.

A transaction can fail because of:

  • Insufficient funds
  • Incorrect card information
  • Bank rejection
  • UPI issues
  • Network problems
  • Payment gateway errors
  • Customer cancellation
  • Session timeout

Your application should clearly distinguish between different states.

Instead of only having:

Success / Failed

consider using:

  • Created
  • Pending
  • Authorized
  • Captured
  • Failed
  • Refunded
  • Unknown

An Unknown or Pending state can be useful when a request times out and you cannot immediately determine whether the transaction succeeded.

11. Do Not Treat a Timeout as an Automatic Failure

This is a common payment integration mistake.

Imagine the following:

Customer → Gateway → Bank

The bank processes the payment successfully, but the response to your application is delayed.

Your server receives a timeout.

If your application immediately marks the transaction as failed, the customer might attempt another payment.

The first transaction could later be successful, resulting in a duplicate payment.

A better approach is to verify the transaction status through the gateway's APIs or wait for the relevant webhook before deciding what happened.

12. Store Payment Information Properly

Your database should maintain a clear relationship between your application order and the payment gateway transaction.

A payment record might contain:

Field Example
Internal Order ID ORD-1050
Gateway Order ID order_xyz
Payment ID pay_xyz
Amount ₹2,500
Currency INR
Status Captured
Created At Timestamp
Updated At Timestamp

Do not store sensitive card information unless your payment architecture and compliance requirements explicitly support it.

In most cases, the payment gateway handles sensitive payment credentials.

13. Protect Your API Credentials

Security should be considered from the beginning.

Follow basic practices such as:

  • Keep secret keys on the backend.
  • Store credentials in environment variables or a secrets manager.
  • Use HTTPS.
  • Validate incoming requests.
  • Verify webhook signatures.
  • Avoid logging sensitive payment information.
  • Restrict access to production credentials.
  • Rotate credentials when necessary.

Never put a secret API key directly into frontend source code.

14. Test Before Going Live

Do not test a payment integration only with a successful transaction.

Test different scenarios, including:

  • Successful payment
  • Failed payment
  • Cancelled payment
  • Payment timeout
  • Duplicate webhook
  • Delayed webhook
  • Invalid webhook signature
  • Server failure
  • Database failure
  • Refund
  • Multiple payment attempts

Razorpay's test environment can be used to validate payment flows without immediately processing real transactions.

Testing these edge cases is especially important because payment problems often happen outside the normal successful flow.

15. Move to Production Carefully

Once testing is complete, review the entire payment flow before switching to live transactions.

Check:

  • Production API credentials
  • HTTPS configuration
  • Webhook URL
  • Webhook signature verification
  • Database updates
  • Error handling
  • Refund handling
  • Logging and monitoring
  • Email/SMS notifications
  • Order confirmation logic

Make sure the production environment does not accidentally use test credentials or test endpoints.

16. Monitor the Integration

After launch, payment integration still needs monitoring.

Track metrics such as:

  • Payment success rate
  • Payment failure rate
  • API response time
  • Webhook failures
  • Pending transactions
  • Refund failures
  • Duplicate events
  • Reconciliation mismatches

For example, if payment failures suddenly increase from 3% to 15%, your monitoring system should help identify the problem quickly.

A Simple Payment Integration Architecture

A practical architecture can look like this:

Customer

Frontend

Your Backend

Razorpay API

Payment Network

Webhook

Your Webhook Handler

Payment Database

Order Confirmation

This approach keeps sensitive operations on the server while allowing the frontend to provide a smooth checkout experience.

Common Mistakes to Avoid

Trusting the frontend for payment confirmation

The frontend response should not be treated as the final source of truth.

Exposing API secrets

Secret credentials should never be included in browser-side code.

Ignoring webhooks

A browser can close or lose connectivity after a payment, so your backend needs another way to receive payment events.

Processing duplicate webhooks

Always design webhook processing to be idempotent.

Marking every timeout as a failed payment

A timeout means the result may be unknown, not necessarily unsuccessful.

Not testing edge cases

Successful payments are only one part of the payment lifecycle.

Conclusion

Integrating a payment gateway into a web application involves several connected components: APIs, checkout, server-side verification, webhooks, database updates, security, and failure handling.

Razorpay can be used as an example of how a modern payment gateway fits into this architecture, but the same principles apply to other payment providers.

The key is to build the integration around server-side verification, secure API communication, reliable webhook handling, idempotency, and clear payment states.

A payment integration should not simply answer the question, "Did the customer click Pay?" It should reliably determine whether the transaction actually succeeded and ensure that your application records that result correctly.

Top comments (1)

Collapse
 
lunarose profile image
Luna Rose

Great breakdown! Payment systems look simple from the outside, but the details really matter. Learned a lot from this guide.