Credentials & Signature
To start integrating with Toko Netzme API make sure you already have all secret keys
Netzme team will provide you the secrets via email.
Key Name | Value | Description |
---|---|---|
CLIENT_ID | e.g: TokoNetmeClientId | Identifier, provided to you by Netzme |
CLIENT_SECRET | e.g: f013bc2810be469790dc99773c08812e | Secret Identifier, provided to you by Netzme |
Private_Key | e.g: MIIBOQIBAAJBAJalQt9eQzzNLvaNRA7WM1nUuFFc06T9TmeIl5Di3VI5IH1Fn//hVqgbCVf9FWPU/hrc0wZzr4dP53o2CnMLqHsCAwEAAQJAcGKB7Rnpl2aLbqwc5eSvEok7qJdT3XaME3k3eYOGEVwf91LUrR9soDJV9QAJA1Vg3vhCbyBwTdjCvnzJNUH1AQIhAMXvclXRO1xPEnSToHEDPv9WT9Q5j5AfYDFeIBC4C/LhAiEAwtZx5kzJUouj1CBhQp0KAOxWs2ecec9PnIUaJR2xItsCIEkdv32F8ciSiP25Ps4gZdgKeSirLqYNgQobe/rREdDhAiBywKiu0lTUiCgCfNurxyAoMQpTedfAKmiiMAaZC6bTdwIgNW0qKB9+h2+v5j3x8BrbQbf80xZRqsBcUyZWr5uGs5U= | Private RSA KEY, provided to you by Netzme |
x-callback-token | e.g: Z3kwbFV5bTZnSTNjSmhlNDhDa2d0UjRORk1abW5NSmVZbTJpbldtbFhUczlnWVBXbG9xdU1mS2d4cWxwUkhJVEcycWx5d0lLRmxsNW8yYURKQlc4YVJYNzE3c0lqVXk1a0Rxdg== | Your Netzme unique callback token to verify the origin of the callback. This parameter will be provided on every callback, e.g Payment Success Callback |
1. Signature Authentication
X-SIGNATURE parameter contains Signature for ensure that the data in every request and response cannot be hijacked and imitated by unauthorized users. You will need to provide the parameters on Authentication endpoint.
How to compute the authentication signature
stringToSign = CLIENT_ID + "|" + X-TIMESTAMP
X-SIGNATURE = SHA256WithRSA(Private_Key, stringToSign)
Key | Value |
---|---|
Private_Key | e.g: MIIBOQIBAAJBAJalQt9eQzzNLvaNRA7WM1nUuFFc06T9TmeIl5Di3VI5IH1Fn//hVqgbCVf9FWPU/hrc0wZzr4dP53o2CnMLqHsCAwEAAQJAcGKB7Rnpl2aLbqwc5eSvEok7qJdT3XaME3k3eYOGEVwf91LUrR9soDJV9QAJA1Vg3vhCbyBwTdjCvnzJNUH1AQIhAMXvclXRO1xPEnSToHEDPv9WT9Q5j5AfYDFeIBC4C/LhAiEAwtZx5kzJUouj1CBhQp0KAOxWs2ecec9PnIUaJR2xItsCIEkdv32F8ciSiP25Ps4gZdgKeSirLqYNgQobe/rREdDhAiBywKiu0lTUiCgCfNurxyAoMQpTedfAKmiiMAaZC6bTdwIgNW0qKB9+h2+v5j3x8BrbQbf80xZRqsBcUyZWr5uGs5U= |
CLIENT_ID | e.g: TokoNetmeClientId |
X-TIMESTAMP | Client's current local time in yyyy-MM-ddTHH:mm:ssTZD |
See the sample code
2. Signature Service
X-SIGNATURE parameter contains Signature for ensure that the data in every request and response cannot be hijacked and imitated by unauthorized users. You will need to provide the parameters on every transactional endpoint (e.g: Get Balance Detail, Get Transaction List, etc).
How to compute the transactional signature
stringToSign = HTTPMethod + ":" + EndpointUrl + ":" + AccessToken + ":" + Lowercase(HexEncode(SHA256(minify(RequestBody)))) + ":" + X-TIMESTAMP
X-SIGNATURE = HMAC_SHA512(CLIENT_SECRET, stringToSign)
Key | Value |
---|---|
CLIENT_SECRET | e.g: f013bc2810be469790dc99773c08812e |
HTTPMethod | Http Method, e.g: POST, GET, PUT, PATCH |
EndpointUrl | Endpoint to hit. e.g: /v1.0/api/transaction-history-list |
AccessToken | accessToken value from Authentication |
RequestBody | Your RAW request body(must be minified). e.g: transaction list request |
See the sample code
1. Authentication Signature
Sample Code (Java)
public void generateSignatureForAuthentication() {
String clientId = "NetmeClientId";
String timeStamp = "2022-08-10T00:00:00+07:00";
String privateKey = "MIIBOQIBAAJBAJalQt9eQzzNLvaNRA7WM1nUuFFc06T9TmeIl5Di3VI5IH1Fn//hVqgbCVf9FWPU/hrc0wZzr4dP53o2CnMLqHsCAwEAAQJAcGKB7Rnpl2aLbqwc5eSvEok7qJdT3XaME3k3eYOGEVwf91LUrR9soDJV9QAJA1Vg3vhCbyBwTdjCvnzJNUH1AQIhAMXvclXRO1xPEnSToHEDPv9WT9Q5j5AfYDFeIBC4C/LhAiEAwtZx5kzJUouj1CBhQp0KAOxWs2ecec9PnIUaJR2xItsCIEkdv32F8ciSiP25Ps4gZdgKeSirLqYNgQobe/rREdDhAiBywKiu0lTUiCgCfNurxyAoMQpTedfAKmiiMAaZC6bTdwIgNW0qKB9+h2+v5j3x8BrbQbf80xZRqsBcUyZWr5uGs5U=";
String stringToSign = clientId + "|" + timeStamp;
try {
byte[] decodeBase64 = org.apache.commons.codec.binary.Base64.decodeBase64(privateKey);
java.security.PrivateKey key = readPkcs1PrivateKey(decodeBase64);
java.security.Signature privateSignature = java.security.Signature.getInstance("SHA256withRSA");
privateSignature.initSign(key);
privateSignature.update(stringToSign.getBytes(StandardCharsets.UTF_8));
byte[] s = privateSignature.sign();
String result = java.util.Base64.getEncoder().encodeToString(s);
//print out :CzXuT1rNLkteTuwMY5tWyg/4lxRLJChag8swpDOiO0IqtwMm8x5O7G+foD7Ufv509Xm6wJJ1lMvBA/pooiM4zQ==
System.out.println("X-SIGNATURE " + result);
} catch (java.security.GeneralSecurityException e) {
e.printStackTrace();
}
}
private java.security.PrivateKey readPkcs8PrivateKey(byte[] pkcs8Bytes) throws java.security.GeneralSecurityException {
java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA", "SunRsaSign");
java.security.spec.PKCS8EncodedKeySpec keySpec = new java.security.spec.PKCS8EncodedKeySpec(pkcs8Bytes);
try {
return keyFactory.generatePrivate(keySpec);
} catch (java.security.spec.InvalidKeySpecException e) {
throw new java.lang.IllegalArgumentException("Unexpected key format!", e);
}
}
private java.security.PrivateKey readPkcs1PrivateKey(byte[] pkcs1Bytes) throws java.security.GeneralSecurityException {
int pkcs1Length = pkcs1Bytes.length;
int totalLength = pkcs1Length + 22;
byte[] pkcs8Header = new byte[]{
0x30, (byte) 0x82, (byte) ((totalLength >> 8) & 0xff), (byte) (totalLength & 0xff), // Sequence + total length
0x2, 0x1, 0x0, // Integer (0)
0x30, 0xD, 0x6, 0x9, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0, // Sequence: 1.2.840.113549.1.1.1, NULL
0x4, (byte) 0x82, (byte) ((pkcs1Length >> 8) & 0xff), (byte) (pkcs1Length & 0xff) // Octet string + length
};
byte[] pkcs8bytes = joinByte(pkcs8Header, pkcs1Bytes);
return readPkcs8PrivateKey(pkcs8bytes);
}
private static byte[] joinByte(byte[] byteArray1, byte[] byteArray2) {
byte[] bytes = new byte[byteArray1.length + byteArray2.length];
System.arraycopy(byteArray1, 0, bytes, 0, byteArray1.length);
System.arraycopy(byteArray2, 0, bytes, byteArray1.length, byteArray2.length);
return bytes;
}
Sample Code (PHP)
<?php
function generateAuthSig($clientId, $clientSecret, $privateKey, $now) {
$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
{$privateKey}
-----END RSA PRIVATE KEY-----
EOD;
$hash = $clientId . '|' . $now;
$signature = '';
// Sign the data with the private key using SHA256
if (openssl_sign($hash, $signature, $privateKey, OPENSSL_ALGO_SHA256)) {
return base64_encode($signature);
} else {
throw new Exception('Unable to sign data.');
}
}
$clientId = "NetmeClientId";
$clientSecret ="";
$privateKey ="MIIBOQIBAAJBAJalQt9eQzzNLvaNRA7WM1nUuFFc06T9TmeIl5Di3VI5IH1Fn//hVqgbCVf9FWPU/hrc0wZzr4dP53o2CnMLqHsCAwEAAQJAcGKB7Rnpl2aLbqwc5eSvEok7qJdT3XaME3k3eYOGEVwf91LUrR9soDJV9QAJA1Vg3vhCbyBwTdjCvnzJNUH1AQIhAMXvclXRO1xPEnSToHEDPv9WT9Q5j5AfYDFeIBC4C/LhAiEAwtZx5kzJUouj1CBhQp0KAOxWs2ecec9PnIUaJR2xItsCIEkdv32F8ciSiP25Ps4gZdgKeSirLqYNgQobe/rREdDhAiBywKiu0lTUiCgCfNurxyAoMQpTedfAKmiiMAaZC6bTdwIgNW0qKB9+h2+v5j3x8BrbQbf80xZRqsBcUyZWr5uGs5U=";
$now ="2022-08-10T00:00:00+07:00";
// Should return CzXuT1rNLkteTuwMY5tWyg/4lxRLJChag8swpDOiO0IqtwMm8x5O7G+foD7Ufv509Xm6wJJ1lMvBA/pooiM4zQ==
echo generateAuthSig($clientId, $clientSecret, $privateKey, $now);
?>
2. Transactional Signature
Sample code (Java)
public void generateTransactionalSignature() {
javax.crypto.Mac hmac512;
String xSignature;
String httpMethod = "GET";
String endpointUrl = "/v1.0/transaction-history-list";
String accessToken = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Njc4MTM1MjcsImlhdCI6MTY2NzgxMjYyNywiaXNzIjoicmFoeWFuX3N0ZyJ9.nMvam42YO7k40ZfZDjl1b24SPcS79Ic6qrhFEx7pEYyDQ8b1EsjHsWpR4DMi_zFLmQB8tJG7-YOmlFfBeKhacg";
String timeStamp = "2022-08-10T00:00:00+07:00";
String rawJsonBody = "{\"body\":{\"limit\":2,\"seqId\":0,\"userId\":\"WXhj9BiA\"},\"requestId\":\"bitdna202106281235010001\",\"type\":\"aggregator_transaction_history\"}";
String secret = "86f03ec237644c61842e970010d453f8";
try {
java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
byte[] hash256 = digest.digest(rawJsonBody.getBytes(StandardCharsets.UTF_8));
String encodedBodyRaw = org.apache.commons.codec.binary.Hex.encodeHexString(hash256).toLowerCase();
String stringToSign = httpMethod + ":" + endpointUrl + ":" + accessToken + ":" + encodedBodyRaw + ":" + timeStamp;
final byte[] byteKey = secret.getBytes(StandardCharsets.UTF_8);
hmac512 = javax.crypto.Mac.getInstance("HmacSHA512");
javax.crypto.spec.SecretKeySpec keySpec = new javax.crypto.spec.SecretKeySpec(byteKey, "HmacSHA512");
hmac512.init(keySpec);
byte[] macData = hmac512.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
xSignature = org.apache.commons.codec.binary.Hex.encodeHexString(macData);
//print out : 0a8577a4a93fe19663ea0b367806ff44ca1695994c3b4719bb95f004e64359248defa0e31888013a89fc7c1fc3ba3906d131af3acc0ae9e3f97cb145747fed1b
System.out.println("X-SIGNATURE " + xSignature);
} catch (java.security.InvalidKeyException | java.security.NoSuchAlgorithmException e) {
// Error generate signature.
e.printStackTrace();
}
}
Sample code (PHP)
<?php
function generateServiceSignature($clientSecret, $method,$uri, $token, $body, $now) {
$data = json_encode($body);
$signature = '';
$data = "{$method}:{$uri}:{$token}:". hash('sha256', $data) .":{$now}";
$signature = hash_hmac('sha512', $data, $clientSecret);
return $signature;
}
$clientSecret = "86f03ec237644c61842e970010d453f8";
$method = "GET";
$uri = "/v1.0/transaction-history-list";
// Token are response from api https://apidocs-vsnap.netzme.id/api-reference/toko-netzme/authentication
$token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Njc4MTM1MjcsImlhdCI6MTY2NzgxMjYyNywiaXNzIjoicmFoeWFuX3N0ZyJ9.nMvam42YO7k40ZfZDjl1b24SPcS79Ic6qrhFEx7pEYyDQ8b1EsjHsWpR4DMi_zFLmQB8tJG7-YOmlFfBeKhacg";
$data = [
"body" => [
"limit" => 2,
"seqId" => 0,
"userId" => "WXhj9BiA"
],
"requestId" => "bitdna202106281235010001",
"type" => "aggregator_transaction_history"
];
$now = "2022-08-10T00:00:00+07:00";
// Should return: 0a8577a4a93fe19663ea0b367806ff44ca1695994c3b4719bb95f004e64359248defa0e31888013a89fc7c1fc3ba3906d131af3acc0ae9e3f97cb145747fed1b%
echo "Service Sig: " . generateServiceSignature($clientSecret, $method, $uri, $token, $data, $now);
?>
Last updated