---
page_title: Status Verification
product: Resources - Global
page_source: https://juspay.io/sea/docs/resources-global/docs/common-resources/status-verification
llms_txt: https://juspay.io/sea/docs/llms.txt
product_llms_txt: https://juspay.io/sea/docs/resources-global/llms.txt
---


# Status Verification



The signature parameter in the return_url gives the [HMAC signature](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code) computed using the algorithm specified by the signature_algorithm parameter. The HMAC is calculated using the following algorithm:

* Get all the parameters (key=value pairs) from the return_url.
* It is assumed that the parameters in the return_url are converted into key/value pairs.
* All parameters except signature and signature_algorithm are used in the following steps.
* Percentage encode each key and value pairs.
* Sort the list of parameters alphabetically (ASCII based sort) by encoded key.
* For each key/value pair:
* Percentage encode the generated string.
* The HMAC of the string can be calculated using the Response Key configured in [merchant settings](https://dashboard.expresscheckout.juspay.in/).
* Percentage encode the generated hash, validate against the signature in response (the signature should percentage decoded once before comparing with the generated hash).

To enable the signature generation at JusPay end for the payment response, you must first create a response key under Settings of Juspay dashboard [[https://dashboard.expresscheckout.juspay.in/](https://dashboard.expresscheckout.juspay.in/)]. Once you have created a key successfully, navigate to Settings-->General ([https://dashboard.expresscheckout.juspay.in/](https://dashboard.expresscheckout.juspay.in/)) 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 the signature and the algorithm.

The 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 the 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.



## Sample Code Snippets:
### HMAC signature verification:

#### Python Code Snippet:

```python
#Python example for HMAC signature verification

python
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
```

#### Ruby Code Snippet:

```ruby
#Ruby example for HMAC signature verification:**
python
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]
```

#### Java Code Snippet:

```java
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;


public class Util {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Ccw8ZE5fkr0%3D&signature_algorithm=HMAC-SHA256
        LinkedHashMap<String, String> param = new LinkedHashMap<String, String>();
        param.put("order_id", ":order_id");
        param.put("status", ":status");
        param.put("status_id", ":status_id");
        
        System.out.println("param :: "+param);
        
        String expectedHashparam="OHEZ3sYJa%2F9ZyNZ79u3r4p4F2p9O8%2FjSCcw8ZE5fkr0%3D";
        
         String scretkey=":Response key";
        
        try {
            System.out.println(" return value :: "+validateHMAC_SHA256(param,expectedHashparam,scretkey));
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
     public static boolean validateHMAC_SHA256(Map<String, String> params, String expectedHash, String key)
                throws java.io.UnsupportedEncodingException, java.security.NoSuchAlgorithmException,
                java.security.InvalidKeyException, java.io.UnsupportedEncodingException {
            if (key == null) return false;

            Map<String, String> sortedParams = new TreeMap<String, String>(params);
            
            System.out.println(""+sortedParams);

            StringBuilder queryStr = new StringBuilder("");
            for (String curkey : sortedParams.keySet())
                queryStr.append(curkey + "=" + sortedParams.get(curkey) + "&");
            queryStr.deleteCharAt(queryStr.length() - 1);
            System.out.println("queryStr ::"+queryStr);
            String message = URLEncoder.encode(queryStr.toString(), "UTF-8");
           
            Mac hasher = Mac.getInstance("HmacSHA256");
            hasher.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
            byte[] hash = hasher.doFinal(message.getBytes());
            String generatedSign = (URLEncoder.encode(DatatypeConverter.printBase64Binary(hash), "UTF-8"));
            System.out.println("generatedSign ::"+generatedSign);
            return (generatedSign.equals(expectedHash));
        }

}
```

#### PHP Code Snippet:

```php
function verify_hmac($params, $secret) {
           $receivedHmac = $params['signature'];
           // UrlEncode key/value pairs
           $encoded_params;
           foreach ($params as $key => $value) {
               if($key!='signature' && $key != 'signature_algorithm') {
                   $encoded_params[urlencode($key)] = urlencode($value);
               }
           }
           ksort($encoded_params);
           $serialized_params = "";
           foreach ($encoded_params as $key => $value) {
               $serialized_params = $serialized_params . $key . "=" . $value . "&";
           }
           $serialized_params = urlencode(substr($serialized_params, 0, -1));
           $computedHmac = base64_encode(hash_hmac('sha256', $serialized_params, $secret, true));
           $receivedHmac = urldecode($receivedHmac);
           return urldecode($computedHmac) == $receivedHmac;
       }
```

#### Node.js Code Snippet:

```node.js
const crypto = require('crypto');

function verify_hmac(params, secret) {

  var paramsList = [];
  for (var key in params) {
    if (key != 'signature' && key != 'signature_algorithm') {
      paramsList[key] = params[key];
    }
  }

  paramsList = sortObjectByKeys(paramsList);

  var paramsString = '';
  for (var key in paramsList) {
    paramsString = paramsString + key + '=' + paramsList[key] + '&';
  }

  let encodedParams = encodeURIComponent(paramsString.substring(0, paramsString.length - 1));
  let computedHmac = crypto.createHmac('sha256', secret).update(encodedParams).digest('base64');
  let receivedHmac = decodeURIComponent(params.signature);

  console.log("computedHmac :", computedHmac)
  console.log("receivedHmac :", receivedHmac)

  return decodeURIComponent(computedHmac) == receivedHmac;
}

function sortObjectByKeys(o) {
  return Object.keys(o)
    .sort()
    .reduce((r, k) => ((r[k] = o[k]), r), {});
}

console.log(verify_hmac({"status_id":"21","status":"CHARGED","order_id":"**6**3**","signature":"******crdU/AW8BkpqnMHK2********TE=","signature_algorithm":"HMAC-SHA256"},{{Response Key}}))
```



---

## See Also

- [Transaction Status](https://juspay.io/sea/docs/resources-global/docs/common-resources/transaction-status)
- [Webhooks](https://juspay.io/sea/docs/resources-global/docs/common-resources/webhooks)
