Java接入微信支付详细全流程

Java接入微信支付详细全流程

一:主要流程

(1)前期准备工作
①注册认证微信公众号/小程序
②申请微信商户号
③配置API安全
(2)环境搭建和主要流程理解
①引入依赖
②确定支付方式,分析其流程
(3)核心代码开发
①配置参数
②向微信发送请求

二:注意事项

(1)个人类型账号无法开通微信支付

(2)切勿泄露APIV3秘钥

三:步骤实现

官方文档(以Native为例):产品介绍_Native支付|微信支付商户文档中心

先查看具体流程


(1)先注册对应的公众号/小程序

官网链接:https://mp.weixin.qq.com/

(2)认证对应的公众号/小程序
①方法一:
②方法二:
(3)注册商户号,开通对应的Native支付权限

官网链接:https://pay.weixin.qq.com/

开通步骤指引链接:申请Native支付权限指引_Native支付|微信支付商户文档中心

(4)绑定商户号与APPID

对应指引链接:管理商户号绑定的APPID账号_Native支付|微信支付商户文档中心

(5)获取对应参数开发

对应指引链接:开发必要参数说明_通用规则|微信支付商户文档中心

(6)核心代码开发
①推荐使用官方SDK:https://github.com/wechatpay-apiv3/wechatpay-java
②引入依赖
<dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.4.13</version> <!-- 注意检查最新版本 --> </dependency>
③代码实现

配置类:

