jollen.org

Jollen 的 Blog
Jollen's email: jollen # jollen.org
more:  Jollen's Training

強化串連智付寶(Pay2go)交易的安全性

.作者:jollen/
.日期:March 31, 2016 2:14 PM


這幾天因為專案需要,開始將線上支付的金流平臺,從 Paypal 轉移到 Pay2go...

本文章採用 Markdown 語法撰寫(why?),若無法完整閱讀全文,請點擊這裡

前言

這幾天因為專案需要,開始將線上支付的金流平臺,從 Paypal 轉移到 Pay2go。要串接 Pay2go 金流平台是一個很簡單的工作,API 文件也很完整。在實作前端與後端的過程中,發現有一些應該要注意的事項,紀錄如下。

關於 MPG 參數

由於 Pay2go 是以 Form Post(HTML5 的 <form></form>)的方式提交付款請求,所以必須使用 <input> 來紀錄交易參數,如圖一。

2016-03-31 11 57 06

圖一:MPG API

一個稱為 CheckValue 的參數,編碼規則如下:

var data = 'HashKey=' + hashKey +
          '&Amt=' + amt +
          '&MerchantID=' + merchantID +
          '&MerchantOrderNo=' + merchantOrderNo +
          '&TimeStamp=' + timeStamp +
          '&Version=1.2' +
          '&HashIV=' + hashIV;
// 使用 SHA256 壓碼後轉大寫
var checkValue = sha256(data).toLocaleUpperCase();

將幾個主要的交易參數、 hashKeyhashIV 連接成 Query String 形式後,再用 SHA256 編碼。CheckCode 看起來是為了檢查交易參數的正確性。不過:

  • CheckCode 放在 Form 的欄位裡,有安全上的疑慮
  • 最好能改用 REST API 的做法,由 Backend 直接向 Pay2go 的 API 送出一個自定的 HTTP headers,來傳送 CheckCode,但 Pay2go 目前不支援這樣的做法

另外,有些前端網頁,直接將 hashKeyhashIV 也紀錄在 Form 裡面,也是非常危險的做法。如圖二(為避免不必要的問題,僅做截圖,恕不註明出處)。

2016-03-31 12 04 17

圖二:曝露在外的 hashKeyhashIV

類似的安全議題,可以在研發或工程階段,就進行嚴格檢視。不過,把交易機制、平台架構與 SDK 做到非常嚴謹,應該是金流平臺的基本責任。

一個安全且嚴謹的交易平臺,也要針對各種「使用不當」的案例,而造成的安全疑慮,進行完整測試。

關於 NotifyURL

NotifyURL 是 Pay2go 用來通知店家後台交易結果的 URL。Pay2go 在訂單完成交易後,會以 HTTP POST 方法,呼叫 NotifyURL。店家的後台則是要實作這個 API,並進行自已的訂單處理流程。

以下是一個 Pay2go 模擬交易,所回送的 POST 資料:

{ JSONData: '{"Status":"SUCCESS","Message":"\\u4ed8\\u6b3e\\u6210\\u529f","Result":"{\\"MerchantID\\":\\"31745140\\",\\"Amt\\":992,\\"TradeNo\\":\\"16033018180593725\\",\\"MerchantOrderNo\\":\\"14593335802368129\\",\\"RespondType\\":\\"JSON\\",\\"CheckCode\\":\\"4E2B2FB0A54CCFECE9616742FE9025EFBBE8FABBC6562268C11D39DFD6E03E9C\\",\\"IP\\":\\"36.231.213.27\\",\\"EscrowBank\\":\\"KGI\\",\\"PaymentType\\":\\"WEBATM\\",\\"PayTime\\":\\"2016-03-30 18:18:05\\",\\"PayerAccount5Code\\":\\"-\\",\\"PayBankCode\\":\\"-\\"}"}' }

這份資料會以 JSON 格式,經由 POST 方法,由 Pay2go 後台傳送到店家的 NotifyURL。將這筆資料的 JSONData 轉換為 JSON 物件:

var jsonData = JSON.parse(postData.JSONData);  // postData 為上述回傳資料

詳細的交易狀態,則是紀錄在 jsonDataResult 裡,再將這個欄位轉換為 JSON 物件:

var result = JSON.parse(jsonData.Result);

