PAYATHON 2026

Prestashop 结账页点击 Add 无法应用 Coupons

支付老李

结论

通常不是优惠码本身失效,而是结账页的购物车状态没有正确初始化,或者优惠码表单没有正常加载。删除商品会让 Prestashop 重新计算购物车并刷新结账区块,优惠码表单也随之恢复。

排查时先关注两方面:

  1. 主题、One Page Checkout 或其他结账模块导致 JavaScript 事件没有绑定、表单提交被拦截,或者页面刷新后仍在使用旧 DOM。
  2. 购物车中的商品组合不符合 Cart Rule,删除商品后才满足使用条件。

不要直接修改 Prestashop 核心文件。先用浏览器开发者工具确认点击 Add 后是否发送了请求,再判断该查前端代码还是后台规则。

第一步:检查点击 Add 时是否发送请求

打开浏览器开发者工具:

  1. 进入 Console,清空现有日志。
  2. 进入 Network,筛选 Fetch/XHR 和 Doc。
  3. 输入优惠码并点击 Add。
  4. 查看是否出现新请求,同时留意 Console 中有没有红色错误。

完全没有请求

如果点击后页面没有跳转,也没有产生网络请求,问题基本出在前端。常见原因有:

  • JavaScript 在页面初始化时已经报错。
  • 结账模块替换了优惠码区域,却没有重新绑定事件。
  • 自定义代码调用了 event.preventDefault(),但没有继续提交表单。
  • Add 按钮不是 type="submit"。
  • 表单嵌套在另一个 <form> 中,导致浏览器解析异常。
  • 遮罩层、透明元素或禁用状态挡住了按钮。
  • 主题模板缺少 Prestashop 要求的属性或字段。

请求已发送,但返回错误

检查该请求的以下内容:

  • URL
  • HTTP 状态码
  • Request Payload / Form Data
  • Response 内容

返回 403 时,重点检查 token、缓存和安全模块。返回 500 时,查看 Prestashop 日志和 PHP 日志。如果返回 200,但页面没有变化,通常要检查响应处理、DOM 更新,或者错误提示是否被 CSS 隐藏。

检查优惠码表单结构

Prestashop 1.7/8 使用的具体模板会因主题和结账模块而异,但表单至少要保留提交地址、token、优惠码字段和提交动作。例如:

<form action="{$urls.pages.cart}" data-link-action="add-voucher" method="post">
  <input type="hidden" name="token" value="{$static_token}">
  <input type="hidden" name="addDiscount" value="1">

  <input
    class="promo-input"
    type="text"
    name="discount_name"
    autocomplete="off"
    placeholder="{l s='Promo code' d='Shop.Theme.Checkout'}"
  >

  <button type="submit" class="btn btn-primary">
    {l s='Add' d='Shop.Theme.Actions'}
  </button>
</form>

实际字段应以当前 Prestashop 版本自带主题的模板为准。检查时注意:

  • 是否有 method="post"。
  • discount_name 是否被改名。
  • token 是否存在,以及它是不是旧值。
  • addDiscount 是否会随表单一起提交。
  • 按钮是否为 type="submit"。
  • 表单是否被错误嵌套。
  • 主题是否删除了 data-link-action="add-voucher"。

可以暂时切换到官方默认主题测试。如果默认主题下功能正常,问题就在当前主题或它覆盖的模板中。

排查动态刷新后的事件绑定

删除商品后再添加优惠码就能成功,很可能与初始化顺序有关。删除商品触发了购物车更新事件,相关脚本这时才完成绑定。

下面这种写法只会给页面加载时已经存在的按钮绑定事件,容易出现问题:

document.querySelector('.promo-code form')
  ?.addEventListener('submit', handleVoucherSubmit);

如果结账模块随后替换了 .promo-code,新表单不会继承原来的监听器。

自定义代码可以改用事件委托:

document.addEventListener('submit', function (event) {
  const form = event.target.closest(
    'form[data-link-action="add-voucher"]'
  );

  if (!form) {
    return;
  }

  // 如果不准备自行发送 AJAX 请求,不要调用 preventDefault()。
});

如果确实需要自行发送请求,就必须完整处理表单提交、服务器响应和购物车刷新,不能只阻止默认行为:

document.addEventListener('submit', async function (event) {
  const form = event.target.closest(
    'form[data-link-action="add-voucher"]'
  );

  if (!form) {
    return;
  }

  event.preventDefault();

  const response = await fetch(form.action, {
    method: 'POST',
    body: new FormData(form),
    credentials: 'same-origin',
    headers: {
      'X-Requested-With': 'XMLHttpRequest'
    }
  });

  if (!response.ok) {
    throw new Error(`Voucher request failed: ${response.status}`);
  }

  const result = await response.text();
  console.debug(result);
});

