Payment Gateway

Hash-Based Signature

A signature is a unique code used to ensure the security and authenticity of data during a transaction. The signature is created using cryptographic algorithms such as RSA and SHA-256. Each time a request is received, Espay will validate the signature to ensure that the transaction data originates from you and has not been altered during transmission.
Parameter Format

Each Espay service has a different parameter format for signature generation. Below is the combination of parameters along with their corresponding services:

Service Message Combination
Virtual Account / Send Invoice.
Visit the service here.
Request
signature key + rq_uuid + rq_datetime + order_id + amount + ccy + comm_code + SENDINVOICE
Inquiry Transaction
Visit the service here.
Request
signature key + rq_datetime + order_id + INQUIRY
Response
signature key + rq_uuid + rs_datetime + order_id + error_code + INQUIRY-RS
Payment Notificatio
Visit the service here.
Request
signature key + rq_datetime + order_id + PAYMENTREPORT
Response
signature key + rq_uuid + rs_datetime + error_code + PAYMENTREPORT-RS
Check Payment Status
Visit the service here.
Request
signature key + rq_datetime + order_id + CHECKSTATUS
Expire Transaction
Visit the service here.

Request

signaturekey + rq_datetime + order_id + EXPIRETRANSACTION
Credit Card - Tokenization
Visit the service here.
Request
signaturekey + comm_code + trx_id + amount
Credit Card - Capture
Visit the service here.
Request
Signature Key + comm_code + trx_id + amount
Credit Card - Void
Visit the service here.
Request
signaturekey + comm_code + trx_id
Credit Card - Refund
Visit the service here.
Request
signaturekey + comm_code + trx_id + amount
Push To Pay / QRIS / Linkage
Visit the service here.
Request
rq_uuid + comm_code + product_code + order_id + amount + signature key + PUSHTOPAY
Settlement Notification
Visit the service here.
Request
rq_uuid + rq_datetime + sender_id + receiver_id
Payment Link
Visit the service here.
Request
comm_code + orderid + amount + key + datetime + password
Signature Component
Component Description
amount
Paid amount.

Example:
150000
ccy
Transaction currency code.

Value:
  • Rupiah: IDR
comm_code
Merchant code from Espay team.

Example:
SGWYESSISHOP
error_code
Error code.

Example:
0000
Key
API Key from Espay team.
order_id / orderid
Unique code to identify the order/billing/invoice.

Example:
Transaction number, invoice ID, etc.
rq_uuid
Request identifier. A unique ID used to identify messages.
rq_datetime / datetime
Date and time of the transaction request.

Example:
2024-01-01 14:39:11
rs_datetime
Date and time of the transaction response.

Example:
2024-01-01 14:39:11
signaturekey
Signature from Espay team.

Example:
s8qndd0ghZdrl04r

Hash-Based Signature Format

In Hash-Based Signature, 3 types of signature formats must be adjusted based on their usage:

  1. Universal Signature Format
  2. Payment Link Signature Format
  3. Settlement Notification Signature Format

The table below explains the differences in the signature formats used for each service:

Characteristics Universal Signature Format Payment Link Signature Format Settlement Notification Signature Format
Service Coverage
Used for all services listed in the Format Combination Parameter table, except Settlement Notification and Payment Link.
Specifically for the Payment Link service.
Specifically for the Settlement Notification service.
Field Separator
Uses ##as a separator between fields.
Uses ## as a separator between fields.
Do not use ## as a separator.
Uppercase Conversion
Uppercase conversion is required for the combined format.
Uppercase conversion is not required for the combined format.
Uppercase conversion is not required for the combined format.
Hash Algorithm
SHA-256
SHA-256.
MD-5 dan SHA-1.
Example of Combined Parameters
##signaturekey##rq_uuid##rq_datetime##order_id##amount##ccy##comm_code##SENDINVOICE##
##comm_code##orderid##amount##key##datetime##password##
rq_uuid+rq_datetime+sender_id+receiver_id

Universal Signature Format

The Universal Signature Format is used for most Espay services listed in the Parameter Combination Format table, except for Payment Link and Settlement Notification services. In this format, all required parameters are combined using the ## separator. After that, the combined string is converted to uppercase before being processed using the SHA-256 hashing algorithm.

