# 微信支付集成指南
## 概述
本项目集成了微信支付功能,支持JSAPI支付、支付回调处理、退款等功能。支付网关采用第三方服务,简化了支付对接流程。
## 功能特性
- ✅ JSAPI支付(微信公众号支付)
- ✅ 支付回调处理
- ✅ 订单状态更新
- ✅ 退款功能
- ✅ 支付日志记录
- ✅ 支付状态查询
## 配置步骤
### 1. 微信支付配置
#### 1.1 获取支付配置
联系支付网关服务商获取以下配置:
- **AppId**: 微信公众号AppId
- **Secret**: 微信公众号Secret
- **BizId**: 支付业务ID
- **AppKey**: 支付密钥
- **PayUrl**: 支付接口地址
- **RefundUrl**: 退款接口地址
#### 1.2 系统配置
修改 `application-dev.yml` 配置文件:
```yaml
wxshop:
appid: wx9922dfbb0d4cd7bb
secret: 7c7ef0dbb90b6be2abc8c269357f980a
pay:
biz_id: wxshop
old_biz_id: wxshop_old
appkey: wxshop202503081132
pay_url: http://222.218.10.217:7890/open/trade/wx/jsapi/precreate
refund_url: http://222.218.10.217:7890/open/trade/refund
```
### 2. 数据库准备
#### 2.1 支付日志表
```sql
CREATE TABLE `payment_operation_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_no` varchar(64) NOT NULL COMMENT '订单号',
`operation_type` varchar(50) NOT NULL COMMENT '操作类型',
`request_data` text COMMENT '请求数据',
`response_data` text COMMENT '响应数据',
`status` tinyint DEFAULT '1' COMMENT '状态',
`error_msg` varchar(500) DEFAULT NULL COMMENT '错误信息',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_order_no` (`order_no`)
);
```
## 核心功能
### 1. 创建支付订单
#### 1.1 支付请求
```bash
POST /payment/create
Content-Type: application/json
{
"orderId": "2025030811320001",
"amount": 99.99,
"openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o",
"payType": "JSAPI",
"subject": "商品订单",
"body": "商品描述"
}
```
#### 1.2 支付响应
```json
{
"code": 200,
"msg": "success",
"data": {
"prepayId": "wx20250308113200abc123",
"paySign": "BDF0099C9FF443C4DC5C5D68C4B97C3F",
"timestamp": "1657794651",
"nonceStr": "1657794651",
"package": "prepay_id=wx20250308113200abc123"
}
}
```
### 2. 支付回调
#### 2.1 回调接口
```
POST /payment/callback
Content-Type: application/xml
```
#### 2.2 回调数据示例
```xml
1
```
#### 2.3 回调响应
```xml
```
### 3. 退款功能
#### 3.1 退款请求
```bash
POST /payment/refund
Content-Type: application/json
{
"orderNo": "2025030811320001",
"refundAmount": 99.99,
"refundReason": "用户申请退款",
"refundNo": "REF2025030811320001"
}
```
#### 3.2 退款响应
```json
{
"code": 200,
"msg": "success",
"data": {
"refundId": "REF2025030811320001",
"status": "PROCESSING",
"refundTime": "2025-03-08 11:32:00"
}
}
```
## 代码实现
### 1. 支付服务
```java
@Service
@RequiredArgsConstructor
public class PaymentService {
private final PaymentGateway paymentGateway;
private final PaymentOperationLogService logService;
public WxJsApiPreCreateResponse createPayment(WxJsApiPreCreateRequest request) {
// 记录请求日志
PaymentOperationLog log = createRequestLog(request);
try {
// 调用支付网关
WxJsApiPreCreateResponse response = paymentGateway.preCreate(request);
// 记录响应日志
updateResponseLog(log, response, true);
return response;
} catch (Exception e) {
// 记录错误日志
updateErrorLog(log, e.getMessage());
throw new ApiException("支付创建失败: " + e.getMessage());
}
}
}
```
### 2. 支付网关
```java
@Component
public class PaymentGateway {
@Value("${wxshop.pay.pay-url}")
private String payUrl;
@Value("${wxshop.pay.appkey}")
private String appKey;
public WxJsApiPreCreateResponse preCreate(WxJsApiPreCreateRequest request) {
// 构建请求参数
Map params = buildParams(request);
// 生成签名
String sign = SignUtils.generateSign(params, appKey);
params.put("sign", sign);
// 发送请求
String response = HttpUtil.post(payUrl, params);
// 解析响应
return parseResponse(response);
}
}
```
### 3. 签名工具
```java
public class SignUtils {
public static String generateSign(Map params, String appKey) {
// 参数排序
List 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.isEmpty()) {
sb.append(key).append("=").append(value).append("&");
}
}
sb.append("key=").append(appKey);
// MD5加密
return DigestUtils.md5Hex(sb.toString()).toUpperCase();
}
}
```
## 支付流程
### 1. 支付创建流程
```mermaid
sequenceDiagram
participant Client
participant Backend
participant PaymentGateway
participant WeChat
Client->>Backend: 创建支付订单
Backend->>PaymentGateway: 预支付请求
PaymentGateway->>WeChat: 统一下单
WeChat-->>PaymentGateway: 返回预支付ID
PaymentGateway-->>Backend: 返回支付参数
Backend-->>Client: 返回前端支付参数
```
### 2. 支付回调流程
```mermaid
sequenceDiagram
participant WeChat
participant Backend
participant Database
WeChat->>Backend: 支付结果通知
Backend->>Backend: 验证签名
Backend->>Database: 更新订单状态
Backend-->>WeChat: 返回成功响应
```
## 错误处理
### 1. 支付错误码
| 错误码 | 说明 | 处理建议 |
|-------|------|----------|
| `SYSTEMERROR` | 系统错误 | 重试操作 |
| `ORDERPAID` | 订单已支付 | 检查订单状态 |
| `OUT_TRADE_NO_USED` | 商户订单号重复 | 使用新订单号 |
| `NOTENOUGH` | 余额不足 | 提示用户 |
| `APPID_NOT_EXIST` | AppID不存在 | 检查配置 |
### 2. 异常处理
```java
@RestControllerAdvice
public class PaymentExceptionHandler {
@ExceptionHandler(PaymentException.class)
public ResponseDTO handlePaymentException(PaymentException e) {
log.error("支付异常: {}", e.getMessage(), e);
return ResponseDTO.fail(e.getCode(), e.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseDTO handleException(Exception e) {
log.error("系统异常: {}", e.getMessage(), e);
return ResponseDTO.fail(500, "系统繁忙,请稍后重试");
}
}
```
## 安全注意事项
### 1. 数据安全
- 支付密钥妥善保管
- 敏感数据传输使用HTTPS
- 支付回调验证签名
- 防止重复支付
### 2. 业务安全
- 订单金额校验
- 用户身份验证
- 防止SQL注入
- 日志记录完整
## 监控和日志
### 1. 监控指标
- 支付成功率
- 支付平均耗时
- 退款成功率
- 回调处理成功率
### 2. 日志记录
- 支付请求/响应日志
- 回调处理日志
- 错误日志
- 性能日志
## 测试建议
### 1. 单元测试
```java
@SpringBootTest
class PaymentServiceTest {
@Autowired
private PaymentService paymentService;
@Test
void testCreatePayment() {
WxJsApiPreCreateRequest request = new WxJsApiPreCreateRequest();
request.setOrderNo("TEST001");
request.setAmount(new BigDecimal("0.01"));
request.setOpenid("test_openid");
WxJsApiPreCreateResponse response = paymentService.createPayment(request);
assertNotNull(response);
assertNotNull(response.getPrepayId());
}
}
```
### 2. 集成测试
- 支付流程完整测试
- 回调处理测试
- 退款流程测试
- 异常场景测试
## 性能优化
### 1. 缓存优化
- 支付配置缓存
- 订单状态缓存
- 用户信息缓存
### 2. 异步处理
- 支付日志异步记录
- 通知消息异步发送
- 统计报表异步生成
### 3. 数据库优化
- 支付日志表分表
- 订单表索引优化
- 定期清理历史数据