Signature Generation
Signature digunakan untuk proses autentikasi request yang di kirimkan ke QRIS MPM. SpeedCash menggunakan 2 type signature Asymmetric Without Token
dan Asymmertic with token
untuk proses mengambil token B2B
diperlukan Asymmetric Without Token
dan untuk autentikasi service lainya menggunakan Asymmertic with token
Rumus Signature Without Token
stringToSign = client_ID + "|" + X-TIMESTAMP
signature = SHA256withRSA (Private_Key, stringToSign)
Source Code Pembuatan Signature Asymetric without token
- Go
- PHP
- Node JS
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"fmt"
"io/ioutil"
"log"
)
func main() {
clientID := "your_client_id"
timestamp := "your_timestamp"
// Construct the string to sign
stringToSign := fmt.Sprintf("%s|%s", clientID, timestamp)
// Read the private key from a PEM file
privateKeyPath := "path/to/your/private_key.pem"
privateKeyBytes, err := ioutil.ReadFile(privateKeyPath)
if err != nil {
log.Fatalf("Failed to read private key file: %v", err)
}
// Parse the private key
privateKey, err := parsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatalf("Failed to parse private key: %v", err)
}
// Compute the SHA256 hash of the string to sign
hash := sha256.New()
hash.Write([]byte(stringToSign))
hashed := hash.Sum(nil)
// Sign the hashed string
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
if err != nil {
log.Fatalf("Failed to sign the string: %v", err)
}
// Encode the signature in base64
base64Signature := base64.StdEncoding.EncodeToString(signature)
fmt.Printf("your signature : %s\n", base64Signature)
}
// parsePrivateKey parses an RSA private key from PEM encoded data
func parsePrivateKey(pemData []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(pemData)
if block == nil || block.Type != "RSA PRIVATE KEY" {
return nil, fmt.Errorf("failed to decode PEM block containing private key")
}
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse RSA private key: %v", err)
}
return privateKey, nil
}
<?php
$clientId = 'your_client_id';
$timestamp = 'your_timestamp';
// Construct the string to sign
$stringToSign = $clientId . '|' . $timestamp;
// Load your private key (assuming it's in PEM format)
$privateKey = openssl_pkey_get_private('file://path/to/your/private_key.pem');
// Create a signature
$signature = '';
openssl_sign($stringToSign, $signature, $privateKey, OPENSSL_ALGO_SHA256);
// Encode the signature in base64
$base64Signature = base64_encode($signature);
echo "your signature : $base64Signature";
?>
const stringToSign = `${CLIENT_ID}|${X-TIMESTAMP}`
const signer = crypto.createSign('RSA-SHA256')
signer.update(stringToSign)
const sign = signer.sign(privatKey, 'base64')
console.log(`your signature : ${sign}`)
Rumus Signature with Token
stringToSign = HTTPMethod +”:“+ pathUrl +":"+ AccessToken +":“+ Lowercase(HexEncode(SHA- 256(minify(RequestBody))))+ ":“ + X- TIMESTAMP
signature = HMAC_SHA512(clientSecret, stringToSign)
Source Code Pembuatan Signature Asymetric with token
- Go
- PHP
- Node JS
package main
import (
"crypto/hmac"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"time"
)
func main() {
// Set the current date and time in the 'Asia/Jakarta' timezone
loc, err := time.LoadLocation("Asia/Jakarta")
if err != nil {
panic(err)
}
dateTime := time.Now().In(loc)
timeStamp := dateTime.Format(time.RFC3339)
// accessToken bisa di isi dari yang di dapatkan di service token B2B
accessToken := "6223e366-6bb6-4486-8ada-dc3831ad9204"
//clientSecret bisa di isi dari yang sudah di kirim lewat email
clientSecret := "42f0e4ae-0158-4218-8e8b-e5d804a6bd24"
// endpoinUrl bisa di isi sesuai dengan path dari servicenya
endPointUrl := "/v1.0/registration-account-creation"
//request body bisa di isi payload sesuai dengan servicenya
requestBody := map[string]interface{}{
"originalReferenceNo": "5188671",
"merchantId": "1212667",
"serviceCode": "47",
}
body, err := json.Marshal(requestBody)
if err != nil {
panic(err)
}
sha256Hash := sha256.Sum256(body)
hexEncode := hex.EncodeToString(sha256Hash[:])
stringToSign := fmt.Sprintf("POST:%s:%s:%s:%s", endPointUrl, accessToken, hexEncode, timeStamp)
h := hmac.New(sha512.New, []byte(clientSecret))
h.Write([]byte(stringToSign))
hmac := base64.StdEncoding.EncodeToString(h.Sum(nil))
fmt.Println(hmac)
}
<?php
$dateTime = new DateTime();
$dateTime->setTimezone(new DateTimeZone('Asia/Jakarta'));
$timeStamp = $dateTime->format(DateTime::ATOM);
// accessToken bisa di isi dari yang di dapatkan di service token B2B
$accessToken = "6223e366-6bb6-4486-8ada-dc3831ad9204";
//clientSecret bisa di isi dari yang sudah di kirim lewat email
$clientSecret = '42f0e4ae-0158-4218-8e8b-e5d804a6bd24';
// endpoinUrl bisa di isi sesuai dengan path dari servicenya
$endPointUrl = '/v1.0/registration-account-creation';
//request body bisa di isi payload sesuai dengan servicenya
$requestBody = [
"originalReferenceNo" => "5188671",
"merchantId" => "1212667",
"serviceCode" => "47",
];
$body = json_encode($requestBody, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$sha256Hash = hash('sha256', $body, true);
$hexEncode = strtolower(bin2hex($sha256Hash));
$stringToSign = "POST:{$endPointUrl}:{$accessToken}:{$hexEncode}:{$timeStamp}";
$stringToSignUtf8 = mb_convert_encoding($stringToSign, 'UTF-8');
$hmac = hash_hmac('sha512', $stringToSignUtf8, $clientSecret, true);
$genHmac = base64_encode($hmac);
print_r($genHmac);
const crypto = require('crypto');
const { DateTime } = require('luxon');
// Set the current date and time in the 'Asia/Jakarta' timezone
const dateTime = DateTime.now().setZone('Asia/Jakarta');
const timeStamp = dateTime.toISO();
// accessToken bisa di isi dari yang di dapatkan di service token B2B
const accessToken = '6223e366-6bb6-4486-8ada-dc3831ad9204';
//clientSecret bisa di isi dari yang sudah di kirim lewat email
const clientSecret = '42f0e4ae-0158-4218-8e8b-e5d804a6bd24';
// endpoinUrl bisa di isi sesuai dengan path dari servicenya
const endPointUrl = '/v1.0/registration-account-creation';
//request body bisa di isi payload sesuai dengan servicenya
const requestBody = {
originalReferenceNo: '5188671',
merchantId: '1212667',
serviceCode: '47',
};
const body = JSON.stringify(requestBody);
const sha256Hash = crypto.createHash('sha256').update(body).digest();
const hexEncode = sha256Hash.toString('hex').toLowerCase();
const stringToSign = `POST:${endPointUrl}:${accessToken}:${hexEncode}:${timeStamp}`;
const hmac = crypto.createHmac('sha512', clientSecret).update(stringToSign).digest('base64');
console.log(hmac);