Sylius 0.13 支付失败后如何让用户重新付款?
支付阿杰
结论
可以直接复用 Sylius 0.13 现有的支付捕获流程:从订单关联的 Payment 对象中取得 securityToken,再通过 sylius_payment_capture 路由生成重试链接。
不要手工拼接 /payment/capture/<hash>。使用路由名称生成链接,可以避免路径或参数名称发生变化后出现问题。
Twig 示例
如果 Sylius 0.13 项目中的订单只关联一个支付对象,可以在订单列表中这样写:
{% set payment = order.payment %}
{% if payment and payment.state == 'failed' %}
<a href="{{ path('sylius_payment_capture', {
'token': payment.securityToken
}) }}">
重新付款
</a>
{% endif %}
生成的地址通常类似:
/payment/capture/支付对象的安全令牌
令牌应取自:
$payment->getSecurityToken();
不要使用订单编号、支付编号或自行计算的哈希值。
在控制器中生成地址
如果需要在 PHP 中生成链接,可以使用路由生成器:
$url = $this->generateUrl(
'sylius_payment_capture',
[
'token' => $payment->getSecurityToken(),
]
);
然后将 $url 传给模板。
为什么这样做
首次下单后,Sylius 会通过支付对象的安全令牌进入 capture 流程。再次访问同一路由,可以让对应的支付网关重新处理该笔支付,无须复制结账控制器中的支付逻辑。
使用 securityToken 也能避免在 URL 中直接暴露数据库里的支付 ID。
注意事项
- 只为属于当前登录用户的订单显示链接。
- 除了检查
failed状态,还应排除已经完成、取消或退款的支付,避免重复扣款。 - 使用
path('sylius_payment_capture', ...)生成 URL,不要硬编码路径。 - 上述示例基于 Sylius 0.13 中订单只有一个
payment关联。如果项目已将其定制为支付记录集合,应选择该订单最近一次且状态为failed的支付对象。 - 某些支付网关不允许再次执行已经失败的支付记录。遇到这种情况,需要为订单创建新的
Payment,重新选择支付方式并生成新的securityToken,而不是继续使用失败记录。具体处理方式取决于项目使用的支付网关及其 Payum 集成。 - 如果重新访问 capture 路由后立即被状态机拒绝,不要在模板或控制器中强制修改支付状态。应按照当前网关的重试要求创建新的支付尝试,以免破坏支付状态和审计记录。
备注:内容仅供参考。
