java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java对接微信支付

Java对接微信支付全过程

作者:伏羲栈

本文主要介绍了Java对接微信支付全过程,涵盖注册商户、生成预支付订单、处理回调和查询订单状态等,具有一定的参考价值,感兴趣的可以了解一下

引言

在数字化商业蓬勃发展的今天,移动支付已成为连接用户与服务的核心纽带。微信支付凭借其庞大的用户基数和成熟的生态体系,成为企业拓展线上业务不可或缺的支付工具。然而,对于Java开发者而言,如何高效、安全地对接微信支付接口,构建稳定可靠的支付系统,仍面临诸多技术挑战——从复杂的签名验签机制到异步通知的幂等性处理,从证书管理到高并发场景下的性能优化,每一步都需要精准的技术设计与严谨的代码实现。

本文将以系统性、实战性为导向,深入剖析Java对接微信支付的核心流程与关键技术。无论是Native支付、JSAPI支付还是小程序支付,其底层逻辑均围绕预支付订单生成、支付结果异步通知、订单状态主动查询三大核心环节展开。文章不仅提供清晰的代码示例(基于Spring Boot框架与微信支付V3 API),更聚焦于实际开发中的高频痛点:如何通过RSA签名保障通信安全?如何设计幂等回调接口避免重复扣款?如何利用微信平台证书防止伪造请求?这些问题将在文中逐一击破。

此外,本文还将探讨企业级支付系统中的最佳实践,例如使用WechatPay Apache HttpClient简化证书管理、通过分布式锁实现订单状态同步、结合日志监控提升系统可观测性等。无论您是初探支付领域的开发者,还是需优化现有支付架构的技术负责人,均可从中获得从基础配置到高阶优化的完整知识链路,助力构建高可用、高安全的支付服务体系,为业务增长筑牢技术基石。

一、准备工作

注册微信商户平台

配置支付参数

# application.properties
wxpay.mch-id=你的商户号
wxpay.api-key=你的API密钥
wxpay.notify-url=https://你的域名/api/wxpay/notify

二、核心接口实现

1. 生成预支付订单(Native支付)

public class WxPayService {
    private String mchId;
    private String apiKey;
    private String notifyUrl;

    // 初始化参数(通过@Value注入或配置文件读取)

    /**
     * 生成Native支付二维码链接
     */
    public String createNativeOrder(String orderId, int amount) throws Exception {
        String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";

        Map<String, Object> params = new HashMap<>();
        params.put("mchid", mchId);
        params.put("appid", "你的AppID");  // 如果是公众号/小程序支付
        params.put("description", "订单描述");
        params.put("out_trade_no", orderId);
        params.put("notify_url", notifyUrl);
        params.put("amount", Map.of("total", amount, "currency", "CNY"));

        // 生成签名并发送请求
        String body = JSON.toJSONString(params);
        String authorization = generateSignature("POST", url, body);
        
        // 使用OkHttp或RestTemplate发送请求
        String response = sendPostRequest(url, body, authorization);
        return JSON.parseObject(response).getString("code_url");
    }

    /**
     * 生成V3接口的Authorization头
     */
    private String generateSignature(String method, String url, String body) {
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        String message = method + "\n" + url + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
        String signature = signWithSHA256RSA(message, apiKey);  // 使用私钥签名
        return "WECHATPAY2-SHA256-RSA2048 " 
                + "mchid=\"" + mchId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"你的证书序列号\","
                + "signature=\"" + signature + "\"";
    }
}

2. 处理微信支付回调(关键!)

@RestController
@RequestMapping("/api/wxpay")
public class WxPayCallbackController {

    @PostMapping("/notify")
    public String handleNotify(@RequestBody String requestBody,
                               @RequestHeader("Wechatpay-Signature") String signature,
                               @RequestHeader("Wechatpay-Timestamp") String timestamp,
                               @RequestHeader("Wechatpay-Nonce") String nonce) {
        // 1. 验证签名(防止伪造请求)
        String message = timestamp + "\n" + nonce + "\n" + requestBody + "\n";
        boolean isValid = verifySignature(message, signature, publicKey); // 使用微信平台公钥验证
        if (!isValid) {
            return "<xml><return_code>FAIL</return_code></xml>";
        }

        // 2. 解析回调数据
        Map<String, String> result = parseXml(requestBody);
        String orderId = result.get("out_trade_no");
        String transactionId = result.get("transaction_id");
        
        // 3. 幂等性处理:检查订单是否已处理
        if (orderService.isOrderPaid(orderId)) {
            return "<xml><return_code>SUCCESS</return_code></xml>";
        }

        // 4. 更新订单状态
        orderService.updateOrderToPaid(orderId, transactionId);
        
        // 5. 返回成功响应(必须!否则微信会重试)
        return "<xml><return_code>SUCCESS</return_code></xml>";
    }
}

3. 查询订单状态

public class WxPayService {
    public Map<String, String> queryOrder(String orderId) throws Exception {
        String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" 
                    + orderId + "?mchid=" + mchId;
        
        String authorization = generateSignature("GET", url, "");
        String response = sendGetRequest(url, authorization);
        return JSON.parseObject(response, Map.class);
    }
}

三、关键注意事项

签名验证

幂等性设计

证书管理

推荐使用WechatPay Apache HttpClient简化证书处理:

<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-apache-httpclient</artifactId>
    <version>0.4.7</version>
</dependency>

日志记录

四、完整调用示例(Spring Boot)

@RestController
public class PaymentController {
    @Autowired
    private WxPayService wxPayService;

    @GetMapping("/createOrder")
    public String createOrder(@RequestParam String orderId, @RequestParam int amount) {
        try {
            String codeUrl = wxPayService.createNativeOrder(orderId, amount);
            return "&lt;img src=\"https://example.com/qr?data=" + codeUrl + "\"&gt;";
        } catch (Exception e) {
            return "支付创建失败: " + e.getMessage();
        }
    }
}

五、常见问题解决

通过以上步骤,可完成微信支付的核心对接,确保支付流程的可靠性和安全性。

到此这篇关于Java对接微信支付全过程的文章就介绍到这了,更多相关Java对接微信支付内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文