SpringBoot如何实现整合微信支付

发布时间:2022-03-03 14:59:30 作者:小新
来源:亿速云 阅读:426
# SpringBoot如何实现整合微信支付

## 目录
- [一、微信支付概述](#一微信支付概述)
  - [1.1 微信支付产品体系](#11-微信支付产品体系)
  - [1.2 开发前准备](#12-开发前准备)
- [二、SpringBoot项目基础搭建](#二springboot项目基础搭建)
  - [2.1 项目初始化](#21-项目初始化)
  - [2.2 核心依赖配置](#22-核心依赖配置)
- [三、微信支付V3接口对接](#三微信支付v3接口对接)
  - [3.1 证书与密钥管理](#31-证书与密钥管理)
  - [3.2 微信支付配置封装](#32-微信支付配置封装)
- [四、支付功能实现](#四支付功能实现)
  - [4.1 Native支付实现](#41-native支付实现)
  - [4.2 JSAPI支付实现](#42-jsapi支付实现)
- [五、支付结果通知处理](#五支付结果通知处理)
  - [5.1 回调通知验签](#51-回调通知验签)
  - [5.2 订单状态更新](#52-订单状态更新)
- [六、安全与最佳实践](#六安全与最佳实践)
  - [6.1 敏感信息加密](#61-敏感信息加密)
  - [6.2 防重复支付处理](#62-防重复支付处理)
- [七、扩展与优化](#七扩展与优化)
  - [7.1 支付日志监控](#71-支付日志监控)
  - [7.2 分布式事务处理](#72-分布式事务处理)
- [八、常见问题排查](#八常见问题排查)
- [九、总结与展望](#九总结与展望)

---

## 一、微信支付概述

### 1.1 微信支付产品体系
微信支付提供多种支付方式:
- **Native支付**:PC网站扫码支付
- **JSAPI支付**:微信公众号/小程序支付
- **H5支付**:手机浏览器支付
- **APP支付**:移动应用集成

### 1.2 开发前准备
1. 注册微信支付商户号
2. 获取API证书和密钥(apiclient_key.pem)
3. 配置商户平台回调域名
4. 记录商户ID(mchid)和APPID

---

## 二、SpringBoot项目基础搭建

### 2.1 项目初始化
```bash
spring init -dweb,mybatis,lombok wechat-pay-demo

2.2 核心依赖配置

<dependencies>
    <!-- 微信支付官方SDK -->
    <dependency>
        <groupId>com.github.wechatpay-apiv3</groupId>
        <artifactId>wechatpay-apache-httpclient</artifactId>
        <version>0.4.7</version>
    </dependency>
    
    <!-- 其他必要依赖 -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
</dependencies>

三、微信支付V3接口对接

3.1 证书与密钥管理

建议采用PKCS12格式证书存储:

public class CertManager {
    private static final String CERT_PATH = "/path/to/apiclient_cert.p12";
    
    public Credentials createCredentials() throws Exception {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
            new FileInputStream("/path/to/apiclient_key.pem"));
            
        return new Credentials(
            "商户号",
            new PrivateKeySigner("商户证书序列号", merchantPrivateKey));
    }
}

3.2 微信支付配置封装

# application.yml
wechat:
  pay:
    mch-id: 1230000109
    app-id: wx8888888888888888
    api-v3-key: your-api-v3-key-32bytes
    notify-url: https://yourdomain.com/api/pay/notify

四、支付功能实现

4.1 Native支付实现

@RestController
@RequestMapping("/api/pay")
public class PayController {
    
    @Autowired
    private WechatPayService payService;
    
    @PostMapping("/native")
    public Result<String> nativePay(@RequestBody OrderDTO dto) {
        String codeUrl = payService.createNativeOrder(
            dto.getOrderId(), 
            dto.getAmount(),
            dto.getDescription());
            
        return Result.success(codeUrl);
    }
}

4.2 JSAPI支付实现

public Map<String, String> createJsapiOrder(String openId, String orderId, int amount) {
    Map<String, Object> params = new HashMap<>();
    params.put("appid", config.getAppId());
    params.put("mchid", config.getMchId());
    params.put("description", "订单描述");
    params.put("out_trade_no", orderId);
    params.put("notify_url", config.getNotifyUrl());
    params.put("amount", Map.of(
        "total", amount,
        "currency", "CNY"
    ));
    params.put("payer", Map.of("openid", openId));
    
    // 调用微信支付API
    HttpResponse response = httpClient.execute(
        new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi")
            .setHeader("Accept", "application/json")
            .setHeader("Content-type", "application/json")
            .setEntity(new StringEntity(JSON.toJSONString(params))));
            
    // 处理返回结果
    return parseJsapiResponse(response);
}

五、支付结果通知处理

5.1 回调通知验签

@PostMapping("/notify")
public String payNotify(HttpServletRequest request, 
                       @RequestBody String notifyData) {
    
    // 1. 获取微信签名头
    String signature = request.getHeader("Wechatpay-Signature");
    String timestamp = request.getHeader("Wechatpay-Timestamp");
    String nonce = request.getHeader("Wechatpay-Nonce");
    String serialNo = request.getHeader("Wechatpay-Serial");
    
    // 2. 验证签名
    if (!signatureVerifier.verify(serialNo, notifyData, 
        signature, timestamp, nonce)) {
        throw new RuntimeException("签名验证失败");
    }
    
    // 3. 处理业务逻辑
    payService.handlePayResult(JSON.parseObject(notifyData));
    
    return "success";
}

5.2 订单状态更新

建议采用状态机模式:

public enum OrderStatus {
    CREATED,
    PAYING,
    PD,
    REFUNDED,
    CLOSED
}

@Transactional
public void updateOrderStatus(String orderId, OrderStatus status) {
    Order order = orderMapper.selectById(orderId);
    if (order.getStatus() == status) {
        return;
    }
    
    // 状态校验逻辑
    if (status == OrderStatus.PD && 
        order.getStatus() != OrderStatus.PAYING) {
        throw new IllegalStateException("订单状态异常");
    }
    
    orderMapper.updateStatus(orderId, status);
}

六、安全与最佳实践

6.1 敏感信息加密

推荐使用Jasypt加密配置:

wechat:
  pay:
    api-v3-key: ENC(AbCdEfGhIjKlMnOpQrStUvWxYz0123456789==)

6.2 防重复支付处理

public String createOrder(OrderDTO dto) {
    // 幂等性控制
    String lockKey = "order:create:" + dto.getOrderId();
    if (redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.MINUTES)) {
        try {
            // 业务处理
        } finally {
            redisTemplate.delete(lockKey);
        }
    } else {
        throw new RuntimeException("订单正在处理中");
    }
}

七、扩展与优化

7.1 支付日志监控

建议集成ELK实现日志分析:

@Aspect
@Component
@Slf4j
public class PayLogAspect {
    
    @Around("execution(* com..pay.*Service.*(..))")
    public Object logPayOperation(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object result = pjp.proceed();
            log.info("[PAY] {}.{} success - {}ms",
                pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(),
                System.currentTimeMillis() - start);
            return result;
        } catch (Exception e) {
            log.error("[PAY] {}.{} failed - {}",
                pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(),
                e.getMessage());
            throw e;
        }
    }
}

7.2 分布式事务处理

采用Seata处理分布式支付:

@GlobalTransactional
public void payWithInventory(String orderId) {
    // 1. 创建支付订单
    payService.create(orderId);
    
    // 2. 扣减库存
    inventoryService.deduct(orderId);
    
    // 3. 更新订单状态
    orderService.updateStatus(orderId, PD);
}

八、常见问题排查

  1. 证书加载失败

    • 检查证书路径权限
    • 确认证书密码正确性
  2. 签名验证不通过

    • 检查时间戳是否同步
    • 验证APIv3密钥是否正确
  3. 支付结果未通知

    • 检查商户平台回调配置
    • 验证服务器网络可达性

九、总结与展望

本文详细介绍了SpringBoot整合微信支付V3接口的全流程实现,包含: - 基础配置与SDK集成 - 多种支付方式实现 - 安全防护措施 - 分布式场景下的解决方案

未来可扩展方向: - 结合微信支付分实现信用支付 - 接入微信发票系统 - 实现跨境支付功能 “`

注:此为精简版框架,完整2万字文档需要补充以下内容: 1. 每个章节的详细实现原理说明 2. 完整的异常处理代码示例 3. 性能优化方案对比 4. 微信支付各接口的完整参数说明 5. 安全性设计的深度分析 6. 实际项目中的踩坑案例 7. 配套的数据库设计说明 8. 压力测试方案与结果 需要扩展哪部分内容可以告诉我,我可以继续补充完善。

推荐阅读:
  1. SpringBoot整合Mybatis实现CRUD
  2. springboot整合微信支付sdk过程的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot

上一篇:如何使用java实现双层圣诞树加修饰

下一篇:element怎么用脚本自动化构建新组件

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》