# 阶段6:支付集成 ## 阶段概述 **时间**: 2周 **目标**: 实现完整的支付系统,包括微信支付、余额支付、积分支付等多种支付方式 **优先级**: P1 (高优先级) ## 详细任务清单 ### 6.1 微信支付集成 (5天) #### 任务描述 集成微信支付SDK,实现微信小程序支付和H5支付 #### 具体工作 - [ ] 集成微信支付SDK - [ ] 实现统一下单接口 - [ ] 实现支付参数签名 - [ ] 实现支付回调处理 - [ ] 实现支付状态查询 - [ ] 实现退款功能 #### 核心接口实现 ##### 创建微信支付订单接口 ```http POST /api/v1/payment/wechat/create Authorization: Bearer {token} Content-Type: application/json Request: { "order_no": "ORD202401010001", "amount": "10.00", "description": "商品购买", "openid": "oABC123456789", "client_ip": "192.168.1.1" } Response: { "status": 1, "msg": "支付订单创建成功", "data": { "appId": "wx1234567890abcdef", "timeStamp": "1704067200", "nonceStr": "abc123def456", "package": "prepay_id=wx123456789012345", "signType": "RSA", "paySign": "signature_string_here" } } ``` ##### 微信支付回调接口 ```http POST /api/v1/payment/wechat/notify Content-Type: application/json Request: { "id": "notification_id", "create_time": "2024-01-01T12:00:00+08:00", "event_type": "TRANSACTION.SUCCESS", "resource_type": "encrypt-resource", "resource": { "original_type": "transaction", "algorithm": "AEAD_AES_256_GCM", "ciphertext": "encrypted_data", "associated_data": "transaction", "nonce": "nonce_string" } } Response: { "code": "SUCCESS", "message": "成功" } ``` #### 技术实现要点 ```csharp // 微信支付服务接口 public interface IWechatPayService { Task CreatePaymentAsync(WechatPayRequest request); Task HandleNotifyAsync(WechatPayNotify notify); Task QueryPaymentAsync(string orderNo); Task RefundAsync(RefundRequest request); } // 微信支付配置 public class WechatPayConfig { public string AppId { get; set; } public string MchId { get; set; } public string ApiKey { get; set; } public string CertPath { get; set; } public string NotifyUrl { get; set; } public string RefundNotifyUrl { get; set; } } // 微信支付服务实现 public class WechatPayService : IWechatPayService { public async Task CreatePaymentAsync(WechatPayRequest request) { // 1. 构建统一下单请求 var unifiedOrderRequest = new UnifiedOrderRequest { AppId = _config.AppId, MchId = _config.MchId, Body = request.Description, OutTradeNo = request.OrderNo, TotalFee = (int)(request.Amount * 100), // 转换为分 SpbillCreateIp = request.ClientIp, NotifyUrl = _config.NotifyUrl, TradeType = "JSAPI", OpenId = request.OpenId }; // 2. 签名 unifiedOrderRequest.Sign = GenerateSign(unifiedOrderRequest); // 3. 调用微信API var response = await CallWechatApiAsync(unifiedOrderRequest); // 4. 生成支付参数 return new WechatPayResult { AppId = response.AppId, TimeStamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), NonceStr = GenerateNonceStr(), Package = $"prepay_id={response.PrepayId}", SignType = "MD5", PaySign = GeneratePaySign(/* parameters */) }; } public async Task HandleNotifyAsync(WechatPayNotify notify) { // 1. 验证签名 if (!VerifyNotifySign(notify)) { return false; } // 2. 解密数据 var paymentData = DecryptNotifyData(notify.Resource); // 3. 更新订单状态 await _orderService.UpdatePaymentStatusAsync( paymentData.OutTradeNo, paymentData.TransactionId, PaymentStatus.Success ); return true; } } ``` ### 6.2 余额支付系统 (3天) #### 任务描述 实现用户余额支付功能 #### 具体工作 - [ ] 实现余额支付接口 - [ ] 实现余额扣减逻辑 - [ ] 实现支付密码验证 - [ ] 实现余额不足处理 - [ ] 实现支付记录 #### 核心接口实现 ##### 余额支付接口 ```http POST /api/v1/payment/balance/pay Authorization: Bearer {token} Content-Type: application/json Request: { "order_no": "ORD202401010001", "amount": "10.00", "pay_password": "123456" } Response: { "status": 1, "msg": "支付成功", "data": { "pay_no": "BAL202401010001", "pay_time": "2024-01-01T12:00:00Z", "remaining_balance": "90.00" } } ``` ##### 设置支付密码接口 ```http POST /api/v1/user/payment-password Authorization: Bearer {token} Content-Type: application/json Request: { "password": "123456", "confirm_password": "123456", "sms_code": "123456" } Response: { "status": 1, "msg": "支付密码设置成功" } ``` #### 技术实现要点 ```csharp // 余额支付服务 public interface IBalancePayService { Task PayAsync(BalancePayRequest request); Task VerifyPayPasswordAsync(int userId, string password); Task SetPayPasswordAsync(int userId, string password, string smsCode); } public class BalancePayService : IBalancePayService { public async Task PayAsync(BalancePayRequest request) { using var transaction = await _context.Database.BeginTransactionAsync(); try { // 1. 验证支付密码 if (!await VerifyPayPasswordAsync(request.UserId, request.PayPassword)) { throw new BusinessException("支付密码错误"); } // 2. 检查余额 var user = await _context.Users.FindAsync(request.UserId); if (user.Money < request.Amount) { throw new BusinessException("余额不足"); } // 3. 扣减余额 user.Money -= request.Amount; // 4. 记录支付记录 var payRecord = new ProfitPay { UserId = request.UserId, ChangeMoney = -request.Amount, Content = "余额支付", OrderNo = request.OrderNo, PayType = (int)PayType.Balance, AddTime = DateTime.Now }; _context.ProfitPays.Add(payRecord); // 5. 更新订单状态 await _orderService.UpdatePaymentStatusAsync( request.OrderNo, payRecord.Id.ToString(), PaymentStatus.Success ); await _context.SaveChangesAsync(); await transaction.CommitAsync(); return new BalancePayResult { PayNo = payRecord.Id.ToString(), PayTime = payRecord.AddTime, RemainingBalance = user.Money }; } catch { await transaction.RollbackAsync(); throw; } } } ``` ### 6.3 积分支付系统 (2天) #### 任务描述 实现积分支付功能 #### 具体工作 - [ ] 实现积分支付接口 - [ ] 实现积分扣减逻辑 - [ ] 实现积分兑换比例配置 - [ ] 实现积分不足处理 #### 核心接口实现 ##### 积分支付接口 ```http POST /api/v1/payment/integral/pay Authorization: Bearer {token} Content-Type: application/json Request: { "order_no": "ORD202401010001", "integral_amount": "100.00", "money_amount": "10.00" } Response: { "status": 1, "msg": "积分支付成功", "data": { "pay_no": "INT202401010001", "pay_time": "2024-01-01T12:00:00Z", "remaining_integral": "900.00" } } ``` ### 6.4 混合支付系统 (2天) #### 任务描述 实现多种支付方式的混合支付 #### 具体工作 - [ ] 实现混合支付接口 - [ ] 实现支付方式优先级 - [ ] 实现支付金额分配 - [ ] 实现混合支付回滚 #### 核心接口实现 ##### 混合支付接口 ```http POST /api/v1/payment/mixed/pay Authorization: Bearer {token} Content-Type: application/json Request: { "order_no": "ORD202401010001", "total_amount": "30.00", "payment_methods": [ { "type": "balance", "amount": "10.00" }, { "type": "integral", "amount": "100.00", "money_equivalent": "10.00" }, { "type": "wechat", "amount": "10.00" } ] } Response: { "status": 1, "msg": "混合支付创建成功", "data": { "balance_paid": "10.00", "integral_paid": "100.00", "wechat_pay_info": { "appId": "wx1234567890abcdef", "timeStamp": "1704067200", "nonceStr": "abc123def456", "package": "prepay_id=wx123456789012345", "signType": "RSA", "paySign": "signature_string_here" } } } ``` ### 6.5 支付状态管理 (2天) #### 任务描述 实现支付状态的统一管理和查询 #### 具体工作 - [ ] 实现支付状态查询接口 - [ ] 实现支付状态同步 - [ ] 实现支付失败处理 - [ ] 实现支付超时处理 #### 核心接口实现 ##### 支付状态查询接口 ```http GET /api/v1/payment/{orderNo}/status Authorization: Bearer {token} Response: { "status": 1, "msg": "请求成功", "data": { "order_no": "ORD202401010001", "pay_status": "SUCCESS", "pay_type": "WECHAT", "pay_amount": "10.00", "pay_time": "2024-01-01T12:00:00Z", "pay_no": "wx123456789012345", "payment_details": [ { "method": "balance", "amount": "5.00", "status": "SUCCESS" }, { "method": "wechat", "amount": "5.00", "status": "SUCCESS" } ] } } ``` ##### 支付重试接口 ```http POST /api/v1/payment/{orderNo}/retry Authorization: Bearer {token} Response: { "status": 1, "msg": "支付重试成功", "data": { "new_pay_info": { // 新的支付参数 } } } ``` ## 支付安全机制 ### 签名验证 ```csharp public class PaymentSecurityService { // 生成签名 public string GenerateSign(Dictionary parameters, string key) { var sortedParams = parameters .Where(p => !string.IsNullOrEmpty(p.Value) && p.Key != "sign") .OrderBy(p => p.Key) .Select(p => $"{p.Key}={p.Value}") .ToList(); var stringToSign = string.Join("&", sortedParams) + "&key=" + key; return MD5Hash(stringToSign).ToUpper(); } // 验证签名 public bool VerifySign(Dictionary parameters, string key, string sign) { var calculatedSign = GenerateSign(parameters, key); return calculatedSign.Equals(sign, StringComparison.OrdinalIgnoreCase); } // 防重放攻击 public async Task CheckNonceAsync(string nonce, TimeSpan expiry) { var key = $"payment_nonce:{nonce}"; var exists = await _redis.ExistsAsync(key); if (exists) { return false; // 重复请求 } await _redis.SetAsync(key, "1", expiry); return true; } } ``` ### 支付密码加密 ```csharp public class PaymentPasswordService { public string HashPassword(string password, string salt) { return BCrypt.Net.BCrypt.HashPassword(password + salt); } public bool VerifyPassword(string password, string salt, string hash) { return BCrypt.Net.BCrypt.Verify(password + salt, hash); } public async Task CheckPayPasswordAttemptsAsync(int userId) { var key = $"pay_password_attempts:{userId}"; var attempts = await _redis.GetAsync(key); if (attempts >= 5) { return false; // 超过最大尝试次数 } return true; } } ``` ## 支付数据模型 ### 支付记录表 ```csharp public class PaymentRecord { public int Id { get; set; } public string PayNo { get; set; } public string OrderNo { get; set; } public int UserId { get; set; } public int PayType { get; set; } public decimal Amount { get; set; } public int Status { get; set; } public string ThirdPartyNo { get; set; } public string NotifyData { get; set; } public DateTime CreateTime { get; set; } public DateTime? PayTime { get; set; } public DateTime? NotifyTime { get; set; } } public class PaymentMethod { public int Id { get; set; } public string PayNo { get; set; } public int MethodType { get; set; } public decimal Amount { get; set; } public int Status { get; set; } public string MethodData { get; set; } public DateTime CreateTime { get; set; } } ``` ## 支付配置管理 ### 支付方式配置 ```csharp public class PaymentConfig { public class WechatPay { public bool Enabled { get; set; } = true; public decimal MinAmount { get; set; } = 0.01m; public decimal MaxAmount { get; set; } = 50000m; public string AppId { get; set; } public string MchId { get; set; } public string ApiKey { get; set; } } public class BalancePay { public bool Enabled { get; set; } = true; public decimal MinAmount { get; set; } = 0.01m; public bool RequirePassword { get; set; } = true; public int MaxDailyAmount { get; set; } = 10000; } public class IntegralPay { public bool Enabled { get; set; } = true; public decimal ExchangeRate { get; set; } = 10m; // 10积分=1元 public decimal MinIntegral { get; set; } = 10m; public decimal MaxIntegralPerOrder { get; set; } = 1000m; } } ``` ## 验收标准 ### 功能验收 - [ ] 微信支付流程完整可用 - [ ] 余额支付功能正常 - [ ] 积分支付功能正常 - [ ] 混合支付功能正常 - [ ] 支付状态管理正确 - [ ] 支付安全机制有效 ### 性能验收 - [ ] 支付创建接口响应时间 < 1000ms - [ ] 支付回调处理时间 < 500ms - [ ] 支付状态查询响应时间 < 200ms - [ ] 支持并发支付 > 100 QPS ### 安全验收 - [ ] 签名验证机制正确 - [ ] 支付密码加密安全 - [ ] 防重放攻击有效 - [ ] 支付数据传输安全 ### 准确性验收 - [ ] 支付金额计算准确率 100% - [ ] 支付状态同步准确率 100% - [ ] 资产扣减准确率 100% - [ ] 支付记录完整性 100% ## 风险点和注意事项 ### 技术风险 1. **支付安全**: 支付接口的安全性和防篡改 2. **网络异常**: 支付过程中的网络中断处理 3. **数据一致性**: 支付状态和订单状态的一致性 4. **并发控制**: 高并发支付时的数据安全 ### 解决方案 1. **多重验证**: 签名验证、时间戳验证、随机数验证 2. **重试机制**: 支付失败时的自动重试 3. **事务管理**: 严格的事务控制确保数据一致性 4. **分布式锁**: 关键支付操作使用分布式锁 ## 下一阶段准备 ### 为阶段7准备的内容 - [ ] 抽奖算法基础 - [ ] 概率计算引擎 - [ ] 随机数生成器 - [ ] 奖品发放机制 ### 交接文档 - [ ] 支付系统架构说明 - [ ] 微信支付集成指南 - [ ] 支付安全机制文档 - [ ] 支付配置管理手册 --- **阶段6完成标志**: 支付系统功能完整,包括微信支付、余额支付、积分支付等功能正常运行,支付安全性和准确性得到保障。