
简介这份资源面向需要在Java应用中接入支付宝支付能力的开发者尤其适合电商、O2O场景下希望快速跑通扫码支付流程的中级Java工程师。项目围绕支付宝SDK展开涵盖扫码支付、订单处理、异步回调、appid与密钥配置、前端二维码展示页面以及API调用与安全防护等核心环节并附有可参考的示例代码帮助理解支付系统的整体架构与前后端交互方式。压缩包共124个文件约27.64MB以jar依赖库、java源码、class编译文件、xml配置、js脚本与properties参数文件为主另含html页面与css样式结构上兼顾可运行与可学习。目前已有2483人学习下载。通过这份资源读者可以对照示例掌握发起支付请求、处理支付结果回调、更新订单状态等关键步骤并借鉴其中的安全实践与测试调试思路为自建支付模块提供可复用的参考。1. Java 集成支付宝扫码支付从沙箱到回调一条能跑通的最小链路很多 Java 后端第一次接支付宝扫码支付卡住的地方往往不是写代码而是「沙箱环境跑通了换正式环境就 400」「回调地址配了但一直收不到通知」「二维码生成了用户扫完订单状态还是待支付」。这篇笔记就围绕 Java 集成支付宝扫码支付这条主线把从依赖引入、密钥配置、下单、生成二维码、异步回调验签到对账的完整链路拆开讲同时把标题里提到的刷脸支付官方奖励政策单独拎出来说清楚——它和扫码支付在代码层是两套东西但很多服务商场景下会一起用。适合谁看正在做 Spring Boot 项目要接支付宝当面付扫码支付的后端做服务商/ISV 需要理解刷脸支付奖励政策怎么落到系统里的技术负责人以及被「支付宝回调」反复折磨、想搞清楚验签和幂等到底怎么写的人。下面所有代码基于支付宝官方 Java SDK沙箱和正式环境只差配置逻辑完全一致。2. 扫码支付的技术选型当面付、预下单和密钥体系怎么定2.1 为什么扫码支付优先选当面付F2F而不是网页支付支付宝的支付产品线里和「扫码」沾边的常见有三种电脑网站支付、手机网站支付、当面付。前两个是跳转到支付宝收银台用户扫码或者登录付款资金流和交互都在支付宝页面完成当面付alipay.trade.precreate是商户自己生成二维码用户用支付宝扫本质是「线下扫码」的线上化。选当面付的理由很直接二维码由你的系统生成你可以控制二维码的展示位置、有效期、订单绑定关系用户扫码后支付宝回调你的服务端整个链路你都能埋点。电脑网站支付虽然也能出二维码但它是支付宝页面渲染的你拿不到二维码图片本身做不了自定义收银台。代价是当面付需要签约个人开发者用沙箱练手没问题正式上线要有营业执照和对公账户。这也是热词里「springboot 支付宝转对公账户签约」被频繁搜的原因——签约是绕不过去的前置条件。2.2 密钥模式公钥证书 vs 普通公钥新手先用哪个支付宝开放平台有两种签名模式普通公钥模式和公钥证书模式。普通公钥模式配置简单一个应用私钥 支付宝公钥就能跑公钥证书模式需要下载证书文件appCertPublicKey.crt、alipayCertPublicKey_RSA2.crt、alipayRootCert.crt安全性更高适合对安全要求高的生产环境。我的建议是沙箱和初期联调用普通公钥模式快速验证链路正式上线如果平台要求或者团队有安全规范再切证书模式。切换时主要改的是AlipayConfig里的证书路径和AlipayClient的初始化方式业务代码基本不动。对比项普通公钥模式公钥证书模式配置复杂度低两个密钥字符串高需管理三个证书文件密钥轮换手动替换支持证书轮换适用场景沙箱、中小项目生产、服务商、高安全要求SDK 初始化AlipayClient直接传公私钥需传CertAlipayRequest2.3 依赖引入与 AlipayClient 的最小初始化先引入官方 SDK。Maven 里加这一条即可版本用当前稳定版不要用太老的版本老版本对证书模式支持不全。dependency groupIdcom.alipay.sdk/groupId artifactIdalipay-sdk-java/artifactId version4.38.0.ALL/version /dependency然后是配置类。把 appId、应用私钥、支付宝公钥、网关地址、回调地址抽到application.yml不要硬编码在代码里否则换环境要改代码。Configuration public class AlipayConfig { Value(${alipay.app-id}) private String appId; Value(${alipay.private-key}) private String privateKey; Value(${alipay.alipay-public-key}) private String alipayPublicKey; Value(${alipay.gateway-url}) private String gatewayUrl; Value(${alipay.notify-url}) private String notifyUrl; Bean public AlipayClient alipayClient() { // 普通公钥模式直接传应用私钥和支付宝公钥 return new DefaultAlipayClient( gatewayUrl, appId, privateKey, json, UTF-8, alipayPublicKey, RSA2 ); } }这里几个参数必须说清楚format固定jsoncharset固定UTF-8signType用RSA2RSA1 已不推荐。gatewayUrl沙箱是https://openapi.alipaydev.com/gateway.do正式是https://openapi.alipay.com/gateway.do。notifyUrl必须是公网可访问的 HTTPS 地址本地开发用内网穿透工具映射一个临时域名否则回调永远收不到。注意应用私钥是 PKCS8 格式不是 PKCS1。如果你从密钥工具生成的是 PKCS1需要转换否则初始化时会报Invalid private key。3. 下单与二维码生成precreate 接口的完整调用与参数拆解3.1 构造 AlipayTradePrecreateRequest 的必填与选填参数当面付预下单的核心接口是alipay.trade.precreate。必填参数只有out_trade_no商户订单号和total_amount金额单位元字符串subject是商品标题虽然文档标为选填但强烈建议填否则用户在支付宝账单里看到的是一串订单号体验很差。Service public class AlipayScanPayService { Autowired private AlipayClient alipayClient; Value(${alipay.notify-url}) private String notifyUrl; public String precreate(String outTradeNo, String subject, String amount) throws AlipayApiException { AlipayTradePrecreateRequest request new AlipayTradePrecreateRequest(); request.setNotifyUrl(notifyUrl); AlipayTradePrecreateModel model new AlipayTradePrecreateModel(); model.setOutTradeNo(outTradeNo); model.setTotalAmount(amount); model.setSubject(subject); // 二维码有效期超时后用户扫码会提示订单已关闭 model.setTimeoutExpress(30m); // 指定收款方服务商模式下必填 // model.setSellerId(2088xxxx); request.setBizModel(model); AlipayTradePrecreateResponse response alipayClient.execute(request); if (!response.isSuccess()) { throw new RuntimeException(预下单失败 response.getSubMsg()); } // qr_code 就是二维码内容前端用它生成图片 return response.getQrCode(); } }timeoutExpress建议设 30 分钟到 2 小时太短用户还没扫就过期太长订单会一直挂着占用库存。out_trade_no必须全局唯一重复调用同一个订单号支付宝会返回「订单已存在」这是幂等的基础。3.2 二维码内容怎么变成图片前端生成还是后端生成qr_code返回的是一串 URL不是图片。两种处理方式后端用 ZXing 生成图片返回给前端或者前端用 qrcode.js 自己渲染。我一般选后端生成因为二维码里可能带商户 logo、有效期水印后端控制更灵活。public byte[] generateQrImage(String qrCode, int width, int height) throws Exception { MapEncodeHintType, Object hints new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, UTF-8); hints.put(EncodeHintType.MARGIN, 1); BitMatrix matrix new MultiFormatWriter().encode(qrCode, BarcodeFormat.QR_CODE, width, height, hints); ByteArrayOutputStream out new ByteArrayOutputStream(); MatrixToImageWriter.writeToStream(matrix, PNG, out); return out.toByteArray(); }MARGIN设 1 是为了减少白边默认是 4二维码会显得很小。宽高建议 300x300 以上太小用户扫不出来。生成后直接以image/png返回前端img src/pay/qr?orderNoxxx即可。3.3 订单状态查询主动轮询和被动回调怎么配合用户扫码付款后支付宝会异步回调你的notifyUrl但回调可能延迟、可能丢失。所以生产环境必须同时做主动查询兜底。alipay.trade.query用out_trade_no或trade_no查返回TRADE_SUCCESS才算支付成功。public boolean queryOrder(String outTradeNo) throws AlipayApiException { AlipayTradeQueryRequest request new AlipayTradeQueryRequest(); AlipayTradeQueryModel model new AlipayTradeQueryModel(); model.setOutTradeNo(outTradeNo); request.setBizModel(model); AlipayTradeQueryResponse response alipayClient.execute(request); if (response.isSuccess() TRADE_SUCCESS.equals(response.getTradeStatus())) { return true; } return false; }轮询策略用户扫码后前端每 3 秒查一次自己的订单状态后端查支付宝查到成功就更新本地订单。同时回调接口收到通知也更新。两边都更新用数据库唯一约束或者状态机保证幂等。4. 异步回调验签与幂等支付宝回调最容易翻车的三个地方4.1 回调参数验签为什么必须用 SDK 的 verify支付宝回调会 POST 一堆参数到你的notifyUrl包括sign、sign_type、trade_status、out_trade_no等。验签必须用 SDK 提供的AlipaySignature.rsaCheckV1不要自己拼字符串验签参数顺序、编码、空值处理任何一个细节错了都会验签失败。PostMapping(/alipay/notify) public String notify(HttpServletRequest request) { MapString, String params new HashMap(); MapString, String[] requestParams request.getParameterMap(); for (String name : requestParams.keySet()) { String[] values requestParams.get(name); StringBuilder valueStr new StringBuilder(); for (int i 0; i values.length; i) { valueStr.append(i values.length - 1 ? values[i] : values[i] ,); } params.put(name, valueStr.toString()); } try { boolean signVerified AlipaySignature.rsaCheckV1( params, alipayPublicKey, UTF-8, RSA2); if (!signVerified) { return failure; } // 验签通过后再处理业务 String tradeStatus params.get(trade_status); String outTradeNo params.get(out_trade_no); if (TRADE_SUCCESS.equals(tradeStatus)) { // 幂等更新订单 orderService.markPaid(outTradeNo, params.get(trade_no)); } return success; } catch (AlipayApiException e) { return failure; } }返回给支付宝的必须是纯字符串success不能是 JSON不能带引号。返回其他任何内容支付宝会认为通知失败按 25 分钟、2 小时、4 小时这样的间隔重试最多 8 次。4.2 幂等处理同一笔订单收到多次回调怎么办支付宝的回调是「至少一次」语义同一笔订单可能收到多次通知。如果你的markPaid里直接update order set status paid第二次回调会重复加积分、重复发货。正确做法是用订单状态做乐观锁。UPDATE t_order SET status PAID, trade_no #{tradeNo}, pay_time NOW() WHERE out_trade_no #{outTradeNo} AND status UNPAID;判断affectedRows等于 1 说明是第一次处理继续做后续业务等于 0 说明已经处理过直接返回 success。这样即使回调重复业务也只执行一次。4.3 回调地址配置为什么沙箱能收到正式收不到沙箱环境的回调地址可以配http://本地地址但正式环境必须是https://公网域名且不能带端口80/443 除外。常见翻车场景本地用localhost:8080测试通过上线后配了http://域名支付宝直接不回调。还有一种是域名解析到了内网 IP支付宝服务器访问不到。排查方法在回调接口第一行打日志看有没有请求进来。如果日志完全没有说明请求没到你的服务器检查域名、HTTPS 证书、防火墙、Nginx 转发。如果有请求但验签失败检查支付宝公钥是不是复制错了或者是不是把应用公钥当成了支付宝公钥。5. 刷脸支付官方奖励政策技术侧要落哪些数据5.1 奖励政策的本质设备激活 交易笔数刷脸支付和扫码支付在代码层是两套接口。刷脸走的是alipay.trade.pay配合人脸识别设备蜻蜓、青蛙等商户需要先购买或租赁设备然后在支付宝开放平台绑定设备 SN。官方奖励政策的核心逻辑是设备激活后在一定周期内达到规定的交易笔数和金额支付宝返还设备款或者发放补贴。技术侧要做的不是「申请奖励」而是把交易数据准确上报让支付宝能统计到。关键数据包括设备 SN、商户 PID、每笔刷脸交易的out_trade_no和trade_no、交易时间、金额。这些数据在调用alipay.trade.pay时由支付宝自动记录但你的系统要能按设备维度聚合查询方便对账。5.2 服务商模式下的数据隔离与分账如果你是服务商ISV下面挂着多个商户奖励政策是按商户和设备算的。系统设计时要在订单表里加seller_id商户 PID和device_sn字段回调时从支付宝通知里取seller_id存下来。分账场景还要用alipay.trade.order.settle或者分账接口把服务商佣金和商户货款分开。热词里「支付宝分账」被搜得多是因为很多服务商场景下奖励政策和分账是绑定的——支付宝把奖励打给服务商服务商再按比例分给商户。这部分逻辑要在你的结算系统里实现支付宝只负责把奖励发放到服务商账户。5.3 扫码支付和刷脸支付在同一个系统里怎么共存实际项目里一个收银台往往同时支持扫码和刷脸。设计上建议把支付方式抽象成策略模式PayStrategy接口定义precreate、query、refundScanPayStrategy和FacePayStrategy分别实现。订单表加pay_channel字段区分。回调接口可以共用一个入口根据trade_type或者商户配置路由到不同处理逻辑。这样做的价值是奖励政策只影响刷脸那条链路的数据上报扫码链路完全不受影响。新增支付方式时也不用改核心订单逻辑。6. 联调排错与上线前检查几个能省半天时间的技巧6.1 沙箱账号和买家账号的坑沙箱环境要用沙箱版支付宝 APP 登录沙箱买家账号不能用真实支付宝扫沙箱二维码。很多人卡在这里二维码生成了用真实支付宝扫提示「订单不存在」。沙箱买家账号在开放平台「沙箱环境」里能查到密码是固定的111111。沙箱版 APP 在开放平台下载安卓和 iOS 都有。6.2 日志里必须打的几个字段联调阶段在预下单和回调两个地方打日志字段包括out_trade_no、trade_no、trade_status、total_amount、seller_id、sign前 20 位即可。这样出问题时能快速定位是下单参数错了、还是回调没来、还是验签失败。生产环境注意脱敏sign和密钥不要打全。6.3 上线前的检查清单检查项沙箱正式网关地址openapi.alipaydev.comopenapi.alipay.com回调地址可 http 本地必须 https 公网密钥沙箱密钥正式密钥勿混用签约产品沙箱默认开通需正式签约当面付买家账号沙箱买家真实用户最后说一个我自己的习惯每次接新的支付渠道先写一个「最小闭环」——下单、生成二维码、手动触发回调、更新订单四个步骤跑通再往上加业务逻辑。支付这东西链路通了什么都好说链路不通写再多业务代码都是白搭。刷脸支付的奖励政策也一样先把alipay.trade.pay调通再研究设备绑定和数据上报顺序反了会浪费很多时间。希望帮到你。本文还有配套的精品资源点击获取