@Configuration public class WeChatPayConfig { @Value("${wechat.pay.mchid}") private String mchId; @Value("${wechat.pay.mchSerialNo}") // 你的商户API证书序列号 private String mchSerialNo; @Value("${wechat.pay.privateKeyPath}") // 你的.p12证书中的私钥文件路径 (.pem格式更佳) private String privateKeyPath; @Value("${wechat.pay.apiV3Key}") private String apiV3Key; @Value("${wechat.pay.certPath}") // 下载的微信平台证书路径 private String certPath; /** * 创建私钥签名对象 */ @Bean public PrivateKey getPrivateKey() throws Exception { return PemUtil.loadPrivateKey( new FileInputStream(privateKeyPath)); } /** * 创建自动更新的Verifier (验证微信响应签名) */ @Bean public Verifier getVerifier() throws Exception { // 方式1: 使用本地已下载的平台证书 (简单,需手动更新) // X509Certificate certificate = PemUtil.loadCertificate(new FileInputStream(certPath)); // return new StaticVerifier(mchId, mchSerialNo, certificate); // 方式2: 使用自动更新机制 (推荐) ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier( new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, getPrivateKey())), apiV3Key.getBytes(StandardCharsets.UTF_8)); return verifier; } /** * 创建HttpClient (用于调用微信API) */ @Bean public CloseableHttpClient getWxPayClient() throws Exception { return WechatPayHttpClientBuilder.create() .withMerchant(mchId, mchSerialNo, getPrivateKey()) .withValidator(new WechatPay2Validator(getVerifier())) .build(); } }

服务层(统一下单)示例与代码(需调整)

@Override public String createNativeOrder(String outTradeNo, int totalFee, String body) { // ... 构建请求参数 (类似JSAPI,但去掉payer,增加scene_info等) json.put("appid", appid); // Native也需要appid json.put("mchid", mchId); json.put("description", body); json.put("out_trade_no", outTradeNo); json.put("notify_url", "https://yourdomain.com/api/wxpay/notify"); JSONObject amount = new JSONObject(); amount.put("total", totalFee); amount.put("currency", "CNY"); json.put("amount", amount); // 场景信息 (可选) JSONObject sceneInfo = new JSONObject(); sceneInfo.put("payer_client_ip", "用户IP"); // 必须传真实IP json.put("scene_info", sceneInfo); // 发送请求到 Native 接口 try { HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native"); // ... 同上设置请求头和实体 // 解析响应,获取 code_url JSONObject result = JSON.parseObject(responseString); return result.getString("code_url"); // 返回二维码链接 } catch (Exception e) { throw new RuntimeException("创建Native订单失败", e); } }
④回调处理

注意:此路径必须是公网能访问的路径

@RestController @RequestMapping("/api/wxpay") public class WeChatPayController { @Autowired private WeChatPayService weChatPayService; @PostMapping("/create-jsapi-order") public ResponseEntity<Map<String, String>> createJsapiOrder(@RequestBody PayRequest request) { // 获取用户openid (通常由前端通过登录态传递或后端通过code换取) String openid = getUserOpenidFromSessionOrToken(request.getToken()); Map<String, String> result = weChatPayService.createJsapiOrder( openid, request.getOutTradeNo(), request.getTotalFee(), request.getBody()); return ResponseEntity.ok(result); } @PostMapping("/notify") public ResponseEntity<String> handleNotify(@RequestBody String notifyData, HttpServletRequest request) { try { // 1. 验证通知的签名和有效性 (SDK提供了工具类) // 这里需要解析请求头中的 Wechatpay-Signature, Wechatpay-Nonce, Wechatpay-Timestamp String signature = request.getHeader("Wechatpay-Signature"); String nonce = request.getHeader("Wechatpay-Nonce"); String timestamp = request.getHeader("Wechatpay-Timestamp"); String body = notifyData; // 请求体 // 使用之前配置的Verifier来验证 // boolean isValid = verifier.verify(timestamp, nonce, body, signature); // if (!isValid) { // return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("签名验证失败"); // } // 2. 解密通知数据 (APIv3通知体是加密的) AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8)); String plainText = aesUtil.decryptToString( nonce.getBytes(StandardCharsets.UTF_8), associatedData.getBytes(StandardCharsets.UTF_8), // 关联数据 ciphertext.getBytes(StandardCharsets.UTF_8)); // 密文 // 3. 解析解密后的JSON数据 JSONObject notifyDataObj = JSON.parseObject(plainText); String eventType = notifyDataObj.getString("event_type"); JSONObject resource = notifyDataObj.getJSONObject("resource"); String ciphertext = resource.getString("ciphertext"); // 加密的数据包 String associatedData = resource.getString("associated_data"); String nonce = resource.getString("nonce"); // 再次解密ciphertext得到最终的订单信息 String orderInfo = aesUtil.decryptToString(nonce.getBytes(), associatedData.getBytes(), ciphertext.getBytes()); JSONObject orderData = JSON.parseObject(orderInfo); String outTradeNo = orderData.getString("out_trade_no"); String transactionId = orderData.getString("transaction_id"); String tradeState = orderData.getString("trade_state"); // SUCCESS为支付成功 // 4. 业务处理 if ("SUCCESS".equals(tradeState)) { // TODO: 更新你的数据库订单状态为"已支付" // TODO: 执行发货、积分发放等后续业务逻辑 // TODO: 记录日志 } else if ("CLOSED".equals(tradeState) || "REVOKED".equals(tradeState)) { // 支付失败或关闭 } // 5. 返回成功响应 (必须是200且内容为"success") return ResponseEntity.ok().body("{\"code\":\"SUCCESS\",\"message\":\"成功\"}"); } catch (Exception e) { // 记录详细的错误日志 log.error("处理微信支付通知失败", e); // 返回失败,微信会在一段时间后重试 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(""); } } }

工具类

public class WeChatPayUtil { // 生成JSAPI调用所需参数的签名 (注意:这是RSA-SHA256,不是APIv3的HMAC-SHA256) public static String sign(Map<String, String> params, String apiKey) { // 1. 参数按key ASCII排序 List<String> keys = new ArrayList<>(params.keySet()); Collections.sort(keys); StringBuilder sb = new StringBuilder(); for (String key : keys) { String value = params.get(key); if (value != null && !value.trim().isEmpty() && !"sign".equals(key)) { sb.append(key).append("=").append(value).append("&"); } } sb.append("key=").append(apiKey); // 2. 计算MD5 (旧版) 或 HMAC-SHA256 (新版推荐,但JSAPI仍多用MD5?实际看文档) // 注意:微信JSAPI目前主流仍是MD5,但请查阅最新官方文档确认! String stringA = sb.toString(); String sign = DigestUtils.md5Hex(stringA).toUpperCase(); return sign; } }

四:总结

对接微信支付主要繁琐的是前期商户号、证书、配置,需仔细阅读文档,后续对接SDK非常简单,注意处理幂等性

Read more

什么是python uv,如何在windows上安装uv,基础的用法有哪些?

什么是python uv,如何在windows上安装uv,基础的用法有哪些?

什么是Python UV? UV是由Astral公司(Rust工具Ruff的开发者)推出的高性能Python包管理工具,基于Rust编写,旨在替代传统的pip和pip-tools。其核心优势在于极快的速度(比pip快10-100倍)、轻量级设计(仅几十MB)以及现代化的依赖管理(支持pyproject.toml和uv.lock文件)。UV集成了虚拟环境管理、Python版本控制、依赖解析等功能,目标是成为类似Rust Cargo的全能工具,简化Python开发流程。 在Windows上安装UV的3种方法 使用Pipx(适合全局工具管理) 若已安装pipx: pipx install uv PowerShell脚本安装 打开PowerShell,执行: irm https://astral.sh/uv/install.ps1 |iex 通过PIP安装(推荐) 直接使用Python自带的pip安装,兼容性最佳: pip install uv 安装后,uv会被添加到系统环境变量,即使切换虚拟环境也能使用。 注意:

By Ne0inhk
Python 基本命令详解:入门必备指南

Python 基本命令详解:入门必备指南

Python 基本命令详解:入门必备指南 📌 引言 Python 是一种简单易学、功能强大的编程语言,广泛用于数据分析、Web 开发、人工智能、自动化脚本等领域。掌握 Python 的基本命令是入门的第一步。本篇文章将详细介绍 Python 基本语法、常用命令及示例代码,帮助你快速上手 Python 编程。 1. Python 环境安装与运行 ✅ 检查 Python 版本 在终端(Mac/Linux)或命令提示符(Windows)中输入: python --version 或 python3 --version 如果 Python 未安装,请前往 Python 官网 下载并安装。 ✅ 运行 Python 交互模式 输入

By Ne0inhk

终极指南:5步掌握Orbbec SDK Python深度摄像头开发

终极指南:5步掌握Orbbec SDK Python深度摄像头开发 【免费下载链接】pyorbbecsdkOrbbecSDK python binding 项目地址: https://gitcode.com/gh_mirrors/py/pyorbbecsdk Orbbec SDK Python绑定为开发者提供了在Python环境中控制奥比中光深度摄像头的完整解决方案。这个开源项目让您能够直接使用Python编程语言来操作Orbbec品牌的RGB-D设备,包括Astra系列、Gemini等产品线,实现数据流获取、设备配置和实时处理等功能,特别适合计算机视觉、三维建模和物体识别等应用场景。 🚀 快速入门:5分钟搭建开发环境 获取项目源码 首先从GitCode仓库克隆项目到本地: git clone https://gitcode.com/gh_mirrors/py/pyorbbecsdk.git cd pyorbbecsdk 安装系统依赖 对于Ubuntu系统,确保安装必要的开发包: sudo apt-get install python3-dev python3-

By Ne0inhk
飞算 JavaAI 深度体验:不止于 “能用“,更是 Java 开发的 “增效神器“

飞算 JavaAI 深度体验:不止于 “能用“,更是 Java 开发的 “增效神器“

飞算JavaAI深度体验:不止于"能用",更是Java开发的"增效神器" 作为一名深耕Java开发十余年的老兵,我曾对各类AI编程工具充满期待,却屡屡被"生成代码跑不通"“逻辑驴唇不对马嘴"的问题泼冷水。直到遇见飞算JavaAI,才真正体会到"AI成为开发助手而非累赘"的畅快。今天就从实战角度,带大家深入解锁这款工具的"超能力”。 一、从"卡壳到通关":一个报表功能的救赎 先分享个上周的真实经历。产品经理突然甩来需求:“明天要上线员工绩效分析模块,得按部门、时间范围做分页查询,还要统计每个部门的平均分、达标率和排名”。看着涉及5张关联表的复杂逻辑,我当时就懵了——正常开发至少要两天,这明显是"不可能完成的任务"。 想起同事推荐的飞算JavaAI,抱着试错心态输入需求:

By Ne0inhk