NAV
shell ruby python

EC: Server-side Integration

Introduction

Express Checkout server-side integration has to handle:

Both these are authenticated (using api-key) calls to JusPay server and hence have to be initiated from the server.

Initiate Order

This call has to be made from the merchant server.

# Creating an order
curl -XPOST https://api.juspay.in/order/create \
  -u api_key: \
  -d "amount=10.00" \
  -d "order_id=order_id_007" \
  -d "customer_id=guest_user_101" \
  -d "customer_email=customer@mail.com" \
  -d "customer_phone=91999000999" \
  -d "product_id=your_product_id" \
  -d "description=order infomation"

# Response
 {
   "status": "CREATED",
   "status_id": 1,
   "order_id": "order_id_007"
 }

# Get list of masked card for customer
curl https://api.juspay.in/card/list \
  -u api_key: \
  -d "customer_id=guest_user_101"
import requests

# Creating an order
payload = {
    'order_id': 'order_id_007',
    'amount': 10.0,
    'customer_id': 'guest_user_101',
    'customer_email': 'customer@mail.com',
    'customer_phone': '91999000999',
    'product_id': 'your_product_id',
    'description': 'order infomation',
    }

r = requests.post('https://api.juspay.in/order/create', \
                  auth=('api_key', None), \
                  data=payload, verify=True)
resp = r.json()

# Getting list of cards
payload = {'customer_id': 'guest_user_101'}

r = requests.get('https://api.juspay.in/card/list', \
                auth=('api_key', None), \
                data=payload, verify=True)
resp = r.json()

require 'net/http'
require 'json'

# Create order
payload = {
    'order_id' => 'order_id_007',
    'amount' => 10.0,
    'customer_id' => 'guest_user_101',
    'customer_email' => 'customer@mail.com',
    'customer_phone' => '91999000999',
    'product_id' => 'your_product_id',
    'description' => 'order infomation',
}
url = URI.parse('https://api.juspay.in/order/create')
req = Net::HTTP::Post.new(url.path)
req.basic_auth 'api_key', nil
req.set_form_data(payload);
sock = Net::HTTP.new(url.host, url.port)
sock.use_ssl = true
resp = sock.start {|http| http.request(req)}
res = JSON.parse(resp.body)

# List cards for a customer
payload = {'customer_id' => 'guest_user_101'}
uri = URI('https://api.juspay.in/card/list')
uri.query = URI.encode_www_form(payload)
req = Net::HTTP::Get.new(uri)
req.basic_auth 'api_key', nil
sock = Net::HTTP.new(uri.host, uri.port)
sock.use_ssl = true
resp = sock.start {|http|http.request(req)}
res = JSON.parse(resp.body)

Creating an order is the first step in the process. This typically happens when the customer confirms his intent to pay. The “order” object has all the details regarding the customer and the purchase like customer_id, amount, etc.

To initialize an order, you require an API authentication key. This API key must not be included in the mobile or web client. Thus the client application has to make a request to your server, which would call the Express Checkout order initialization API. A successful order creation marks the start of the payment process.

The order_id should be a unique reference generated for the order by you and the customer_id should refer to the unique id for the customer. Once the order is created for a customer_id, you could list cards to get all the stored cards from the locker, if any. These cards could be used in the proceeding steps, for faster checkout.

APIs: order/create, /card/list

Client-side Integration

After an order is created, the next two steps are handled by the client before the control is transferred back to the server again. These steps include presenting a card/checkout form and proceeding to pay. The client can be web or mobile and different strategies can be used to show the checkout form or the UI.

Please proceed to the client-side integration guide here.

Handle Payment Response

Status check is a server-to-server call

curl https://api.juspay.in/order/status?order_id=order_id_007 \
  -u api_key:

# The response will include all the order details,
# payment status, gateway response and
# refunds related to that order
import requests

# Fetch order status
payload = {'order_id': 'order_id_007'}
r = requests.get('https://api.juspay.in/order/status', \
                auth=('api_key', None), \
                data=payload, verify=True)
