Да, вы правильно прочитали! Здесь, в этом блоге, в ходе нашего индивидуального разговора мы обсудим, как интегрировать платежный шлюз Razorpay в reactjs с API, написанными на Node.js.

Кстати, логика останется прежней, так что неважно, какие языки. Итак, начнем-

Шаг 1.
Создайте учетную запись на Razorpay здесь — Razorpay Dashboard и получите свой идентификатор ключа и Ключевой секрет. Вы получите их в Настройках -> Ключи API.

Примечание. Просто проверьте и подтвердите, что вы находитесь в тестовом режиме.

Шаг 2: я назову этот шаг «Gyaan Charcha» простыми словами «Сессия знаний», потому что на этом этапе мы поймем, как работает платежный шлюз Razorpay. Каков поток платежного шлюза Razorpay?

Эти шаги являются основными блоками платежного потока в Razorpay.

  1. Клиент создает Заказ.
  2. Razorpay создает для него идентификатор заказа, который мы используем в нашей интеграции.
  3. Используя идентификатор заказа, открывается пользовательский интерфейс оформления заказа, в котором клиент вводит данные и выбирает способы оплаты, а также оплачивает сумму.
  4. Затем этот отдельный платеж получает идентификатор платежа, который обрабатывается, и в ответ мы получаем razorpay_signature, razorpay_order_id и razorpay_payment_id.
  5. Затем мы должны авторизовать и зафиксировать этот платеж, чтобы урегулировать и завершить всю транзакцию.
    На следующих этапах мы будем создавать и обрабатывать эти указатели.

Шаг 3. Давайте напишем код.

Примечание. Пожалуйста, прочитайте комментарии, потому что я постарался охватить в комментариях все возможные детали.

Бэкэнд

Инициализация Razorpay

const Razorpay = require('razorpay')

Маршрут API для создания заказа

app.post('/order', async (req, res) => {
    // initializing razorpay
    const razorpay = new Razorpay({
        key_id: req.body.keyId,
        key_secret: req.body.keySecret,
    });
    
    // setting up options for razorpay order.
    const options = {
        amount: req.body.amount,
        currency: req.body.currency,
        receipt: "any unique id for every order",
        payment_capture: 1
    };
    try {
        const response = await razorpay.orders.create(options)
        res.json({
            order_id: response.id,
            currency: response.currency,
            amount: response.amount,
        })
    } catch (err) {
       res.status(400).send('Not able to create order. Please try again!');
    }
});

Для приема и подтверждения платежа

app.post('/payment', async(req,res) => {
  // Here you can retrieve the transaction id and amount from client.
});

Шаг 4:

Внешний интерфейс

Базовый код для кнопки с жестко заданными значениями

const [displayRazorpay, setDisplayRazorpay] = useState(false);
const [orderDetails, setOrderDetails] = useState({
  orderId: null,
  currency: null,
  amount: null,
 });

