CheckMacValue 驗證機制完整解析:綠界金流安全的第一道防線

CheckMacValue 驗證機制完整解析:綠界金流安全的第一道防線

如果你只打算在金流串接中認真理解一個機制,那就是 CheckMacValue。它是綠界所有 API 交互的安全基礎,作用是「確保資料在傳輸過程中沒有被竄改」。不管是你送給綠界的請求,還是綠界回傳給你的通知,都會帶上這組驗證碼。理解它的運作原理和不驗它的風險,是每一個經手金流的人都應該具備的基本認知。

用一個生活中的比喻來說明。假設你寄了一封掛號信給銀行,信封上蓋了你的印章。銀行收到信後會先比對印章是不是你的,確認沒問題才處理信件內容。CheckMacValue 就是這個「印章」。綠界配給每一個特店一組 HashKey 和 HashIV(可以理解為你的專屬印章),只有你和綠界知道這兩組值。每次你送請求給綠界,或者綠界送通知給你,都會用這兩組值加上交易參數,經過一套固定的演算法,算出一組驗證碼。收到的那一方用同樣的方式重新算一次,如果算出來的結果一致,就代表資料沒有被中途竄改。

計算的流程如下。第一步,把所有要傳送的參數(不含 CheckMacValue 本身)依照參數名稱做「自然排序」(A-Z,不分大小寫)。第二步,在排序後的字串最前面加上 HashKey=你的HashKey值,最後面加上 HashIV=你的HashIV值。第三步,將整串字串做 URL Encode,且編碼規則需遵循 .NET 的標準(空白編碼為 + 而非 %20,部分特殊字元需要手動置換回來)。第四步,把編碼後的字串全部轉成小寫。第五步,對結果做 SHA256 雜湊運算。第六步,把雜湊結果轉成大寫。最終產出的就是 CheckMacValue。

最常導致 CheckMacValue 算錯的三個原因。第一是參數排序錯誤。綠界要求使用「自然排序法(Natural Sort)」,這跟一般程式語言預設的 ASCII 排序不完全相同,對大小寫的處理方式不一樣。PHP 裡要用 uksort 搭配 strcasecmp,其他語言需要找對應的自然排序方法。第二是 URL Encode 的字元差異。不同程式語言的 URL Encode 函式行為不一致,例如空白字元在某些函式中會編碼為 %20 而非 +,括號的編碼也可能不同。綠界的文件有提供一張特殊字元置換對照表,%2d 要換回 -、%5f 換回 _、%2e 換回 . 等等,這些都要手動處理。第三是 HashKey 或 HashIV 複製貼上出錯。這些金鑰裡面常有 l(小寫 L)、I(大寫 i)、1(數字一)這類容易混淆的字元,用肉眼辨認手打非常容易出錯,建議務必用複製貼上。另外,同一個 MerchantID 底下金流、物流、發票的 HashKey/HashIV 各不相同,千萬不要拿錯組。

現在來談最重要的事:為什麼不驗 CheckMacValue 等於在裸奔。當綠界透過 ReturnURL 通知你「某筆訂單付款成功」時,這個通知是透過 HTTP POST 送到你公開的伺服器。如果你的程式收到通知後不驗 CheckMacValue,只看 RtnCode 等於 1 就認定付款成功,那任何人只要知道你的 ReturnURL 網址(這通常不難猜),就可以自己偽造一筆 POST 請求,假裝是綠界通知你付款成功。你的系統就會把訂單標為已付款、觸發出貨流程,結果你根本沒收到錢。這不是理論上的風險——在沒有驗證機制的情況下,這是一個極其簡單的攻擊。

驗證的方式就是反向操作:收到綠界的通知後,把通知裡的所有參數(排除 CheckMacValue)用同樣的方式重新計算一次 CheckMacValue,然後比對你算出來的值跟通知裡帶的值是否一致。一致才處理,不一致就視為無效通知直接丟棄。這個驗證邏輯只需要幾十行程式碼,但它是整個金流安全的基石。省掉這一步,後果可能是無法估算的財務損失。

分享文章: