Skip to main content

Signature Callback Validation

SNAP API

Signature Callback Validation

Signature validation is used to authenticate callback requests sent from the Winpay server to the merchant callback url using Winpay's public key.

Public Key

In validating the callback signature, the merchant requires winpay's public key in the process. Production will be sent via email with a certain format.

Signature Formula

The signature on the callback validation takes data in the request header sent by winpay.


stringToSign = HTTPMethod +":"+ EndpointUrl +":"+ Lowercase(HexEncode(SHA-256(minify(RequestBody)))) + ":" + TimeStamp
signature = base64_decode(SHA256withRSA(private_key, stringToSign))

Source Code Signature Validation

Virtual Account

$path = '/sandbox_prod/url_listener.php/v1.0/transfer-va/payment';
$timestamp = '2024-01-11T08:57:55+07:00'; //ambil dari header X-Timestamp
$signature = 'Zng8tJgtK2lPd8CP89KyO1OGEKXn1tFfXevTGIn5IhHYDpobp7+4uvuczP5HwldghO5mzkh03v6wnggoZev8M2RyKegbrRaIr66KbAgr6sfKfH9MfkXFcEKpF/am8QMr4oExKPdYTdGEr6pq6m1CzUjFQsyu9z6JuMGrjXrxFXU='; //ambil dari header X-Signature
$httpMethod = 'POST';
$partnerId = '170041'; //ambil dari header X-Partner-Id
$body = [
"partnerServiceId"=> " 9042",
"customerNo"=> "00000009",
"virtualAccountNo"=> " 904200000009",
"virtualAccountName"=> "WINPAY - fiandi",
"trxId"=> "INV-000000023220",
"paymentRequestId"=> "45539",
"paidAmount"=> [
"value"=> "10000.00",
"currency"=> "IDR"
],
"trxDateTime"=> "2024-01-11T08:57:55+07:00",
"additionalInfo"=> [
"contractId"=> "si1cd5671d-2ffe-4cca-aff0-b8ee9bc1c041",
"channel"=> "BSI"
]
];

$payload = json_encode($body, JSON_UNESCAPED_SLASHES);

$stringToSignArr = [
$httpMethod,
$path,
strtolower(bin2hex(hash('sha256', $payload, true))),
$timestamp
];

$stringToSign = implode(':', $stringToSignArr);

try {
$publicKey = openssl_get_publickey($publicKey);
$verify = openssl_verify($stringToSign, base64_decode($signature), $publicKey, OPENSSL_ALGO_SHA256);

if($verify !== 1){
$response = [
'message' => 'Cannot verify signature'
];

print_r($response);
} else {
$response = [
'responseCode' => '2002500',
'responseMessage' => 'Successful'
];

print_r($response);
}


} catch(Exception $e) {
$response = [
'message' => 'Invalid signature {'.$e->getMessage().'}'
];

print_r($response);
}

E-Wallet

$path = '/v1/test';
$timestamp = '2024-01-11T17:01:35+07:00'; //ambil dari header X-Timestamp
$signature = 'SbplyMG0x4igUO8ZqkgUDqNXIzZ6eryz1eNWFfUT499/ulgCLKDJifPtdQH/WBWg5BnKTn+AaKK6inll7h7gJbojC/85TH1QNFnzz8fR4ds+BmFhQaYhys1G5upm4h9x/2hFIznFsEYlc+Ggljs5kXi9wezsltlEkAf5w6snCf4='; //ambil dari header X-Signature
$httpMethod = 'POST';
$partnerId = '170041'; //ambil dari header X-Partner-Id
$body = [
"originalPartnerReferenceNo"=> "0000000000591y",
"originalReferenceNo"=> "45588",
"merchantId"=> 170041,
"amount"=> [
"value"=> "1000",
"currency"=> "IDR"
],
"latestTransactionStatus"=> "00",
"additionalInfo"=> [
"channel"=> "OVO",
"contractId"=> "ovb7b5599b-cce7-4f0f-8c34-fa283185945b"
]
];

$payload = json_encode($body, JSON_UNESCAPED_SLASHES);

$stringToSignArr = [
$httpMethod,
$path,
strtolower(bin2hex(hash('sha256', $payload, true))),
$timestamp
];

$stringToSign = implode(':', $stringToSignArr);

try {
$publicKey = openssl_get_publickey($publicKey);
$verify = openssl_verify($stringToSign, base64_decode($signature), $publicKey, OPENSSL_ALGO_SHA256);

if($verify !== 1){
$response = [
'message' => 'Cannot verify signature'
];

print_r($response);
} else {
$response = [
'responseCode' => '2005600',
'responseMessage' => 'Successful'
];

print_r($response);
}


} catch(Exception $e) {
$response = [
'message' => 'Invalid signature {'.$e->getMessage().'}'
];

print_r($response);
}

QRIS

$path = '/sandbox_prod/url_listener.php/v1.0/qr/qr-mpm-notify';
$timestamp = '2024-01-11T16:36:57+07:00'; //ambil dari header X-Timestamp
$signature = 'Zeqi6FIJ1Po8JU2tc0yqfqEbiHNfBYkvesbKIcPIEomsBpqriWrD5cqMH2Tb8Ys8U5CSqBhSliM8KnQ0YIyk444mCEe4M4eKnGVYA3YVfE3Bg1IOviugqzCeNPKxU8kxARdaXVlCo7s+tA9roHt+fE5ZTRYeGkAEC3ChM8277aI='; //ambil dari header X-Signature
$httpMethod = 'POST';
$partnerId = '170041'; //ambil dari header X-Partner-Id
$body = [
"originalReferenceNo"=> "45584",
"originalPartnerReferenceNo"=> "abctoxfzxc",
"latestTransactionStatus"=> "00",
"amount"=> [
"value"=> "45000",
"currency"=> "IDR"
],
"additionalInfo"=> [
"channel"=> "QRIS",
"contractId"=> "qr748ad360-9755-40af-a201-e44b45c4568f",
"brandName"=> "DANA",
"rrn"=> "027364710019",
"buyerRef"=> "WINPAY",
"terminalId"=> null
]
];

$payload = json_encode($body, JSON_UNESCAPED_SLASHES);

$stringToSignArr = [
$httpMethod,
$path,
strtolower(bin2hex(hash('sha256', $payload, true))),
$timestamp
];

$stringToSign = implode(':', $stringToSignArr);

try {
$publicKey = openssl_get_publickey($publicKey);
$verify = openssl_verify($stringToSign, base64_decode($signature), $publicKey, OPENSSL_ALGO_SHA256);

if($verify !== 1){
$response = [
'message' => 'Cannot verify signature'
];

print_r($response);
} else {
$response = [
'responseCode' => '2005200',
'responseMessage' => 'Successful'
];

print_r($response);
}


} catch(Exception $e) {
$response = [
'message' => 'Invalid signature {'.$e->getMessage().'}'
];

print_r($response);
}