Signature Generation Steps
Use the following steps to generate a signature based on the service you are using. The example below uses the Virtual Account (Send Invoice) service.
  1. Combine the signature parameters specified by Espay using "##" as the separator.
Combination format
##SignatureKey##rq_uuid##rq_datetime##order_id##amount##ccy##comm_code##SENDINVOICE##
##cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504##rfbd39734-ed32-490d-98c4-e91bcd91037a##2024-01-01 14:39:11##ORDER001##100000##IDR##SGWDIGALLERY##SENDINVOICE##
  1. Convert the combined string from step 1 into uppercase.
Format before uppercase
##cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504##rfbd39734-ed32-490d-98c4-e91bcd91037a##2024-01-01 14:39:11##ORDER001##100000##IDR##SGWDIGALLERY##SENDINVOICE##
Format after uppercase
##CC256D3A2D7687E6F4E1F4217C534BC6B18F66E3552AA9D312F5F4808130504##RFBD39734-ED32-490D-98C4-E91BCD91037A##2024-01-01 14:39:11##ORDER001##100000##IDR##SGWDIGALLERY##SENDINVOICE##
  1. Apply the SHA-256 hashing algorithm to the formatted string from step 2.
Format after hash SHA-256
##CC256D3A2D7687E6F4E1F4217C534BC6B18F66E3552AA9D312F5F4808130504##RFBD39734-ED32-490D-98C4-E91BCD91037A##2024-01-01 14:39:11##ORDER001##100000##IDR##SGWDIGALLERY##SENDINVOICE##
Format before hash SHA-256
b474188c95439412262f5808473caa8c12676acf4381842ff43b1b4a22493808
Sample Code


Generate Signature Universal Virtual Account (Send Invoice)

$signatureKey = 'cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504';
$rq_uuid      = 'rfbd39734-ed32-490d-98c4-e91bcd91037a';
$rq_datetime  = '2024-01-01 14:39:11';
$order_id     = 'ORDER001';
$amount       = '100000';
$ccy          = 'IDR';
$comm_code    = 'SGWYESSISHOP';
$action       = 'SENDINVOICE';
                                  
$raw_string = strtoupper("##{$signatureKey}##{$rq_uuid}##{$rq_datetime}##{$order_id}##{$amount}##{$ccy}##{$comm_code}##{$action}##");

$signature = hash('sha256', $raw_string);
         
echo "Raw String: " . $raw_string . PHP_EOL;
echo "Signature : " . $signature;
                
              