这段代码只是演示正确的处理流程,不建议用它直接覆盖 Prestashop 原生购物车逻辑。更稳妥的处理方式,是找出当前主题或结账模块中重复绑定、遗漏绑定,或者错误调用 preventDefault() 的代码并加以修复。

还可以在项目脚本中搜索:

add-voucher
discount_name
promo-code
preventDefault
updatedCart
updateCart

检查时尤其要留意第三方 One Page Checkout、快速结账、Ajax Cart、营销弹窗和缓存优化模块。

检查是否存在 JavaScript 错误

最先报错的不一定是优惠码脚本。页面上的任何未捕获异常都可能中断后续初始化,例如:

Uncaught TypeError
Cannot read properties of null
prestashop is not defined
jQuery is not defined

发现错误后,先处理 Console 中最早出现的异常。常见诱因包括:

  • 主题脚本与 Prestashop 版本不兼容。
  • jQuery 被延迟加载或重复加载。
  • JavaScript 合并、压缩或延迟执行改变了加载顺序。
  • 某个模块仍在引用已经被替换的结账页面元素。
  • CDN 或浏览器还在使用旧脚本。

可以暂时关闭以下优化,再重新测试:

  • JavaScript 合并
  • JavaScript 压缩
  • 延迟加载或推迟执行
  • 第三方前端缓存
  • CDN 脚本优化

关闭后,清除 Prestashop 缓存、反向代理或 CDN 缓存,以及浏览器缓存。

核对购物车规则

如果点击 Add 后请求正常发送,但服务器判定优惠码无效,就要检查后台的 Cart Rule 配置:

  • 优惠码是否启用。
  • 开始和结束时间是否正确。
  • 剩余总数量和每位客户的可用数量是否足够。
  • 是否限制了客户或客户组。
  • 是否限制国家、配送方式或承运商。
  • 是否限制币种。
  • 最低消费金额按含税还是不含税计算。
  • 最低金额是否排除运费。
  • 是否只适用于指定商品、分类、品牌、供应商或属性。
  • 是否与购物车中已有规则互斥。
  • 当前客户是否已经使用过该优惠码。
  • 当前购物车是否包含特殊价格、赠品或不可组合的优惠。

建议使用同一个账号建立两个购物车进行对比:

  • 一个使用可以成功的商品组合。
  • 一个使用不能成功的商品组合。

逐件增加商品,比一次删除多件商品更容易判断是哪件商品或哪种属性触发了限制。

检查错误提示是否被隐藏

有时服务器已经拒绝优惠码,但主题没有显示错误信息。查看响应后,再检查页面中是否有被隐藏的提示节点,例如:

.alert-danger,
.promo-code .alert,
.js-error {
  display: none;
}

还要确认提示是否被渲染到了已经隐藏或被替换的购物车区块中。临时移除 display: none、visibility: hidden 和异常的 overflow: hidden,可以快速验证这个问题。

清除缓存并重新生成前端资源

修改模板或 JavaScript 后,至少要完成以下操作:

  1. 在后台清除 Prestashop 缓存。
  2. 暂时关闭模板缓存和前端合并压缩。
  3. 清理主题编译缓存。
  4. 清理 CDN、反向代理和浏览器缓存。
  5. 使用无痕窗口重新测试。

生产环境中不要直接手动删除用途不明的缓存目录。优先使用后台提供的清理功能,并先确认站点采用了哪种缓存部署方式。

建议的定位顺序

可以按以下顺序排查:

  1. 在 Network 中确认点击 Add 后是否产生请求。
  2. 没有请求时,检查 Console、按钮、表单和事件绑定。
  3. 请求报错时,检查状态码、响应内容和服务器日志。
  4. 请求成功但页面没有更新时,检查 Ajax 回调、购物车刷新和被隐藏的错误提示。
  5. 服务器明确判定优惠码无效时,检查 Cart Rule 条件和商品组合。
  6. 切换到默认主题,并停用第三方结账模块进行对照测试。

根据修改购物车后功能立即恢复这一现象,应先检查第三方结账模块或主题如何动态渲染优惠码区域,以及刷新后是否重新绑定了事件。只有确认请求已经发送,而且服务器返回的是规则错误,才需要把排查重点转到优惠码的后台配置。

备注:内容仅供参考。