---
page_title: Create an Order to Open Payment Page
product: SmartGateway Kits Integration
platform: Web
page_source: https://smartgateway.hdfc.bank.in/docs/smartgateway-kits-integration/web/how-to-integrate-kits/create-an-order-to-open-payment-page
llms_txt: https://smartgateway.hdfc.bank.in/docs/llms.txt
product_llms_txt: https://smartgateway.hdfc.bank.in/docs/smartgateway-kits-integration/llms.txt
---


# Create an Order to Open Payment Page




### Step 1 Add Session Create function in your backend


Expose `/initiatePayment.php`API endpoint in your backend that calls the `Create` function. This API endpoint will be called from your frontend to open the payment page.

For ease of implementation, you can refer to session( ) function from ‘PaymentHandler.php’ file and update the following parameters:


| Parameters | Type  | Description |
|---|---|---|
| order_id | Mandatory  | Unique identifier for the order |
| customer_id | Optional | It is the ID with which merchant refers to a customer object. This id is used to access the stored payment methods, allow EMI transactions and setup subscriptions. In case of guest login it should be an empty string |
| amount | Mandatory | Amount that the customer has to pay. Will accept stringified double or integer values with upto two decimal places (Example: "100.15" and "100" are valid input but "100.1532" is not valid) |
| return_url | Optional  | A fully qualified URL on which the customer will be redirected after payment completion |
| payment_page_client_id | Mandatory  | For Sandbox, add 'hdfcmaster' as your client_id |
| merchant_id  | Optional   | Add the Merchant_ID provided by the bank |




#### Code Snippets: -

#### PHP Code Snippet:

```php
$params = json_decode("{\n\"amount\":\"10.00\",\n\"order_id\":\"$orderId\",\n\"customer_id\":\"$customerId\",\n\"action\":\"paymentPage\",\n\"return_url\": \"http://localhost:5000/handlePaymentResponse.php\"\n}", true);
try {
    $session = $paymentHandler->orderSession($params);
```



### Step 2 (Optional) Additional params for Order Session function


You may add these below mentioned **optional params**  in your order session function added in the previous step as per your use case:


