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

使用OAuth 2.0 MAC通过PHP对接Paysera授权时持续返回401错误求助

排查OAuth 2.0 MAC认证对接Paysera接口401未授权问题

以下是几个关键排查点和修复建议:

1. Authorization头参数的引号问题

你当前代码里把每个参数值都用双引号包裹了(比如id="KEY_ID"),但根据MAC认证规范以及多数服务的实现,参数值不需要额外添加双引号。Paysera接口可能因为无法正确解析带引号的参数值而返回401。

修复:修改_getHeader方法里的参数拼接逻辑,去掉引号:

$parts[] = $name . '=' . $value;

2. 默认端口的处理问题

对于HTTPS请求,默认端口是443,根据MAC认证规范,当使用协议默认端口时,签名串里的port字段应该留空,而不是传入443。如果传入了默认端口,会导致签名计算错误。

修复:在调用_getMac前处理端口值:

// 在_getHeader方法中添加端口处理逻辑
$port = $port === 443 ? '' : $port;
$mac = $this->_getMac($ts, $nonce, $method, $path, $host, $port, $key);

3. 时间同步问题

MAC认证的ts参数用于防止重放攻击,服务器会校验时间戳是否在允许的时间窗口内(通常5-15分钟)。如果你的服务器本地时间和Paysera服务器时间偏差过大,会直接返回401。

验证:校准本地服务器时间,确保和Paysera服务器时间同步,可使用NTP服务完成时间校准。

4. Nonce格式优化

虽然uniqid()生成的字符串符合规范,但部分服务可能要求nonce具备更高随机性。可以改用更随机的生成方式:

private function _getNonce() {
    return bin2hex(random_bytes(16));
}

修改后的完整代码示例

private function _getTs() {
    return time();
}

private function _getNonce() {
    return bin2hex(random_bytes(16));
}

private function _getMac($ts, $nonce, $method, $path, $host, $port, $key) {
    return base64_encode(hash_hmac("sha256", implode("\n", [
        $ts,
        $nonce,
        $method,
        $path,
        $host,
        $port,
        "",
    ]), $key, true));
}

private function _getHeader($id, $method, $path, $host, $port, $key) {
    $ts = $this->_getTs();
    $nonce = $this->_getNonce();
    // 处理HTTPS默认端口
    $port = $port === 443 ? '' : $port;
    $mac = $this->_getMac($ts, $nonce, $method, $path, $host, $port, $key);

    $params = [
        "id" => $id,
        "ts" => $ts,
        "nonce" => $nonce,
        "mac" => $mac,
    ];

    $parts = [];
    foreach ($params as $name => $value) {
        // 去掉参数值的双引号
        $parts[] = $name . '=' . $value;
    }

    return "MAC " . implode(", ", $parts);
}

public function test() {
    $httpClient = new \Bitrix\Main\Web\HttpClient();
    $httpClient->setHeader("Authorization", $this->_getHeader(
        KEY_ID,
        "GET",
        "/rest/v1/post-offices",
        "delivery-api.paysera.com",
        443,
        KEY,
    ));
    $httpClient->query("GET", "https://delivery-api.paysera.com/rest/v1/post-offices");
    return $httpClient->getResult();
}

额外验证步骤

  • 开启HTTP客户端调试模式,查看实际发送的Authorization头内容,确认格式符合要求。
  • 对比Paysera官方示例(若有)的签名计算逻辑,确保你的MAC值生成过程一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:27:01