Nonce 為每次發出請求API服務前必須取得的參數之一,
而這個是需要在請求前要先請求的API,且其時效性只有60秒
好我知道這樣講有點混亂,
依照自己的解釋簡單來說 前置API動作
,
請求其他API前,必定要先取得這個,取得這個也很簡單,提供商店代號
就行,
但要注意的是發出下一個請求的IP要一致
,但自己是覺得在同一台伺服器是不用太擔心
這裡用範例程式來改,
因為 post_data 需要轉譯成 json,回應後直接解譯,
不用每次都要寫 json_encode 或 json_decode
程式碼如下:
這裡 url 是隱藏的,看起來應該不能把 API 網址直接打出來,各位需要的話再自行修改吧
$nonce_url = 'https://localhost/api/get_nonce';
function WebApi($url, $post_data) {
$ch=curl_init($url);
curl_setopt_array($ch, [
CURLOPT_HEADER => 0,
CURLOPT_NOBODY => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => ["Content-type: application/json; charset=utf-8"],
CURLOPT_POST=> 1,
CURLOPT_POSTFIELDS=> json_encode($post_data),
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSLVERSION => 6
]);
$result=curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}
$responce = WebApi($nonce_url, ['ShopNo' => "ITBON_001"]);
// Response 內容
// [ "Nonce" => "不是這個字串,是Encode 的內容" ]
官方提供四組雜湊值,分別為 a1, a2, b1, b2
(皆為 0~9,A-F 的十六進位字串),
依照 a 對 a,b 對 b 做 XOR運算,
再把兩個結果組合起來,並把英文字母轉大寫
官方提供的是逐個算,而自己有發現兩個好用的函數,
分別是 hexdec 跟 dechex,缺點是一次只能 4 個字元(bytes),
寫法因人而異,這裡提供我的寫法,有興趣的各位歡迎在調整。
$a1 = '1234567890ABCDEF';
$a2 = 'ABCDEF1234567890';
$b1 = '0987654321FEDCBA';
$b2 = 'FEDCBA0987654321';
function calcHashId($a1, $a2, $b1, $b2) {
$a = $b = '';
$length = strlen($a1);
for($i = 0; $i < $length; $i+=4) {
$a .= dechex(hexdec(substr($a1, $i, 4)) ^ hexdec(substr($a2, $i, 4)));
$b .= dechex(hexdec(substr($b1, $i, 4)) ^ hexdec(substr($b2, $i, 4)));
}
return strtoupper($a . $b);
}
calcHashID($a1, $a2, $b1, $b2);
// result: "B9F9B96AA4FDB57FF75BDF4AA69B9F9B";
第二點比較麻煩一些,一開始以為是依照 ASCII 的順序,看到 a < B,就發現不太對勁,要處理的程序會多一些
而第三點只需要把內容為 array 的都排除,這點倒是還好
假設要傳送的內容如下(文件範例為JSON,這裡有改成PHP的陣列)
$data = [
"ShopNo" => "BA0026_001",
"OrderNo" => "A202109140001",
"Amount" => 16888,
"CurrencyID" => "TWD",
"PayType" => "A",
"ATMParam" => ["ExpireDate" => "20210921"],
"CardParam" => [],
"ConvStoreParam" => [],
"PrdtName" => "虛擬帳號訂單",
"ReturnURL" => "https://127.0.0.1/Store/Return",
"BackendURL" => "https://127.0.0.1/AutoPush/PushSuccess"
];
輸出 Sign (安全簽章) 的程式如下
function generateSign($data, $nonce, $hash_id) {
$keys = array_keys($data);
foreach($keys as $key) {
$value = array_shift($data);
if (gettype($value) === 'array' || trim($value) === '') {
continue;
}
$upper_key = strtoupper($key);
$data[$upper_key] = "$key=$value";
}
ksort($data);
$body = implode('&', $data) . $nonce . $hash_id;
return strtoupper(hash('sha256', $body));
}
generateSign($data, 'test_nonce', 'test_hash_id');
// result: "1B97B8BD80C3B9DCA14343318BE30940247EEDD871F180F4C9230B6A5E5615AD"
hexdec
, dechex
寫到後面才發現長度不太對,只支援 4 bytes (32 bit)
,Nonce 跟 Hash Id 要接在內文後面