Razorpay Payment Integration using PHP
GuruPrakash August 16, 2025

Simplified Razorpay Integration with Core PHP
Introduction
This blog post provides a comprehensive, step-by-step guide for integrating the Razorpay payment gateway into a website using core PHP. It focuses on a simple, direct approach, covering the entire payment lifecycle from initial setup and order creation to secure payment handling, verification, and robust error management. By following these instructions, developers can quickly and securely enable online payments, ensuring a smooth transaction experience for their users. Razorpay is widely recognized for its straightforward integration process and extensive support for various payment methods, including debit and credit cards, net banking, UPI, and digital wallets. This versatility makes it a highly effective choice for businesses of all sizes. The design of Razorpay, including its well-documented PHP SDK and clear integration steps, directly addresses the need for a "simple" integration using "core PHP". This approach highlights a broader trend in payment gateway development, where prioritizing developer experience and reducing implementation barriers fosters wider adoption and a more resilient ecosystem.
1. Getting Started with Razorpay and PHP
This section lays the groundwork, ensuring all necessary accounts, API keys, and the PHP environment are properly configured to begin the integration.
1.1. Prerequisites: Razorpay Account & API Keys
Before initiating any code development, establishing a Razorpay merchant account is a fundamental prerequisite. Users must sign up for an account on the official Razorpay website and then proceed to generate their unique API credentials from the Razorpay Dashboard. These credentials typically consist of a Publishable Key and a Secret Key. The Publishable Key is intended for client-side use, such as within JavaScript for the checkout form, while the Secret Key is exclusively for server-side operations, where it is used to authenticate requests to Razorpay's APIs.
References:
- Prerequisites: https://razorpay.com/docs/payments/…
- Integration Steps: https://razorpay.com/docs/payments/server-integration/…
A critical aspect of the development workflow involves the distinction between Test Mode API Keys and Live Mode API Keys. Test Keys are designed for development and testing purposes, allowing developers to simulate transactions without any real financial deductions. This provides a risk-free environment for iterative development and debugging. Once the integration has been thoroughly tested and is deemed production-ready, the system must be switched to Live Mode API Keys to begin accepting actual payments.
The management of the Secret Key demands the highest level of security. This key is highly sensitive and must never be exposed in client-side code, committed to version control systems like Git or GitHub, or shared unnecessarily. The Secret Key grants comprehensive access to your Razorpay account's API functionalities. Its compromise would lead to severe financial and data breaches, including the potential for unauthorized order creation, refund initiation, or transaction manipulation. Therefore, it is imperative to store the Secret Key securely on the server, ideally utilizing environment variables or a secure vault, and to restrict access to it on a strict need-to-know basis. This practice reinforces that even for seemingly "simple" core PHP integrations, adherence to enterprise-level security awareness for credential management is non-negotiable.
1.2. Setting Up Your PHP Environment & SDK
To facilitate efficient interaction with Razorpay's APIs, utilizing their official PHP SDK is highly recommended.
The Razorpay PHP SDK mandates a modern PHP environment, specifically PHP v8.3 or higher. This requirement is significant as it ensures compatibility with the latest SDK features and allows the integration to leverage the performance enhancements and security improvements inherent in contemporary PHP versions. While older documentation might reference PHP 5.3 , the current requirement for PHP 8.3+ is a clear indication of Razorpay's commitment to modern development stacks. This implicitly encourages developers to maintain up-to-date environments, leading to more stable, secure, and performant payment integrations.
composer require razorpay/razorpay
The most straightforward method for installing the Razorpay PHP SDK is through Composer, the widely adopted PHP dependency manager. For projects already utilizing
Composer, the following entry should be added to the composer.json
file:
{ "require": { "razorpay/razorpay": "1.*" } }
Subsequently, executing composer update
in the terminal will install the necessary dependencies. For environments where Composer is not an option, the razorpay-php.zip
file can be downloaded directly
from Razorpay's GitHub releases section. This archive is pre-compiled to include all required dependencies.
The SDK itself is designed with modern programming practices, namespaced under Razorpay\Api
. This structure prevents naming conflicts in larger projects and promotes code organization. Interactions with various API
resources, such as payment, order, or customer, are performed using an object-oriented syntax, for example, $api->class->function()
. A notable aspect of the SDK's design is its approach to error handling: it throws
exceptions rather than returning simple error codes. This design compels developers to explicitly implement try-catch blocks
, which is crucial for gracefully managing unexpected issues and ensuring application
stability. This structured error management leads to more robust applications that can handle failures predictably, improving both user experience and debugging efficiency.
A typical project structure for a simple core PHP integration often includes index.php
for handling order creation and displaying the checkout interface, config.php
for securely storing API keys, and
verify.php for processing payment signature verification. This separation of concerns contributes to a cleaner and more maintainable codebase.
References:
- razorpay-php: https://leopride.in/public/razorpay-php…
2. The Core Payment Flow: A Simple Walkthrough
This section details the fundamental steps involved in processing a payment, from initiating an order on the server to presenting the checkout form and receiving payment responses.
2.1. Creating an Order on the Server-Side (PHP)
A crucial initial step in the Razorpay payment flow involves creating an "Order" on the server. This server-side action is paramount for security and ensures that sensitive payment details cannot be manipulated on the
client-side. An order serves as a secure container for transaction details, including the amount and currency. By creating it server-side, the system prevents malicious users from altering critical parameters before the payment
is initiated. The order_id
returned by Razorpay after this creation acts as a unique, untamperable reference for the specific payment. This design pattern ensures that the actual transaction amount
and
currency
are determined and locked down by the trusted backend, making it impossible for a malicious user to alter these critical values on the client-side. The order_id then serves as an immutable reference,
significantly enhancing the security of the payment process.
Developers will utilize the Razorpay PHP SDK to interact with the Orders API. This interaction is a server-to-server call, authenticated securely using the Secret Key. When creating an order, it is mandatory to specify the
amount and currency. The amount must be provided in the smallest currency subunit; for instance, for INR 500, the value 50000
(representing 50000 paise) should be passed. Similarly, for USD 2.95, the value
295
(representing 295 cents) would be used. This approach to specifying amounts in currency subunits is a vital financial best practice. It effectively circumvents the inherent precision issues associated with
floating-point numbers in computer arithmetic, which can lead to inaccuracies when processing monetary values. By exclusively using integers for the smallest currency unit, Razorpay ensures exact calculations, thereby preventing
potential discrepancies in financial reporting and reconciliation.
Optional parameters can also be included during order creation, such as receipt
, which serves as an internal reference ID for your system (maximum 40 characters), and notes
, a key-value pair object for
storing additional relevant information (up to 15 pairs, each 256 characters long). Other optional parameters include partial_payment
(a boolean indicating if partial payments are allowed) and
first_payment_min_amount
(an integer specifying the minimum amount for the first partial payment, applicable only if partial_payment is true).
A conceptual PHP code example for creating an order is as follows:
require 'vendor/autoload.php'; // Or path to Razorpay SDK if downloaded manually
use Razorpay\Api\Api;
// Load your API keys from a secure configuration (e.g., environment variables)
$keyId = getenv('RAZORPAY_KEY_ID');
$keySecret = getenv('RAZORPAY_KEY_SECRET'); // THIS MUST BE KEPT ABSOLUTELY SECURE AND NEVER EXPOSED
$api = new Api($keyId, $keySecret);
$amount = 50000; // Amount in paise (e.g., 500 INR)
$currency = 'INR';
$receiptId = 'order_rcptid_'.uniqid(); // Generate a unique receipt ID for your reference
try {
$order = $api->order->create();
$orderId = $order['id'];
// Store $orderId in your database along with other order details.
// This $orderId will be passed to the client-side for checkout.
} catch (Exception $e) {
// Handle API errors gracefully
error_log('Razorpay Order Creation Error: '. $e->getMessage());
echo 'An error occurred during order creation. Please try again.';
exit();
}
?>
References:
- Create an Order: https://razorpay.com/docs/api/orders/create
2.2. Displaying the Checkout Form (HTML & JavaScript)
Once an order has been securely created on the server, the next step involves presenting the Razorpay Checkout form to the customer on the client-side. This is typically achieved using a combination of HTML for a "Pay" button and JavaScript to invoke the Razorpay Checkout SDK.
To enable the Razorpay Checkout functionality, the Checkout JavaScript library must be included in your HTML page by adding the following script tag:
The options object passed to the rzp1.open()
method is crucial for configuring the appearance and behavior of the checkout experience. Mandatory parameters include your API Key ID (key), the amount (which must be
the same as the server-side order amount, in currency subunits), the currency (matching the order's currency), your business name, a description for the purchase, and most importantly, the order_id
obtained from the
server-side order creation.
Beyond these mandatory fields, a wide array of recommended and optional parameters are available to enhance the user experience and optimize conversion rates. For instance, the prefill object allows pre-populating customer details such as name, email, and contact. Prefilling contact information, especially the phone number, is specifically recommended as it can significantly boost conversions. The image parameter allows displaying your business logo on the checkout form. The theme object enables customization of the checkout's appearance, including color for text, icons, and call-to-action buttons, and backdrop_color for the background. The modal object provides granular control over the checkout modal's behavior, offering options like backdropclose (to close on outside click), escape (to close on escape key press), confirm_close (to show a confirmation dialog), ondismiss (a function to track modal closure), and animation.
For handling the payment response, developers have two primary choices: a callback_url
or a handler function. A callback_url is a specified URL to which Razorpay will POST payment response data upon successful
completion, typically redirecting the user. Alternatively, a handler function allows the success or failure response to be processed directly within a JavaScript function, keeping the user on the current page.
The rzp1.open()
method is invoked, typically tied to a user action such as clicking a "Pay" button. The extensive customization options available for the checkout form are not merely aesthetic; they are instrumental
in optimizing the user experience. Features like prefilling customer data, thematic customization, and modal behavior controls directly influence how seamless and trustworthy the checkout process feels to the customer. By
thoughtfully utilizing these options, developers can craft a more professional and user-friendly checkout interface, which directly leads to higher conversion rates and a reduction in abandoned carts.
2.3. Handling Payment Responses (Client-Side & Server-Side)
Upon the successful completion of a payment, the Razorpay Checkout form returns three crucial fields: razorpay_payment_id, razorpay_order_id, and razorpay_signature
. It is imperative that these fields are securely
received and stored on your server for subsequent verification and record-keeping.
The method of receiving these response fields depends on the approach chosen during checkout configuration:
- Callback URL:
- If a callback_url was specified in the checkout options, Razorpay will perform an HTTP POST request to this URL upon successful payment. The request body will contain the razorpay_payment_id, razorpay_order_id, and razorpay_signature. This method typically involves a redirect of the user's browser to the specified callback URL.
- Handler Function:
- If a JavaScript handler function was used, the success response is received directly within this function on the client-side. This approach allows the user to remain on your web page without redirection. In this scenario, it is the developer's responsibility to then send these received details to the server via an AJAX call for server-side processing and verification.
For failed payments, Razorpay provides an error object within the response, which includes parameters such as code, description, and field. This information allows the application to gracefully handle failures, notify the customer about the issue, and provide options to retry the payment.
Regardless of the method used to receive the response, the transaction details, including payment status, payment ID, amount, and the time of payment, should be promptly inserted or updated in your database. It is important to
understand that the client-side response, whether from a callback URL or a handler function, is merely an indication of the payment initiation. The true and definitive status of the payment, along with its integrity, is
established through server-side verification against Razorpay's API and the securely stored order_id
. This critical distinction prevents fraudulent claims or data inconsistencies, as the authoritative source for
payment status remains the server-side validation.
Table 3: Razorpay Payment Response Fields for Server-Side Handling
This table outlines the essential fields returned by Razorpay Checkout upon a successful payment, which are crucial for server-side processing and verification. These fields form the cornerstone of ensuring transaction security and integrity within your application.
Field Name | Type | Description |
---|---|---|
razorpay_payment_id | string | A unique identifier for the payment, returned by Checkout only for successful payments. |
3. Securing Your Payments: Verification and Best Practices
Security is paramount in payment processing. This section details the essential steps to verify payments and outlines general security best practices for your PHP integration.
3.1. Verifying Payment Signature (Server-Side PHP)
Payment signature verification is a mandatory step that must be performed on your server to confirm the authenticity and integrity of the payment details received from Razorpay Checkout. This process ensures that the payment data has not been tampered with during transmission and that it genuinely originated from Razorpay.
To verify the razorpay_signature
received from the checkout, a signature must be created on your server. This server-side signature is generated using a combination of the order_id (which should be retrieved from
your own trusted database, not the one returned by Checkout), the razorpay_payment_id
(received from Checkout), and your Key Secret (stored securely on your server). The signature is computed using the
HMAC with SHA256 algorithm. The formula for this generation is:
generated_signature = hmac_sha256(order_id + "|" + razorpay_payment_id, secret);
Once the generated_signature
is computed, it is compared against the razorpay_signature
that was returned by the Razorpay Checkout. If these two signatures match, it confirms that the payment is
authentic and the data has not been altered, originating from a legitimate source.
The Razorpay PHP SDK provides a convenient utility function to simplify this verification process:
// Assuming $api is already initialized with your Key ID and Key Secret
try {
$api->utility->verifyPaymentSignature(array(
'razorpay_order_id' => $razorpayOrderId, // Your order ID from your database
'razorpay_payment_id' => $razorpayPaymentId, // Received from Razorpay Checkout
'razorpay_signature' => $razorpaySignature // Received from Razorpay Checkout
));
// Signature is valid, payment is successful and authentic
// Proceed to update your database, fulfill the order, etc.
echo "Payment successful and verified!";
} catch (Exception $e) {
// Signature verification failed
error_log('Razorpay Signature Verification Failed: '. $e->getMessage());
echo "Payment failed or tampered. Verification failed.";
// Handle fraudulent attempt or log for investigation
}
?>
This server-side validation is crucial because client-side data can be easily manipulated. By performing this cryptographic check on the server, the system establishes a robust defense against various forms of payment fraud, ensuring that only legitimate and untampered transactions are processed.
3.2. Capturing Payments
After a payment is successfully authorized through the Razorpay Checkout, it needs to be captured for the funds to be settled into your bank account. Payments that are authorized but not captured are automatically refunded by Razorpay after a fixed period. It is a critical operational guideline that products or services should only be delivered to the customer after the payment has been successfully captured.
Razorpay offers two primary methods for capturing payments:
- Auto-capture Payments (Recommended):
- The most efficient and recommended approach is to configure global settings on your Razorpay Dashboard to automatically capture all authorized payments. This streamlines the payment fulfillment process and requires integration with the Orders API on your server side to ensure proper tracking and reconciliation.
- Manually Capture Payments:
- Payments can also be captured manually through the Razorpay Dashboard or programmatically using the Razorpay API. This method might be preferred for businesses requiring manual review or additional checks before capturing funds.
The status of payments can be tracked using the Fetch a Payment API or by subscribing to webhook events.
3.3. General Security Best Practices for PHP Integration
Beyond payment-specific security measures, adhering to general web security best practices is vital for any PHP application handling sensitive data.
- Use HTTPS/TLS:
- All communication between the user's browser and your web server must be encrypted using HTTPS (TLS/SSL). This protocol encrypts data in transit, protecting it from interception and man-in-the-middle attacks.
- Validate User Input:
- All user input, whether from forms or URL parameters, must be rigorously validated before being processed by your PHP code. This prevents various vulnerabilities, including SQL injection and cross-site scripting (XSS).
- Limit Error Messages:
- Error messages displayed to users should be generic and avoid revealing sensitive details about your server environment, application logic, or database structure. Detailed error logs should be stored securely on the server for debugging purposes.
- Perform Regular Security Audits:
- Regularly auditing your website and application code helps identify and fix vulnerabilities before they can be exploited by attackers.
- Secure Configuration Files:
- Configure your web server to restrict direct access to sensitive configuration files (e.g., config.php) that contain API keys or database credentials. These files should be placed outside the web-accessible root directory or protected with .htaccess rules.
- Keep PHP and Dependencies Updated:
- Consistently update your PHP version to the latest stable release (e.g., PHP 8.3+) and keep all external libraries and frameworks (including the Razorpay PHP SDK) up-to-date. This ensures that your application benefits from the latest security patches and performance improvements, minimizing exposure to known vulnerabilities.
- Protect Against XSS and CSRF:
- Implement measures to protect against Cross-Site Scripting (XSS) by escaping all user-generated content before displaying it. Guard against Cross-Site Request Forgery (CSRF) attacks by using anti-CSRF tokens in forms.
- Implement Proper Authentication and Authorization:
- Ensure your application correctly verifies user identity (authentication) and controls access to resources based on user roles and permissions (authorization).
- Secure API Key Storage:
- As previously emphasized, API Secret Keys must never be hardcoded directly into public-facing files or committed to version control. They should be stored in secure environment variables or a dedicated secure vault, with access granted only on a strict need-to-know basis.
- Implement Two-Factor Authentication (2FA):
- For access to your Razorpay Dashboard and any internal systems managing sensitive payment data, enable and enforce Two-Factor Authentication across your team. This adds an extra layer of security beyond passwords.
Reference:
- Business Security Checklist: https://razorpay.com/docs/security/checklist
- SaaS tools
4. Enhancing Reliability with Webhooks
Webhooks provide a robust and real-time mechanism for receiving notifications about events related to your payment flow. They are crucial for maintaining data consistency and reacting promptly to transaction status changes without constant polling.
4.1. Understanding Webhooks
Webhooks, also known as Web Callbacks or HTTP Push APIs, enable one web application to send information to another in real-time when a specific event occurs. Instead of your application continuously polling Razorpay's APIs for status updates (e.g., checking if a payment link has been paid), webhooks allow Razorpay to send an automatic HTTP POST payload in JSON format to a configured URL on your server when an event is triggered.
For payment integrations, webhooks are invaluable for receiving notifications about critical events such as payment.authorized, payment.captured, payment.failed, and others
related to orders, settlements, or
refunds. This real-time notification system helps in managing late authorizations, updating order statuses, and promptly addressing failed payments.
When setting up webhooks from your Razorpay Dashboard, it is possible to configure separate URLs for Live mode and Test mode. This allows for comprehensive testing of your webhook listener in a sandbox environment before deploying it to production. It is important to note that webhook delivery requires a publicly accessible URL; localhost cannot be used directly. For testing purposes on a local development machine, tunneling tools like ngrok or localtunnel can be utilized to expose your local server to the internet.
4.2. Setting Up and Validating Razorpay Webhooks in PHP
To set up a webhook, navigate to the "Webhooks" section in your Razorpay Dashboard and add a new webhook endpoint, specifying the URL on your server that will receive the notifications. You will also select the specific events you wish to be notified about (e.g., payment.captured, payment.failed). Crucially, you should also set a "Webhook Secret".
When Razorpay sends a webhook request, it includes an X-Razorpay-Signature header in the HTTP request. This signature is a hash calculated using HMAC with the SHA256 algorithm, where your configured Webhook Secret acts as the key and the raw webhook request body serves as the message. Validating this signature on your server is paramount for security, as it confirms the authenticity of the webhook request and ensures that the payload has not been tampered with.
The Razorpay PHP SDK provides a utility function for webhook signature validation. Alternatively, manual validation can be performed:
// webhook.php
require 'vendor/autoload.php'; // Or path to Razorpay SDK if downloaded manually
use Razorpay\Api\Api;
// Load your Razorpay Key Secret and Webhook Secret from secure configuration
$keyId = getenv('RAZORPAY_KEY_ID');
$keySecret = getenv('RAZORPAY_KEY_SECRET');
$webhookSecret = getenv('RAZORPAY_WEBHOOK_SECRET');
$api = new Api($keyId, $keySecret);
// Get the raw POST body
$webhookBody = file_get_contents('php://input');
$webhookSignature = isset($_SERVER)? $_SERVER : '';
// Parse the JSON payload
$eventData = json_decode($webhookBody, true);
if (empty($webhookSecret)) {
// Webhook secret not configured, log and exit
error_log("Webhook secret not set. Cannot verify signature.");
http_response_code(400); // Bad Request
exit();
}
try {
// Verify the webhook signature using the SDK utility
$api->utility->verifyWebhookSignature($webhookBody, $webhookSignature, $webhookSecret);
// Signature is valid, process the webhook event
$eventType = $eventData['event'];
$payload = $eventData['payload'];
switch ($eventType) {
case 'payment.authorized':
// Handle payment authorized event
// Update your database to mark the payment as authorized
// This is useful if auto-capture is off or for specific workflows
error_log("Payment Authorized: ". $payload['payment']['entity']['id']);
break;
case 'payment.captured':
// Handle payment captured event
// Update your database to mark the payment as captured
// Fulfill the order, send confirmation emails, etc.
error_log("Payment Captured: ". $payload['payment']['entity']['id']);
break;
case 'payment.failed':
// Handle payment failed event
// Update your database, notify customer, etc.
error_log("Payment Failed: ". $payload['payment']['entity']['id']. " - ". $payload['payment']['entity']['error_description']);
break;
// Add more cases for other events as needed
default:
error_log("Unhandled webhook event type: ". $eventType);
break;
}
http_response_code(200); // Acknowledge receipt of the webhook
} catch (Exception $e) {
// Signature verification failed
error_log('Razorpay Webhook Signature Verification Failed: '. $e->getMessage());
http_response_code(400); // Bad Request
exit();
}
?>
To handle duplicate webhook events, which can occur due to network issues or retries, developers can utilize the x-razorpay-event-id header. This header contains a unique ID for each event. By checking if an event with the same ID has already been processed, applications can prevent redundant processing and maintain data integrity. Additionally, for enhanced security, it is advisable to whitelist Razorpay's IP addresses from which webhook requests originate.
4.3. Testing Webhook Integration
Thoroughly testing webhook integration is crucial to ensure reliable real-time updates. This can be achieved through several methods:
- Request Interceptor Tools:
- Services like requestbin allow developers to create a temporary public endpoint to capture and inspect incoming webhook payloads. This is useful for verifying the structure and content of the data sent by Razorpay.
- Localhost Tunneling:
- As direct localhost access is not possible for webhooks, tools such as ngrok or localtunnel create a secure tunnel from a public URL to your local development server. This enables testing webhook events on your local machine.
- Staging Environment:
- Before going live, it is highly recommended to test the webhook integration in a staging environment. This mirrors the production setup, allowing for comprehensive testing with test mode transactions and a configured staging host endpoint.
- Validate and Test Webhooks: https://razorpay.com/docs/webhooks/…
5. Error Handling and Troubleshooting
Implementing robust error handling is fundamental for creating a reliable payment integration. It allows the application to gracefully manage unexpected issues, provide informative feedback to users, and facilitate debugging.
5.1. Understanding Razorpay API Errors
Razorpay APIs, when invoked, can result in either a successful response (HTTP Status code 200) or a failure response. In the event of a failure, Razorpay returns a JSON error response that provides valuable diagnostic
information. This error response typically contains parameters such as code, description, field, source, step, reason, and metadata
.
These parameters are designed to help developers:
- Map and Analyze Failure Reasons: Understand common causes of errors.
- Identify Source of Failure: Determine if the error originated from a customer action, Razorpay's system, the payment gateway, the bank, or network issues. Razorpay categorizes errors into "Business" (requiring merchant action) and "Internal" (technical errors on Razorpay's server).
- Pinpoint Failure Stage: Identify the exact step in the transaction flow where the error occurred.
- Provide User Feedback: Display appropriate and meaningful messages to customers, guiding them on next steps.
Common HTTP error codes include 400 (Bad Request), 401 (Unauthorized), and 500 (Internal Server Error). For instance, a BAD_REQUEST_ERROR with a description like
"Authentication failed due to incorrect otp" and a reason of invalid_otp
indicates a customer-side issue during payment authentication.
5.2. Implementing Robust PHP Error Handling
Given that the Razorpay PHP SDK is designed to throw exceptions for errors , implementing try {} catch {}
blocks is the standard and most effective way to handle these situations in your core PHP application.
A basic try-catch structure in PHP, especially since PHP 7, should utilize the Throwable interface in the catch block to ensure that both Error and Exception types are caught, thereby increasing the robustness of error management.
// Example of try-catch for API calls
require 'vendor/autoload.php';
use Razorpay\Api\Api;
use Razorpay\Api\Errors\BadRequestError; // Example of a specific Razorpay SDK exception
$keyId = getenv('RAZORPAY_KEY_ID');
$keySecret = getenv('RAZORPAY_KEY_SECRET');
$api = new Api($keyId, $keySecret);
try {
// Code that might throw a Razorpay SDK exception, e.g., order creation
$order = $api->order->create();
echo "Order created successfully: ". $order['id'];
} catch (BadRequestError $e) {
// Handle specific Razorpay API bad request errors
error_log("Razorpay Bad Request Error: ". $e->getMessage(). " - Code: ". $e->getCode());
echo "Payment request invalid. Please check details and try again.";
} catch (Throwable $e) {
// Catch any other general exceptions or errors
error_log("An unexpected error occurred: ". $e->getMessage());
echo "An unexpected error occurred. Please try again later.";
} finally {
// Optional: Code that always runs, regardless of whether an exception was thrown
// e.g., closing database connections or releasing resources
}
?>
Logging errors is a critical practice for troubleshooting and analyzing failure reasons. Detailed error logs should capture the error code, description, source, step, and reason
provided by Razorpay to facilitate
quicker diagnosis and resolution.
For network issues resulting in 5XX errors (e.g., timeouts), Razorpay's idempotency feature is specifically designed to handle such scenarios. If a request times out or returns a 5XX error, the same request can be safely retried using the exact same request body and idempotency key within a 7-day window. Razorpay ensures that the request is not processed again if it has already been completed on their end. It is recommended to implement retry logic with increasing intervals (e.g., 1, 2, and 5 minutes for each retry).
Finally, while detailed error logging is essential for developers, user-facing error messages should be concise and user-friendly. Instead of displaying raw API error codes, the application should translate these into understandable instructions for the customer, such as "Payment failed due to incorrect OTP. Please try again with the correct OTP."
6. Testing Your Integration and Going Live
A robust payment integration requires thorough testing before deployment to a live environment. This section covers the testing process and the final steps for going live.
6.1. Comprehensive Testing with Test Cards
Before accepting real payments, it is imperative to conduct comprehensive testing of your Razorpay integration. This should always be done using your Test Mode API Keys and the specific test cards provided by Razorpay. Using test keys ensures that no real money is transacted during these simulated payments.
The testing process should cover the entire payment flow:
- Order Creation: Verify that orders are successfully created on your server and that the order_id is correctly generated and passed to the client-side.
- Checkout Display: Confirm that the Razorpay Checkout form appears correctly, pre-fills customer details (if configured), and reflects the correct amount and currency.
-
Payment Success: Simulate successful payments using test cards. Verify that the
razorpay_payment_id, razorpay_order_id, and razorpay_signature
are correctly received by your server, and that the payment signature verification passes. Crucially, ensure that your database is updated accurately to reflect the successful transaction. - Payment Failure: Test various failure scenarios using provided test card numbers for failed transactions. Verify that your application correctly handles the error response from Razorpay, displays appropriate messages to the user, and updates your database accordingly.
- Webhooks: If webhooks are configured, ensure that your webhook listener correctly receives, validates, and processes the payment.authorized, payment.captured, and payment.failed events. Verify that your system reacts appropriately to these real-time notifications, such as updating order statuses or triggering fulfillment processes.
7. Conclusion and Recommendations
Integrating Razorpay payment gateway using core PHP, while seemingly simple, involves a series of critical steps that, when implemented correctly, result in a secure, efficient, and reliable payment solution. The process begins with meticulous setup, including generating and securely managing API keys, and configuring the PHP environment with the appropriate SDK version. The core payment flow emphasizes server-side order creation to prevent tampering, followed by a customizable client-side checkout experience.
The robustness of the integration hinges on rigorous server-side payment signature verification, which is a non-negotiable step for authenticating transactions. Leveraging webhooks is highly recommended for real-time updates and efficient asynchronous processing of payment events, significantly enhancing the reliability of the system. Furthermore, comprehensive error handling, coupled with general web security best practices, ensures that the application can gracefully manage failures and protect sensitive financial data.
By adhering to these principles, developers can establish a robust and secure Razorpay payment integration using core PHP, providing a seamless and trustworthy transaction experience for their users.