You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel对接Hotelbeds API:Hex格式SHA256哈希鉴权解决方案

解决Hotelbeds API鉴权400 Bad Request问题

问题背景

在集成Hotelbeds API时,鉴权环节返回400 Bad Request错误。该API要求请求必须同时携带Api-key和X-Signature请求头,其中X-Signature的生成规则为:将Api密钥 + 共享密钥 + 当前秒级时间戳拼接成字符串后,生成Hex格式的SHA256哈希值。

官方提供的示例代码如下:

Bash示例

#!/bin/bash 
apiKey="yourApiKey"
secret="yourSecret"
curl -i \
-X GET \
-H 'Accept:application/json' \
-H 'Api-key:'$apiKey'' \
-H 'X-Signature:'$(echo -n ${apiKey}${secret}$(date +%s)|sha256sum|awk '{ print $1}')'' \
https://api.test.hotelbeds.com/hotel-api/1.0/status

Postman示例

//Begin UTC creation
var utcDate = Math.floor(new Date().getTime() / 1000);

//Begin Signature Assembly
var publicKey = environment["Api-key"];
var privateKey = environment["secret"];

var assemble = (publicKey+privateKey+utcDate);

//Begin SHA-256 Encryption
hash = CryptoJS.SHA256(assemble).toString();
encryption = (hash.toString(CryptoJS.enc.Hex));
postman.setEnvironmentVariable("X-Signature", encryption);

我用Laravel编写的初始代码如下,但请求始终返回400错误:

$client = new \GuzzleHttp\Client();

$apiKey = "apiXXXXXXX";
$secret = "seceretXXXXX";

$assemble = $apiKey . $secret . Carbon::now()->timestamp;

// $hash = Hash::make($assemble);
$hash =  base64_encode(hash('sha512', $assemble));

$headers = [
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Api-key' => $apiKey,
    'X-Signature' => $$hash,
];

$apiURL = 'https://api.test.hotelbeds.com/hotel-api/1.0/status';

$res = $client->request('GET', $apiURL, [
    'headers' => $headers,
    'json' => [
        "data" => [
            "type" => "flight-offers-pricing",
        ]
    ],
]);

$statusCode = $res->getStatusCode();
$responseBody = json_decode($res->getBody(), true);

dd($responseBody);

错误原因分析

初始代码存在几个关键问题:

  • 哈希算法不符合要求:使用了SHA512算法而非API要求的SHA256,还额外进行了base64编码,而API需要的是Hex格式的SHA256哈希
  • 变量引用错误:X-Signature的值写成了$$hash,多了一个美元符号,导致无法正确引用哈希变量
  • 冗余请求参数:GET请求中携带了json请求体,但/hotel-api/1.0/status接口不需要该参数,可能导致请求格式错误
  • (非核心)时间戳获取:虽然Carbon::now()->timestamp能获取秒级时间戳,但time()更直接,和官方示例逻辑一致

修正后的代码

$client = new \GuzzleHttp\Client();

$apiKey = "apixxxxxx";
$secret = "secxxxxxx";

// 按照规则生成X-Signature:SHA256(Api-Key + 共享密钥 + 秒级时间戳),默认返回Hex格式
$signature = hash("sha256", $apiKey . $secret . time());

$headers = [
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Api-key' => $apiKey,
    'X-Signature' => $signature,
];

$apiURL = 'https://api.test.hotelbeds.com/hotel-api/1.0/status';

$res = $client->request('GET', $apiURL, [
    'headers' => $headers,
]);

$statusCode = $res->getStatusCode();
$responseBody = json_decode($res->getBody(), true);

return $responseBody;

修正说明

  1. 使用hash("sha256", $string)直接生成符合要求的Hex格式SHA256哈希,无需额外编码
  2. 修正变量引用错误,将$$hash改为正确的$signature
  3. 移除GET请求中不必要的json参数,符合接口要求
  4. 用time()获取秒级时间戳,和官方示例逻辑保持一致

内容的提问来源于stack exchange,提问作者user17171534

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:44:57