API驗證
Spiral網關使用RSA數碼簽署作為API驗證方法。
產生公/私鑰
Spiral會提供一組公鑰給商戶,以用作校驗由Spiral發出的API。相對地,商戶亦同樣要提供一組公鑰給Spiral系統,並使用其私鑰上簽署由商戶發出的API。
你可以用以下 OpenSSL 指令去產生公/私鑰:
1. 執行`openssl genrsa -out clientId_private_key.pem 2048` 以獲取商戶的私鑰。 (用作簽署API) 2. 執行`openssl rsa -in clientId_private_key.pem -pubout > clientId_public_key.pem` 以獲取商戶的公鑰。 (在Spiral網站中導入)
|
簽署API訊息
作為簽署內容的payload由下列三部份組成:
資料元素 |
描述 |
clientId |
Client ID, 由Spiral 指發 |
MerchantRef |
商戶參考號,每單交易均要有不同值 (可以考慮由商戶本身的訂單號加上第幾次嘗試支付去組成) |
Datetime |
訊息組成的時間,使用UTC 時區, ISO格式 %Y-%m-%d’T’%H:%M:%S’Z’ |
如何簽署
產生Spiral-Client-Signature:
- 使用client ID, merchant reference and Spiral-Request-Datetime的順序去構成一個payload。
- 使用SHA256 with RSA 及商戶自己的私鑰去簽署payload。
- 用Base64 去將簽署後的位元組編碼成為字串。
Payload 範例:
Client ID: 000000000000001
Merchant reference: 123456789012
Spiral-Request-Datetime: 2020-08-01T10:22:34Z
結果Payload: 0000000000000011234567890122020-08-01T10:22:34Z
產生簽署的範例源碼:
- php
- Node.js
- .net (framework 4.5)
define(“ClientPrivateKey”, “file://./Cert/custpri.pem”);
public function signing($cliendId, $merchantRef){
$now = new Datetime(“now”);
$now->setTimeZone(new DateTimeZone(‘UTC’));
$request_datetime = $now->format(‘Y-m-d\TH:i:s\Z’);
$payload = $cliendId . $merchantRef . $request_datetime;
$pkeyid = openssl_pkey_get_private(ClientPrivateKey);
openssl_sign($payload, $signature, $pkeyid, OPENSSL_ALGO_SHA256);
return $signature;
}
var clientPrivateKey = ‘/Cert/custpri.pem’;
function signing(clientId, merchantRef) {
const crypto = require(‘crypto’);
const sign = crypto.createSign(‘SHA256’);
const fs = require(‘fs’);
var isoTime = d.toISOString();
isoTime = isoTime.replace(/\.\d+/, “”);
sign.write(clientId + merchantRef + isoTime);
sign.end();
const key = fs.readFileSync(clientPrivateKey);
return sign.sign(key, ‘base64’);
}
const String clientPrivateKey = @”C:\cert\custpri.xml”;
static String RSA_Sha256_Signature(String clientId, String merchantRef)
{
// Using private key in XML format, there are online tool available to convert pem into xml format
// e.g.: https://the-x.cn/en-us/certificate/PemToXml.aspx
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(File.ReadAllText(clientPrivateKey));
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] binData = encoder.GetBytes(clientId + merchantRef + isoTime);
byte[] binSignature = rsa.SignData(binData, CryptoConfig.CreateFromName(“SHA256”));
return Convert.ToBase64String(binSignature);
}
如何校驗
- 使用client ID, merchant reference and Spiral-Request-Datetime的順序去構成一個payload。
- 用Base64 去將回覆訊息的簽署字串轉位元組。
- 使用SHA256 with RSA 及Spiral提供的公鑰去校驗payload及簽署位元組。
校驗簽署的範例源碼:
- php
- Node.js
- .net (framework 4.5)
define(“SpiralPublicKey”, “file://./Cert/spiralpub.pem”);
// check server signature
public function verify($clientId, $merchantRef, $requestDateTime, $signature)
{
$pubkeyid = openssl_pkey_get_public(SpiralPublicKey);
$server_sig_payload = $clientId . $merchantRef . $requestDateTime;
$ok = openssl_verify($server_sig_payload, base64_decode($signature), $pubkeyid, OPENSSL_ALGO_SHA256);
return ($ok == 1);
}
var spiralPublicKey = ‘/Cert/spiralpub(UAT).pem’;
function verifying(clientId, merchantRef, dateTime, signature) {
const crypto = require(‘crypto’);
const verify = crypto.createVerify(‘SHA256’);
const fs = require(‘fs’);
verify.write(clientId + merchantRef + dateTime);
verify.end();
const key = fs.readFileSync(spiralPublicKey);
return verify.verify(key, signature, ‘base64’);
}
const String clientPrivateKey = @”C:\cert\spiralpub.xml”;
static bool RSA_Sha256_Verify(String clientId, String merchantRef, String isoTime, String signature)
{
// Using XML format, there are online tool available to convert pem into xml format
// e.g.: https://the-x.cn/en-us/certificate/PemToXml.aspx
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(File.ReadAllText(fileName));
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] binData = encoder.GetBytes(clientId + merchantRef + isoTime);
byte[] binSignature = Convert.FromBase64String(signature);
return rsa.VerifyData(binData, CryptoConfig.CreateFromName(“SHA256”), binSignature);
}
下面的工具可以產生簽署,用作檢查程序的簽署結果。