跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
JavaWeChatPayjava

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

综述由AI生成Java 接入微信支付的完整流程,涵盖前期准备(注册认证、商户号申请)、环境搭建(依赖引入、参数配置)、核心代码开发(统一下单、回调处理)及注意事项。重点讲解了使用官方 SDK 进行 Native 支付对接的步骤,包括证书配置、签名验证、APIv3 密钥管理及支付通知解密。通过示例代码展示了 Spring Boot 配置类与服务层实现,强调了幂等性处理与安全性要求。

GitMaster发布于 2026/3/24更新于 2026/5/416 浏览
Java 接入微信支付详细全流程

主要流程

前期准备工作

  • 注册认证微信公众号/小程序
  • 申请微信商户号
  • 配置 API 安全

环境搭建和主要流程理解

  • 引入依赖
  • 确定支付方式,分析其流程

核心代码开发

  • 配置参数
  • 向微信发送请求

注意事项

  1. 个人类型账号无法开通微信支付
  2. 切勿泄露 APIV3 秘钥

步骤实现

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

文章配图

先查看具体流程

注册公众号/小程序

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

认证公众号/小程序

方法一

文章配图

方法二

文章配图

注册商户号并开通 Native 支付权限

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

开通步骤指引:申请 Native 支付权限指引

绑定商户号与 APPID

对应指引:管理商户号绑定的 APPID 账号

获取对应参数开发

对应指引:开发必要参数说明

文章配图

文章配图

核心代码开发

推荐使用官方 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}")
    private String mchSerialNo;

    @Value("${wechat.pay.privateKeyPath}")
    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 {
        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);
    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");
    json.put("scene_info", sceneInfo);

    try {
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
        // ... 同上设置请求头和实体
        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) {
        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 {
            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);

            // 解密通知数据 (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));

            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 nonceStr = resource.getString("nonce");

            String orderInfo = aesUtil.decryptToString(nonceStr.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");

            if ("SUCCESS".equals(tradeState)) {
                // TODO: 更新你的数据库订单状态为"已支付"
                // TODO: 执行发货、积分发放等后续业务逻辑
                // TODO: 记录日志
            } else if ("CLOSED".equals(tradeState) || "REVOKED".equals(tradeState)) {
                // 支付失败或关闭
            }

            return ResponseEntity.ok().body("{\"code\":\"SUCCESS\",\"message\":\"成功\"}");
        } catch (Exception e) {
            log.error("处理微信支付通知失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("");
        }
    }
}

工具类:

public class WeChatPayUtil {
    public static String sign(Map<String, String> params, String apiKey) {
        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);
        String stringA = sb.toString();
        String sign = DigestUtils.md5Hex(stringA).toUpperCase();
        return sign;
    }
}

总结

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

目录

  1. 主要流程
  2. 前期准备工作
  3. 环境搭建和主要流程理解
  4. 核心代码开发
  5. 注意事项
  6. 步骤实现
  7. 注册公众号/小程序
  8. 认证公众号/小程序
  9. 方法一
  10. 方法二
  11. 注册商户号并开通 Native 支付权限
  12. 绑定商户号与 APPID
  13. 获取对应参数开发
  14. 核心代码开发
  15. 推荐使用官方 SDK
  16. 引入依赖
  17. 代码实现
  18. 回调处理
  19. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 动态规划经典题型:最小花费爬楼梯与解码方法
  • OpenTiny NEXT 前端智能化征文:AI 前端与 WebAgent 学习路径
  • 人工智能应用工程师(高级)课程体系与报考指南
  • MySQL MVCC 原理:并发控制与隔离级别深度解析
  • Python 数据分析替代方案:Mito 与 Bamboolib 实战指南
  • OpenClaw 部署方式对比:云端、WSL、Mac 及 Ubuntu 虚拟机
  • JavaShop 百万级并发场景下的性能表现与架构解析
  • AIGC 赋能插画创作:技术解析与代码实战
  • 无需公网 IP 安全访问本地 AI 服务的实践方案
  • Vivado 项目 Git 版本管理实战指南:FPGA 工程师必读
  • VSCode Copilot MCP 快速上手指南
  • Minecraft 假面骑士 100 天整合包安装与环境配置指南
  • 临床智能体AI与环境感知AI的融合:基于python的医疗自然语言处理深度分析
  • 前端面试核心知识点与高频八股文汇总
  • DeepSeek-R1-Distill-Llama-8B 实战:快速搭建智能问答系统
  • AI 辅助解码加密字符串的技术实践与实现
  • 产品经理如何利用 AI Agent 提升工作效率
  • MySQL 与 Navicat 安装及配置教程(Windows)
  • Stable Diffusion 核心流程解析:从文本提示到图像生成的潜空间原理
  • 深入理解 HTML5 Web Workers:提升网页性能的关键技术

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online