支付宝如何生成消费者无需填写金额的定额收款码?
结论
可以使用支付宝当面付的 alipay.trade.precreate 接口实现。
商户服务端先创建一笔指定金额的交易,支付宝会返回 qr_code。商户将这段内容生成二维码后,消费者使用支付宝扫码确认付款,不需要手动填写金额。
消费者扫码后如何验证身份,由支付宝客户端和风控策略决定。验证方式可能是支付密码、指纹、人脸识别或免密支付,商户无法强制消费者只使用支付密码。
实现流程
具体流程如下:
- 商户系统生成唯一订单号,并确定收款金额。
- 服务端调用
alipay.trade.precreate创建预下单交易。 - 接口返回
qr_code。 - 商户端将
qr_code渲染为二维码并展示。 - 消费者使用支付宝扫码并确认付款。
- 支付宝向商户配置的
notify_url发送异步通知。 - 商户完成验签,核对订单号、金额、商户身份和交易状态后更新订单。
qr_code 是需要写入二维码的原始字符串,不是图片地址。商户需要通过二维码组件将其生成 PNG、SVG 或前端二维码。
Java 调用示例
下面使用支付宝 Java SDK 的常见调用方式。不同 SDK 版本和密钥模式的构造参数可能有所不同,请以当前接入版本的 SDK 文档为准。
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
public class AlipayPrecreateExample {
public static void main(String[] args) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
"YOUR_APP_ID",
"YOUR_APP_PRIVATE_KEY",
"json",
"UTF-8",
"ALIPAY_PUBLIC_KEY",
"RSA2"
);
String outTradeNo = "ORDER_202609090001";
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount("19.90");
model.setSubject("门店商品");
model.setTimeoutExpress("10m");
AlipayTradePrecreateRequest request =
new AlipayTradePrecreateRequest();
request.setBizModel(model);
request.setNotifyUrl(
"https://merchant.example.com/alipay/notify"
);
AlipayTradePrecreateResponse response =
alipayClient.execute(request);
if (response.isSuccess()) {
String qrCode = response.getQrCode();
System.out.println("预下单成功");
System.out.println("二维码内容:" + qrCode);
// 将 qrCode 交给二维码组件生成二维码图片。
} else {
System.err.println("预下单失败");
System.err.println("code: " + response.getCode());
System.err.println("subCode: " + response.getSubCode());
System.err.println("subMsg: " + response.getSubMsg());
}
}
}
主要业务参数包括:
out_trade_no:商户订单号,在商户系统内必须唯一。total_amount:订单总金额,单位为元,例如19.90。subject:订单标题。timeout_express:二维码对应交易的有效期,例如10m。notify_url:支付宝异步通知地址,必须能够被支付宝服务器通过公网访问。
生产环境应使用应用私钥以及支付宝公钥或证书完成签名和验签。私钥不能放在浏览器、小程序或其他客户端中。
将返回内容生成二维码
假设接口返回:
https://qr.alipay.com/xxxxxxxxxxxxxxxx
应将整个字符串原样编码到二维码中,不要自行修改、拼接或解析该地址。
前端可以使用二维码组件生成图片,例如:
<div id="qrcode"></div>
<script src="https://cdn.example.com/qrcode.min.js"></script>
<script>
const qrCodeContent = "服务端返回的 qr_code";
new QRCode(document.getElementById("qrcode"), {
text: qrCodeContent,
width: 240,
height: 240
});
</script>
实际项目中,应由商户自己的服务端创建订单,再将 qr_code 返回给受控前端展示。不要从前端直接调用支付宝预下单接口,以免暴露签名密钥。
支付结果处理
二维码展示成功并不表示支付已经完成。最终支付结果应以支付宝异步通知或主动查询结果为准。
收到异步通知后,至少要完成以下校验:
- 使用支付宝公钥或支付宝证书验证通知签名。
- 检查
app_id是否属于当前应用。 - 检查
seller_id是否为预期收款方。 - 检查
out_trade_no是否存在且尚未处理。 - 检查
total_amount是否与本地订单金额一致。 - 确认
trade_status为可确认收款的状态。 - 以幂等方式更新订单,避免重复通知引起重复发货。
处理成功后,通知接口应按照支付宝要求返回:
success
如果页面需要及时显示支付结果,可以定时调用 alipay.trade.query 查询订单。查询只能作为辅助机制,异步通知和验签仍然不能省略。
常见误区
收款码和预下单二维码不是一回事
使用普通支付宝收款码时,通常需要付款人输入金额。alipay.trade.precreate 返回的是针对某笔订单生成的动态二维码,订单中已经包含金额,消费者扫码后无需再次填写。
不能由商户控制密码验证方式
商户可以创建指定金额的交易,但不能要求消费者必须输入支付密码。支付宝会根据消费者设置和风控策略,决定使用密码、指纹、人脸或免密支付。
二维码不应长期重复使用
预下单二维码通常对应一笔具体交易。每笔订单都应使用新的 out_trade_no 重新预下单,不能将某次返回的二维码作为永久定额收款码反复使用。
如果业务需要长期展示固定金额二维码,可以在消费者扫码后,由商户页面实时创建新订单,再跳转到支付流程。已经支付过的交易二维码不能直接复用。
必须开通相应产品能力
调用接口前,应用和商户账号需要具备当面付及相应接口权限。调用失败时,可以结合 code、sub_code 和 sub_msg 判断问题来自签约权限、密钥配置、参数还是商户状态。
实现这一需求时,应调用 alipay.trade.precreate 获取二维码内容,再由商户系统自行渲染和展示,无需寻找单独的二维码图片接口。
备注:内容仅供参考。
