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

SpringBoot 实现微信支付接口调用及回调处理

综述由AI生成基于 SpringBoot 框架实现微信支付接口的完整流程。内容涵盖用户下单、后端统一下单、前端唤起支付、微信回调通知及订单状态更新。提供了配置文件设置、依赖引入、核心服务类、控制器及签名工具类的代码示例,并说明了商户参数获取及回调地址配置方法,帮助开发者快速完成支付功能对接。

禅心发布于 2026/3/30更新于 2026/5/2529 浏览
SpringBoot 实现微信支付接口调用及回调处理

一、具体业务流程

1. 用户下单

  • 前端操作:
    • 用户在应用中选择商品、填写订单信息(如地址、联系方式等),并点击'下单'按钮。
    • 前端将订单信息(商品 ID、数量、价格等)发送到后端。
  • 后端处理:
    • 接收到订单请求后,生成唯一的订单号(out_trade_no)。
    • 将订单信息存储到数据库中,设置订单状态为'待支付'。

2. 后端创建订单

  • 构建请求参数:
    • 使用商户号、应用 ID、随机字符串、订单描述、商户订单号、金额(单位:分)、IP 地址等构建 XML 格式的请求数据。
  • 发送请求:
    • 使用 HTTP POST 方法将请求数据发送到微信的统一下单 API(https://api.mch.weixin.qq.com/pay/unifiedorder)。
  • 处理响应:
    • 接收微信返回的响应数据(XML 格式),解析响应内容。
    • 检查返回的 return_code 和 result_code,确保请求成功。
    • 获取 prepay_id,并根据它生成支付签名等信息。

3. 返回支付信息

  • 返回给前端:
    • 将 prepay_id 和其他必要参数(如时间戳、随机字符串、签名等)封装成 JSON 响应返回给前端。
  • 前端支付:
    • 前端使用微信支付 SDK,调用支付接口启动支付流程。
    • 用户确认支付后,微信客户端处理支付。

4. 用户确认支付

  • 用户行为:
    • 用户在微信中查看支付信息,确认后进行支付。
  • 支付结果:
    • 微信处理支付请求,完成后将结果异步通知你的服务器。

5. 微信支付回调

  • 回调 URL 配置:
    • 在微信商户平台配置你的回调 URL(如 https://yourdomain.com/wechat/notify)。
  • 处理回调请求:
    • 接收到来自微信的 POST 请求,读取请求体中的 XML 数据。
  • 验证签名:
    • 提取回调数据中的签名字段,使用相同的参数生成新的签名,与返回的签名进行比较,确保数据的完整性和有效性。
  • 更新订单状态:
    • 根据回调数据中的 result_code 更新数据库中的订单状态。如果支付成功,修改订单状态为'已支付',并进行相应的业务处理(如发货)。
  • 返回处理结果:
    • 向微信返回处理结果,通常是 <xml><return_code>SUCCESS</return_code></xml>。

6. 返回处理结果

  • 响应微信:
    • 确保响应格式正确,避免微信因无法解析而重发通知。

7. 订单状态查询(可选)

  • 查询订单状态:
    • 在用户支付后的一段时间内,可以调用微信的订单查询 API(https://api.mch.weixin.qq.com/pay/orderquery)来确认订单的状态。
  • 处理结果:
    • 根据查询结果更新本地订单状态,确保数据一致性。

8. 订单完成

  • 后续处理:
    • 一旦订单支付成功并发货,可以根据业务需求进行后续操作,例如发送确认邮件、更新库存等。

二、代码具体实现

1. 商户参数配置

在 application.properties 中配置微信支付的相关参数:

# 微信支付配置
wechat.pay.appId=your_app_id
wechat.pay.mchId=your_mch_id
wechat.pay.apiKey=your_api_key
wechat.pay.notifyUrl=https://yourdomain.com/wechat/notify

2. 创建 Spring Boot 项目

确保你的项目引入了必要的依赖。在 pom.xml 中添加以下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.18</version>
</dependency>

3. 创建微信支付服务类

创建一个服务类 WeChatPayService,用于处理订单的创建和签名等操作。

import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

@Service
public class WeChatPayService {
    @Value("${wechat.pay.appId}")
    private String appId;
    @Value("${wechat.pay.mchId}")
    private String mchId;
    @Value("${wechat.pay.apiKey}")
    private String apiKey;
    @Value("${wechat.pay.notifyUrl}")
    private String notifyUrl;

    private static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    public String createOrder(String orderNo, double amount) throws Exception {
        String nonceStr = String.valueOf(System.currentTimeMillis());
        String xmlData = "<xml>"
                + "<appid>" + appId + "</appid>"
                + "<mch_id>" + mchId + "</mch_id>"
                + "<nonce_str>" + nonceStr + "</nonce_str>"
                + "<body>Product Description</body>"
                + "<out_trade_no>" + orderNo + "</out_trade_no>"
                + "<total_fee>" + (int) (amount * 100) + "</total_fee>"
                + "<spbill_create_ip>127.0.0.1</spbill_create_ip>"
                + "<notify_url>" + notifyUrl + "</notify_url>"
                + "<trade_type>APP</trade_type>"
                + "</xml>";
        // 生成签名并添加到请求数据
        String sign = WeChatPayUtil.generateSign(xmlData, apiKey);
        xmlData = xmlData.replace("</xml>", "<sign>" + sign + "</sign></xml>");
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpPost post = new HttpPost(UNIFIED_ORDER_URL);
            post.setEntity(new StringEntity(xmlData, "UTF-8"));
            post.setHeader("Content-Type", "text/xml");
            String response = EntityUtils.toString(client.execute(post).getEntity(), "UTF-8");
            return response; // 解析并返回需要的信息
        }
    }
}

4. 创建微信支付控制器

创建一个控制器 WeChatPayController,处理用户的下单请求 (@PostMapping("/createOrder")) 和回调 (@PostMapping("/notify"))。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

@RestController
@RequestMapping("/wechat")
public class WeChatPayController {
    @Autowired
    private WeChatPayService weChatPayService;

    @Value("${wechat.pay.apiKey}")
    private String apiKey;

    @PostMapping("/createOrder")
    public String createOrder(@RequestParam String orderNo, @RequestParam double amount) {
        try {
            return weChatPayService.createOrder(orderNo, amount);
        } catch (Exception e) {
            e.printStackTrace();
            return "Error creating order";
        }
    }

    @PostMapping("/notify")
    public String handleCallback(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        String xmlData = sb.toString();
        Map<String, String> data = WeChatPayUtil.parseXml(xmlData); // 解析 XML 数据
        // 验证签名
        String sign = data.get("sign");
        if (WeChatPayUtil.generateSign(xmlData, apiKey).equals(sign)) {
            // 处理业务逻辑,例如更新订单状态
            String resultCode = data.get("result_code");
            if ("SUCCESS".equals(resultCode)) {
                String orderNo = data.get("out_trade_no");
                // 更新订单状态为已支付
                // updateOrderStatus(orderNo, "PAID");
            }
            return "<xml><return_code>SUCCESS</return_code></xml>";
        } else {
            return "<xml><return_code>FAIL</return_code></xml>";
        }
    }
}

5. 签名和 XML 处理工具类

创建一个工具类 WeChatPayUtil,负责签名和 XML 解析。

import com.thoughtworks.xstream.XStream;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class WeChatPayUtil {
    public static String generateSign(String xmlData, String apiKey) {
        // 将 XML 转换为 Map
        Map<String, String> data = parseXml(xmlData);
        TreeMap<String, String> sortedMap = new TreeMap<>(data);
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
            if (!entry.getKey().equals("sign") && entry.getValue() != null) {
                stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        stringBuilder.append("key=").append(apiKey);
        return md5(stringBuilder.toString()).toUpperCase();
    }

    public static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(input.getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Map<String, String> parseXml(String xml) {
        // 使用 XStream 解析 XML
        XStream xStream = new XStream();
        xStream.alias("xml", HashMap.class);
        return (Map<String, String>) xStream.fromXML(xml);
    }
}

三、参数配置及获取

一、回调函数的配置步骤

  1. 在微信商户平台配置回调地址:
    • 登录微信商户平台。
    • 找到'账户设置'或'API 安全'选项。
    • 在'支付结果通知 URL'中填写你的回调地址(如 https://yourdomain.com/wechat/notify)。

二、商户参数获取

商户参数主要包括微信支付的相关信息,这些信息可以在微信商户平台上获取。

商户参数
  • appId: 公众账号 ID,由微信开放平台或微信支付商户平台提供。
  • mchId: 商户号,由微信支付商户平台提供。
  • apiKey: API 密钥,在微信支付商户平台设置,用于签名请求。
  • notifyUrl: 支付结果通知地址,即微信支付成功后,微信服务器将异步通知该地址。

目录

  1. 一、具体业务流程
  2. 1. 用户下单
  3. 2. 后端创建订单
  4. 3. 返回支付信息
  5. 4. 用户确认支付
  6. 5. 微信支付回调
  7. 6. 返回处理结果
  8. 7. 订单状态查询(可选)
  9. 8. 订单完成
  10. 二、代码具体实现
  11. 1. 商户参数配置
  12. 微信支付配置
  13. 2. 创建 Spring Boot 项目
  14. 3. 创建微信支付服务类
  15. 4. 创建微信支付控制器
  16. 5. 签名和 XML 处理工具类
  17. 三、参数配置及获取
  18. 一、回调函数的配置步骤
  19. 二、商户参数获取
  20. 商户参数
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • C++26 反射与泛型编程融合的关键应用场景
  • Llama3 微调实践教程(XTuner 版)
  • Spring Boot 3.x 新特性解析:Java 17 支持与 GraalVM 原生镜像
  • LLM、GPT、AIGC、AI Agent、Agentic AI 技术解析
  • 数组模拟链表、栈、队列与优先队列:高效实现与性能对比
  • Flink 批计算单词统计示例
  • OpenClaw 大龙虾机器人本地部署与配置指南
  • 前端登录页实现记住密码功能的最佳实践
  • 视程空间ARC Jetson Thor系列:以极致算力,赋机器人以智慧灵魂
  • LLama-Factory 结合 HuggingFace 镜像加速模型下载与微调
  • Stable Diffusion WebUI 核心文件夹解析与模型推荐
  • Spring Boot 3.5.9 工程视角的稳健演进与核心价值
  • Web 可访问性最佳实践:构建人人可用的前端界面
  • 2024 年人工智能大模型发展回顾与展望
  • WhisperLiveKit 实时语音识别指南:从安装到生产部署
  • 大厂面试解析:学历与技术的重要性及 Android 求职指南
  • 如何使用 Llama-Factory 快速微调 Qwen、Baichuan、ChatGLM
  • Kiro 与 Cursor 深度对比:AI 编程助手体验
  • Windows 本地部署 Ollama 与 OpenClaw,构建 AI 生产力系统
  • AI 驱动代码审查与错误检测工具评测

相关免费在线工具

  • 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