9.8 KiB
Design Document: 支付集成迁移
Overview
本设计文档描述了将PHP支付系统迁移到.NET 8的技术方案。支付系统主要包括微信支付统一下单、支付回调处理、余额/积分/哈尼券支付、以及订单发货通知等功能。
Architecture
┌─────────────────────────────────────────────────────────────┐
│ API Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │PayController│ │NotifyController│ │OrderController │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
└─────────┼────────────────┼─────────────────────┼────────────┘
│ │ │
┌─────────▼────────────────▼─────────────────────▼────────────┐
│ Service Layer │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │WechatPayService │ │PaymentService │ │NotifyService│ │
│ └────────┬────────┘ └────────┬────────┘ └──────┬──────┘ │
└───────────┼────────────────────┼──────────────────┼─────────┘
│ │ │
┌───────────▼────────────────────▼──────────────────▼─────────┐
│ Data Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Order │ │ User │ │ProfitPay │ │OrderNotify │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Components and Interfaces
1. IWechatPayService - 微信支付服务接口
public interface IWechatPayService
{
/// <summary>
/// 创建微信支付统一下单
/// </summary>
Task<WechatPayResult> CreatePaymentAsync(WechatPayRequest request);
/// <summary>
/// 验证支付签名
/// </summary>
bool VerifySign(Dictionary<string, string> parameters, string sign);
/// <summary>
/// 生成支付签名
/// </summary>
string MakeSign(Dictionary<string, string> parameters);
/// <summary>
/// 发送订单发货通知到微信
/// </summary>
Task<bool> PostOrderShippingAsync(string orderNo, string openId);
}
2. IPaymentNotifyService - 支付回调服务接口
public interface IPaymentNotifyService
{
/// <summary>
/// 处理微信支付回调
/// </summary>
Task<NotifyResult> HandleWechatNotifyAsync(string xmlData);
/// <summary>
/// 处理一番赏订单支付成功
/// </summary>
Task<bool> ProcessLotteryOrderAsync(int orderId, int userId, int goodsId, int num);
/// <summary>
/// 处理无限赏订单支付成功
/// </summary>
Task<bool> ProcessInfiniteOrderAsync(int orderId, int userId, int goodsId);
/// <summary>
/// 处理充值订单支付成功
/// </summary>
Task<bool> ProcessRechargeOrderAsync(string orderNo);
/// <summary>
/// 处理发货运费支付成功
/// </summary>
Task<bool> ProcessShippingFeeOrderAsync(string orderNo);
}
3. IPaymentService - 统一支付服务接口
public interface IPaymentService
{
/// <summary>
/// 扣减用户余额
/// </summary>
Task<bool> DeductBalanceAsync(int userId, decimal amount, string content);
/// <summary>
/// 扣减用户积分
/// </summary>
Task<bool> DeductIntegralAsync(int userId, decimal amount, string content);
/// <summary>
/// 扣减用户哈尼券
/// </summary>
Task<bool> DeductMoney2Async(int userId, decimal amount, string content);
/// <summary>
/// 记录支付流水
/// </summary>
Task<bool> RecordPaymentAsync(int userId, string orderNo, decimal amount, int payType, string content);
}
Data Models
Request/Response Models
// 微信支付请求
public class WechatPayRequest
{
public string OrderNo { get; set; }
public decimal Amount { get; set; }
public string Body { get; set; }
public string Attach { get; set; }
public string OpenId { get; set; }
public int UserId { get; set; }
}
// 微信支付结果
public class WechatPayResult
{
public int Status { get; set; }
public string Msg { get; set; }
public WechatPayData Data { get; set; }
}
public class WechatPayData
{
[JsonPropertyName("appId")]
public string AppId { get; set; }
[JsonPropertyName("timeStamp")]
public string TimeStamp { get; set; }
[JsonPropertyName("nonceStr")]
public string NonceStr { get; set; }
[JsonPropertyName("package")]
public string Package { get; set; }
[JsonPropertyName("signType")]
public string SignType { get; set; }
[JsonPropertyName("paySign")]
public string PaySign { get; set; }
[JsonPropertyName("is_weixin")]
public int IsWeixin { get; set; }
}
// 支付回调通知结果
public class NotifyResult
{
public bool Success { get; set; }
public string Message { get; set; }
public string XmlResponse { get; set; }
}
Database Entities
// 支付通知记录表
public class OrderNotify
{
public int Id { get; set; }
public string OrderNo { get; set; }
public string NotifyUrl { get; set; }
public string NonceStr { get; set; }
public DateTime PayTime { get; set; }
public decimal PayAmount { get; set; }
public int Status { get; set; }
public int RetryCount { get; set; }
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
}
Correctness Properties
A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.
Property 1: 支付签名正确性
For any set of payment parameters and secret key, generating a signature and then verifying it with the same parameters should return true.
Validates: Requirements 1.4, 7.1, 7.2
Property 2: 支付回调幂等性
For any payment notification, processing it multiple times should produce the same result as processing it once (order status should not change after first successful processing).
Validates: Requirements 2.8
Property 3: 资产扣减原子性
For any mixed payment transaction, either all asset deductions succeed or none of them succeed (transaction rollback on failure).
Validates: Requirements 6.7
Property 4: 余额扣减正确性
For any balance payment, the user's balance after payment should equal the original balance minus the payment amount.
Validates: Requirements 3.3, 3.4
Property 5: 支付记录完整性
For any successful payment, there should be a corresponding record in the profit_pay table with correct order number, amount, and payment type.
Validates: Requirements 8.1, 8.2
Error Handling
Payment Errors
| Error Code | Description | Handling |
|---|---|---|
| NOTENOUGH | 余额不足 | 返回错误提示,不扣款 |
| SIGNERROR | 签名错误 | 拒绝请求,记录日志 |
| ORDERPAID | 订单已支付 | 返回成功,不重复处理 |
| SYSTEMERROR | 系统错误 | 重试或返回错误 |
Transaction Handling
public async Task<bool> ProcessPaymentAsync(PaymentRequest request)
{
using var transaction = await _context.Database.BeginTransactionAsync();
try
{
// 1. 验证订单状态
// 2. 扣减用户资产
// 3. 更新订单状态
// 4. 记录支付流水
// 5. 触发后续业务(抽奖等)
await transaction.CommitAsync();
return true;
}
catch (Exception ex)
{
await transaction.RollbackAsync();
_logger.LogError(ex, "Payment processing failed");
throw;
}
}
Testing Strategy
Unit Tests
- 测试签名生成和验证逻辑
- 测试余额/积分/哈尼券扣减逻辑
- 测试支付参数构建逻辑
Property-Based Tests
- 使用FsCheck或类似库测试签名的正确性
- 测试支付回调的幂等性
- 测试资产扣减的原子性
Integration Tests
- 测试完整的支付流程
- 测试支付回调处理流程
- 测试混合支付场景
Test Configuration
- 使用InMemory数据库进行单元测试
- 使用测试商户配置进行集成测试
- 模拟微信支付API响应