Interact with Gateway
Overview
ZOLOZ SaaS API is language independent, which means the customer could integrate the API with any programmatic language. However, the customer needs to fully understand ZOLOZ gateway protocol, properly create the request and handle the response. If the customer's project is written in Java, the customer could utilize an existing API SDK provided by ZOLOZ to integrate the API with ease, or else the customer could attempt to make his own implementation.
In this chapter, we will firstly introduce how to utilize ZOLOZ API SDK, and then introduce how to use ZOLOZ help script to interact with ZOLOZ gateway, and finally introduce the advanced usage of ZOLOZ help script targeting on assisting the customer to validate his own implementation of the gateway protocol.
Utilize ZOLOZ API SDK
Integrate
To utilize ZOLOZ API SDK, the customer only needs to introduce the library into the maven project by adding following dependency in the main POM file:
<dependency>
<groupId>com.zoloz.api.sdk</groupId>
<artifactId>zoloz-api-sdk</artifactId>
<version>0.1.0</version>
</dependency>
Usage
// initialize OpenApiClient
String clientId = "<Client ID>";
String zolozPublicKey = "<ZOLOZ's public key content encoded in base64>";
String merchantPrivateKey = "<The merchant's private key content encoded in base64>";
OpenApiClient client = new OpenApiClient(); // construct with signature and encryption by default
client.setHostUrl("https://sg-production-api.zoloz.com");
client.setClientId(clientId);
client.setMerchantPrivateKey(merchantPrivateKey);
client.setOpenApiPublicKey(zolozPublicKey);
//client.setSigned(false); // signature (of response) validation can be turned off
//client.setEncrypted(false); // encryption can be turned off
String response = client.callOpenApi(
"v1.zoloz.authentication.test",
"{\"title\": \"hello\", \"description\": \"just for demonstration.\"}"
);
Get the source code
ZOLOZ API SDK has been open sourced on Github, please check the source code here.
PHP sample code
we also provide a php sample code here.
Utilize ZOLOZ Helper Script
Get the script
The helper script has been open sourced on Github, please check the source code here.
Usage
./zoloz.sh \
-c 2188000123456789 \
-P merchant_private_key.pem \
-K 'MIIBIj...QIDAQAB' \
-a /api/v1/zoloz/authentication/test \
-d '{\n "title": "hello",\n "description": "just for demonstration."\n}'
- 2188000123456789 is a dummy client Id, the customer should replace with his own one acquired from ZOLOZ portal.
- merchant_private_key.pem is the private key generated at the customer's side, of which the corresponding public key has been registered in ZOLOZ portal.
- 'MIIBIj...QIDAQAB' is the dummy content of the ZOLOZ public key, the customer should replace with his own one acquired from ZOLOZ portal.
Other control options:
-e
: disable encryption-i
: skip response signature validation
Own's Implementation Validation
In case the customer would like to implement the gateway protocol by his own, it's important for the customer to be capable of validating his own's implementation.
The helper script mentioned in previous section could help the customer a lot for validation purpose by adding some other options:
-v
or-vv
: this will make the script more verbose and output much more intermediate data for validation.-t <request time>
: this will make the request adopt specified time instead of invoking time.-k <AES128 key>
: this will make the request adopt specified AES128 key to encrypt request content instead of a randomly generated one.
Here's an live example of API call:
The customer could validate as following steps:
1 Invoke the script to call the API
./zoloz.sh \
-c 2**************4 \
-P merchant_private_key.pem \
-K 'MIIBIj...QIDAQAB' \
-a /api/v1/zoloz/authentication/test \
-d '{
"title": "hello",
"description": "This is just a demonstration."
}' \
-vv \
-k 31313131313131313131313131313131 \
-t 2020-12-01T00:00:00+0800
Here list some important options:
- Enable verbose mode by adding
-vv
option - Specify the AES128 key used to encrypt the request content with
-k
option (in the example we assume that the randomly generated AES128 key is 0x31313131313131313131313131313131) - Specify the request time directly with
-t
option (in the example we assume that the desired time is 2020-12-01 00:00:00 Singapore time)
2. Validate request encryption
Confirm the final request content (“request body“) is the same with that of the customer's implementation:
> request data length: 75
>> request data: '{\n "title": "hello",\n "description": "This is just a demonstration."\n}'
>
> encryption: 1
> aes128 key: 0x31313131313131313131313131313131
> encrypted aes128 key: DcTqQNe9wc8HZByHRKZBM5HNAypDAWvHD8ugVxiQBdjosM4qzGPtI/sj58V48I0hYK/NLM3J1BcWf+TEXQzz7WkKl1+IVyF+2iYxe8Dx6UJeLNXFsHMKYWNiIdo4cKzkBL4lBEdJhZJwZtkYePq9dNAtXXWxBAsSDFDLejH1sTfBdpVUvGz0xUBZHeisNDS4Z1a/Em+RUtTZo7RqdGlBiUrSwVTOCcsrbaVk+LSP/GpVzbxMZU+FQ38/dvvHf6M7LlreRdyVIz4Rcz74sLOoEuYSg9ccTwp5modp04WRkCFYGI4FyMfZzam/hUWwe194LdUFpR+Dqp4GIiKVY5Vgjg==
> urlencoded encrypted aes128 key: DcTqQNe9wc8HZByHRKZBM5HNAypDAWvHD8ugVxiQBdjosM4qzGPtI%2fsj58V48I0hYK%2fNLM3J1BcWf%2bTEXQzz7WkKl1%2bIVyF%2b2iYxe8Dx6UJeLNXFsHMKYWNiIdo4cKzkBL4lBEdJhZJwZtkYePq9dNAtXXWxBAsSDFDLejH1sTfBdpVUvGz0xUBZHeisNDS4Z1a%2fEm%2bRUtTZo7RqdGlBiUrSwVTOCcsrbaVk%2bLSP%2fGpVzbxMZU%2bFQ38%2fdvvHf6M7LlreRdyVIz4Rcz74sLOoEuYSg9ccTwp5modp04WRkCFYGI4FyMfZzam%2fhUWwe194LdUFpR%2bDqp4GIiKVY5Vgjg%3d%3d
>
> request body length: 108
>> request body: 'Ve/sPNvLd1pDkl6gZURFrHS0mtzz2a0aCt927jgTarQbCBZYn2ikk8nrT5ymQ7YgqrqaOs2qnQW/3G/uVN+n6XJn5jVHTUfTTGJki/Gnqvs='
NOTE:
Most implementations of RSA encryption add random information to avoid possible attacks, so it is as expected that the customer's implementation produces different result for AES128 key encryption. However, the request content encryption is verifiable.
3. Validate request signature
Confirm the request signature (“urlencoded request signature“) is the same with that of the customer's implementation:
>> request content to be signed: 'POST /api/v1/zoloz/authentication/test\n2188423368528034.2020-12-23T16:00:07+0800.Ve/sPNvLd1pDkl6gZURFrHS0mtzz2a0aCt927jgTarQbCBZYn2ikk8nrT5ymQ7YgqrqaOs2qnQW/3G/uVN+n6XJn5jVHTUfTTGJki/Gnqvs='
> request signature: DXFMXcAw9+tx48c47ilhYY0yTBst0u4f2jLMBJl2H9dfPYiOwXH6EWTIyijGPUPVmWFK9pVx8fbUBeS2eIlRluxk+gKA/SuOIMg0VmQAyglIZjJKT7ecdYAqs90f76Pp3MM9LEyAeINlajd6lKyjJwN9YiNoRMoD1g78w7OOw8MbPY52hag0RoV1UGydC8ifK24amyu6+WVVy6XuLgcL1n/CaSk1urIUSFAm9Mq1xQ/ndz9VRHDLspbyfEt/2eML5vWoTyYxZxm9KYyMBjTVmZ9R0mbQMpFPXC0LA89PR8aqv6pCyoTpQ5c5ECrVhgIokdYs5Uf05P0APeShRar2/g==
> urlencoded request signature: DXFMXcAw9%2btx48c47ilhYY0yTBst0u4f2jLMBJl2H9dfPYiOwXH6EWTIyijGPUPVmWFK9pVx8fbUBeS2eIlRluxk%2bgKA%2fSuOIMg0VmQAyglIZjJKT7ecdYAqs90f76Pp3MM9LEyAeINlajd6lKyjJwN9YiNoRMoD1g78w7OOw8MbPY52hag0RoV1UGydC8ifK24amyu6%2bWVVy6XuLgcL1n%2fCaSk1urIUSFAm9Mq1xQ%2fndz9VRHDLspbyfEt%2f2eML5vWoTyYxZxm9KYyMBjTVmZ9R0mbQMpFPXC0LA89PR8aqv6pCyoTpQ5c5ECrVhgIokdYs5Uf05P0APeShRar2%2fg%3d%3d
4. Validate response signature
Confirm the signature (“response signature“) could pass the signature validation of the customer's implementation against the target content (“response content to be verified“):
> response signature: OPiRd8jwCpP8M/Z+oNYjJLUU5zWd5XTk1XFQwX7+00AvIsAJpnP0YqgBfDrvlGuic38m164wAQUqKbFmSe6tNUFTmA+JZxnrwGSZmEbBuRzbB44h0Srgq+W6rC8oqntqjEWDVkdWzaayij5E/2ZAvsKKrTHPBjmECQ+jb78kwRo+jOlZ6rIOqSmKo2UL7XKsYhChKwrUe7nbwpBIg+fBEqMglCDCbMsSSsuavMpco1cwBtAXaZyPRmsqA27bTo9TSij65ovbeOxdZmBZqLXc7jiFKYFOJdLREXC022gLYALuUeP/PWecargIduHg5D+2+MXKiWYIhBZ7RYQe7Qtnew==
> response time: 2020-12-23T08:01:04+0000
>> response content to be verified: 'POST /api/v1/zoloz/authentication/test\n2188423368528034.2020-12-23T08:01:04+0000.Ve/sPNvLd1pDkl6gZURFrHS0mtzz2a0aCt927jgTarQbCBZYn2ikk8nrT5ymQ7YgqrqaOs2qnQW/3G/uVN+n6XJn5jVHTUfTTGJki/Gnqvs='
> response signature verification result: 'Verified OK'
5. Validate response decryption
Confirm the customer's implementation could decrypt the encrypted AES128 key (“response encrypted symmetric key“) to the same AES128 key (“response symmetric key“), and could decrypt the encrypted response content (”response body“) to the same plain content (“response content“).
>> response body: 'Ve/sPNvLd1pDkl6gZURFrHS0mtzz2a0aCt927jgTarQbCBZYn2ikk8nrT5ymQ7YgqrqaOs2qnQW/3G/uVN+n6XJn5jVHTUfTTGJki/Gnqvs='
> response encrypted symmetric key: I6dJGifO9pwTN26uoeET/T/aF8sDVBjnZY0dLaQu5WVbIbZTHEabGg8810N1tJGvbYtWjcJmM1XwKlOieLtVMElPgEpfQ3H3hrFotBpJM5qkYRaUKnJIQpWJSm5fPP4Pr+Lye2M+uVjkieNvTGe36OhBWOfxuhfo70x4jMENXHj2QuEP0JLu0peQBaoMKh/0C47fCQgijBrjcG0ON3eUe4jTvGQ5t00dFKhVmOnnHrP4zOFA6nfgGV4+T702fGxgIoq2CByT+hEWqvVXsEgZWzLse0RDcBjZ/ValRAxQYNuKP8ZzUNGiUt5GlyRmMi4aB69oFTx65Ey//5UXAxFvpg==
> response symmetric key: 0x31313131313131313131313131313131
> response content length: 72
>> response content: {
>> "title": "hello",
>> "description": "This is just a demonstration."
>> }