仿阿里巴巴行业门户贸易网站模板,建立网站免费,济南网站建设小程序,建设人行官方网站下载作为后端开发者#xff0c;对接微信支付是绕不开的核心需求。本文将从微信开放平台配置、项目环境搭建、JSAPI 支付、H5 支付、支付回调处理五个核心模块#xff0c;手把手教你完成微信支付全流程对接#xff0c;全程附代码 截图#xff0c;小白也能独立落地#xff01; …作为后端开发者对接微信支付是绕不开的核心需求。本文将从微信开放平台配置、项目环境搭建、JSAPI 支付、H5 支付、支付回调处理五个核心模块手把手教你完成微信支付全流程对接全程附代码 截图小白也能独立落地一、前置知识微信支付核心概念扫盲在动手前先搞懂 3 个关键概念避免踩坑appid微信公众平台 / 开放平台的应用唯一标识JSAPI 用公众号 appidH5 用服务号 / 小程序 appidmch_id微信支付商户号在微信支付商户平台申请需企业资质api_key微信支付 API 密钥商户平台设置用于签名验证千万别泄露openid用户在当前公众号 / 小程序下的唯一标识JSAPI 支付必须传H5 支付可选回调通知地址支付成功后微信主动调用的接口必须公网可访问用于更新订单状态核心流程创建订单 → 调用微信支付接口获取支付参数 → 前端发起支付 → 微信回调通知 → 验证回调并更新订单二、第一步微信开放平台 商户平台配置关键所有对接的前提是完成配置少一步都会报错按以下步骤操作2.1 注册并获取核心账号微信公众平台JSAPI 支付用地址https://mp.weixin.qq.com/注册服务号个人订阅号不支持微信支付完成实名认证和微信支付开通记录「开发 → 基本配置」中的appid和「公众号设置 → 功能设置」中的「网页授权域名」JSAPI 支付需授权获取 openid微信支付商户平台地址https://pay.weixin.qq.com/用服务号关联的企业资质注册完成开户记录「账户中心 → 商户信息」中的mch_id设置 API 密钥「账户中心 → API 安全 → 设置 API 密钥」32 位字母数字组合自己记好后续代码要用配置支付回调通知地址「产品中心 → 开发配置 → 支付回调 URL」必须是公网 HTTPS 地址比如https://xxx.com/pay/wechat/callback2.2 关键配置项避坑重点配置项用途注意事项网页授权域名JSAPI 支付获取 openid需备案域名添加后下载校验文件放到服务器根目录支付回调通知地址接收支付成功通知必须 HTTPS无端口路径自定义公网可访问API 密钥接口签名 回调验证绝对不能泄露一旦泄露立即重置H5 支付域名配置H5 支付跳转域名商户平台「产品中心 → H5 支付 → 域名配置」三、第二步项目环境搭建SpringBoot 为例本文用 SpringBoot 微信支付 SDK 开发简化加密、XML/JSON 转换等复杂操作。3.1 引入依赖pom.xml微信支付官方推荐使用weixin-java-paySDK开源维护功能齐全!-- 微信支付SDK -- dependency groupIdcom.github.binarywang/groupId artifactIdweixin-java-pay/artifactId version4.5.0/version !-- 建议用最新稳定版 -- /dependency !-- SpringBoot Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 工具类可选 -- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.20/version /dependency3.2 配置微信支付参数application.yml将第一步获取的核心参数配置到配置文件wechat: pay: appid: 你的公众号appid mch-id: 你的商户号 mch-key: 你的API密钥 notify-url: https://xxx.com/pay/wechat/callback # 回调通知地址公网HTTPS trade-type-jsapi: JSAPI # 支付类型固定 trade-type-h5: H5 # 支付类型固定 h5: scene-info: {h5_info:{type:Wap,wap_url:https://xxx.com,wap_name:你的网站名称}} # H5支付场景信息3.3 初始化微信支付客户端核心配置类创建配置类通过 SDK 初始化支付客户端后续所有接口调用都依赖这个客户端import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class WxPayConfig { Value(${wechat.pay.appid}) private String appid; Value(${wechat.pay.mch-id}) private String mchId; Value(${wechat.pay.mch-key}) private String mchKey; Value(${wechat.pay.notify-url}) private String notifyUrl; Bean public WxPayService wxPayService() { com.github.binarywang.wxpay.config.WxPayConfig config new com.github.binarywang.wxpay.config.WxPayConfig(); config.setAppId(appid); config.setMchId(mchId); config.setMchKey(mchKey); config.setNotifyUrl(notifyUrl); // 可选配置证书退款、企业付款等接口需要支付接口不需要 // config.setKeyPath(证书路径); WxPayService wxPayService new WxPayServiceImpl(); wxPayService.setConfig(config); return wxPayService; } }四、第三步JSAPI 支付对接公众号内支付JSAPI 支付是在微信公众号内发起的支付核心是先获取用户 openid再调用支付接口。4.1 核心流程前端跳转公众号授权页面获取 code后端通过 code 换取用户 openid后端创建订单调用微信支付统一下单接口微信返回支付参数前端调用微信 JSAPI 发起支付支付成功后微信回调后端通知地址后端验证回调更新订单状态4.2 后端实现3 个核心接口4.2.1 接口 1获取公众号授权 code引导用户授权用户需要先授权后端才能获取 openid。前端需跳转以下地址后端拼接 URL 返回给前端import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; RestController RequestMapping(/pay/wechat/jsapi) public class WxJsapiPayController { Value(${wechat.pay.appid}) private String appid; // 授权回调地址需在公众号「网页授权域名」中配置 private static final String REDIRECT_URI https://xxx.com/pay/wechat/jsapi/callback/code; /** * 生成授权URL前端跳转此地址获取code */ GetMapping(/get-auth-url) public String getAuthUrl() { // 拼接授权URLscopesnsapi_base静默授权无需用户确认snsapi_userinfo需用户确认 String authUrl String.format( https://open.weixin.qq.com/connect/oauth2/authorize?appid%sredirect_uri%sresponse_typecodescopesnsapi_basestate123#wechat_redirect, appid, java.net.URLEncoder.encode(REDIRECT_URI) // 必须URL编码 ); return authUrl; } }4.2.2 接口 2通过 code 换取 openid并发起统一下单用户授权后微信会跳转到REDIRECT_URI并携带 code 参数后端通过 code 换 openid再调用统一下单接口import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxOAuth2AccessTokenResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.UUID; RestController RequestMapping(/pay/wechat/jsapi) public class WxJsapiPayController { Autowired private WxPayService wxPayService; Value(${wechat.pay.trade-type-jsapi}) private String tradeTypeJsapi; Value(${wechat.pay.notify-url}) private String notifyUrl; /** * 授权回调通过code换openid发起统一下单 */ GetMapping(/callback/code) public WxPayMpOrderResult codeCallback(RequestParam(code) String code) throws WxPayException { // 1. 通过code换取openid静默授权仅能获取openid WxOAuth2AccessTokenResult accessTokenResult wxPayService.oauth2getAccessToken(code); String openid accessTokenResult.getOpenid(); // 2. 构建统一下单参数核心 WxPayUnifiedOrderRequest orderRequest WxPayUnifiedOrderRequest.newBuilder() .outTradeNo(generateOrderNo()) // 商户订单号唯一自己生成 .totalFee(1) // 支付金额单位分10.01元 .body(测试商品-JSAPI支付) // 商品描述 .spbillCreateIp(127.0.0.1) // 客户端IP实际用用户真实IP .notifyUrl(notifyUrl) // 回调地址 .tradeType(tradeTypeJsapi) // 支付类型JSAPI .openid(openid) // 必须传openidJSAPI核心 .build(); // 3. 调用微信统一下单接口获取支付参数 WxPayMpOrderResult payResult wxPayService.createOrder(orderRequest); return payResult; // 返回给前端用于发起支付 } /** * 生成唯一商户订单号年月日时分秒随机数 */ private String generateOrderNo() { return System.currentTimeMillis() UUID.randomUUID().toString().substring(0, 6); } }4.2.3 前端实现调用微信 JSAPI 发起支付前端拿到后端返回的支付参数后通过微信公众号 JS-SDK 发起支付需先配置 JS 接口安全域名!DOCTYPE html html head meta charsetUTF-8 titleJSAPI支付/title !-- 引入微信JS-SDK -- script srchttps://res.wx.qq.com/open/js/jweixin-1.6.0.js/script /head body button onclickpay()发起支付/button script // 1. 先调用后端接口获取授权URL跳转授权实际项目中可在页面加载时自动跳转 window.onload function() { fetch(/pay/wechat/jsapi/get-auth-url) .then(res res.text()) .then(authUrl { // 跳转授权页面 window.location.href authUrl; }); }; // 2. 授权回调后后端返回支付参数发起支付 function pay() { // 假设后端回调后将支付参数存入payParams变量实际项目中从接口获取 const payParams { appId: xxx, // 公众号appid timeStamp: xxx, // 时间戳 nonceStr: xxx, // 随机串 package: prepay_idxxx, // 预支付ID signType: MD5 // 签名类型 }; // 调用微信JSAPI支付 wx.chooseWXPay({ appId: payParams.appId, timestamp: payParams.timeStamp, nonceStr: payParams.nonceStr, package: payParams.package, signType: payParams.signType, paySign: payParams.paySign, // 签名 success: function(res) { // 支付成功回调仅前端提示最终状态以后端回调为准 alert(支付成功); window.location.href /pay/success; }, fail: function(res) { alert(支付失败 res.err_msg); } }); } /script /body /html五、第四步H5 支付对接外部浏览器支付H5 支付是在非微信浏览器如 Chrome、Safari中发起的支付用户点击后会跳转到微信支付页面完成支付无需获取 openid。5.1 核心流程后端创建订单调用微信支付统一下单接口tradeTypeH5微信返回支付跳转 URL前端重定向到该 URL用户在微信支付页面完成支付支付成功后微信回调后端通知地址同时跳转回商户页面5.2 后端实现1 个核心接口import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.UUID; RestController RequestMapping(/pay/wechat/h5) public class WxH5PayController { Autowired private WxPayService wxPayService; Value(${wechat.pay.trade-type-h5}) private String tradeTypeH5; Value(${wechat.pay.notify-url}) private String notifyUrl; Value(${wechat.pay.h5.scene-info}) private String sceneInfo; /** * H5支付下单返回支付跳转URL */ GetMapping(/create-order) public String createH5Order() throws WxPayException { // 1. 构建统一下单参数H5专用 WxPayUnifiedOrderRequest orderRequest WxPayUnifiedOrderRequest.newBuilder() .outTradeNo(generateOrderNo()) // 商户订单号唯一 .totalFee(1) // 支付金额分 .body(测试商品-H5支付) // 商品描述 .spbillCreateIp(127.0.0.1) // 客户端IP .notifyUrl(notifyUrl) // 回调地址 .tradeType(tradeTypeH5) // 支付类型H5 .sceneInfo(sceneInfo) // H5场景信息必须配置 .build(); // 2. 调用统一下单接口获取支付跳转URL WxPayUnifiedOrderResult orderResult wxPayService.unifiedOrder(orderRequest); return orderResult.getMwebUrl(); // 返回跳转URL前端重定向到此地址 } /** * 生成唯一商户订单号 */ private String generateOrderNo() { return System.currentTimeMillis() UUID.randomUUID().toString().substring(0, 6); } }5.3 前端实现重定向到支付页面H5 支付前端非常简单只需调用后端接口获取跳转 URL然后重定向即可!DOCTYPE html html head meta charsetUTF-8 titleH5支付/title /head body h1H5支付测试/h1 button onclickgoPay()立即支付0.01元/button script function goPay() { // 调用后端H5下单接口获取支付跳转URL fetch(/pay/wechat/h5/create-order) .then(res res.text()) .then(mwebUrl { // 重定向到微信支付页面 window.location.href mwebUrl; }) .catch(err { alert(下单失败 err); }); } /script /body /html六、第五步支付回调处理核心确保订单状态一致性用户支付成功后微信会主动调用你配置的「回调通知地址」后端必须处理这个回调验证签名 更新订单状态这是保证资金和订单一致的关键6.1 回调核心要点回调是 POST 请求参数以 XML 格式传递必须验证签名防止伪造回调处理完后必须返回指定格式的 XML 响应告诉微信 “已处理”否则微信会重复回调需处理重复回调微信可能多次发送同一回调需通过订单号去重6.2 后端回调接口实现import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.util.XmlUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.Map; RestController RequestMapping(/pay/wechat) public class WxPayCallbackController { Autowired private WxPayService wxPayService; /** * 微信支付回调通知接口必须POST公网HTTPS */ PostMapping(/callback) public String payCallback(RequestBody String xmlData, HttpServletRequest request) { try { // 1. 解析XML回调参数 MapString, String callbackMap XmlUtils.xmlToMap(xmlData); System.out.println(微信支付回调参数 callbackMap); // 2. 验证回调签名关键防止伪造 WxPayOrderNotifyResult notifyResult wxPayService.parseOrderNotifyResult(xmlData); // 3. 验证支付状态只有return_code和result_code都为SUCCESS才是支付成功 if (SUCCESS.equals(notifyResult.getReturnCode()) SUCCESS.equals(notifyResult.getResultCode())) { String outTradeNo notifyResult.getOutTradeNo(); // 商户订单号 String transactionId notifyResult.getTransactionId(); // 微信支付订单号 Integer totalFee notifyResult.getTotalFee(); // 支付金额分 // 4. 核心业务逻辑更新订单状态需加锁防止重复处理 boolean isUpdated updateOrderStatus(outTradeNo, transactionId, totalFee); if (isUpdated) { // 5. 返回成功响应微信收到后不再回调 return xmlreturn_code![CDATA[SUCCESS]]/return_codereturn_msg![CDATA[OK]]/return_msg/xml; } } } catch (WxPayException e) { e.printStackTrace(); // 签名验证失败或其他异常返回失败响应 return xmlreturn_code![CDATA[FAIL]]/return_codereturn_msg![CDATA[ e.getMessage() ]]/return_msg/xml; } // 处理失败返回失败响应 return xmlreturn_code![CDATA[FAIL]]/return_codereturn_msg![CDATA[处理失败]]/return_msg/xml; } /** * 更新订单状态实际项目中对接自己的订单系统 * 注意需加分布式锁或乐观锁防止重复回调导致的订单状态异常 */ private boolean updateOrderStatus(String outTradeNo, String transactionId, Integer totalFee) { System.out.println(订单支付成功 商户订单号 outTradeNo , 微信订单号 transactionId , 支付金额 totalFee 分); // 这里写你的业务逻辑比如查询订单、更新为“已支付”、记录支付日志等 // 示例orderService.updatePayStatus(outTradeNo, transactionId, totalFee); return true; } }七、联调测试 避坑指南7.1 测试工具公网穿透本地开发需用 ngrok、cpolar、花生壳等工具将本地服务暴露到公网微信回调必须公网可访问微信开发者工具用于测试 JSAPI 支付模拟公众号环境手机浏览器用于测试 H5 支付如 Chrome、Safari7.2 常见坑 解决方案签名错误检查 appid、mch_id、mch_key 是否正确大小写、空格都可能导致错误检查参数是否完整如 JSAPI 的 openid、H5 的 sceneInfo检查编码格式统一用 UTF-8回调接收不到确认回调地址是 HTTPS 且无端口确认公网穿透工具正常工作可通过 Postman 模拟回调测试检查服务器防火墙是否拦截了微信的 IP微信回调 IP 段可在商户平台查询H5 支付提示 “商家参数格式有误”检查 sceneInfo 格式是否正确必须是 JSON 字符串且包含 wap_url 和 wap_name确认 H5 支付域名已在商户平台配置JSAPI 支付提示 “invalid openid”确认 openid 是当前公众号的不同公众号的 openid 不通用确认授权 scope 正确snsapi_base 或 snsapi_userinfo7.3 联调步骤启动本地服务通过公网穿透获取公网地址更新微信商户平台的回调地址、公众号的网页授权域名用微信开发者工具测试 JSAPI 支付用手机浏览器测试 H5 支付支付成功后查看后端日志是否收到回调订单状态是否更新八、总结本文从配置到代码完整覆盖了微信支付 JSAPI 和 H5 场景的全流程核心要点配置是基础必须正确配置公众号、商户平台的域名、回调地址、API 密钥SDK 是利器使用 weixin-java-pay SDK 可大幅简化签名、接口调用等复杂操作回调是关键务必验证签名、处理重复回调确保订单状态一致性测试要细致用公网穿透工具 真实环境测试避免线上踩坑按照本文步骤小白也能独立完成微信支付对接如果需要退款、订单查询等扩展功能可参考weixin-java-paySDK 的官方文档https://github.com/binarywang/weixin-java-tools用法和下单接口类似非常简单。如果在对接过程中遇到问题可在微信支付商户平台的「帮助中心」或开发者社区查找答案也可以留言交流