PAYATHON 2026

如何集成 Paybox system 实现 deferred payment?

支付小周

结论

PBX_DIFF 是普通的 Paybox 请求参数,需要随表单一起提交,并计入 PBX_HMAC。如果只在表单中增加:

<input type="hidden" name="PBX_DIFF" value="7">

却仍使用原来的签名,Paybox 会判定请求内容发生了变化,并拒绝交易。

商户合同也必须支持延迟扣款。即使参数和签名没有问题,如果 Paybox 或收单机构尚未为商户开通这项能力,请求仍可能失败。

正确的处理方式

生成请求时,按以下顺序处理:

  1. 将 PBX_DIFF 加入待提交参数。
  2. 使用包含 PBX_DIFF 的完整参数串重新计算 PBX_HMAC。
  3. 按照计算签名时的参数顺序输出表单字段。
  4. 最后提交 PBX_HMAC。

PBX_DIFF 表示延迟处理的天数,不需要填写单位。例如,延迟 7 天可填写 7。部分 Paybox 接口或合同文档可能要求固定宽度格式,如 07,具体应以当前使用的 Paybox System 接口文档和商户配置为准。

PHP 示例

下面的示例使用同一个参数数组生成签名和 HTML 表单,可以避免提交内容与签名内容不一致:

<?php

$payboxUrl = 'PAYBOX_SYSTEM_ENDPOINT';
$hmacKey  = 'YOUR_HEXADECIMAL_HMAC_KEY';

$params = [
    'PBX_SITE'        => 'YOUR_SITE_NUMBER',
    'PBX_RANG'        => 'YOUR_RANK_NUMBER',
    'PBX_IDENTIFIANT' => 'YOUR_IDENTIFIER',
    'PBX_TOTAL'       => '1250', // 最小货币单位,例如 12.50 EUR
    'PBX_DEVISE'      => '978',
    'PBX_CMD'         => 'ORDER-12345',
    'PBX_PORTEUR'     => 'customer@example.com',
    'PBX_RETOUR'      => 'Mt:M;Ref:R;Auto:A;Erreur:E',
    'PBX_EFFECTUE'    => 'https://example.com/payment/success',
    'PBX_ANNULE'      => 'https://example.com/payment/cancel',
    'PBX_REFUSE'      => 'https://example.com/payment/refused',
    'PBX_REPONDRE_A'  => 'https://example.com/payment/callback',
    'PBX_HASH'        => 'SHA512',
    'PBX_TIME'        => gmdate('c'),
    'PBX_DIFF'        => '7',
];

/*
 * Paybox 的签名基于按顺序连接的 name=value 参数。
 * PBX_HMAC 本身不能参与签名计算。
 */
$signingString = http_build_query($params, '', '&', PHP_QUERY_RFC1738);

/*
 * Paybox 后台提供的 HMAC 密钥通常是十六进制字符串,
 * 因此签名前需要转换为二进制。
 */
$binaryKey = pack('H*', $hmacKey);

$hmac = strtoupper(
    hash_hmac('sha512', $signingString, $binaryKey)
);
?>

<form method="post"
      action="<?= htmlspecialchars($payboxUrl, ENT_QUOTES, 'UTF-8') ?>">

    <?php foreach ($params as $name => $value): ?>
        <input
            type="hidden"
            name="<?= htmlspecialchars($name, ENT_QUOTES, 'UTF-8') ?>"
            value="<?= htmlspecialchars($value, ENT_QUOTES, 'UTF-8') ?>"
        >
    <?php endforeach; ?>

    <input
        type="hidden"
        name="PBX_HMAC"
        value="<?= htmlspecialchars($hmac, ENT_QUOTES, 'UTF-8') ?>"
    >

    <button type="submit">Payer</button>
</form>

实际参与签名的字符串现在包含:

...&PBX_HASH=SHA512&PBX_TIME=...&PBX_DIFF=7

如果原来的代码在计算 HMAC 时没有包含 PBX_DIFF=7,新增这个表单字段后,原签名就会失效。

常见问题

参数顺序不同

Paybox 的 HMAC 与参数顺序有关。下面两段内容虽然字段相同,生成的签名却不同:

PBX_TIME=...&PBX_DIFF=7
PBX_DIFF=7&PBX_TIME=...

不要用一套代码拼接签名,再按照另一种顺序手工编写表单。更稳妥的做法是像示例一样,让签名和表单都由同一个有序数组生成。

参数编码不一致

签名字符串中的值必须与表单实际提交的值完全一致,尤其需要检查:

  • 空格和特殊字符的 URL 编码;
  • PBX_CMD 中的特殊字符;
  • PBX_PORTEUR 中的 +;
  • 回调 URL 中的查询参数;
  • 字符编码,通常应统一使用 UTF-8。

如果现有项目已经有一套通过验证的参数拼接方式,应保留原来的编码规则,只将 PBX_DIFF 加入同一套处理流程。

HMAC 密钥处理错误

Paybox 提供的密钥通常采用十六进制格式,此时应使用:

$binaryKey = pack('H*', $hmacKey);

不要把十六进制字符串直接当作普通文本密钥传给 hash_hmac()。如果当前环境使用其他密钥格式,则应按照该环境的 Paybox 配置说明处理。

延迟天数超出允许范围

PBX_DIFF 的可用范围、格式和最大延迟时间可能受以下条件限制:

  • Paybox System 接口版本;
  • 支付卡类型;
  • 收单机构规则;
  • 商户合同配置;
  • 授权有效期。

不能假设任意天数都可以使用。建议先在测试环境中用较短的延迟时间验证,并检查 Paybox 返回的错误代码。

商户合同未开通 deferred payment

PBX_DIFF 并非单纯的前端显示参数,它会影响交易授权和后续扣款流程,通常要求商户账户具备相应能力。如果签名正确但交易仍被拒绝,应向 Paybox 支持方确认:

  • 当前 PBX_SITE 是否已开通延迟扣款;
  • 允许的最大延迟天数;
  • 是否只支持指定卡种;
  • 是否还需要后台或合同级配置;
  • 延迟期结束后由 Paybox 自动扣款,还是需要商户执行后续 capture。

最后一点需要特别确认。不同合同下,“延迟扣款”和”先授权、后手工扣款”可能属于不同的处理模式,不能只根据 PBX_DIFF 判断完整的资金处理流程。

备注:内容仅供参考。