PAYATHON 2026

支付券无法使用,调用alipay.trade.precreate未显示单品券扣减

支付阿杰

结论

在 alipay.trade.precreate 中填写 goods_detail,只是向支付宝提交订单的商品明细,并不代表单品券一定会生效。用户支付时,支付宝还会根据券的适用商品、商户、门店、金额、有效时间和用户资格等规则实时判断,最终决定是否展示和扣减优惠。

常见原因有两类:一是 goods_detail 中的商品标识与单品券配置不一致;二是订单、券规则或支付环境不符合使用条件。

可能原因

1. 商品标识没有匹配

单品券通常根据商品编号识别适用商品,排查时应重点核对:

  • goods_id 是否与发券或活动配置中的商品编号完全一致。
  • 如果券配置使用支付宝侧的统一商品编号,是否需要传入对应的 alipay_goods_id。
  • 商品编号是否有大小写、空格、前导零或编码转换方面的差异。
  • 测试环境和生产环境是否配置了不同的商品编号。

不要为每笔订单临时生成商品编号,例如时间戳、流水号或随机 UUID。单品券需要稳定、可匹配的商品标识。

2. 商品金额或数量不一致

先检查以下关系:

商品金额 = price × quantity
订单总金额 = 各商品金额之和 + 其他应计金额

如果商品明细金额与 total_amount 明显不一致,或者商品价格的单位填错,优惠计算可能失败。支付宝金额字段通常以元为单位,并使用字符串表示,例如 "19.90",不要误传为分值 "1990"。

订单中如果有不可优惠金额,也要核对相关金额字段,避免把原本应参与优惠的商品计入不可优惠部分。

3. 单品券不满足使用条件

即使商品编号正确,仍需逐项检查券的规则:

  • 券是否已经生效,是否已过期、已核销或被冻结。
  • 当前用户是否已经领取该券。
  • 当前支付金额是否达到最低消费门槛。
  • 券是否限制商户、门店、终端、城市或支付渠道。
  • 券是否仅适用于特定商品、商品分类或购买数量。
  • 券是否允许与其他优惠叠加。
  • 用户是否符合活动的人群限制。
  • 当前应用、商户账号和收款主体是否在券配置的适用范围内。

最终应以该券的实际配置规则为准。不同券产品或活动平台使用的匹配字段可能不同,不能仅凭是否传入 goods_detail 判断优惠能否生效。

4. 商户、应用或门店信息不匹配

需要核对创建订单时使用的以下信息:

  • app_id
  • 收款商户 PID
  • 门店编号
  • 订单所属商户或服务商关系
  • 券活动绑定的商户主体

在服务商代商户调用、间连模式或门店券场景中,应用主体、调用主体和实际收款主体可能并不相同。任何一项超出券的适用范围,都可能导致优惠无法使用。

5. 只检查了预下单响应

alipay.trade.precreate 返回的是二维码预下单结果。单品券是否可用,通常要等具体用户扫码进入支付流程后,再根据该用户的账户和券状态实时计算。

因此,预下单响应中没有优惠明细,并不能说明 goods_detail 没有生效。还应继续检查:

  • 用户扫码后,收银台是否展示优惠。
  • 实际支付金额是否发生变化。
  • 支付成功后查询到的交易金额和优惠明细。
  • 异步通知或交易查询结果中是否包含相关优惠信息。

6. 二维码或订单被重复使用

out_trade_no 必须保持唯一。如果修改商品明细后仍然复用旧订单号或旧二维码,系统可能继续使用原订单数据,修改后的 goods_detail 也就不会参与计算。

排查时应换用新的 out_trade_no 重新调用接口,并让用户扫描新生成的二维码。

建议的请求示例

下面只展示与商品明细有关的核心结构。实际请求还需按照所用 SDK 的要求完成签名和公共参数设置。

{
  "out_trade_no": "ORDER_202609130001",
  "total_amount": "39.80",
  "subject": "商品订单",
  "goods_detail": [
    {
      "goods_id": "SKU_10001",
      "goods_name": "测试商品",
      "quantity": 2,
      "price": "19.90",
      "goods_category": "TEST_CATEGORY"
    }
  ]
}

Java SDK 可参考以下写法:

AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();

JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", "ORDER_202609130001");
bizContent.put("total_amount", "39.80");
bizContent.put("subject", "商品订单");

JSONArray goodsDetail = new JSONArray();

JSONObject goods = new JSONObject();
goods.put("goods_id", "SKU_10001");
goods.put("goods_name", "测试商品");
goods.put("quantity", 2);
goods.put("price", "19.90");
goods.put("goods_category", "TEST_CATEGORY");

goodsDetail.add(goods);
bizContent.put("goods_detail", goodsDetail);

request.setBizContent(bizContent.toJSONString());

AlipayTradePrecreateResponse response = alipayClient.execute(request);

如果券活动明确要求使用支付宝统一商品编号,应按照所用 SDK 和接口模型补充相应字段,例如:

{
  "goods_id": "MERCHANT_SKU_10001",
  "alipay_goods_id": "ALIPAY_GOODS_ID",
  "goods_name": "测试商品",
  "quantity": 1,
  "price": "19.90"
}

是否需要填写 alipay_goods_id,以及该编号从哪里取得,应以券活动采用的商品配置方式和当前接口文档为准。不要自行填写无法与活动配置对应的编号。

推荐排查步骤

  1. 在券活动后台确认适用商品的准确编号,同时记录券对商户、门店、金额、时间和用户的限制。
  2. 打印实际发送给支付宝的完整 biz_content,不能只查看业务代码中的对象值。
  3. 逐字符比较券配置中的商品编号和 goods_detail.goods_id,必要时一并核对 alipay_goods_id。
  4. 检查 price × quantity、商品明细合计与 total_amount 是否一致。
  5. 确认测试所用的支付宝账号已经领取该券,并且符合活动条件。
  6. 使用全新的 out_trade_no 创建订单,再扫描新生成的二维码。
  7. 保存预下单响应、用户支付页面截图、支付时间、商户订单号和支付宝交易号。
  8. 支付完成后调用交易查询接口,核对实付金额和优惠明细。
  9. 如果商品编号和各项规则都已确认匹配,优惠仍未生效,可将上述信息提交给支付宝技术支持,进一步核查券规则的命中情况。

注意事项

  • 不要把商品名称作为单品券的主要匹配依据。名称相同并不代表商品编号相同。
  • 不要使用浮点数计算金额。建议使用 BigDecimal,并明确保留两位小数。
  • 日志中不要记录用户隐私、支付授权信息、私钥或完整的敏感凭证。
  • 沙箱环境、测试活动和生产环境的数据通常相互隔离,不能据此推断生产券会在沙箱订单中生效。
  • 优惠展示和最终核销可能受实时风控及活动库存影响。如果接口请求正确,但特定用户仍然无法使用,需要结合具体券实例和交易号继续排查。

备注:内容仅供参考。