如何集成 Paybox system 实现 deferred payment?
结论
PBX_DIFF 是普通的 Paybox 请求参数,需要随表单一起提交,并计入 PBX_HMAC。如果只在表单中增加:
<input type="hidden" name="PBX_DIFF" value="7">
却仍使用原来的签名,Paybox 会判定请求内容发生了变化,并拒绝交易。
商户合同也必须支持延迟扣款。即使参数和签名没有问题,如果 Paybox 或收单机构尚未为商户开通这项能力,请求仍可能失败。
正确的处理方式
生成请求时,按以下顺序处理:
- 将
PBX_DIFF加入待提交参数。 - 使用包含
PBX_DIFF的完整参数串重新计算PBX_HMAC。 - 按照计算签名时的参数顺序输出表单字段。
- 最后提交
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 判断完整的资金处理流程。
备注:内容仅供参考。
