跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaWeChatPayjava

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

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

GitMaster发布于 2026/3/24更新于 2026/10/15124 浏览
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. 总结

更多推荐文章

查看全部
  • ORA-24550 Signal Received 错误排查与解决方案
  • Virt-A-Mate (VAM) v1.22 虚拟实境软件介绍
  • AI 时代初级开发者如何从执行者升级为创意主厨
  • Python 技能变现指南:合法合规的兼职方向与技术实践
  • Web 创建与设计指南
  • C++ 入门:发展历史、命名空间与输入输出详解
  • 基于 OpenClaw 与飞书构建 7x24 小时服务器运维机器人
  • Midjourney 官网地址查询与中文支持说明
  • OpenWebUI 配合 SearXNG 实现本地大模型联网搜索及国内引擎配置
  • C# 老项目里怎么搭配 Visual Studio 和 VSCode
  • LangChain 框架入门:核心组件、模块与文档指南
  • Ubuntu Edgy Eft 完整软件源列表配置指南
  • LeetCode 20. 有效的括号:栈的典型应用
  • 数据结构之带头双向循环链表
  • Java 版雪花算法 ID 生成工具类
  • PyTorch 自定义特征嵌入模块 FeatureEmbedder 实现解析
  • AI 绘画的商业应用、代码案例与版权探讨
  • 常用 JDK 国内下载镜像站推荐
  • 2025 AI 问道之旅:个人成长与深度学习理解
  • 无人机 Remote ID Beacon 帧结构深度解析

相关免费在线工具

  • 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