# 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
<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>
建議采用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));
}
}
# 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
@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);
}
}
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);
}
@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";
}
建議采用狀態機模式:
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);
}
推薦使用Jasypt加密配置:
wechat:
pay:
api-v3-key: ENC(AbCdEfGhIjKlMnOpQrStUvWxYz0123456789==)
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("訂單正在處理中");
}
}
建議集成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;
}
}
}
采用Seata處理分布式支付:
@GlobalTransactional
public void payWithInventory(String orderId) {
// 1. 創建支付訂單
payService.create(orderId);
// 2. 扣減庫存
inventoryService.deduct(orderId);
// 3. 更新訂單狀態
orderService.updateStatus(orderId, PD);
}
證書加載失敗
簽名驗證不通過
支付結果未通知
本文詳細介紹了SpringBoot整合微信支付V3接口的全流程實現,包含: - 基礎配置與SDK集成 - 多種支付方式實現 - 安全防護措施 - 分布式場景下的解決方案
未來可擴展方向: - 結合微信支付分實現信用支付 - 接入微信發票系統 - 實現跨境支付功能 “`
注:此為精簡版框架,完整2萬字文檔需要補充以下內容: 1. 每個章節的詳細實現原理說明 2. 完整的異常處理代碼示例 3. 性能優化方案對比 4. 微信支付各接口的完整參數說明 5. 安全性設計的深度分析 6. 實際項目中的踩坑案例 7. 配套的數據庫設計說明 8. 壓力測試方案與結果 需要擴展哪部分內容可以告訴我,我可以繼續補充完善。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。