終於得到以下內容(疑問:為什麼不直接回傳一個 Stringify 過的 JSON 物件就好?):

{ MerchantID: '31745140',
  Amt: 992,
  TradeNo: '16033018180593725',
  MerchantOrderNo: '14593335802368129',
  RespondType: 'JSON',
  CheckCode: '4E2B2FB0A54CCFECE9616742FE9025EFBBE8FABBC6562268C11D39DFD6E03E9C',
  IP: '36.231.213.27',
  EscrowBank: 'KGI',
  PaymentType: 'WEBATM',
  PayTime: '2016-03-30 18:18:05',
  PayerAccount5Code: '-',
  PayBankCode: '-' }

這個回傳結果也是頗耐人尋味:

  • CheckCode 放在這裡面,不但有安全上的疑慮,必要性也值得探討
  • CheckCode 的目的,如果是為了 Pay2go 與店家,自行驗證交易資料使用(檢查交易參數是否被竄改),或許可以在各自的後台運算即可,是否以明文傳送,有討論空間

回傳的結果,在交易使用的 Form 裡面幾乎都可以取得。因此向店家發出一個「模擬交易成功」的請求並不是太困難。

強化方案

消極作為:

  1. 不要在 Form 裡面傳送 NotifyURL 參數,避免用心人士,向店家發出「模擬交易成功」的通知。可以在 Pay2go 的管理介面設定 NotifyURL,減少 NotifyURL 曝露的機會。

  2. 不要在 Form 裡面放入 hashKeyhashIV

  3. 店家的 NotifyURL 實作,可以考慮移除「自動出貨」、「自動付款銷核」等流程,取消部份自動化,改採手工銷核。

  4. 店家的 NotifyURL 實作,可以考慮加入更嚴謹的檢查,例如查看 HTTP 的 Origin:,或是 Referer: 等檔頭,或是使用 DNS 反查詢等機制。不過因為 HTTP headers 也是很容易變造,所以根本之道還是 Pay2go 的後台能強化相關機制。

最後,展示如何用 curl 進行「模擬交易成功」。首先,在店家的 Form 裡面取得 MerchantIDCheckValueMerchantOrderNoAmt 四個參數。

接著,將以上參數帶入以下的內容模板:

{
"JSONData": "{\"Status\":\"SUCCESS\",\"Message\":\"\\u4ed8\\u6b3e\\u6210\\u529f\",\"Result\":\"{\\\"MerchantID\\\":\\\"31745140\\\",\\\"Amt\\\":992,\\\"TradeNo\\\":\\\"16033018180593725\\\",\\\"MerchantOrderNo\\\":\\\"14593258232469307\\\",\\\"RespondType\\\":\\\"JSON\\\",\\\"CheckCode\\\":\\\"4E2B2FB0A54CCFECE9616742FE9025EFBBE8FABBC6562268C11D39DFD6E03E9C\\\",\\\"IP\\\":\\\"36.231.213.27\\\",\\\"EscrowBank\\\":\\\"KGI\\\",\\\"PaymentType\\\":\\\"WEBATM\\\",\\\"PayTime\\\":\\\"2016-03-30 18:18:05\\\",\\\"PayerAccount5Code\\\":\\\"-\\\",\\\"PayBankCode\\\":\\\"-\\\"}\"}"
}

將上述內容儲存為 test.json。最後利用 curl 向店家的 NotifyURL 發出 POST 請求:

curl -X POST -d @test.json --header "Content-Type: application/json" http://localhost:80/pay2go/notify

從這個「模擬交易」的測試可以知道,把自已的 NotifyURL 藏好是一個很重要的工作。提供 REST API 來替代 Form Post 方式,可以消除主要的安全疑慮。

Reports and Discussion

Tags:

純手工打造說明:技術專欄文章為 Jollen 原創,內容皆為人工撰寫,無 AI 生成。轉載請註明出處與作者,並全文引用。轉載時請在文章開頭或結尾明顯處註明「本文出處:https://www.jollen.org,已取得原作者同意並授權使用。」
訂閱電子報:不定期 Jollen's Blog 精選文章隨 Moko365 電子報寄送;請透過 Moko365 電子報訂閱(可隨時取消)。

Copyright(c) 2001–2016 www.jollen.org. All rights reserved.
Last update: 2026-07-22