本文的目標是將如 Message 欄位的內文使用 AES 加密機制將其進行加密,並轉換成如下圖所示的 16 進制字串。

圖 7-1
圖 7-1: 各欄位資料範例

AES 加密機制

在筆者本身串接各家金流的經驗中,AES (advanced encryption standard) 區塊加密法最常見到的,其中加密模式又以 ECB 與 CBC 使用頻率最高。ECB 是最簡單的加密模式,不需要 IV 值,大部分廠商在安全要求更嚴謹的資料上會使用 CBC 加密模式。

本系列的永豐金收款系統正是使用 CBC 加密模式。

CBC 加密模式需要一個初始化向量 (initialization vector) 來對其第一個區塊加鹽,也就是我們在 Day 6 產生的 IV 值。

依賴套件

在 PHP 中使用 AES-CBC 加密模式是使用 openssl_encrypt 函式,如果執行時發生找不到函式的錯誤,可以先使用 php -m 指令確認一下有無安裝 OpenSSL 擴展。如果沒有的話則必須先安裝唷!

圖 7-2
圖 7-2: CLI 指令範例 php -m

如上圖紅箭頭標示,找到的話表示您的 PHP 版本已安裝 OpenSSL。

加密實作

在使用 openssl_encrypt 函式時有三個參數我們必須提供。請見以下說明。

Message 加密要件

圖 7-3
圖 7-3: Message 欄位要件,文件第 22 頁

(1) JSON 訊息內文

圖 7-4
圖 7-4: 範例 - 建立訂單的資料結構

JSON 訊息內文為要傳送給 API 的資料結構,作為 openssl_encrypt 函式的第一個參數。

(2) HashId

openssl_encrypt 函式的第三個參數,作為加密的 key。
取得方法參閱 Day 3 - 安全簽章: HashId 計算

(3) IV

openssl_encrypt 函式的第四個參數。
取得方法參閱 Day 6 - 產生內文加密所需的 IV 值

範例

圖 7-5
圖 7-5: PHP SDK - aesEncrypt 方法

本範例是 PHP SDK 中用來進行 AES-CBC 加密的方法。

第13行 為使用 PHP 函式 openssl_encrypt 進行加密。
第14行 將加密後產生的 binary string 轉成 HEX,接著轉成大寫字元。

驗證加密結果

圖 7-6
圖 7-6: 加密測試網頁

API 文件第 22 頁提供兩個線上測試工具來驗證加密是否正確。

網址
加密 https://sandbox.sinopac.com/QPay.ApiClient/Calc/Encrypt
解密 https://sandbox.sinopac.com/QPay.ApiClient/Calc/Descrypt

在筆者進行線上工具測試時,發現程式的加密程式碼算出來的結果和線上測試工具的結果不同,再進一步比對輸入的 JSON 字串,發現必須要一模一樣,多一個空格、斷行或者跳脫字元都不行。

例如,單純使用 json_encode 函式將陣列轉換成 JSON 字串時,中文字會被編碼,反斜線也被加了跳脫字元,因此在測試的時候可以考慮以下兩個方法之一:

(1) json_encode 加上旗標

可以在 json_encode 函式加上旗標值讓 JSON 字串的輸出和我們貼到測試網頁的一致,不然加密後的結果會不一樣喔!

關於 json_encode 的旗標值可參閱 PHP 官方手冊 這一頁

圖 7-7
圖 7-7: json_encode 加上 flag 差異

上圖是使用 json_encode 將陣列轉成 JSON 字串有無使用旗標的差異,標市示綠色螢光色是中文字被轉成 Unicode 編碼字符,標市示黃色螢光色是反斜線也被加了跳脫字元。經由此圖可以一眼看出其中的差別。

常數名 旗標值 說明 
JSON_UNESCAPED_UNICODE 256 不把中文字轉成 Unicode 編碼字符
JSON_UNESCAPED_SLASHES 64 不把反斜線加上跳脫字元 \
JSON_FORCE_OBJECT 16 會把空陣列 [] 轉成 {}

以上是一些可以參考使用的旗標常數,總而言之,程式轉出來的 JSON 字串要和網頁上的一樣就對了。

(2) 使用程式產生的 JSON 字串

另外一個方法是,使用程式產生的 JSON 字串貼到測試網頁上的輸入框。雖然中文字被轉碼,也會有跳脫字元,不過只要兩邊的字串是完全一致,加密後的結果就會一樣。

流程總結

今天的文章完成了發送請求給 Order API 需要的 Message 欄位,其它需要的欄位也已取得,明天的進度就來建立我們第一筆的測試訂單吧!

最後修改日期: 2022-02-06

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。