Codementor Events

React - Payment Gateway Integration

Published Apr 12, 2020Last updated Sep 25, 2020
React - Payment Gateway Integration

In this post we will cover Razorpay Payment Gateway integration with Express (server-side) and React (client-side) App. First, understand the payment flow as per their documention.

paymentFlow.JPG

Step 1: Create an Order: Guest select a tariff from property website based on availablity. Our React App sends a request to Express Api to create Order. Express in turn call Razorpay to create an order and razorpay_order_ID is created in Razorpay's servers and returned to Express and then forwarded to Client App.

Step 2: Collect Payment Details: On successful order creation, Payment form is present to Guest. Guest selects the appropriate payment method, fill the deatils and completes the payment. This request is directly sent to RazorPay Server with the details obtained from the Guest along with razorpay_order_ID recived in step 1.

Step 3: Authentication and Authorization of a Payment: The payment details collected from the customer are sent to your bank. Internally, Razorpay sends an authentication request to the customer's bank. After appropriate authentication, Razorpay is authorized to deduct the amount from the customer's bank account. Once authorized, the transaction amount is retained with Razorpay and is not settled to your account immediately. Razorpay returns payment_id which we can finally persist along with Booking details.

Step 4: Capture Payments: Once the payment is authorized by the customer's bank, you must verify if the authorized amount deducted from the customer's account is the same as the amount entered by the customer in the Checkout form. The authorized amount will be settled to your account only after this validation step.

Note:
Any authorization not followed by a capture within 5 days is automatically deemed void and a refund is initiated. If we want to skip step 4 and we have an option of Auto Capture.
This enables the payments to be captured automatically before the end of the authorization period.

Let's check out the code.

Express(Server-side) Code:

First install razorpay node package to Express app.

npm install  razorpay

Next, in controller add below 2 endpoints -

var Razorpay = require('razorpay');

router.post('/sites/:siteAddress/createBookingOrder', async (req,res,next)=> {
    let instance = new Razorpay({
    key_id: hotel.key_id,
    key_secret: hotel.key_secret
  });

  let orderDate = {
    "amount": req.body.bookingAmount * 100,
    "currency": "INR",
    "receipt": "receipt",
    "payment_capture": 1
  };

  instance.orders.create(orderDate, function(err, order) {
    res.status(200).send(order);
  });
});

router.post('/sites/:siteAddress/confirmBooking', async (req,res,next)=> {
  var newEvent = new Event.model({
    name : req.body.name,
    checkinDate : req.body.checkinDate,
    checkoutDate : req.body.checkoutDate,           
    guest : req.body.guest,
    payments : [],
    hotel_id : req.body.hotel_id
  });
  
  let payment = {
    amount : req.body.bookingAmount,
    order_id : req.body.order_id,
    payment_id : req.body.payment_id
  };
  
  newEvent.payments = [...newEvent.payments, payment];
  await newEvent.save().catch(err => {throw err});
  res.status(200).send(newEvent);
});

Important point to note here- "payment_capture": 1 in create order. This enables to skip step 4 and payment is Auto captured.

React(Client-side) Code:

Include script tag to load RazorPay checkout.js file in index.html.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/logo.png" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <script src="https://checkout.razorpay.com/v1/checkout.js"></script>
    <meta name="theme-color" content="#000000" />
    <title>Hotel Front Desk</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

Next in Booking Component add below method -

handleBooking() {       
  CreateBookingOrder({
    "bookingAmount" : this.state.bookingAmount,
    "hotel_id" : this.state.site._id,
    "siteAddress" : this.state.site.siteAddress
  })
  .then(res => {
    this.handleBookingCheckout(res);
  })
  .catch(err => {
    // Handle error.
  });
}

Above, you can see on sucess status we call handleBookingCheckout with the service response which include order_id.

handleBookingCheckout = (res) => {
  var options = {
    "key_id": this.state.site.key_id,
    "amount": res.amount, 
    "currency": "INR",
    "name": this.state.site.name,
    "description": "Booking Request amount for "+this.state.site.name,
    "image": "https://example.com/your_logo",
    "order_id": res.id,
    "handler": this.handleBookingPaymentResponse,
    "prefill": {
      "name": this.state.guest.name,
      "email": this.state.guest.email,
      "contact": this.state.guest.phone,
    },
    "notes": {
      "address": "note value"
    },
    "theme": {
      "color": "#FFFF00"
    }
  };
  
  let rzp = new window.Razorpay(options);
  rzp.open();
}

The above code present a Payment popup where Guest fill the deatils and click pay. Once again you can see we call handleBookingPaymentResponse to handle Razorpay sucess or failure response -

handleBookingPaymentResponse = (res) => {
  this.setState({ loading: true });
  let selectedTariff = this.state.selectedTariff;
  let bookingData = {
    "name": "Booking",
    "checkinDate": this.state.checkin + "T12:00:00",
    "checkoutDate": this.state.checkout + "T12:00:00",
    "bookingAmount" : this.state.bookingAmount,
    "order_id" : res.razorpay_order_id,
    "payment_id" : res.razorpay_payment_id,
    "guest" : this.state.guest,
    "hotel_id" : this.state.site._id,
    "siteAddress" : this.state.site.siteAddress
  };

  ConfirmBooking(bookingData)
  .then(res => {
    // Handle successful booking.
  })
  .catch(err => {
    // Handle booking failure.
  });        
}
Discover and read more posts from DhananjayKumar
get started
post commentsBe the first to share your opinion
Gabriel Hart
a year ago

As someone who works in the payments industry, I find this site to be a valuable resource. They cover a wide range of topics, from payment processing to digital currencies. I recently read an article about the challenges facing the payments industry in a post-pandemic world and found it thought-provoking. If you are interested in keeping up with the latest trends in the payments news industry, this site is a must-read.

Show more replies