| Parameters | Description |
|---|---|
| customer_email | Email address of the customer. If the backend gateway requires it, then you must send this value. |
| customer_phone | Mobile number or fixed line number of the customer. If the backend gateway requires it, then you must send this value. We recommend passing a 10-digit number without including the "+91" or any mobile country code at the beginning. |
| first_name | First Name of customer. This value will be used for customer identification. |
| last_name | Last name of customer. This value will be used for customer identification. |
| description | Description for order to be displayed to the user on amountBar. |
| currency | Currency for the order. It should only be passed when supported by the Payment Gateway and enabled in the SmartGateway Dashboard within EC Operations → PGCC → Select PG → Edit → Supported Currencies. |
| udf1, udf2, udf3, udf4, udf5 (No Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |
| udf6, udf7, udf8, udf9, udf10 (Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |




#### Code Snippets: -

#### PHP Code Snippet:

```php
<?php
use PaymentHandler\APIException;
require_once realpath("./PaymentHandler.php");
use PaymentHandler\PaymentHandler;

$paymentHandler = new PaymentHandler("resources/config.json");

$orderId = "php_sdk_" . uniqid();
$customerId = "php_sdk_customer" . uniqid();
// block:start:session-function
$params = json_decode("{\n\"amount\":\"10.00\",\n\"order_id\":\"$orderId\",\n\"customer_id\":\"$customerId\",\n\"action\":\"paymentPage\",\n\"return_url\": \"http://localhost:5000/handlePaymentResponse.php\"\n}", true);
try {
    $session = $paymentHandler->orderSession($params);
    // block:end:session-function
    $redirect = $session["payment_links"]["web"];
    header("Location: {$redirect}");
    exit;

} catch (APIException $e ) {
    http_response_code(500);
    $error = json_encode(["message" => $e->getErrorMessage(), "error_code" => $e->getErrorCode(), "http_response_code" => $e->getHttpResponseCode()]);
    echo "<p> Payment server threw a non-2xx error. Error message: {$error} </p>";
    exit;
 } catch (Exception $e) {
    http_response_code(500);
    echo " <p> Unexpected error occurred, Error message:  {$e->getMessage()} </p>";
    exit;
}
?>

```



### Step 1 Add Session Create function in your backend


Expose `/initiatePayment` API endpoint in your backend. This API endpoint will be called from your frontend to open the payment page.

For ease of implementation, you can refer to order session function from ‘index.js’ file and update the following parameters:


| Parameter | Type | Description |
|---|---|---|
| order_id | Mandatory | Unique identifier for the order |
| customer_id | Optional | It is the ID with which merchant refers to a customer object. This id is used to access the stored payment methods, allow EMI transactions and setup subscriptions. In case of guest login it should be an empty string |
| payment_page_client_id | Mandatory | For Sandbox, add 'hdfcmaster' as your client_id |
| amount | Mandatory | Amount that the customer has to pay. Will accept stringified double or integer values with upto two decimal places. (Example, "100.15" and "100" are valid input but "100.1532" is not valid) |
| return_url | Optional | A fully qualified URL on which the customer will be redirected after payment completion |
| merchant_id | Mandatory | Add the Merchant_ID provided by the bank |




#### Code Snippets: -

#### NodeJS Code Snippet:

```nodejs
const express = require("express");
const {
  PaymentHandler,
  APIException,
  validateHMAC_SHA256,
} = require("./PaymentHandler");
const crypto = require("crypto");
const path = require("path");
const app = express();
const port = process.env.PORT || 5000;

app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
app.get("/", (_, res) =>
  res.sendFile(path.join(__dirname, "public", "initiatePaymentDataForm.html"))
);

app.post("/initiatePayment", async (req, res) => {
  const orderId = `order_${Date.now()}`;
  const amount = 1 + crypto.randomInt(100);
  const returnUrl = `${req.protocol}://${req.hostname}:${port}/handlePaymentResponse`;
  const paymentHandler = PaymentHandler.getInstance();
  try {
    const orderSessionResp = await paymentHandler.orderSession({
      order_id: orderId,
      amount,
      currency: "INR",
      return_url: returnUrl,
      // [MERCHANT_TODO]:- please handle customer_id, it's an optional field but we suggest to use it.
      customer_id: "sample-customer-id",
      // please note you don't have to give payment_page_client_id here, it's mandatory but
      // PaymentHandler will read it from config.json file
      // payment_page_client_id: paymentHandler.getPaymentPageClientId()
    });
    return res.redirect(orderSessionResp.payment_links.web);
  } catch (error) {
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

app.post("/handlePaymentResponse", async (req, res) => {
  const orderId = req.body.order_id || req.body.orderId;
  const paymentHandler = PaymentHandler.getInstance();

  if (orderId === undefined) {
    return res.send("Something went wrong");
  }

  try {
    const orderStatusResp = await paymentHandler.orderStatus(orderId);
    if (
      validateHMAC_SHA256(req.body, paymentHandler.getResponseKey()) === false
    ) {
      // [MERCHANT_TODO]:- validation failed, it's critical error
      return res.send("Signature verification failed");
    }

    const orderStatus = orderStatusResp.status;
    let message = "";
    switch (orderStatus) {
      case "CHARGED":
        message = "order payment done successfully";
        break;
      case "PENDING":
      case "PENDING_VBV":
        message = "order payment pending";
        break;
      case "AUTHORIZATION_FAILED":
        message = "order payment authorization failed";
        break;
      case "AUTHENTICATION_FAILED":
        message = "order payment authentication failed";
        break;
      default:
        message = "order status " + orderStatus;
        break;
    }

    const html = makeOrderStatusResponse(
      "Merchant Payment Response Page",
      message,
      req,
      orderStatusResp
    );
    res.set("Content-Type", "text/html");
    return res.send(html);
  } catch (error) {
    console.error(error);
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

app.post("/initiateRefund", async (req, res) => {
  const paymentHandler = PaymentHandler.getInstance();

  try {
    const refundResp = await paymentHandler.refund({
      order_id: req.body.order_id,
      amount: req.body.amount,
      unique_request_id: req.body.unique_request_id || `refund_${Date.now()}`,
    });
    const html = makeOrderStatusResponse(
      "Merchant Refund Page",
      `Refund status:- ${refundResp.status}`,
      req,
      refundResp
    );
    res.set("Content-Type", "text/html");
    return res.send(html);
  } catch (error) {
    console.error(error);
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

// [MERCHAT_TODO]:- Please modify this as per your requirements
const makeOrderStatusResponse = (title, message, req, response) => {
  let inputParamsTableRows = "";
  for (const [key, value] of Object.entries(req.body)) {
    const pvalue = value !== null ? JSON.stringify(value) : "";
    inputParamsTableRows += `<tr><td>${key}</td><td>${pvalue}</td></tr>`;
  }

  let orderTableRows = "";
  for (const [key, value] of Object.entries(response)) {
    const pvalue = value !== null ? JSON.stringify(value) : "";
    orderTableRows += `<tr><td>${key}</td><td>${pvalue}</td></tr>`;
  }

  return `
        <html>
        <head>
            <title>${title}</title>
        </head>
        <body>
            <h1>${message}</h1>

            <center>
                <font size="4" color="blue"><b>Return url request body params</b></font>
                <table border="1">
                    ${inputParamsTableRows}
                </table>
            </center>

            <center>
                <font size="4" color="blue"><b>Response received from order status payment server call</b></font>
                <table border="1">
                    ${orderTableRows}
                </table>
            </center>
        </body>
        </html>
    `;
};

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

```



### Step 1 Add orderSessionResponse in your backend


This initiates payment to payment server it calls our /session api for JAVA 


| Parameter | Type  | Description |
|---|---|---|
| order_id | Mandatory  | Unique identifier for the order |
| customer_id | Optional  | It is the ID with which merchant refers to a customer object. This id is used to access the stored payment methods, allow EMI transactions and setup subscriptions. In case of guest login it should be an empty string |
| payment_page_client_id | Mandatory  | For Sandbox, add 'hdfcmaster' as your client_id |
| amount | Mandatory  | Amount that the customer has to pay. Will accept stringified double or integer values with upto two decimal places. (Example, "100.15" and "100" are valid input but "100.1532" is not valid) |
| return_url | Optional  | A fully qualified URL on which the customer will be redirected after payment completion |
| merchant_id  | Optional  | Add the Merchant_ID provided by the bank |




#### Code Snippets: -

#### Java Code Snippet:

```java
<%@ page import = "java.io.*,java.util.*,in.samplekit.PaymentHandler,java.security.*" %>
<html>
<head>
	<title>Merchant checkout page</title>
</head>
<body>
	<%
     try {
         PaymentHandler paymentHandler = new PaymentHandler();

         String orderId = "ord_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
         int amount = new SecureRandom().nextInt(100) + 1;

         String serverName = request.getServerName();
         int serverPort = request.getServerPort();
         String contextPath = request.getContextPath();

         String customerId = "hdfc-testing-customer-one";
         String scheme = request.getScheme();
         String returnUrl = scheme + "://" + serverName + ":" + serverPort + contextPath + "/handlePaymentResponse";

         Map<String, Object> params = new LinkedHashMap<String, Object>();
         params.put("order_id", orderId);
         params.put("payment_page_client_id", paymentHandler.paymentHandlerConfig.getPaymentPageClientId());
         params.put("amount", amount);
         params.put("customer_id", customerId);
         params.put("action", "paymentPage");
         params.put("return_url", returnUrl);
         params.put("currency", "INR");
         Map<String, Object> orderSessionResponse = paymentHandler.orderSession(params);
         Map<String, Object> paymentLinksObject = (Map<String, Object>) orderSessionResponse.get("payment_links");
         String webPaymentLink = (String) paymentLinksObject.get("web");
         response.sendRedirect(webPaymentLink);
    } catch (PaymentHandler.APIException e) {
%>
        <p> Payment server threw a non-2xx error. Error message:  <%= e.getMessage() %> </p>
<%
    } catch (Exception e) {
%>
        <p> Unexpected error occurred </p>
<%
    }
%>

 </body>
</html>

```



### Step 1 Add Session Create function in your backend


Expose `/initiatePayment`API endpoint in your backend that calls the `Create` function. This API endpoint will be called from your frontend to open the payment page.

For ease of implementation, you can refer to session( ) function from ‘InitiatePayment.cs’ file and update the following parameters:


| Parameters | Type | Description |
|---|---|---|
| order_id | Mandatory | Unique identifier for the order |
| customer_id | Optional | It is the ID with which merchant refers to a customer object. This id is used to access the stored payment methods, allow EMI transactions and setup subscriptions. In case of guest login it should be an empty string |
| amount | Mandatory | Amount that the customer has to pay. Will accept stringified double or integer values with upto two decimal places (Example: "100.15" and "100" are valid input but "100.1532" is not valid) |
| return_url | Optional | A fully qualified URL on which the customer will be redirected after payment completion |
| payment_page_client_id | Mandatory | For Sandbox, add 'hdfcmaster' as your client_id |
| merchant_id | Optional | Add the Merchant_ID provided by the bank |




#### Code Snippets: -

#### .Net Code Snippet:

```.net
string orderId = $"order_{new Random().Next()}";
            int amount = new Random().Next(0, 100);
            string customerId = "testing-customer-one";
            PaymentHandler paymentHandler = new PaymentHandler();
            var sessionInput = new Dictionary<string, object>
                    {
                            { "amount", "10.00" },
                            { "order_id", orderId },
                            { "customer_id", customerId },
                            { "payment_page_client_id", paymentHandler.paymentHandlerConfig.PAYMENT_PAGE_CLIENT_ID },
                            { "action", "paymentPage" },
                            { "return_url", "http://localhost:5000/handlePaymentResponse" }
                    };
            var orderSession = await paymentHandler.OrderSession(sessionInput);
```



### Step 2 Additional params for Order Session function


You may add these below mentioned **optional params**  in your order session function added in the previous step as per your use case:


| Parameters | Description |
|---|---|
| customer_email | Email address of the customer. If the backend gateway requires it, then you must send this value. |
| customer_phone | Mobile number or fixed line number of the customer. If the backend gateway requires it, then you must send this value. We recommend passing a 10-digit number without including the "+91" or any mobile country code at the beginning. |
| first_name | First Name of customer. This value will be used for customer identification. |
| last_name | Last name of customer. This value will be used for customer identification. |
| description | Description for order to be displayed to the user on amountBar. |
| currency | Currency for the order. It should only be passed when supported by the Payment Gateway and enabled in the SmartGateway Dashboard within EC Operations → PGCC → Select PG → Edit → Supported Currencies. |
| udf1, udf2, udf3, udf4, udf5 (No Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |
| udf6, udf7, udf8, udf9, udf10 (Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |




#### Code Snippets: -

#### .Net Code Snippet:

```.net
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using SmartGatewayDotnetBackendApiKeyKit.Models;
using Microsoft.Extensions.Logging;
using PaymentHandlers;
using System.Collections.Generic;
using System;
using System.Threading.Tasks;

namespace SmartGatewayDotnetBackendApiKeyKit.Controllers {

    public class InitiatePayment : Controller
    {
        private readonly ILogger<InitiatePayment> _logger;

        public InitiatePayment(ILogger<InitiatePayment> logger)
        {
            _logger = logger;
        }

        [HttpPost]
        public async Task<IActionResult> Index()
        {
            // block:start:session-function
            string orderId = $"order_{new Random().Next()}";
            int amount = new Random().Next(0, 100);
            string customerId = "testing-customer-one";
            PaymentHandler paymentHandler = new PaymentHandler();
            var sessionInput = new Dictionary<string, object>
                    {
                            { "amount", "10.00" },
                            { "order_id", orderId },
                            { "customer_id", customerId },
                            { "payment_page_client_id", paymentHandler.paymentHandlerConfig.PAYMENT_PAGE_CLIENT_ID },
                            { "action", "paymentPage" },
                            { "return_url", "http://localhost:5000/handlePaymentResponse" }
                    };
            var orderSession = await paymentHandler.OrderSession(sessionInput);
            // block:end:session-function
            if (orderSession?.payment_links?.web != null) return Redirect((string)orderSession.payment_links.web);
            throw new Exception("Invalid Response unable to find web payment link");
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }

}

```



### Step 2 Additional params for Order Session function


You may add these below mentioned **optional params**  in your order session function added in the previous step as per your usecase:


| Parameters | Description |
|---|---|
| customer_email | Email address of the customer. If the backend gateway requires it, then you must send this value. |
| customer_phone | Mobile number or fixed line number of the customer. If the backend gateway requires it, then you must send this value. We recommend passing a 10-digit number without including the "+91" or any mobile country code at the beginning. |
| first_name | First Name of customer. This value will be used for customer identification. |
| last_name | Last name of customer. This value will be used for customer identification. |
| description | Description for order to be displayed to the user on amount bar. |
| currency | Currency for the order. It should only be passed when supported by the Payment Gateway and enabled in the SmartGateway Dashboard within EC Operations → PGCC → Select PG → Edit → Supported Currencies. |
| udf1, udf2, udf3, udf4, udf5 (No Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |
| udf6, udf7, udf8, udf9, udf10 (Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |




#### Code Snippets: -

#### NodeJS Code Snippet:

```nodejs
const express = require("express");
const {
  PaymentHandler,
  APIException,
  validateHMAC_SHA256,
} = require("./PaymentHandler");
const crypto = require("crypto");
const path = require("path");
const app = express();
const port = process.env.PORT || 5000;

app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
app.get("/", (_, res) =>
  res.sendFile(path.join(__dirname, "public", "initiatePaymentDataForm.html"))
);

app.post("/initiatePayment", async (req, res) => {
  const orderId = `order_${Date.now()}`;
  const amount = 1 + crypto.randomInt(100);
  const returnUrl = `${req.protocol}://${req.hostname}:${port}/handlePaymentResponse`;
  const paymentHandler = PaymentHandler.getInstance();
  try {
    const orderSessionResp = await paymentHandler.orderSession({
      order_id: orderId,
      amount,
      currency: "INR",
      return_url: returnUrl,
      // [MERCHANT_TODO]:- please handle customer_id, it's an optional field but we suggest to use it.
      customer_id: "sample-customer-id",
      // please note you don't have to give payment_page_client_id here, it's mandatory but
      // PaymentHandler will read it from config.json file
      // payment_page_client_id: paymentHandler.getPaymentPageClientId()
    });
    return res.redirect(orderSessionResp.payment_links.web);
  } catch (error) {
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

app.post("/handlePaymentResponse", async (req, res) => {
  const orderId = req.body.order_id || req.body.orderId;
  const paymentHandler = PaymentHandler.getInstance();

  if (orderId === undefined) {
    return res.send("Something went wrong");
  }

  try {
    const orderStatusResp = await paymentHandler.orderStatus(orderId);
    if (
      validateHMAC_SHA256(req.body, paymentHandler.getResponseKey()) === false
    ) {
      // [MERCHANT_TODO]:- validation failed, it's critical error
      return res.send("Signature verification failed");
    }

    const orderStatus = orderStatusResp.status;
    let message = "";
    switch (orderStatus) {
      case "CHARGED":
        message = "order payment done successfully";
        break;
      case "PENDING":
      case "PENDING_VBV":
        message = "order payment pending";
        break;
      case "AUTHORIZATION_FAILED":
        message = "order payment authorization failed";
        break;
      case "AUTHENTICATION_FAILED":
        message = "order payment authentication failed";
        break;
      default:
        message = "order status " + orderStatus;
        break;
    }

    const html = makeOrderStatusResponse(
      "Merchant Payment Response Page",
      message,
      req,
      orderStatusResp
    );
    res.set("Content-Type", "text/html");
    return res.send(html);
  } catch (error) {
    console.error(error);
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

app.post("/initiateRefund", async (req, res) => {
  const paymentHandler = PaymentHandler.getInstance();

  try {
    const refundResp = await paymentHandler.refund({
      order_id: req.body.order_id,
      amount: req.body.amount,
      unique_request_id: req.body.unique_request_id || `refund_${Date.now()}`,
    });
    const html = makeOrderStatusResponse(
      "Merchant Refund Page",
      `Refund status:- ${refundResp.status}`,
      req,
      refundResp
    );
    res.set("Content-Type", "text/html");
    return res.send(html);
  } catch (error) {
    console.error(error);
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

// [MERCHAT_TODO]:- Please modify this as per your requirements
const makeOrderStatusResponse = (title, message, req, response) => {
  let inputParamsTableRows = "";
  for (const [key, value] of Object.entries(req.body)) {
    const pvalue = value !== null ? JSON.stringify(value) : "";
    inputParamsTableRows += `<tr><td>${key}</td><td>${pvalue}</td></tr>`;
  }

  let orderTableRows = "";
  for (const [key, value] of Object.entries(response)) {
    const pvalue = value !== null ? JSON.stringify(value) : "";
    orderTableRows += `<tr><td>${key}</td><td>${pvalue}</td></tr>`;
  }

  return `
        <html>
        <head>
            <title>${title}</title>
        </head>
        <body>
            <h1>${message}</h1>

            <center>
                <font size="4" color="blue"><b>Return url request body params</b></font>
                <table border="1">
                    ${inputParamsTableRows}
                </table>
            </center>

            <center>
                <font size="4" color="blue"><b>Response received from order status payment server call</b></font>
                <table border="1">
                    ${orderTableRows}
                </table>
            </center>
        </body>
        </html>
    `;
};

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

```



### Step 2 (Optional) Additional params for Order Session function


You may add these below mentioned **optional params**  in your order session function added in the previous step as per your usecase:


| Parameters | Description |
|---|---|
| customer_email | Email address of the customer. If the backend gateway requires it, then you must send this value. |
| customer_phone | Mobile number or fixed line number of the customer. If the backend gateway requires it, then you must send this value. We recommend passing a 10-digit number without including the "+91" or any mobile country code at the beginning. |
| first_name | First Name of customer. This value will be used for customer identification. |
| last_name | Last name of customer. This value will be used for customer identification. |
| description | Description for order to be displayed to the user on amountBar. |
| currency | Currency for the order. It should only be passed when supported by the Payment Gateway and enabled in the SmartGateway Dashboard within EC Operations → PGCC → Select PG → Edit → Supported Currencies. |
| udf1, udf2, udf3, udf4, udf5 (No Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |
| udf6, udf7, udf8, udf9, udf10 (Special Characters Supported) | User Defined Parameter (UDF) field can be used to send any user defined parameters and it can be seen in the SmartGateway dashboard under each order. Example - abc5349       |




#### Code Snippets: -

#### Java Code Snippet:

```java
<%@ page import = "java.io.*,java.util.*,in.samplekit.PaymentHandler,java.security.*" %>
<html>
<head>
	<title>Merchant checkout page</title>
</head>
<body>
	<%
     try {
         PaymentHandler paymentHandler = new PaymentHandler();

         String orderId = "ord_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
         int amount = new SecureRandom().nextInt(100) + 1;

         String serverName = request.getServerName();
         int serverPort = request.getServerPort();
         String contextPath = request.getContextPath();

         String customerId = "hdfc-testing-customer-one";
         String scheme = request.getScheme();
         String returnUrl = scheme + "://" + serverName + ":" + serverPort + contextPath + "/handlePaymentResponse";

         Map<String, Object> params = new LinkedHashMap<String, Object>();
         params.put("order_id", orderId);
         params.put("payment_page_client_id", paymentHandler.paymentHandlerConfig.getPaymentPageClientId());
         params.put("amount", amount);
         params.put("customer_id", customerId);
         params.put("action", "paymentPage");
         params.put("return_url", returnUrl);
         params.put("currency", "INR");
         Map<String, Object> orderSessionResponse = paymentHandler.orderSession(params);
         Map<String, Object> paymentLinksObject = (Map<String, Object>) orderSessionResponse.get("payment_links");
         String webPaymentLink = (String) paymentLinksObject.get("web");
         response.sendRedirect(webPaymentLink);
    } catch (PaymentHandler.APIException e) {
%>
        <p> Payment server threw a non-2xx error. Error message:  <%= e.getMessage() %> </p>
<%
    } catch (Exception e) {
%>
        <p> Unexpected error occurred </p>
<%
    }
%>

 </body>
</html>

```


> **Note**
> Please pass parameters given above in **String**  format




### Sample Response




#### Sample Response of OrderSession.create Function Code Snippet:

```sample response of ordersession.create function
{
  "status": "NEW",
  "id": "ordeh_xxxxxxxxxxxxxxxxxxxx",
  "order_id": "testing-order-one",
  "payment_links": {
      "web": "https://smartgatewayuat.hdfcbank.com/merchant/ipay/ordeh_57dfd768bb7d4896bc042y0b90bc9ad77/payment-page"
  },
  "sdk_payload": {
      "requestId": "12398b5571d74c3388a74004bc24370c",
      "service": "in.juspay.hyperpay",
      "payload": {
          "clientId": "yourClientId",
          "amount": "1.0",
          "merchantId": "yourMerchantId",
          "clientAuthToken": "tkn_xxxxxxxxxxxxxxxxxxxxx",
          "clientAuthTokenExpiry": "2022-03-12T20:29:23Z",
          "environment": "production",
          "options.getUpiDeepLinks": "true",
          "lastName": "wick",
          "action": "paymentPage",
          "customerId": "testing-customer-one",
          "returnUrl": "https://shop.merchant.com",
          "currency": "INR",
          "firstName": "John",
          "customerPhone": "9876543210",
          "customerEmail": "test@mail.com",
          "orderId": "testing-order-one",
          "description": "Complete your payment"
      }
  }
}

```


---

## Complete Code Reference

The following code files are referenced in the steps above:

### initiatePayment.php

```
<?php
use PaymentHandler\APIException;
require_once realpath("./PaymentHandler.php");
use PaymentHandler\PaymentHandler;

$paymentHandler = new PaymentHandler("resources/config.json");

$orderId = "php_sdk_" . uniqid();
$customerId = "php_sdk_customer" . uniqid();
// block:start:session-function
$params = json_decode("{\n\"amount\":\"10.00\",\n\"order_id\":\"$orderId\",\n\"customer_id\":\"$customerId\",\n\"action\":\"paymentPage\",\n\"return_url\": \"http://localhost:5000/handlePaymentResponse.php\"\n}", true);
try {
    $session = $paymentHandler->orderSession($params);
    // block:end:session-function
    $redirect = $session["payment_links"]["web"];
    header("Location: {$redirect}");
    exit;

} catch (APIException $e ) {
    http_response_code(500);
    $error = json_encode(["message" => $e->getErrorMessage(), "error_code" => $e->getErrorCode(), "http_response_code" => $e->getHttpResponseCode()]);
    echo "<p> Payment server threw a non-2xx error. Error message: {$error} </p>";
    exit;
 } catch (Exception $e) {
    http_response_code(500);
    echo " <p> Unexpected error occurred, Error message:  {$e->getMessage()} </p>";
    exit;
}
?>

```

### index.js

```
const express = require("express");
const {
  PaymentHandler,
  APIException,
  validateHMAC_SHA256,
} = require("./PaymentHandler");
const crypto = require("crypto");
const path = require("path");
const app = express();
const port = process.env.PORT || 5000;

app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
app.get("/", (_, res) =>
  res.sendFile(path.join(__dirname, "public", "initiatePaymentDataForm.html"))
);

app.post("/initiatePayment", async (req, res) => {
  const orderId = `order_${Date.now()}`;
  const amount = 1 + crypto.randomInt(100);
  const returnUrl = `${req.protocol}://${req.hostname}:${port}/handlePaymentResponse`;
  const paymentHandler = PaymentHandler.getInstance();
  try {
    const orderSessionResp = await paymentHandler.orderSession({
      order_id: orderId,
      amount,
      currency: "INR",
      return_url: returnUrl,
      // [MERCHANT_TODO]:- please handle customer_id, it's an optional field but we suggest to use it.
      customer_id: "sample-customer-id",
      // please note you don't have to give payment_page_client_id here, it's mandatory but
      // PaymentHandler will read it from config.json file
      // payment_page_client_id: paymentHandler.getPaymentPageClientId()
    });
    return res.redirect(orderSessionResp.payment_links.web);
  } catch (error) {
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

app.post("/handlePaymentResponse", async (req, res) => {
  const orderId = req.body.order_id || req.body.orderId;
  const paymentHandler = PaymentHandler.getInstance();

  if (orderId === undefined) {
    return res.send("Something went wrong");
  }

  try {
    const orderStatusResp = await paymentHandler.orderStatus(orderId);
    if (
      validateHMAC_SHA256(req.body, paymentHandler.getResponseKey()) === false
    ) {
      // [MERCHANT_TODO]:- validation failed, it's critical error
      return res.send("Signature verification failed");
    }

    const orderStatus = orderStatusResp.status;
    let message = "";
    switch (orderStatus) {
      case "CHARGED":
        message = "order payment done successfully";
        break;
      case "PENDING":
      case "PENDING_VBV":
        message = "order payment pending";
        break;
      case "AUTHORIZATION_FAILED":
        message = "order payment authorization failed";
        break;
      case "AUTHENTICATION_FAILED":
        message = "order payment authentication failed";
        break;
      default:
        message = "order status " + orderStatus;
        break;
    }

    const html = makeOrderStatusResponse(
      "Merchant Payment Response Page",
      message,
      req,
      orderStatusResp
    );
    res.set("Content-Type", "text/html");
    return res.send(html);
  } catch (error) {
    console.error(error);
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

app.post("/initiateRefund", async (req, res) => {
  const paymentHandler = PaymentHandler.getInstance();

  try {
    const refundResp = await paymentHandler.refund({
      order_id: req.body.order_id,
      amount: req.body.amount,
      unique_request_id: req.body.unique_request_id || `refund_${Date.now()}`,
    });
    const html = makeOrderStatusResponse(
      "Merchant Refund Page",
      `Refund status:- ${refundResp.status}`,
      req,
      refundResp
    );
    res.set("Content-Type", "text/html");
    return res.send(html);
  } catch (error) {
    console.error(error);
    // [MERCHANT_TODO]:- please handle errors
    if (error instanceof APIException) {
      return res.send("PaymentHandler threw some error");
    }
    // [MERCHANT_TODO]:- please handle errors
    return res.send("Something went wrong");
  }
});

// [MERCHAT_TODO]:- Please modify this as per your requirements
const makeOrderStatusResponse = (title, message, req, response) => {
  let inputParamsTableRows = "";
  for (const [key, value] of Object.entries(req.body)) {
    const pvalue = value !== null ? JSON.stringify(value) : "";
    inputParamsTableRows += `<tr><td>${key}</td><td>${pvalue}</td></tr>`;
  }

  let orderTableRows = "";
  for (const [key, value] of Object.entries(response)) {
    const pvalue = value !== null ? JSON.stringify(value) : "";
    orderTableRows += `<tr><td>${key}</td><td>${pvalue}</td></tr>`;
  }

  return `
        <html>
        <head>
            <title>${title}</title>
        </head>
        <body>
            <h1>${message}</h1>

            <center>
                <font size="4" color="blue"><b>Return url request body params</b></font>
                <table border="1">
                    ${inputParamsTableRows}
                </table>
            </center>

            <center>
                <font size="4" color="blue"><b>Response received from order status payment server call</b></font>
                <table border="1">
                    ${orderTableRows}
                </table>
            </center>
        </body>
        </html>
    `;
};

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

```

### initiatePayment.jsp

```
<%@ page import = "java.io.*,java.util.*,in.samplekit.PaymentHandler,java.security.*" %>
<html>
<head>
	<title>Merchant checkout page</title>
</head>
<body>
	<%
     try {
         PaymentHandler paymentHandler = new PaymentHandler();

         String orderId = "ord_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
         int amount = new SecureRandom().nextInt(100) + 1;

         String serverName = request.getServerName();
         int serverPort = request.getServerPort();
         String contextPath = request.getContextPath();

         String customerId = "hdfc-testing-customer-one";
         String scheme = request.getScheme();
         String returnUrl = scheme + "://" + serverName + ":" + serverPort + contextPath + "/handlePaymentResponse";

         Map<String, Object> params = new LinkedHashMap<String, Object>();
         params.put("order_id", orderId);
         params.put("payment_page_client_id", paymentHandler.paymentHandlerConfig.getPaymentPageClientId());
         params.put("amount", amount);
         params.put("customer_id", customerId);
         params.put("action", "paymentPage");
         params.put("return_url", returnUrl);
         params.put("currency", "INR");
         Map<String, Object> orderSessionResponse = paymentHandler.orderSession(params);
         Map<String, Object> paymentLinksObject = (Map<String, Object>) orderSessionResponse.get("payment_links");
         String webPaymentLink = (String) paymentLinksObject.get("web");
         response.sendRedirect(webPaymentLink);
    } catch (PaymentHandler.APIException e) {
%>
        <p> Payment server threw a non-2xx error. Error message:  <%= e.getMessage() %> </p>
<%
    } catch (Exception e) {
%>
        <p> Unexpected error occurred </p>
<%
    }
%>

 </body>
</html>

```

### InitiatePayment.cs

```
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using SmartGatewayDotnetBackendApiKeyKit.Models;
using Microsoft.Extensions.Logging;
using PaymentHandlers;
using System.Collections.Generic;
using System;
using System.Threading.Tasks;

namespace SmartGatewayDotnetBackendApiKeyKit.Controllers {

    public class InitiatePayment : Controller
    {
        private readonly ILogger<InitiatePayment> _logger;

        public InitiatePayment(ILogger<InitiatePayment> logger)
        {
            _logger = logger;
        }

        [HttpPost]
        public async Task<IActionResult> Index()
        {
            // block:start:session-function
            string orderId = $"order_{new Random().Next()}";
            int amount = new Random().Next(0, 100);
            string customerId = "testing-customer-one";
            PaymentHandler paymentHandler = new PaymentHandler();
            var sessionInput = new Dictionary<string, object>
                    {
                            { "amount", "10.00" },
                            { "order_id", orderId },
                            { "customer_id", customerId },
                            { "payment_page_client_id", paymentHandler.paymentHandlerConfig.PAYMENT_PAGE_CLIENT_ID },
                            { "action", "paymentPage" },
                            { "return_url", "http://localhost:5000/handlePaymentResponse" }
                    };
            var orderSession = await paymentHandler.OrderSession(sessionInput);
            // block:end:session-function
            if (orderSession?.payment_links?.web != null) return Redirect((string)orderSession.payment_links.web);
            throw new Exception("Invalid Response unable to find web payment link");
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }

}

```


---

## See Also

- [Getting the Backend Setup](https://smartgateway.hdfc.bank.in/docs/smartgateway-kits-integration/web/how-to-integrate-kits/getting-the-backend-setup)
- [Handle Payment Responses](https://smartgateway.hdfc.bank.in/docs/smartgateway-kits-integration/web/how-to-integrate-kits/handle-payment-responses)