const handleCreateOrder = async (amount, currency) => {
  const data = await axios.post(serverBaseUrl + '/order',
   {
    amount: amount*100, //convert amount into lowest unit. here, Dollar->Cents
    currency,
    keyId: process.env.REACT_APP_RAZORPAY_KEY_ID,
    KeySecret: process.env.REACT_APP_RAZORPAY_KEY_SECRET,
   }
  );

  if(data && data.order_id){
    setOrderDetails({
      orderId: data.order_id,
      currency: data.currency,
      amount: data.amount,
    });
    setDisplayRazorpay(true);
};

return (
  <div>
    <button 
      onClick={() => handleCreateOrder(100, 'USD')}
    >Place Order
    </button>

  {displayRazorpay && (
  <RenderRazorpay
    amount={orderDetails.amount}
    currency={orderDetails.currency}
    orderId={orderDetails.orderId}
    keyId={process.env.REACT_APP_RAZORPAY_KEY_ID}
    keySecret={process.env.REACT_APP_RAZORPAY_KEY_SECRET}
  />
  }
  </div>
);

Теперь код для рендеринга Razorpay

import { useEffect, useRef } from 'react';
import crypto from 'crypto-js';
import PropTypes from 'prop-types';
import Axios from 'axios';

// Function to load script and append in DOM tree.
const loadScript = src => new Promise((resolve) => {
  const script = document.createElement('script');
  script.src = src;
  script.onload = () => {
    console.log('razorpay loaded successfully');
    resolve(true);
  };
  script.onerror = () => {
    console.log('error in loading razorpay');
    resolve(false);
  };
  document.body.appendChild(script);
});


const RenderRazorpay = ({
  orderId,
  keyId,
  keySecret,
  currency,
  amount,
}) => {
  const paymentId = useRef(null);
  const paymentMethod = useRef(null);

  // To load razorpay checkout modal script.
  const displayRazorpay = async (options) => {
    const res = await loadScript(
      'https://checkout.razorpay.com/v1/checkout.js',
    );

    if (!res) {
      console.log('Razorpay SDK failed to load. Are you online?');
      return;
    }
    // All information is loaded in options which we will discuss later.
    const rzp1 = new window.Razorpay(options);

    // If you want to retreive the chosen payment method.
    rzp1.on('payment.submit', (response) => {
      paymentMethod.current = response.method;
    });

    // To get payment id in case of failed transaction.
    rzp1.on('payment.failed', (response) => {
      paymentId.current = response.error.metadata.payment_id;
    });

    // to open razorpay checkout modal.
    rzp1.open();
  };


  // informing server about payment
  const handlePayment = async (status, orderDetails = {}) => {
    await Axios.post(`${serverBaseUrl}/payment`,
      {
        status,
        orderDetails,
      });
  };


  // we will be filling this object in next step.
  const options = {},

  useEffect(() => {
    console.log('in razorpay');
    displayRazorpay(options);
  }, []);

  return null;
};

export default RenderRazorpay;

Теперь самая важная часть интеграции

const options = {
    key: keyId, // key id from props
    amount, // Amount in lowest denomination from props
    currency, // Currency from props.
    name: 'My custom title', // Title for your organization to display in checkout modal
    // image, // custom logo  url
    order_id: orderId, // order id from props
    // This handler menthod is always executed in case of succeeded payment
    handler: (response) => {
      console.log('succeeded');
      console.log(response);
      paymentId.current = response.razorpay_payment_id;

      // Most important step to capture and authorize the payment. This can be done of Backend server.
      const succeeded = crypto.HmacSHA256(`${orderId}|${response.razorpay_payment_id}`, keySecret).toString() === response.razorpay_signature;
   
      // If successfully authorized. Then we can consider the payment as successful.
      if (succeeded) {
        handlePayment('succeeded', {
          orderId,
          paymentId,
          signature: response.razorpay_signature,
        });
      } else {
        handlePayment('failed', {
          orderId,
          paymentId: response.razorpay_payment_id,
        });
      }
    },
    modal: {
      confirm_close: true, // this is set to true, if we want confirmation when clicked on cross button.
      // This function is executed when checkout modal is closed
      // There can be 3 reasons when this modal is closed.
      ondismiss: async (reason) => {
        const {
          reason: paymentReason, field, step, code,
        } = reason && reason.error ? reason.error : {};
        // Reason 1 - when payment is cancelled. It can happend when we click cross icon or cancel any payment explicitly. 
        if (reason === undefined) {
          console.log('cancelled');
          handlePayment('Cancelled');
        } 
        // Reason 2 - When modal is auto closed because of time out
        else if (reason === 'timeout') {
          console.log('timedout');
          handlePayment('timedout');
        } 
        // Reason 3 - When payment gets failed.
        else {
          console.log('failed');
          handlePayment('failed', {
            paymentReason, field, step, code,
          });
        }
      },
    },
    // This property allows to enble/disable retries.
    // This is enabled true by default. 
    retry: {
      enabled: false,
    },
    timeout: 900, // Time limit in Seconds
    theme: {
      color: 'green', // Custom color for your checkout modal.
    },
  };

Шаг 5. Теперь давайте заплатим.

Вот как это выглядит

Вот несколько важных ссылок, которые могут быть вам полезны:

На этой ноте я возьму отпуск до следующего блога.
В следующем блоге мы обязательно узнаем что-то новое.

Пока.

Если вы читаете этот блог до сих пор, подписывайтесь на меня в Твиттере — @ShubhInTech

окончательное до свидания.