Integrating Razorpay Payment Gateway in ASP.NET Core with Webhook Verification
Overview
The Razorpay Payment Gateway is a powerful tool for enabling online transactions in web applications. It provides a seamless experience for users and developers alike, allowing businesses to accept payments through various methods, including credit cards, debit cards, net banking, UPI, and wallets. The service exists to simplify the payment process, making it easier for businesses to manage finances and for customers to make purchases conveniently.
In today's digital economy, integrating a payment gateway is essential for e-commerce platforms, subscription services, and any application that requires monetary transactions. Razorpay stands out due to its robust API, ease of use, and comprehensive documentation, making it a popular choice among developers. Real-world use cases include online stores, digital service providers, and SaaS applications that require reliable payment processing capabilities.
Prerequisites
- ASP.NET Core SDK: Ensure you have the latest version installed to create and run the application.
- Razorpay Account: Sign up for a Razorpay account to obtain your API keys for integration.
- Basic C# Knowledge: Understanding of C# and ASP.NET Core is necessary to implement the integration.
- Postman or similar tool: For testing API requests and webhook verifications.
Setting Up Razorpay in ASP.NET Core
To begin with, you need to install the Razorpay SDK for .NET, which simplifies the integration process. This can be achieved via NuGet Package Manager. The Razorpay SDK allows you to interact with their API seamlessly, handling requests and responses efficiently.
Install-Package Razorpay.ApiThis command installs the Razorpay API library, which includes necessary classes and methods to create and manage payments. Once the package is installed, you can start configuring your application to use Razorpay.
Configuring Razorpay API Keys
After setting up the Razorpay SDK, the next step involves configuring your API keys in your application. These keys are essential for authenticating API calls to Razorpay's server.
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.Configure(Configuration.GetSection("Razorpay"));
}
} This code snippet shows how to bind your Razorpay configuration section from the appsettings.json file. You will need to create a RazorpayOptions class to hold your API keys.
public class RazorpayOptions
{
public string Key { get; set; }
public string Secret { get; set; }
}In your appsettings.json, you should store your keys securely:
"Razorpay": {
"Key": "YOUR_RAZORPAY_KEY",
"Secret": "YOUR_RAZORPAY_SECRET"
}Creating Payment Orders
Once the Razorpay SDK is set up, the next step is to create a payment order. This is crucial for initiating the payment process in your application. The payment order contains details such as the amount to be charged, currency, and order ID.
public async Task CreateOrder(decimal amount)
{
var options = new Dictionary();
options.Add("amount", amount * 100); // amount in paise
options.Add("currency", "INR");
options.Add("receipt", Guid.NewGuid().ToString());
var client = new RazorpayClient(_razorpayOptions.Key, _razorpayOptions.Secret);
var order = await client.Order.CreateAsync(options);
return Json(order);
} This code creates a payment order by specifying the amount, currency, and a unique receipt ID. The RazorpayClient is instantiated with your API credentials to authenticate the request. The order is then created asynchronously and returned as a JSON response.
Handling the Payment Response
After creating the order, you will receive a unique order ID that you must send to the client-side for processing the payment. On the client side, you will use Razorpay's checkout script to handle the payment.
This script handles the payment process on the client side. It utilizes the Razorpay checkout script to open a payment modal, allowing users to complete their transactions. The response handler function captures payment details that you'll need for verification.
Implementing Webhook Verification
Webhook verification is an essential step in ensuring that the payment confirmation is legitimate. Razorpay sends a webhook to your specified endpoint once a payment is completed. You must verify this webhook to prevent fraud.
[HttpPost]
[Route("api/webhook")]
public async Task Webhook([FromBody] JObject payload)
{
var secret = _razorpayOptions.Secret;
var signature = Request.Headers["X-Razorpay-Signature"];
// Verify the signature
var isValid = VerifySignature(payload.ToString(), signature, secret);
if (!isValid)
{
return BadRequest();
}
// Process the payment
var paymentId = payload["payload"]["payment"]["entity"]["id"].ToString();
// Implement your logic to mark the order as paid
return Ok();
} This code snippet represents a webhook endpoint where Razorpay sends payment notifications. The signature is verified using a custom method, ensuring that the request originated from Razorpay. If the verification fails, it responds with a bad request; otherwise, it processes the payment.
Verifying the Signature
The signature verification method is crucial for maintaining security. It ensures that the payload has not been tampered with. The following code demonstrates how to implement this:
private bool VerifySignature(string payload, string signature, string secret)
{
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
var computedSignature = Convert.ToBase64String(hash);
return computedSignature == signature;
}This method generates a HMAC SHA256 hash of the payload using your secret key and compares it to the signature received from Razorpay. This ensures that only legitimate requests are processed.
Edge Cases & Gotchas
When integrating with Razorpay, developers often encounter several pitfalls. Here are some common edge cases and how to handle them.
Incorrect Amount Handling
One common mistake is incorrectly calculating the amount. Razorpay expects the amount in paise, not rupees. Ensure that you multiply the amount by 100 when creating an order.
// Wrong approach
options.Add("amount", amount); // This will lead to incorrect transaction amountAlways ensure that the amount is multiplied correctly to avoid transaction failures.
Webhook URL Accessibility
Another potential issue is the accessibility of your webhook URL. If the URL is not publicly accessible, Razorpay will not be able to send event notifications. Ensure that your application is deployed and the URL is correctly specified in the Razorpay dashboard.
Performance & Best Practices
To ensure optimal performance and security when integrating Razorpay, consider the following best practices:
- Secure API Keys: Store your API keys securely using environment variables or a secure vault instead of hardcoding them in your application.
- Asynchronous Processing: Handle payment processing asynchronously to avoid blocking the main thread, especially when dealing with multiple transactions.
- Logging: Implement logging for payment transactions and webhook events to facilitate debugging and monitoring.
- Testing Webhooks: Use tools like Postman to simulate webhook events for testing purposes, ensuring your application handles various scenarios correctly.
Real-World Scenario: E-commerce Application
Let's create a simple e-commerce application that integrates Razorpay for handling payments. In this scenario, we'll allow users to add items to a cart and proceed to checkout, where they will complete their payment via Razorpay.
public class CartItem
{
public string ProductId { get; set; }
public int Quantity { get; set; }
}
public class CheckoutController : Controller
{
private readonly RazorpayOptions _razorpayOptions;
public CheckoutController(IOptions razorpayOptions)
{
_razorpayOptions = razorpayOptions.Value;
}
[HttpPost]
public async Task Checkout(List cartItems)
{
var totalAmount = cartItems.Sum(item => item.Quantity * GetProductPrice(item.ProductId));
var order = await CreateOrder(totalAmount);
return Json(order);
}
private decimal GetProductPrice(string productId)
{
// Assume this method fetches the product price from a database
return 500; // For example purposes
}
} This CheckoutController receives a list of cart items, calculates the total amount, creates a Razorpay order, and returns the order details. This is a simplified example; in a real application, you would retrieve product prices from a database.
Conclusion
- Razorpay is a powerful payment gateway that simplifies online transactions.
- Securely implementing webhook verification is crucial for ensuring legitimate payments.
- Always handle amounts in paise to avoid transaction errors.
- Follow best practices for security and performance to enhance application reliability.
- Testing is vital for ensuring your payment integration works under various scenarios.