PC 网站如何使用 Factory.Payment.FaceToFace().preCreate() 生成支付二维码?
结论
Factory.Payment.FaceToFace().preCreate() 对应支付宝当面付中的“扫码支付”,底层调用 alipay.trade.precreate。接口返回二维码内容 qr_code,商户网站将其生成二维码图片后,用户便可使用支付宝扫码付款。
当面付的产品介绍虽然主要针对实体门店,但接口没有要求二维码必须展示在实体收银台,因此 PC 网站也能使用。商户账号需要先签约并开通当面付,网站的业务场景也要符合支付宝的产品和风控要求。
使用支付宝 Easy SDK 时,可以通过 Factory.Payment.FaceToFace().preCreate() 简化调用。也可以使用支付宝开放平台的通用 Java SDK,直接调用 alipay.trade.precreate。
实现流程
常见的实现流程如下:
- PC 网站前端请求服务端创建支付订单。
- 服务端生成唯一的商户订单号
out_trade_no。 - 服务端调用
Factory.Payment.FaceToFace().preCreate()。 - 从接口响应中读取
qr_code。 - 前端通过二维码组件将
qr_code渲染成二维码图片。 - 用户使用支付宝扫码付款。
- 服务端根据异步通知或主动查询结果确认支付状态。
- 前端轮询商户系统中的订单状态,支付成功后更新页面。
支付接口必须由服务端调用。商户私钥不能放在浏览器中,前端也不应直接请求支付宝接口。
Easy SDK 示例
下面是 Java Easy SDK 的常见调用方式。不同 SDK 版本的配置字段和响应对象访问方式可能略有差异,请以项目实际依赖中的类定义为准。
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
public class AlipayQrCodeService {
public static void init() {
Config config = new Config();
config.protocol = "https";
config.gatewayHost = "openapi.alipay.com";
config.signType = "RSA2";
config.appId = "你的应用AppId";
config.merchantPrivateKey = "你的应用私钥";
config.alipayPublicKey = "支付宝公钥";
// 建议配置可被支付宝公网访问的异步通知地址
config.notifyUrl = "https://www.example.com/alipay/notify";
Factory.setOptions(config);
}
public static String createQrCode(
String subject,
String outTradeNo,
String totalAmount) throws Exception {
AlipayTradePrecreateResponse response =
Factory.Payment.FaceToFace()
.preCreate(subject, outTradeNo, totalAmount);
if ("10000".equals(response.code)) {
return response.qrCode;
}
throw new IllegalStateException(
"创建支付宝二维码失败,code=" + response.code
+ ", msg=" + response.msg
+ ", subCode=" + response.subCode
+ ", subMsg=" + response.subMsg
);
}
}
调用示例:
public static void main(String[] args) throws Exception {
AlipayQrCodeService.init();
String qrCode = AlipayQrCodeService.createQrCode(
"网站订单支付",
"ORDER_202609090001",
"99.00"
);
System.out.println(qrCode);
}
部分版本可能需要通过 getter 读取字段,例如:
String qrCode = response.getQrCode();
请根据当前 Easy SDK 生成的响应类,选择 response.qrCode 或 response.getQrCode(),不要只参照示例判断。
在网页中显示二维码
接口返回的 qr_code 通常是供支付宝客户端识别的二维码内容,不一定是 PNG 图片。服务端可以将它返回给前端,再由前端二维码库渲染:
<div id="alipay-qrcode"></div>
<script src="https://cdn.example.com/qrcode.min.js"></script>
<script>
async function createPayment() {
const response = await fetch("/api/payment/alipay/pre-create", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
orderId: "ORDER_202609090001"
})
});
const result = await response.json();
new QRCode(document.getElementById("alipay-qrcode"), {
text: result.qrCode,
width: 220,
height: 220
});
}
createPayment();
</script>
示例中的 CDN 地址仅为占位符。实际项目应使用经过审核并固定版本的二维码组件。服务端也可以将 qr_code 生成 PNG,再把图片地址或图片数据返回给前端。
如何判断支付成功
二维码创建成功不等于用户已经付款。处理支付结果时应注意:
- 主要以支付宝异步通知为准;
- 对通知内容进行验签;
- 校验
app_id、out_trade_no、金额和收款方等字段; - 以幂等方式更新订单;
- 必要时调用交易查询接口补偿确认;
- PC 页面只轮询商户系统中的订单状态,不能直接信任前端提交的“支付成功”结果。
如果长时间没有收到通知,可以通过 Easy SDK 查询交易状态:
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
AlipayTradeQueryResponse response =
Factory.Payment.Common().query("ORDER_202609090001");
if ("TRADE_SUCCESS".equals(response.tradeStatus)) {
// 再次核对订单号、金额等信息后,以幂等方式更新业务订单
}
具体的字段访问方式也可能随 SDK 版本变化。
是否应该改用电脑网站支付
支付宝电脑网站支付通常调用 alipay.trade.page.pay,标准流程是跳转至支付宝收银台,或向收银台提交表单。如果业务要求用户留在当前 PC 页面,并用手机支付宝扫码付款,alipay.trade.precreate 更符合这种交互方式。
两种方式的主要区别如下:
| 方式 | 接口 | 用户体验 |
|---|---|---|
| 当面付扫码支付 | alipay.trade.precreate | 网站展示二维码,用户用支付宝扫码 |
| 电脑网站支付 | alipay.trade.page.pay | 浏览器进入支付宝收银台完成支付 |
具体选择取决于商户已签约的产品、应用权限,以及支付宝对实际业务场景的审核结果。
其他可选 SDK
除了 Easy SDK,也可以使用支付宝开放平台对应语言的通用 SDK,直接构造 alipay.trade.precreate 请求。在 Java 中,通常需要创建 AlipayTradePrecreateRequest,再通过 AlipayClient.execute() 发起调用。
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
request.setNotifyUrl("https://www.example.com/alipay/notify");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "99.00",
"subject": "网站订单支付"
}
""");
AlipayTradePrecreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
String qrCode = response.getQrCode();
}
这里省略了通用 SDK 的配置和异常处理代码。通用 SDK 更接近原始接口,适合需要传入更多业务参数、统一封装支付宝接口或细化响应处理的项目。
注意事项
out_trade_no在商户系统中必须唯一。- 金额应由服务端根据订单计算,不能直接使用前端传入的金额。
total_amount应使用十进制金额字符串,例如"99.00"。- 不要自行拼接二维码内容,应完整使用支付宝返回的
qr_code。 - 商户私钥只能保存在服务端,并通过安全配置或密钥管理系统加载。
- 异步通知地址必须能从公网访问,并且需要正确处理重复通知。
- 支付完成后必须验签并核对订单信息,不能只根据页面轮询结果发货。
- 应为二维码设置合理的业务有效期,超时后关闭订单或重新创建订单。
- 该接口能否正式使用,取决于商户签约状态、应用配置和支付宝当前的产品准入要求。
备注:内容仅供参考。
