Java 使用 new BigInteger(bytes).toString() 將 HMAC-SHA1 位元組陣列轉為帶符號十進位字串(如 -653068794747578802236590292838260814592085857640),PHP 需產出相同字串。
mhash() 返回原始位元組,需手動實現有符號大整數轉換。function hmacSha1ToBigIntegerString($data, $keyBase64) {
$key = base64_decode($keyBase64);
$hash = hash_hmac('sha1', $data, $key, true); // 原始二進位
// 轉為有符號大整數字串(模擬 Java BigInteger)
$hex = bin2hex($hash);
// 判斷最高位
$firstByte = hexdec($hex[0].$hex[1]);
$isNegative = ($firstByte & 0x80) !== 0;
if ($isNegative) {
// 取反加一(補碼轉正數)
$bytes = array_map('ord', str_split($hash));
for ($i = count($bytes)-1; $i >= 0; $i--) {
$bytes[$i] = (~$bytes[$i]) & 0xFF;
if ($bytes[$i] !== 0xFF) break; // 處理進位
}
$hash = implode('', array_map('chr', $bytes));
$hex = bin2hex($hash);
return '-' . gmp_strval(gmp_init($hex, 16));
} else {
return gmp_strval(gmp_init($hex, 16));
}
}
// 使用
$sig = hmacSha1ToBigIntegerString($param, $appkey);
雙方協議改用 Base64 或十六進位輸出,避免大整數符號位陷阱:
Base64.getEncoder().encodeToString(bytes) 或 Hex.encodeHexString(bytes)。base64_encode($hash) 或 bin2hex($hash)。此為業界標準做法,跨語言零歧義、可讀性強、無大數庫依賴。