PAYATHON 2026

支付宝API支付是否按笔收费及实际到账金额说明

支付阿杰

结论

支付宝不会因为商户”调用一次 API”就固定收取一笔费用。交易手续费是否收取、费率是多少、如何结算,要看商户签约的支付产品、所属行业、费率协议、优惠政策和结算规则。API 调用次数和交易手续费是两回事。

异步通知中的 receipt_amount 指”商家在交易中实际收到的款项”,也就是商家在该笔交易支付环节实际收取的金额。它不一定是扣除支付宝逐笔手续费后的净到账金额。交易服务费可能单独记账、汇总扣收,或按照协议结算,因此不能只看 receipt_amount 来判断最终净收益。

金额字段如何理解

支付宝交易通知中常见的金额字段有:

  • total_amount:订单总金额。
  • buyer_pay_amount:买家实际支付金额。
  • receipt_amount:商家在该笔交易中实际收到的款项。
  • point_amount:使用积分支付的金额。
  • invoice_amount:可开具发票的金额。

这些字段描述的是交易本身的资金构成,不等于商户最终的财务结算结果。

例如,一笔订单金额为 100 元。如果买家使用了平台优惠、商家优惠或积分,total_amount、buyer_pay_amount 和 receipt_amount 可能并不相同。即使 receipt_amount 是 100 元,也不能据此认定支付宝没有收取服务费。反过来,也不能直接把 total_amount - receipt_amount 当作手续费。

是否按每笔交易收费,应以支付宝商家平台中的产品签约信息和费率协议为准。常见的计费方式可能是交易金额乘以约定费率,但具体规则仍要结合商户合同判断。

正确的核对方法

可以按以下顺序核对:

  1. 登录支付宝商家平台,检查当前应用对应的支付产品及签约状态。
  2. 查看签约协议中约定的费率、免费额度、优惠期、计费范围和手续费扣收方式。
  3. 保存异步通知中的 trade_no、out_trade_no、total_amount、buyer_pay_amount 和 receipt_amount。
  4. 下载支付宝账单或调用账单下载接口,核对交易明细、业务明细和资金明细。
  5. 根据账单中的服务费记录、资金收支记录和实际结算记录,计算净到账金额。

财务上的净到账金额通常要按账务记录计算,不能只根据通知字段推算:

净到账金额 = 交易收入 - 服务费 - 退款支出 - 其他调整项

具体应包含哪些项目,以商户签约协议和支付宝账单的统计口径为准。

异步通知处理示例

下面的 Java 示例演示了如何验签并保存通知中的金额字段。其中,receipt_amount 只作为交易金额信息保存,不直接标记为”已扣手续费金额”。

Map<String, String> params = new HashMap<>();

for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
    String value = String.join(",", entry.getValue());
    params.put(entry.getKey(), value);
}

boolean verified = AlipaySignature.rsaCheckV1(
    params,
    ALIPAY_PUBLIC_KEY,
    "UTF-8",
    "RSA2"
);

if (!verified) {
    response.getWriter().write("failure");
    return;
}

String appId = params.get("app_id");
String outTradeNo = params.get("out_trade_no");
String tradeNo = params.get("trade_no");
String tradeStatus = params.get("trade_status");

BigDecimal totalAmount =
    new BigDecimal(params.getOrDefault("total_amount", "0"));

BigDecimal buyerPayAmount =
    new BigDecimal(params.getOrDefault("buyer_pay_amount", "0"));

BigDecimal receiptAmount =
    new BigDecimal(params.getOrDefault("receipt_amount", "0"));

if (!EXPECTED_APP_ID.equals(appId)) {
    response.getWriter().write("failure");
    return;
}

Order order = orderService.findByOutTradeNo(outTradeNo);

if (order == null || totalAmount.compareTo(order.getOrderAmount()) != 0) {
    response.getWriter().write("failure");
    return;
}

if ("TRADE_SUCCESS".equals(tradeStatus)
        || "TRADE_FINISHED".equals(tradeStatus)) {
    orderService.markPaid(
        outTradeNo,
        tradeNo,
        totalAmount,
        buyerPayAmount,
        receiptAmount
    );
}

response.getWriter().write("success");

不要使用下面的方式计算手续费:

BigDecimal fee = totalAmount.subtract(receiptAmount);

两者的差额可能来自优惠、积分或其他资金构成,不一定是支付宝服务费。手续费应从支付宝账单或明确的计费明细中获取。

注意事项

异步通知用于传递交易状态和相关交易数据,不能代替财务对账。接收通知时还要注意:

  • 必须验证支付宝签名。
  • 必须校验 app_id、out_trade_no 和订单金额。
  • 通知可能重复发送,业务处理必须保证幂等。
  • 金额应使用 BigDecimal,不要使用 float 或 double。
  • 不要根据单个通知字段自行推算费率。
  • 退款、部分退款和后续调账会改变最终的资金结果。
  • 如果合同约定汇总扣收服务费,单笔通知中的 receipt_amount 更不能视为净到账金额。

receipt_amount 可以用来记录商家在该笔交易中的实收金额,但商户最终实际到账金额和手续费金额,仍应以签约规则、资金流水及支付宝账单为准。

备注:内容仅供参考。