PAYATHON 2026

无资金优惠券订单的 total_amount 应传优惠前还是优惠后金额?

支付老李

结论

如果优惠券由支付宝支付链路识别和核销,调用 alipay.trade.create 时,total_amount 应传优惠前的订单金额,也就是 10.00 元。

支付宝会根据订单金额判断是否满足”满 10 减 2”的使用条件,并在支付时抵扣 2 元,用户最终支付 8.00 元。如果直接将 total_amount 传为 8.00,优惠券可能无法达到满减门槛,也可能导致其他优惠的计算出现偏差。

原因

total_amount 表示提交给支付宝的订单总金额,不是用户使用支付宝优惠后的实际付款金额。

以该订单为例:

订单原价:10.00 元
优惠券:满 10.00 减 2.00 元
total_amount:10.00 元
用户实际支付:8.00 元

计算关系为:

实际支付金额 = 订单总金额 - 优惠金额
             = 10.00 - 2.00
             = 8.00

支付宝需要先收到 10.00 元的订单金额,才能判断该订单符合”满 10”的用券条件。

调用示例

以下示例只包含与金额相关的核心参数。签名、应用授权及其他必填参数,需要根据实际接入方式补充:

{
  "out_trade_no": "ORDER_202609090001",
  "total_amount": "10.00",
  "subject": "商品订单",
  "buyer_id": "2088xxxxxxxxxxxx"
}

不能因为预计优惠 2 元,就把请求改为:

{
  "total_amount": "8.00"
}

处理流程如下:

  1. 商户按优惠前金额创建订单,订单金额为 10.00。
  2. 调用 alipay.trade.create 时传入 "total_amount": "10.00"。
  3. 支付宝在收银台校验并核销”满 10 减 2”优惠券。
  4. 用户实际支付 8.00。
  5. 商户通过支付通知或交易查询结果,核对交易状态及实际支付相关金额。

服务端校验示例

收到支付通知后,不能只根据前端展示的金额判断支付是否成功。服务端还需要验签,并核对订单号、交易状态和金额字段:

BigDecimal orderAmount = new BigDecimal("10.00");
BigDecimal requestTotalAmount = new BigDecimal(notifyParams.get("total_amount"));

if (orderAmount.compareTo(requestTotalAmount) != 0) {
    throw new IllegalStateException("订单金额不一致");
}

String tradeStatus = notifyParams.get("trade_status");
if (!"TRADE_SUCCESS".equals(tradeStatus)
        && !"TRADE_FINISHED".equals(tradeStatus)) {
    throw new IllegalStateException("交易尚未成功");
}

需要核对哪些通知金额字段,应以当前使用的支付宝接口文档和实际返回结果为准。不能自行认定 total_amount、买家实付金额和商户实收金额始终相同。

注意事项

区分支付宝券和商户自行优惠

上述结论只适用于优惠券由支付宝支付链路判断、抵扣和核销的场景。

如果所谓的”无资金优惠券”实际来自商户自己的优惠系统,支付宝不参与核销,并且商户在创建支付订单前已将商品金额从 10 元结算为 8 元,那么 total_amount 通常应传实际需要收取的 8.00 元。

判断时要看优惠由谁核销,而不是优惠券是否”有资金”:

  • 由支付宝核销优惠券时,传优惠前金额。
  • 商户已自行完成优惠结算,支付宝只负责收款时,传优惠后的应收金额。

避免重复优惠

不能先在商户系统中把金额减为 8 元,再让支付宝核销满减券,否则可能造成重复减免。优惠金额应明确由一方计算和执行。

金额使用十进制计算

金额应使用 BigDecimal 等十进制类型处理,不要直接使用 double:

BigDecimal originalAmount = new BigDecimal("10.00");
BigDecimal couponAmount = new BigDecimal("2.00");
BigDecimal payableAmount = originalAmount.subtract(couponAmount);

以支付结果为准

前端显示”支付成功”不能作为最终入账依据。服务端应完成通知验签,必要时还要调用交易查询接口确认订单状态,并核对以下内容:

  • out_trade_no 与本地订单一致;
  • 收款应用和商户身份正确;
  • 交易状态有效;
  • 订单总金额与本地记录一致;
  • 优惠金额和实付金额符合业务预期。

备注:内容仅供参考。