resp = r.json()
payload = {'order_id' => 'order_id_007'}
uri = URI('https://api.juspay.in/order/status')
uri.query = URI.encode_www_form(payload)
req = Net::HTTP::Get.new(uri)
req.basic_auth 'api_key', nil
sock = Net::HTTP.new(uri.host, uri.port)
sock.use_ssl = true
resp = sock.start {|http| \
                  http.request(req)}
res = JSON.parse(resp.body)

The last step is to handle the response from Express Checkout. Once the payment is complete the user is redirected to the return_url configured by you. Following is the typical destination where the user is taken to:

HTTP GET https://merchant.shop.com/paymentresponse/handler?order_id=order_id_007&status=CHARGED&status_id=21&signature=euKzwwiUztPPg3MCEYpgKZfcyTr1uQq1hzKkhP8G1vQ%253D&signature_algorithm=HMAC-SHA256

Please note that the parameters are sent using HTTP GET.

The recommended way would be to follow the regular flow which finally redirects to the pre-configured return_url where you get the HMAC signed response parameters like order_id, status, status_code, etc. The return_url can be configured in the settings page or sent as a parameter when the order is created.

Transaction is successful only if you receive CHARGED as the value in status. For all other cases, you must assume that the payment has failed.

Status Verification

# Sample code for ruby & python are provided.
# Please choose the appropriate language on the top of the page.
import urllib
import hmac
import hashlib
import base64

key = 'your_secret_key'
# params := key/value dictionary except `signature`
#           and `signature_algorithm`
# signature := "5ctBJ0vURSTS9awUhbTBXCpUeDEJG8X%252B6c%253D"
# signature_algorithm := "HMAC-SHA256"

encoded_sorted = []
for i in sorted(params.keys()):
    encoded_sorted.append(urllib.quote_plus(i) + '=' + \
      urllib.quote_plus(params.get(i)))

encoded_string = urllib.quote_plus('&'.join(encoded_sorted))
dig = hmac.new(key, \
              msg=encoded_string, \
              digestmod=hashlib.sha256).digest()

assert urllib.quote_plus(base64.b64encode(dig).decode()) == \
       signature
require 'uri'
require 'cgi'
require 'openssl'
require 'Base64'

key = "your_secret_key"
# params := key/value hash except `signature`
#           and `signature_algorithm`
# signature := "5ctBJ0vURSTS9awUhbTBXCpUeDEJG8X%252B6c%253D"
# signature_algorithm := "HMAC-SHA256"

encoded_sorted = []
params.keys.sort.each { |k| encoded_list << URI.encode(k) + \
                        "=" + URI.encode(params[k]) }

encoded_string = CGI.escape(encoded_sorted.join("&"))

hash_string = CGI.escape(Base64.encode64(OpenSSL::HMAC. \
                        digest(OpenSSL::Digest.new('sha256'), \
                        key, data)).strip())
hash_string == URI.decode(return_url). \
                  split("signature=")[1].split("&")[0]

After the redirect, the authenticity should be verified using the signature in the response. The signature parameter in the return_url gives the HMAC signature computed using the algorithm specified by the signature_algorithm parameter. The HMAC is calculated using the following algorithm:

To enable the signature generation at JusPay end for the payment response, you must first create a response key here: https://merchant.juspay.in/settings/api-keys. Once you have created a key successfully, navigate to General settings section and select “Yes” for the option “Use signed response”.

Once you have completed the above two steps, all the redirection to your website from JusPay will have signature and the algorithm.

Signature algorithm used by JusPay is HMAC-SHA256. The algorithm is explicitly passed as an argument so that verification is accurate. Newer or more secure algorithms might be introduced in future.

It is also possible to check the status using the order/status API. Based on the response object, a success confirmation page or failure message can be shown to the customer. Since this is an authenticated call, done from the server side, signature verification is not required.

List of Payment statuses:

Status ID Meaning
NEW 10 Newly created order
PENDING_VBV 23 Authentication is in progress
CHARGED 21 Successful transaction
AUTHENTICATION_FAILED 26 User did not complete authentication
AUTHORIZATION_FAILED 27 User completed authentication. But bank refused the transaction

API: order/status

Managing Cards

The stored cards can be managed by using card APIs.

This would include using list to get all stored cards based on the customer_id. These can be deleted or modified. New cards can be added using the API.