Transaction Signature
This page to learn how to generate signature for every transaction endpoint
Relative Path
GET
/game-top-up
Webview
GET
/public/api/ppob/v1/product/{productID}
Open API
GET
/public/api/ppob/v1/product?limit=10&page=1&search=&orderBy=&merchantId={merchantId}
Open API
POST
/public/api/ppob/v1/order
Open API
POST
/public/api/ppob/v1/product/validate
Open API
GET
/public/api/ppob/v1/order/detail
Open API
Step 1
Before a partner create a signature transaction, make sure the partner has received a token from Authentication token, eg
eyJzaWduYXR1cmUiOiIwZGEwYmQ1MWU0MjI2Mzc4YWZhMTliYTM5MDRlZjg5NzQxNWY4ODgzZWI0YjI5ZDM5NzM4YTllZjE2OWIxYzc3IiwidG9rZW5QcG9iVXNlclJlc3BvbnNlIjp7InVzZXJJZCI6InJhaHlhbi1jbGllbnQiLCJleHBpcmVkVHMiOjE3MDk3MjE3NzM5NDksInJvbGVzIjpbInBwb2IuZ2FtZV90b3B1cF9pbl9nYW1lIl19fQ%3D%3D
Step 2
Decode that`s token using URLDecoder / decodeURIComponent, example result :
eyJzaWduYXR1cmUiOiIwZGEwYmQ1MWU0MjI2Mzc4YWZhMTliYTM5MDRlZjg5NzQxNWY4ODgzZWI0YjI5ZDM5NzM4YTllZjE2OWIxYzc3IiwidG9rZW5QcG9iVXNlclJlc3BvbnNlIjp7InVzZXJJZCI6InJhaHlhbi1jbGllbnQiLCJleHBpcmVkVHMiOjE3MDk3MjE3NzM5NDksInJvbGVzIjpbInBwb2IuZ2FtZV90b3B1cF9pbl9nYW1lIl19fQ==
Step 3
Visit base64decode.org, then decode that`s token
{"signature":"9c3a68e2e9d0593beeab9466c09c8bd546b49aea1807735a1b125b8b9e1e2c29","tokenPpobUserResponse":{"userId":"Xersia01","expiredTs":1709817873986,"roles":["ppob.game_topup_in_game"]}}
Partner will see a signature hash, use this value to next step
Step 4
<result_signature> = HMAC_SHA256(ClientId + ClientKeyPattern + ClientKey + ClientKeyPattern + pathurl + ClientKeyPattern + <signature>, minify(<request_body>) )
// <result_signature> = 808cac29deaf1efc7f99e1f8aaefdccfbe9e135756ada8b3ab906124a6be19d0
// Passing <result_signature> value to X-SIGNATURE header
Example Code (Golang)
import (
"crypto"
"crypto/hmac"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"fmt"
)
func main() {
minifyJsonBody := "{\"type\":\"ORDER_PRODUCT\",\"body\":{\"merchantId\":\"M_YDXabcd1\",\"denomId\":1,\"denomCode\":\"ML185\",\"validationUserResponse\":{\"username\":123456,\"validation_token\":\"VT17084167245Y1f1\"}}}"
clientId := "Xersia01"
clientKey := "jH45gXeSW3T8eCCoZQ5{I@iH99D]q9dQ_{{sl@|{xxAvDq?A~92Zw?<(0Mnz8Ygw"
clientKeyPattern := "||/cd"
// this is relative path of endpoint do you want to access
pathUrl := "/public/api/ppob/v1/order"
sampleSignatureFromToken := "9c3a68e2e9d0593beeab9466c09c8bd546b49aea1807735a1b125b8b9e1e2c29"
key := []byte(clientId + clientKeyPattern + clientKey + pathUrl + clientKeyPattern + sampleSignatureFromToken)
h := hmac.New(sha256.New, key)
h.Write([]byte(minifyJsonBody))
signatureTransaction := hex.EncodeToString(h.Sum(nil))
fmt.Println("signatureTrx =", signatureTransaction)
// Output is = a1774d303e66a4655ec65c1f30ddb53964a79482e0574290509f6451a171e617
}
Example Code (Java)
// Hashing method
private String hmacSHA256(String salt, String minifyJsonBody) {
try {
javax.crypto.Mac hmac256SHAInstance = javax.crypto.Mac.getInstance("HmacSHA256");
javax.crypto.spec.SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(salt.getBytes(java.nio.charset.StandardCharsets.UTF_8), "HmacSHA256");
hmac256SHAInstance.init(secret_key);
return org.apache.commons.codec.binary.Hex.encodeHexString(hmac256SHAInstance.doFinal(minifyJsonBody.getBytes(java.nio.charset.StandardCharsets.UTF_8)));
} catch (Exception exception) {
System.out.println("Oops something went wrong.");
return null;
}
}
public void sampleTransactionSignaturePost() {
//body should be minified
String minifyJsonBody = "{\"type\":\"ORDER_PRODUCT\",\"body\":{\"merchantId\":\"M_YDXabcd1\",\"denomId\":1,\"denomCode\":\"ML185\",\"validationUserResponse\":{\"username\":123456,\"validation_token\":\"VT17084167245Y1f1\"}}}";
String clientId = "Xersia01";
String clientKey = "jH45gXeSW3T8eCCoZQ5{I@iH99D]q9dQ_{{sl@|{xxAvDq?A~92Zw?<(0Mnz8Ygw";
String clientKeyPattern = "||/cd";
// this is relative path of endpoint do you want to access
String pathUrl = "/public/api/ppob/v1/order";
String sampleSignatureFromToken = "9c3a68e2e9d0593beeab9466c09c8bd546b49aea1807735a1b125b8b9e1e2c29";
String signature = hmacSHA256(clientId + clientKeyPattern + clientKey + pathUrl + clientKeyPattern + sampleSignatureFromToken, minifyJsonBody);
System.out.println("Transaction signature = " + signature);
// Output = a1774d303e66a4655ec65c1f30ddb53964a79482e0574290509f6451a171e617
}
Step 1
Before a partner create a signature transaction, make sure the partner has received a token from Authentication token, eg
eyJzaWduYXR1cmUiOiI5YzNhNjhlMmU5ZDA1OTNiZWVhYjk0NjZjMDljOGJkNTQ2YjQ5YWVhMTgwNzczNWExYjEyNWI4YjllMWUyYzI5IiwidG9rZW5QcG9iVXNlclJlc3BvbnNlIjp7InVzZXJJZCI6IlhlcnNpYTAxIiwiZXhwaXJlZFRzIjoxNzA5ODE3ODczOTg2LCJyb2xlcyI6WyJwcG9iLmdhbWVfdG9wdXBfaW5fZ2FtZSJdfX0%3D
Step 2
Decode that`s token using URLDecoder / decodeURIComponent, example result :
eyJzaWduYXR1cmUiOiI5YzNhNjhlMmU5ZDA1OTNiZWVhYjk0NjZjMDljOGJkNTQ2YjQ5YWVhMTgwNzczNWExYjEyNWI4YjllMWUyYzI5IiwidG9rZW5QcG9iVXNlclJlc3BvbnNlIjp7InVzZXJJZCI6IlhlcnNpYTAxIiwiZXhwaXJlZFRzIjoxNzA5ODE3ODczOTg2LCJyb2xlcyI6WyJwcG9iLmdhbWVfdG9wdXBfaW5fZ2FtZSJdfX0=
Step 3
Visit base64decode.org, then decode that`s token
{"signature":"9c3a68e2e9d0593beeab9466c09c8bd546b49aea1807735a1b125b8b9e1e2c29","tokenPpobUserResponse":{"userId":"Xersia01","expiredTs":1709817873986,"roles":["ppob.game_topup_in_game"]}}
Partner will see a signature hash, use this value to next step
Step 4
<result_signature> = HMAC_SHA256(ClientId + ClientKeyPattern + ClientKey + ClientKeyPattern + pathurl + ClientKeyPattern + <signature>, "") )
// Passing <result_signature> value to X-SIGNATURE header
Example for Open Webview (Golang)
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
privateKey := "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCI4yKrJ0b7L54UDW5raqctBu21aWdPh+tqHgmHRiiAg3wnhvDzTJJMk9UCa7IKMt95X6zoQHC/Dj3pBgP2DwLj7O3ldE1umSR7N89d+xbPk6X2mmjtdTS2/G6rBUNMh9LiZ9oFdSup7CFJmimM5m17PY7Cr+PtOZ2VThmnqET4OfO/TuOlXmNJd8bnuHdy3VNFZCEUSBV01ItADWEyt8UVHRNFdl9zoBNCKJN/F8DhsEOINDt8ekWd7+J2uz6vJqwBV3jYw41ZMMSmSJUncoH9pd1A7plf+Xd6TZFQE2Gs8RMo6buIjxSUeRMI93LFYbdUPeftk3WMTi8DVGFPCCyPAgMBAAECggEAXxHA5jWlKpbrpumdIqUz7iW9uhy2T5oKeezamUS0pGytMZaaiZ9IjD6v1bqOMF8creMw5yy6ITb28HvpDF9olnvazV102bcqixk7v/2+3fOhdB/Rd/nK3rt68PP6xZAfena+CMRTyvPgOooDCYSPzOP33mbiWcOGGkffsX1ASVSRP8gcrHW9n607/0E4xaTsFCPKlGeoi9kKzcUmOMbqg7r/DAufeFu7RrM5kVkOBI2rSOPc4KcirbecHoVOL5/5m/769kBwdVyjLGUxbpOjJlMX/ud54Qfp4i4Fj+oWsxraNg4TxKNrAMvthR66hLGJ0gEMJZmT4x6g2jOi+wxDoQKBgQDNQ1+bOykUNV+UpfFPCg1P0E8trb8D49pDTwDgLn1n8SdukdvamHIepzpPwzVwSISTxMdMm9n+QDvbNm61eprzsRG4S2E2vQu2FFq0izpZAKAp6bzagljJ1TrGiNx5WdYs5NG4tTuP/VZivQBaARJsnZUheJt1f1HZ/Gg5ex8tiwKBgQCquRNSScDOAHuo85HLHkqAztNPXpqLPGw9JkGCIWxnBkbYEaal3DgJVZRAEEe8zXqy8ZKm0JXSN2CByJTRFG34omKlGSo8kfJ6tcnNsOlAWjHT5+bYwfIO491cnn7uGYwq2yQU/P8QY58+p9JK8I/py+dC69BUHsoj4z0SnrUljQKBgQCmmf2amB0SevO2Si4fMhB17KSndbNpa+H26cPTMci1ueWAeEDTHxLZUHAi11Wjaii5a2k8A++ezvIGThrzj6z/CIRSalRgQnaj9cddbPgRz1EwU7fmPw/j2f8Xr3QLxt/wllSmr+rFRyF7iN4lL2ON5yVpAmRjrNB5tsW9ifJXWwKBgCWvCIbHZNmT3bfjW7EcFJHuFVKVrUNCqRmuUhNpUUZEamrTKpe9zlixHTIu5cbVDFpnXFmZ/RgTxSegoMit28BgB6otrdcE2CMh8VOH01SzFACUVa5O0SFcRsZk7ducpAXprUM8vQhfFQ19ebu08e9HZNqutqN60F+vjxGHGrEZAoGAYFXY4qzMOLPIbJztbL6mnVB2Ntg8+8Jvz0YGe4s2ye2ol7vNZ4d0DE7P4Z66EPTJovpmvpjw5XT1RuK4CrNXvoJ4oxBdm3yF9BhobDxO5L5pWaWThxzNH8W61JwisUwDl5IbRRjwPovt5NXHZ/E/fUQ96jjt4NGftOcceD/ggKA="
dataJson := "{\"requestId\":\"{ed3f6763-b1bd-40e3-aecb-ddaa2c3a9775\",\"requestTime\"1863147517949:,\"type\":\"TYPE_GENERATE_TOKEN\",\"body\":{\"merchantId\":\"M_YDXabcd1\",\"webview\":true,\"additionalInfo\":\"\"}}"
signatureToken := generateSignatureToken(privateKey, dataJson)
fmt.Println("signatureToken =", signatureToken)
minifyJsonBody := ""
clientId := "Xersia01"
clientKey := "jH45gXeSW3T8eCCoZQ5{I@iH99D]q9dQ_{{sl@|{xxAvDq?A~92Zw?<(0Mnz8Ygw"
clientKeyPattern := "||/cd"
clientId = "Xersia01"
clientKey = "jH45gXeSW3T8eCCoZQ5{I@iH99D]q9dQ_{{sl@|{xxAvDq?A~92Zw?<(0Mnz8Ygw"
clientKeyPattern = "||/cd"
// this is relative path of endpoint do you want to access
pathUrl := "/game-top-up?token=eyJzaWduYXR1cmUiOiIwZGEwYmQ1MWU0MjI2Mzc4YWZhMTliYTM5MDRlZjg5NzQxNWY4ODgzZWI0YjI5ZDM5NzM4YTllZjE2OWIxYzc3IiwidG9rZW5QcG9iVXNlclJlc3BvbnNlIjp7InVzZXJJZCI6InJhaHlhbi1jbGllbnQiLCJleHBpcmVkVHMiOjE3MDk3MjE3NzM5NDksInJvbGVzIjpbInBwb2IuZ2FtZV90b3B1cF9pbl9nYW1lIl19fQ==&merchantId=M_YDXabcd1"
sampleSignatureFromToken := "9c3a68e2e9d0593beeab9466c09c8bd546b49aea1807735a1b125b8b9e1e2c29"
key := []byte(clientId + clientKeyPattern + clientKey + pathUrl + clientKeyPattern + sampleSignatureFromToken)
h := hmac.New(sha256.New, key)
h.Write([]byte(minifyJsonBody))
signatureTransaction := hex.EncodeToString(h.Sum(nil))
fmt.Println("signatureTrx =", signatureTransaction)
// Output is = eb4c884430ea87b73ba05927affb1a72b2a07e56874a624aff752281ff39c502
}
Example for Open Webview (Java)
// Hashing method
private String hmacSHA256(String salt, String minifyJsonBody) {
try {
javax.crypto.Mac hmac256SHAInstance = javax.crypto.Mac.getInstance("HmacSHA256");
javax.crypto.spec.SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(salt.getBytes(java.nio.charset.StandardCharsets.UTF_8), "HmacSHA256");
hmac256SHAInstance.init(secret_key);
return org.apache.commons.codec.binary.Hex.encodeHexString(hmac256SHAInstance.doFinal(minifyJsonBody.getBytes(java.nio.charset.StandardCharsets.UTF_8)));
} catch (Exception exception) {
System.out.println("Oops something went wrong.");
return null;
}
}
public void sampleSignatureGet() {
//ENDPOINT GET : leave as empty string
String minifyJsonBody = "";
String clientId = "Xersia01";
String clientKey = "jH45gXeSW3T8eCCoZQ5{I@iH99D]q9dQ_{{sl@|{xxAvDq?A~92Zw?<(0Mnz8Ygw";
String clientKeyPattern = "||/cd";
String sampleSignatureFromToken = "9c3a68e2e9d0593beeab9466c09c8bd546b49aea1807735a1b125b8b9e1e2c29";
String pathUrl = "/game-top-up?token=eyJzaWduYXR1cmUiOiIwZGEwYmQ1MWU0MjI2Mzc4YWZhMTliYTM5MDRlZjg5NzQxNWY4ODgzZWI0YjI5ZDM5NzM4YTllZjE2OWIxYzc3IiwidG9rZW5QcG9iVXNlclJlc3BvbnNlIjp7InVzZXJJZCI6InJhaHlhbi1jbGllbnQiLCJleHBpcmVkVHMiOjE3MDk3MjE3NzM5NDksInJvbGVzIjpbInBwb2IuZ2FtZV90b3B1cF9pbl9nYW1lIl19fQ==&merchantId=M_YDXabcd1";
String signature = hmacSHA256(clientId + clientKeyPattern + clientKey + pathUrl + clientKeyPattern + sampleSignatureFromToken, minifyJsonBody);
System.out.println("Transaction signature = " + signature);
// Output = eb4c884430ea87b73ba05927affb1a72b2a07e56874a624aff752281ff39c502
}
Last updated