退款后如何禁用自动生成 voucher
结论
在 PrestaShop 的标准退款流程中,勾选 Generate a credit slip 只会生成退款单(credit slip),不会创建供客户下次购物使用的 voucher。系统只有在勾选 Generate a voucher 后,才会创建相应金额的购物优惠券。
如果没有勾选 Generate a voucher,系统却仍然生成了 voucher,通常需要排查支付模块、第三方模块或 AdminOrdersController 的 override。不要以关闭 credit slip 的方式规避问题,应找到退款流程中创建 CartRule 的代码并将其移除。
先确认生成的到底是什么
PrestaShop 中有两个容易混淆的对象:
- Credit slip:退款凭证,通常可以生成 PDF,数据保存在
order_slip等相关表中。 - Voucher:客户下次下单时可以使用的优惠券,本质上是
CartRule,数据通常保存在cart_rule、cart_rule_lang等表中。
如果客户收到的只是退款单 PDF,这是勾选 Generate a credit slip 后的正常结果,不等于客户获得了可消费余额。
只有当后台的 Catalog → Discounts 中出现新规则,或者客户账户中出现可用于购物车的优惠码时,才能确定系统确实创建了 voucher。
检查退款请求参数
经典版 PrestaShop 的订单退款页面通常使用两个独立参数控制退款单和优惠券:
generateCreditSlip
generateDiscount
正常情况下,只生成退款单的请求应为:
$generateCreditSlip = true;
$generateDiscount = false;
可以打开浏览器开发者工具,在 Network 面板中检查退款请求。确认请求中没有以下参数,或者该参数的值为空、0:
generateDiscount
如果页面上没有勾选对应选项,但提交的请求中仍包含有效的 generateDiscount,需要检查后台模板、JavaScript 或相关模块是否改动了表单。
检查支付模块和 override
搜索退款相关代码时,重点查看是否创建并保存了 CartRule:
$cartRule = new CartRule();
$cartRule->reduction_amount = $refundAmount;
$cartRule->add();
还可以搜索以下关键词:
CartRule
generateDiscount
reduction_amount
actionProductCancel
actionOrderStatusPostUpdate
actionOrderStatusUpdate
refund
常见的检查位置有:
/modules/你的支付模块/
/override/controllers/admin/AdminOrdersController.php
/override/classes/order/
/controllers/admin/AdminOrdersController.php
具体目录和退款实现会因 PrestaShop 版本而异。核心文件可以用来对照标准流程,但不建议直接修改,因为升级时很容易被覆盖。
如果模块中有类似代码,可以删除创建 voucher 的逻辑,或者为它增加明确的配置条件:
if ((bool) Configuration::get('PAYMENT_MODULE_CREATE_REFUND_VOUCHER')) {
$cartRule = new CartRule();
// 仅在商店明确启用退款优惠券时设置并保存 CartRule。
// 具体必填字段取决于当前 PrestaShop 版本。
$cartRule->add();
}
如果退款已经通过支付渠道或线下方式返还,该配置默认应为关闭状态:
Configuration::updateValue(
'PAYMENT_MODULE_CREATE_REFUND_VOUCHER',
false
);
外部退款、生成 credit slip 和创建 voucher 应是三个彼此独立的操作。
排查订单状态触发逻辑
部分模块会在订单状态变为“已退款”时自动创建优惠券。例如:
public function hookActionOrderStatusPostUpdate(array $params)
{
$newOrderStatus = $params['newOrderStatus'];
if ((bool) $newOrderStatus->refunded) {
$this->createRefundVoucher($params);
}
}
如果退款已经在 PrestaShop 外部完成,应删除这段创建 voucher 的逻辑,或者至少使用单独的配置项控制它:
public function hookActionOrderStatusPostUpdate(array $params)
{
if (!(bool) Configuration::get('PAYMENT_MODULE_CREATE_REFUND_VOUCHER')) {
return;
}
$newOrderStatus = $params['newOrderStatus'];
if ((bool) $newOrderStatus->refunded) {
$this->createRefundVoucher($params);
}
}
不要只根据订单状态为“已退款”就无条件创建 CartRule,否则后台手工退款、API 退款和状态同步都可能导致重复发券。
修改后清理缓存
删除或修改 override 后,需要清理 PrestaShop 缓存。可以通过后台的性能设置操作;如果项目使用命令行工具,则应采用当前版本支持的缓存清理方式。不同 PrestaShop 版本的缓存目录和控制台命令可能不同,不要直接套用。
清理后还要确认 override 是否继续生效。某些旧版本会生成类索引缓存,如果只删除源文件而不重建缓存,修改可能不会生效。
已经创建的 voucher 如何处理
修复代码不会自动撤销之前生成的 voucher。对于已经创建的优惠券,建议在后台禁用,不要直接删除数据库记录:
- 找到退款后生成的购物车规则。
- 确认它对应相关客户和订单。
- 将状态改为禁用。
- 检查优惠券是否已经使用。
如果优惠券已经被使用,不应直接删除,以免影响历史订单的核对和审计。
注意事项
- 不要修改 PrestaShop 核心控制器来强制关闭 voucher,应优先修复模块或 override。
- 不要将 credit slip 和 voucher 混为一谈。credit slip 是退款凭证,通常可以保留。
- 部分退款可能多次触发退款事件,模块需要避免重复创建优惠券或重复执行外部退款。
- 修改前应确认 PrestaShop 的具体版本,并检查是否安装了退货、钱包、积分或店铺余额模块。这些模块也可能在退款后创建可用余额,来源不一定是支付模块。
- 如果标准请求中的
generateDiscount为假,代码中也没有执行CartRule::add(),还需要检查第三方模块注册的退款或订单状态 hooks。
备注:内容仅供参考。