Generate Signature Universal Virtual Account (Send Invoice)

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class UniversalSignatureGenerator {

    public static void main(String[] args) {
        String signatureKey = "cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504";
        String rq_uuid      = "rfbd39734-ed32-490d-98c4-e91bcd91037a";
        String rq_datetime  = "2024-01-01 14:39:11";
        String order_id     = "ORDER001";
        String amount       = "100000";
        String ccy          = "IDR";
        String comm_code    = "SGWYESSISHOP";
        String action       = "SENDINVOICE";

        // Buat raw string dan ubah ke uppercase
        String rawString = String.format("##%s##%s##%s##%s##%s##%s##%s##%s##",
                signatureKey, rq_uuid, rq_datetime, order_id, amount, ccy, comm_code, action
        ).toUpperCase();

        try {
          // Hash menggunakan SHA-256
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(rawString.getBytes(StandardCharsets.UTF_8));

            // Konversi hasil hash ke hex string
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                hexString.append(String.format("%02x", b));
            }

            // Output hasil
            System.out.println("Raw String: " + rawString);
            System.out.println("Signature : " + hexString.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
                
              


Generate Signature Universal Virtual Account (Send Invoice)

const crypto = require('crypto');

const signatureKey = 'cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504';
const rq_uuid      = 'rfbd39734-ed32-490d-98c4-e91bcd91037a';
const rq_datetime  = '2024-01-01 14:39:11';
const order_id     = 'ORDER001';
const amount       = '100000';
const ccy          = 'IDR';
const comm_code    = 'SGWYESSISHOP';
const action       = 'SENDINVOICE';

// Gabungkan dan ubah ke UPPERCASE
const rawString = `##${signatureKey}##${rq_uuid}##${rq_datetime}##${order_id}##${amount}##${ccy}##${comm_code}##${action}##`.toUpperCase();

// Buat SHA-256 hash
const signature = crypto.createHash('sha256').update(rawString).digest('hex');

// Output
console.log("Raw String :", rawString);
console.log("Signature  :", signature);
                
              

The Payment Link Signature Format is explicitly used for Payment Link services. In this format, parameters are combined using the ## separator, without converting them to uppercase. The combined parameters are then processed using the SHA-256 hashing algorithm.

Signature Generation Steps

Use the following steps to generate a signature for the Payment Link service.

  1. Combine the signature parameters specified by Espay using "##" as the separator.
Combination format
##comm_code##orderid##amount##key##datetime##password##
##ESPAYCOMMCODE##ORDER001-JKT-2020##200000.00##rwjfiwhrwrwhugdsdfyfyd##2020-08-08 09:17:45##P@ssw0rd!##
  1. Convert the combined string from step 1 into uppercase..
Format before hash SHA-256
##ESPAYCOMMCODE##ORDER001-JKT-2020##200000.00## rwjfiwhrwrwhugdsdfyfyd##2020-08-08 09:17:45##P@ssw0rd!##
Format after hash SHA-256
b958d232cb4b5aad3ee37f44ebc89f149083cdd5f8ae100fa0d96776bcae718d
Sample Code


Generate Signature Payment Link

$comm_code = 'SGWYESSISHOP';
$order_id  = 'ORDER001';
$amount    = '200000.00';
$key       = 'rwjfiwhrwrwhugdsdfyfyd';
$datetime  = '2020-08-08 09:17:45';
$password  = 'P@ssw0rd!';

$raw_string = ("##{$comm_code}##{$order_id}##{$amount}##{$key}##{$datetime}##{$password}##");

$signature = hash('sha256', $raw_string);

echo "Raw String : $raw_string\n";
echo "Signature  : $signature\n";
                
              


Generate Signature Payment Link

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class SettlementSignatureExample {
    public static void main(String[] args) {
        String comm_code = "SGWYESSISHOP";
        String order_id  = "ORDER001";
        String amount    = "200000.00";
        String key       = "rwjfiwhrwrwhugdsdfyfyd";
        String datetime  = "2020-08-08 09:17:45";
        String password  = "P@ssw0rd!";

        // Buat raw string dan ubah ke upper
        String rawString = String.format("##%s##%s##%s##%s##%s##%s##",
                comm_code, order_id, amount, key, datetime, password
        );

        try {
            // Hash menggunakan SHA-256
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(rawString.getBytes(StandardCharsets.UTF_8));

            // Konversi hasil hash ke hex string
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                hexString.append(String.format("%02x", b));
            }

            // Output
            System.out.println("Raw String : " + rawString);
            System.out.println("Signature  : " + hexString.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
                
              


Generate Signature Payment Link

const crypto = require('crypto');

const comm_code = 'SGWYESSISHOP';
const order_id  = 'ORDER001';
const amount    = '200000.00';
const key       = 'rwjfiwhrwrwhugdsdfyfyd';
const datetime  = '2020-08-08 09:17:45';
const password  = 'P@ssw0rd!';

// Buat raw string seperti PHP
const rawString = `##${comm_code}##${order_id}##${amount}##${key}##${datetime}##${password}##`;

// Buat hash SHA256
const signature = crypto.createHash('sha256').update(rawString).digest('hex');

// Output
console.log("Raw String :", rawString);
console.log("Signature  :", signature);
                
              

Settlement Notification Signature Format

The Settlement Notification Signature Format is used explicitly for Settlement Notification services. In this format, parameters are combined without using the ## separator and do not require uppercase conversion. The signature is generated using a combination of MD5 and SHA-1 hashing algorithms.

Signature Generation Steps

Use the following steps to generate a signature for the Settlement Notification service:

  1. Combine the signature parameters specified by Espay.
rq_uuid : cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504
rq_datetime: 2024-01-01 14:39:11
sender_id: GOWORLDPG
receiver_id: SGWYESSISHOP
Parameter combination
rq_uuid + rq_datetime + sender_id + receiver_id
Combination format
cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f48081305042024-01-01 14:39:11GOWORLDPGSGWYESSISHOP
  1. Generate the hash using the MD5 algorithm.
Format before hash MD5
cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f48081305042024-01-01 14:39:11GOWORLDPGSGWYESSISHOP
Format after hash MD5
cc29f34e06e17749b0b82e9bf8c4229a
  1. Generate a SHA1 hash from the MD5 output.
Format before SHA1
cc29f34e06e17749b0b82e9bf8c4229a
Format after SHA1
591e6edde42e0d63705ccca9d7ff077392aa7f03
Sample Code


Generate Signature untuk Settlement Notification

$rq_uuid      = "cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504";
$rq_datetime  = "2024-01-01 14:39:11";
$sender_id    = "GOWORLDPG";
$receiver_id  = "SGWYESSISHOP";

$raw_string = $rq_uuid . $rq_datetime . $sender_id . $receiver_id;

$md5_hash = md5($raw_string);
$final_signature = sha1($md5_hash);

echo $final_signature;
                
              


Generate Signature untuk Settlement Notification

import java.nio.charset.StandardCharsets;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class DualHashSignature {

    public static void main(String[] args) {
        String rq_uuid     = "cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504";
        String rq_datetime = "2024-01-01 14:39:11";
        String sender_id   = "GOWORLDPG";
        String receiver_id = "SGWYESSISHOP";

        // Gabungkan string seperti PHP
        String rawString = rq_uuid + rq_datetime + sender_id + receiver_id;

        try {
            // Step 1: MD5 hash
            String md5Hash = hashString(rawString, "MD5");

            // Step 2: SHA1 hash dari hasil MD5
            String finalSignature = hashString(md5Hash, "SHA-1");

            // Output hasil
            System.out.println("Raw String       : " + rawString);
            System.out.println("MD5 Hash         : " + md5Hash);
            System.out.println("Final Signature  : " + finalSignature);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String hashString(String input, String algorithm) throws Exception {
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        byte[] hashedBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        for (byte b : hashedBytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}
                
              


Generate Signature untuk Settlement Notification

const crypto = require('crypto');

const rq_uuid     = "cc256d3a2d7687e6f4e1f4217c534bc6b18f66e3552aa9d312f5f4808130504";
const rq_datetime = "2024-01-01 14:39:11";
const sender_id   = "GOWORLDPG";
const receiver_id = "SGWYESSISHOP";

// Gabungkan raw string
const rawString = rq_uuid + rq_datetime + sender_id + receiver_id;

// Hash MD5
const md5Hash = crypto.createHash('md5').update(rawString).digest('hex');

// Hash SHA1 dari MD5
const finalSignature = crypto.createHash('sha1').update(md5Hash).digest('hex');

// Output
console.log("Raw String     :", rawString);
console.log("MD5 Hash       :", md5Hash);
console.log("Final Signature:", finalSignature);
                
              

Try It!

You can enter data using the input provided. After that, you submit and see the results!

Request
Value
Request

FAQ

A Hash-Based Signature is used to ensure the authenticity and integrity of request data sent to Espay by hashing specific parameters using a signature key provided by Espay. This method is required to:
  1. Ensure that a valid merchant sends the request.
  2. Prevent data tampering during transmission.
  3. Secure transactions from unauthorized use.
A Hash-Based Signature works by:
  • Combining specific parameters according to the defined rules.
  • Hashing the combined parameters using the specified algorithm.
  • • Sending the generated hash as a signature in the request.
Espay will perform the same process to verify whether the signature matches the request data.
The main difference lies in the security mechanism used: Hash-Based Signature
  • Uses the same signature key shared between you and Espay to generate and verify the signature.
  • Used for non-SNAP services.
Signature Asymmetric
  • Uses a private key to generate the signature and a public key to validate it.
  • Used for SNAP services.
The “Credential is not Valid” error occurs when the signature value you send does not comply with Espay’s specifications or does not match the request received by the system.

If you encounter an invalid signature error, please perform the following checks:

  1. Ensure the data used to generate the signature matches exactly the data sent in the request (no differences in value or format).
  2. Check the parameter format, especially the timestamp, parameter order, and naming.
  3. Ensure there are no data format differences, such as extra spaces, letter case changes, or value changes, during request transmission.
  4. Use the Try It feature available in the Espay documentation to compare the generated signature with the signature sent in the request.

If the signature matches the result from the Try It feature but the request is still rejected, please contact the Espay technical team for further investigation.

Each service has a different signature format.
Please ensure that the signature format used matches the service type and request flow. Refer to the signature format table in the Espay Hash-Based Signature documentation here.
Scroll to Top