diff --git a/.kiro/settings/mcp.json b/.kiro/settings/mcp.json
index 19d6a71f..df158fef 100644
--- a/.kiro/settings/mcp.json
+++ b/.kiro/settings/mcp.json
@@ -46,7 +46,7 @@
"mysql": {
"command": "node",
"args": [
- "D:/CodeManage/HaniBlindBox/server/scripts/mysql-mcp-server/index.js"
+ "D:/outsource/HaniBlindBox/server/scripts/mysql-mcp-server/index.js"
],
"env": {
"MYSQL_HOST": "192.168.195.16",
@@ -62,7 +62,7 @@
"sqlserver": {
"command": "node",
"args": [
- "D:/CodeManage/HaniBlindBox/server/scripts/mssql-mcp-server/index.js"
+ "D:/outsource/HaniBlindBox/server/scripts/mssql-mcp-server/index.js"
],
"env": {
"MSSQL_SERVER": "192.168.195.15",
@@ -78,7 +78,7 @@
"admin-sqlserver": {
"command": "node",
"args": [
- "D:/CodeManage/HaniBlindBox/server/scripts/mssql-mcp-server/index.js"
+ "D:/outsource/HaniBlindBox/server/scripts/mssql-mcp-server/index.js"
],
"env": {
"MSSQL_SERVER": "192.168.195.15",
diff --git a/.kiro/specs/wechat-pay-v3-upgrade/design.md b/.kiro/specs/wechat-pay-v3-upgrade/design.md
new file mode 100644
index 00000000..9109e0c3
--- /dev/null
+++ b/.kiro/specs/wechat-pay-v3-upgrade/design.md
@@ -0,0 +1,630 @@
+# Design Document: 微信支付 V3 升级
+
+## Overview
+
+本设计文档描述将微信支付从 V2 版本升级到 V3 版本的技术方案。V3 版本使用更安全的 RSA-SHA256 签名算法和 AES-256-GCM 加密,替代 V2 的 MD5 签名和 XML 格式。
+
+### 核心变更
+
+| 特性 | V2 版本 | V3 版本 |
+|------|---------|---------|
+| 数据格式 | XML | JSON |
+| 签名算法 | MD5 | RSA-SHA256 |
+| 认证方式 | API密钥 | 商户API证书 + 微信支付公钥 |
+| 回调解密 | 无加密 | AES-256-GCM |
+
+## Architecture
+
+### 整体架构
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ 小程序前端 │
+│ (honey_box/common/server/pay.js) │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ API 层 │
+│ (HoneyBox.Api) │
+│ ┌─────────────────────────────────────────────────────────┐ │
+│ │ PayController │ │
+│ │ - CreatePayment() → 根据配置选择 V2/V3 │ │
+│ │ - NotifyCallback() → 自动识别 V2/V3 格式 │ │
+│ └─────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ Core 层 │
+│ (HoneyBox.Core) │
+│ ┌──────────────────────┐ ┌──────────────────────┐ │
+│ │ IWechatPayService │ │ IWechatPayV3Service │ (新增) │
+│ │ (V2 实现) │ │ (V3 实现) │ │
+│ └──────────────────────┘ └──────────────────────┘ │
+│ │ │ │
+│ └────────────┬───────────┘ │
+│ ▼ │
+│ ┌─────────────────────────────────────────────────────────┐ │
+│ │ IWechatPayConfigService │ │
+│ │ - GetMerchantByOrderNo() → 返回包含 PayVersion 的配置 │ │
+│ └─────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ 微信支付平台 │
+│ V2: https://api.mch.weixin.qq.com/pay/unifiedorder │
+│ V3: https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+### 版本路由策略
+
+```
+支付请求 → 获取商户配置 → 检查 PayVersion
+ │
+ ┌───────────────┴───────────────┐
+ ▼ ▼
+ PayVersion = "V2" PayVersion = "V3"
+ │ │
+ ▼ ▼
+ WechatPayService.CreatePaymentAsync() WechatPayV3Service.CreateJsapiOrderAsync()
+ │ │
+ ▼ ▼
+ XML + MD5签名 JSON + RSA签名
+```
+
+## Components and Interfaces
+
+### 1. 配置模型扩展
+
+#### WeixinPayMerchant (扩展)
+
+```csharp
+// 文件: HoneyBox.Admin.Business/Models/Config/ConfigModels.cs
+
+public class WeixinPayMerchant
+{
+ // 现有字段保持不变
+ [JsonPropertyName("name")]
+ public string Name { get; set; } = string.Empty;
+
+ [JsonPropertyName("mch_id")]
+ public string MchId { get; set; } = string.Empty;
+
+ [JsonPropertyName("order_prefix")]
+ public string OrderPrefix { get; set; } = string.Empty;
+
+ [JsonPropertyName("api_key")]
+ public string? ApiKey { get; set; }
+
+ [JsonPropertyName("is_enabled")]
+ public string? IsEnabled { get; set; }
+
+ // ===== V3 新增字段 =====
+
+ ///
+ /// 支付版本: "V2" 或 "V3",默认 "V2"
+ ///
+ [JsonPropertyName("pay_version")]
+ public string PayVersion { get; set; } = "V2";
+
+ ///
+ /// APIv3 密钥(32位字符串)
+ ///
+ [JsonPropertyName("api_v3_key")]
+ public string? ApiV3Key { get; set; }
+
+ ///
+ /// 商户API证书序列号
+ ///
+ [JsonPropertyName("cert_serial_no")]
+ public string? CertSerialNo { get; set; }
+
+ ///
+ /// 商户私钥文件路径
+ ///
+ [JsonPropertyName("private_key_path")]
+ public string? PrivateKeyPath { get; set; }
+
+ ///
+ /// 微信支付公钥ID
+ ///
+ [JsonPropertyName("wechat_public_key_id")]
+ public string? WechatPublicKeyId { get; set; }
+
+ ///
+ /// 微信支付公钥文件路径
+ ///
+ [JsonPropertyName("wechat_public_key_path")]
+ public string? WechatPublicKeyPath { get; set; }
+}
+```
+
+#### WechatPayMerchantConfig (扩展)
+
+```csharp
+// 文件: HoneyBox.Model/Models/Payment/PaymentModels.cs
+
+public class WechatPayMerchantConfig
+{
+ // 现有字段保持不变
+ public string Name { get; set; } = string.Empty;
+ public string MchId { get; set; } = string.Empty;
+ public string AppId { get; set; } = string.Empty;
+ public string Key { get; set; } = string.Empty;
+ public string OrderPrefix { get; set; } = string.Empty;
+ public int Weight { get; set; } = 1;
+ public string NotifyUrl { get; set; } = string.Empty;
+
+ // ===== V3 新增字段 =====
+ public string PayVersion { get; set; } = "V2";
+ public string? ApiV3Key { get; set; }
+ public string? CertSerialNo { get; set; }
+ public string? PrivateKeyPath { get; set; }
+ public string? WechatPublicKeyId { get; set; }
+ public string? WechatPublicKeyPath { get; set; }
+}
+```
+
+### 2. V3 支付服务接口
+
+```csharp
+// 文件: HoneyBox.Core/Interfaces/IWechatPayV3Service.cs (新建)
+
+public interface IWechatPayV3Service
+{
+ ///
+ /// 创建 JSAPI 下单(小程序支付)
+ ///
+ Task CreateJsapiOrderAsync(WechatPayRequest request);
+
+ ///
+ /// 查询订单状态
+ ///
+ Task QueryOrderAsync(string orderNo);
+
+ ///
+ /// 关闭订单
+ ///
+ Task CloseOrderAsync(string orderNo);
+
+ ///
+ /// 申请退款
+ ///
+ Task RefundAsync(WechatPayV3RefundRequest request);
+
+ ///
+ /// 验证回调签名
+ ///
+ bool VerifyNotifySignature(string timestamp, string nonce, string body, string signature, string serialNo);
+
+ ///
+ /// 解密回调数据
+ ///
+ string DecryptNotifyResource(string ciphertext, string nonce, string associatedData, string apiV3Key);
+
+ ///
+ /// 生成 V3 请求签名
+ ///
+ string GenerateSignature(string method, string url, string timestamp, string nonce, string body, string privateKey);
+}
+```
+
+### 3. V3 请求/响应模型
+
+```csharp
+// 文件: HoneyBox.Model/Models/Payment/WechatPayV3Models.cs (新建)
+
+///
+/// V3 JSAPI 下单请求
+///
+public class WechatPayV3JsapiRequest
+{
+ [JsonPropertyName("appid")]
+ public string AppId { get; set; } = string.Empty;
+
+ [JsonPropertyName("mchid")]
+ public string MchId { get; set; } = string.Empty;
+
+ [JsonPropertyName("description")]
+ public string Description { get; set; } = string.Empty;
+
+ [JsonPropertyName("out_trade_no")]
+ public string OutTradeNo { get; set; } = string.Empty;
+
+ [JsonPropertyName("notify_url")]
+ public string NotifyUrl { get; set; } = string.Empty;
+
+ [JsonPropertyName("amount")]
+ public WechatPayV3Amount Amount { get; set; } = new();
+
+ [JsonPropertyName("payer")]
+ public WechatPayV3Payer Payer { get; set; } = new();
+
+ [JsonPropertyName("attach")]
+ public string? Attach { get; set; }
+}
+
+///
+/// V3 金额信息
+///
+public class WechatPayV3Amount
+{
+ [JsonPropertyName("total")]
+ public int Total { get; set; }
+
+ [JsonPropertyName("currency")]
+ public string Currency { get; set; } = "CNY";
+}
+
+///
+/// V3 支付者信息
+///
+public class WechatPayV3Payer
+{
+ [JsonPropertyName("openid")]
+ public string OpenId { get; set; } = string.Empty;
+}
+
+///
+/// V3 下单响应
+///
+public class WechatPayV3JsapiResponse
+{
+ [JsonPropertyName("prepay_id")]
+ public string PrepayId { get; set; } = string.Empty;
+}
+
+///
+/// V3 回调通知
+///
+public class WechatPayV3Notification
+{
+ [JsonPropertyName("id")]
+ public string Id { get; set; } = string.Empty;
+
+ [JsonPropertyName("create_time")]
+ public string CreateTime { get; set; } = string.Empty;
+
+ [JsonPropertyName("event_type")]
+ public string EventType { get; set; } = string.Empty;
+
+ [JsonPropertyName("resource_type")]
+ public string ResourceType { get; set; } = string.Empty;
+
+ [JsonPropertyName("resource")]
+ public WechatPayV3Resource Resource { get; set; } = new();
+}
+
+///
+/// V3 回调资源(加密数据)
+///
+public class WechatPayV3Resource
+{
+ [JsonPropertyName("algorithm")]
+ public string Algorithm { get; set; } = string.Empty;
+
+ [JsonPropertyName("ciphertext")]
+ public string Ciphertext { get; set; } = string.Empty;
+
+ [JsonPropertyName("nonce")]
+ public string Nonce { get; set; } = string.Empty;
+
+ [JsonPropertyName("associated_data")]
+ public string AssociatedData { get; set; } = string.Empty;
+}
+
+///
+/// V3 解密后的支付结果
+///
+public class WechatPayV3PaymentResult
+{
+ [JsonPropertyName("appid")]
+ public string AppId { get; set; } = string.Empty;
+
+ [JsonPropertyName("mchid")]
+ public string MchId { get; set; } = string.Empty;
+
+ [JsonPropertyName("out_trade_no")]
+ public string OutTradeNo { get; set; } = string.Empty;
+
+ [JsonPropertyName("transaction_id")]
+ public string TransactionId { get; set; } = string.Empty;
+
+ [JsonPropertyName("trade_state")]
+ public string TradeState { get; set; } = string.Empty;
+
+ [JsonPropertyName("trade_state_desc")]
+ public string TradeStateDesc { get; set; } = string.Empty;
+
+ [JsonPropertyName("success_time")]
+ public string SuccessTime { get; set; } = string.Empty;
+
+ [JsonPropertyName("payer")]
+ public WechatPayV3Payer Payer { get; set; } = new();
+
+ [JsonPropertyName("amount")]
+ public WechatPayV3PaymentAmount Amount { get; set; } = new();
+}
+
+///
+/// V3 支付金额(回调)
+///
+public class WechatPayV3PaymentAmount
+{
+ [JsonPropertyName("total")]
+ public int Total { get; set; }
+
+ [JsonPropertyName("payer_total")]
+ public int PayerTotal { get; set; }
+
+ [JsonPropertyName("currency")]
+ public string Currency { get; set; } = "CNY";
+}
+
+///
+/// V3 退款请求
+///
+public class WechatPayV3RefundRequest
+{
+ public string OrderNo { get; set; } = string.Empty;
+ public string RefundNo { get; set; } = string.Empty;
+ public string? Reason { get; set; }
+ public int TotalAmount { get; set; }
+ public int RefundAmount { get; set; }
+}
+
+///
+/// V3 查询结果
+///
+public class WechatPayV3QueryResult
+{
+ public bool Success { get; set; }
+ public string TradeState { get; set; } = string.Empty;
+ public string TradeStateDesc { get; set; } = string.Empty;
+ public string? TransactionId { get; set; }
+ public string? ErrorCode { get; set; }
+ public string? ErrorMessage { get; set; }
+}
+
+///
+/// V3 关闭结果
+///
+public class WechatPayV3CloseResult
+{
+ public bool Success { get; set; }
+ public string? ErrorCode { get; set; }
+ public string? ErrorMessage { get; set; }
+}
+
+///
+/// V3 退款结果
+///
+public class WechatPayV3RefundResult
+{
+ public bool Success { get; set; }
+ public string? RefundId { get; set; }
+ public string? Status { get; set; }
+ public string? ErrorCode { get; set; }
+ public string? ErrorMessage { get; set; }
+}
+```
+
+## Data Models
+
+### 数据库配置存储
+
+配置存储在 `config` 表中,key 为 `weixinpay_setting`,value 为 JSON 格式:
+
+```json
+{
+ "merchants": [
+ {
+ "name": "商户名称",
+ "mch_id": "1738725801",
+ "order_prefix": "MYH",
+ "is_enabled": "1",
+ "api_key": "V2密钥(兼容)",
+
+ "pay_version": "V3",
+ "api_v3_key": "d1cxc0vXCUH2984901DxddPJMYqcwcnd",
+ "cert_serial_no": "证书序列号",
+ "private_key_path": "certs/1738725801/apiclient_key.pem",
+ "wechat_public_key_id": "PUB_KEY_ID_0117387258012026012500291641000801",
+ "wechat_public_key_path": "certs/1738725801/pub_key.pem"
+ }
+ ]
+}
+```
+
+### 证书文件存储
+
+证书文件存储在服务器的 `certs` 目录下:
+
+```
+server/HoneyBox/certs/
+└── 1738725801/ # 商户号目录
+ ├── apiclient_key.pem # 商户私钥
+ └── pub_key.pem # 微信支付公钥
+```
+
+## 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: 配置序列化 Round-Trip
+
+*For any* 有效的 `WeixinPayMerchant` 配置对象(包含 V2 或 V3 字段),序列化为 JSON 后再反序列化,应该得到与原始对象等价的配置。
+
+**Validates: Requirements 1.4, 1.5**
+
+### Property 2: V3 配置字段完整性
+
+*For any* PayVersion 为 "V3" 的商户配置,当配置加载成功时,ApiV3Key、CertSerialNo、PrivateKeyPath、WechatPublicKeyId、WechatPublicKeyPath 字段应该都能正确读取(非空或有默认值)。
+
+**Validates: Requirements 1.1, 1.2**
+
+### Property 3: V2 向后兼容性
+
+*For any* PayVersion 为 "V2" 的商户配置,ApiKey 字段应该能正确读取,且 V3 字段不影响 V2 功能。
+
+**Validates: Requirements 1.3**
+
+### Property 4: 版本路由正确性
+
+*For any* 支付请求,当商户配置的 PayVersion 为 "V3" 时,应该调用 V3 接口;当 PayVersion 为 "V2" 时,应该调用 V2 接口。
+
+**Validates: Requirements 3.1, 3.5**
+
+### Property 5: V3 请求签名正确性
+
+*For any* V3 请求数据,使用相同的私钥和参数生成的签名应该是确定性的(相同输入产生相同输出),且签名格式符合 RSA-SHA256 规范。
+
+**Validates: Requirements 3.3**
+
+### Property 6: V3 请求字段完整性
+
+*For any* V3 JSAPI 下单请求,构建的请求体应该包含所有必要字段:appid、mchid、description、out_trade_no、notify_url、amount、payer。
+
+**Validates: Requirements 3.2**
+
+### Property 7: V3 支付参数完整性
+
+*For any* 成功的 V3 下单响应,返回给前端的支付参数应该包含:timeStamp、nonceStr、package、signType(RSA)、paySign。
+
+**Validates: Requirements 3.4**
+
+### Property 8: 回调格式识别正确性
+
+*For any* 支付回调请求,当请求体为 JSON 格式且包含 resource 字段时,应该使用 V3 解密流程;当请求体为 XML 格式时,应该使用 V2 解密流程。
+
+**Validates: Requirements 4.1, 4.5**
+
+### Property 9: V3 回调解密 Round-Trip
+
+*For any* 有效的支付结果数据,使用 AES-256-GCM 加密后再解密,应该得到与原始数据等价的结果。
+
+**Validates: Requirements 4.3**
+
+### Property 10: V3 回调签名验证
+
+*For any* V3 回调请求,使用正确的微信支付公钥验证签名应该返回 true;使用错误的公钥或篡改的数据应该返回 false。
+
+**Validates: Requirements 4.2**
+
+### Property 11: 回调响应格式正确性
+
+*For any* 回调处理结果,V3 回调应该返回 JSON 格式响应,V2 回调应该返回 XML 格式响应。
+
+**Validates: Requirements 4.6**
+
+### Property 12: 部分退款金额正确性
+
+*For any* 部分退款请求,退款金额应该小于等于订单总金额,且退款请求中的金额字段应该正确设置。
+
+**Validates: Requirements 7.4**
+
+## Error Handling
+
+### 配置错误处理
+
+| 错误场景 | 处理方式 |
+|---------|---------|
+| V3 配置缺少必要字段 | 记录警告日志,回退到 V2 |
+| 私钥文件不存在 | 抛出配置异常,阻止启动 |
+| 公钥文件不存在 | 抛出配置异常,阻止启动 |
+| APIv3 密钥格式错误 | 记录错误日志,返回配置错误 |
+
+### 支付错误处理
+
+| 错误场景 | 处理方式 |
+|---------|---------|
+| V3 签名生成失败 | 记录错误日志,返回系统错误 |
+| V3 下单请求失败 | 解析错误码,返回友好提示 |
+| V3 回调验签失败 | 记录警告日志,返回失败响应 |
+| V3 回调解密失败 | 记录错误日志,返回失败响应 |
+
+### 错误码映射
+
+```csharp
+private static readonly Dictionary V3ErrorMessages = new()
+{
+ { "PARAM_ERROR", "参数错误" },
+ { "OUT_TRADE_NO_USED", "订单号已使用" },
+ { "ORDER_NOT_EXIST", "订单不存在" },
+ { "ORDER_CLOSED", "订单已关闭" },
+ { "SIGN_ERROR", "签名错误" },
+ { "MCH_NOT_EXISTS", "商户号不存在" },
+ { "APPID_MCHID_NOT_MATCH", "AppID和商户号不匹配" },
+ { "FREQUENCY_LIMITED", "请求频率超限" },
+ { "SYSTEM_ERROR", "系统错误" }
+};
+```
+
+## Testing Strategy
+
+### 单元测试
+
+1. **配置模型测试**
+ - 测试 V3 字段序列化/反序列化
+ - 测试 V2 向后兼容性
+ - 测试配置验证逻辑
+
+2. **签名算法测试**
+ - 测试 RSA-SHA256 签名生成
+ - 测试签名验证
+ - 测试签名字符串构建
+
+3. **加解密测试**
+ - 测试 AES-256-GCM 加密
+ - 测试 AES-256-GCM 解密
+ - 测试解密失败场景
+
+### 属性测试
+
+使用 FsCheck 进行属性测试:
+
+```csharp
+// 配置 round-trip 测试
+[Property]
+public Property ConfigRoundTrip()
+{
+ return Prop.ForAll(
+ Arb.From(),
+ config =>
+ {
+ var json = JsonSerializer.Serialize(config);
+ var deserialized = JsonSerializer.Deserialize(json);
+ return config.Equals(deserialized);
+ });
+}
+
+// 签名确定性测试
+[Property]
+public Property SignatureDeterministic()
+{
+ return Prop.ForAll(
+ Arb.From(), // method
+ Arb.From(), // url
+ Arb.From(), // body
+ (method, url, body) =>
+ {
+ var sign1 = service.GenerateSignature(method, url, timestamp, nonce, body, privateKey);
+ var sign2 = service.GenerateSignature(method, url, timestamp, nonce, body, privateKey);
+ return sign1 == sign2;
+ });
+}
+```
+
+### 集成测试
+
+1. **支付流程测试**
+ - 测试 V3 下单流程(使用 Mock)
+ - 测试 V3 回调处理
+ - 测试版本路由逻辑
+
+2. **后台配置测试**
+ - 测试配置保存和加载
+ - 测试 V2/V3 切换
diff --git a/.kiro/specs/wechat-pay-v3-upgrade/requirements.md b/.kiro/specs/wechat-pay-v3-upgrade/requirements.md
new file mode 100644
index 00000000..b6131f13
--- /dev/null
+++ b/.kiro/specs/wechat-pay-v3-upgrade/requirements.md
@@ -0,0 +1,101 @@
+# Requirements Document
+
+## Introduction
+
+将现有的微信支付从 V2 版本升级到 V3 版本,以支持更安全的 RSA-SHA256 签名和 AES-GCM 加密。当前系统使用 V2 版本(XML格式、MD5签名),需要升级到 V3 版本(JSON格式、RSA-SHA256签名)以满足微信支付的最新安全要求。
+
+## Glossary
+
+- **WechatPay_V2**: 微信支付 V2 版本,使用 XML 数据格式和 MD5 签名算法
+- **WechatPay_V3**: 微信支付 V3 版本,使用 JSON 数据格式和 RSA-SHA256 签名算法
+- **APIv3_Key**: 微信支付 V3 版本的 API 密钥,用于 AES-GCM 解密回调通知
+- **Merchant_Private_Key**: 商户 API 私钥,用于请求签名
+- **Wechat_Public_Key**: 微信支付平台公钥,用于验证回调签名
+- **JSAPI_Payment**: 小程序/公众号内支付方式
+- **Payment_Callback**: 微信支付结果异步通知
+- **Config_System**: 后台配置管理系统,存储支付参数到数据库
+
+## Requirements
+
+### Requirement 1: V3 配置模型扩展
+
+**User Story:** As a 开发者, I want 后端配置模型支持 V3 字段, so that 系统能够存储和读取 V3 支付配置。
+
+#### Acceptance Criteria
+
+1. WHEN 系统加载微信支付配置 THEN THE Config_System SHALL 支持读取 PayVersion 字段(值为 "V2" 或 "V3")
+2. WHEN PayVersion 为 "V3" THEN THE Config_System SHALL 读取以下字段:ApiV3Key、CertSerialNo、PrivateKeyPath、WechatPublicKeyId、WechatPublicKeyPath
+3. WHEN PayVersion 为 "V2" THEN THE Config_System SHALL 保持原有字段兼容(ApiKey)
+4. WHEN 配置保存时 THEN THE Config_System SHALL 正确序列化 V3 字段到 JSON 格式
+5. WHEN 配置加载时 THEN THE Config_System SHALL 正确反序列化 V3 字段
+
+### Requirement 2: 后台管理页面配置
+
+**User Story:** As a 系统管理员, I want 在后台管理页面配置微信支付 V3 参数, so that 系统能够使用 V3 接口进行支付。
+
+#### Acceptance Criteria
+
+1. WHEN 管理员打开微信支付配置页面 THEN THE Admin_System SHALL 显示「支付版本」选择项(V2/V3)
+2. WHEN 管理员选择 V3 版本 THEN THE Admin_System SHALL 显示 V3 专属配置项:APIv3密钥、证书序列号、商户私钥路径、微信支付公钥ID、微信支付公钥路径
+3. WHEN 管理员选择 V2 版本 THEN THE Admin_System SHALL 隐藏 V3 配置项并显示 V2 配置项
+4. WHEN 管理员保存配置 THEN THE Admin_System SHALL 验证必填字段并保存到数据库
+5. WHEN 页面加载时 THEN THE Admin_System SHALL 正确回显已保存的配置值
+
+### Requirement 3: V3 JSAPI 下单接口
+
+**User Story:** As a 小程序用户, I want 使用 V3 接口发起支付, so that 完成商品购买。
+
+#### Acceptance Criteria
+
+1. WHEN 用户发起支付请求且商户配置为 V3 THEN THE WechatPay_V3 SHALL 调用 V3 JSAPI 下单接口
+2. WHEN 构建 V3 请求 THEN THE WechatPay_V3 SHALL 使用 JSON 格式并包含:appid、mchid、description、out_trade_no、notify_url、amount、payer
+3. WHEN 签名 V3 请求 THEN THE WechatPay_V3 SHALL 使用 RSA-SHA256 算法对请求进行签名
+4. WHEN 下单成功 THEN THE WechatPay_V3 SHALL 返回小程序调起支付所需参数:timeStamp、nonceStr、package、signType(RSA)、paySign
+5. WHEN 商户配置为 V2 THEN THE WechatPay_V3 SHALL 回退到 V2 接口处理
+
+### Requirement 4: V3 支付回调处理
+
+**User Story:** As a 系统, I want 正确解密 V3 支付回调通知, so that 更新订单支付状态。
+
+#### Acceptance Criteria
+
+1. WHEN 收到 V3 格式回调(JSON格式且包含 resource 字段)THEN THE Payment_Callback SHALL 使用 V3 解密流程
+2. WHEN 验证 V3 回调签名 THEN THE Payment_Callback SHALL 使用微信支付公钥验证 Wechatpay-Signature 头
+3. WHEN 解密 V3 回调数据 THEN THE Payment_Callback SHALL 使用 AES-256-GCM 算法和 APIv3 密钥解密 resource.ciphertext
+4. WHEN 解密成功 THEN THE Payment_Callback SHALL 提取订单号和支付状态并更新订单
+5. WHEN 收到 V2 格式回调(XML格式)THEN THE Payment_Callback SHALL 使用 V2 解密流程
+6. WHEN 回调处理成功 THEN THE Payment_Callback SHALL 返回正确的响应格式(V3: JSON, V2: XML)
+
+### Requirement 5: V3 订单查询
+
+**User Story:** As a 系统, I want 使用 V3 接口查询订单状态, so that 处理支付超时和异常情况。
+
+#### Acceptance Criteria
+
+1. WHEN 查询订单且商户配置为 V3 THEN THE WechatPay_V3 SHALL 调用 V3 订单查询接口
+2. WHEN 构建查询请求 THEN THE WechatPay_V3 SHALL 使用商户订单号作为路径参数
+3. WHEN 查询成功 THEN THE WechatPay_V3 SHALL 解析返回的订单状态(SUCCESS、NOTPAY、CLOSED 等)
+4. IF 查询失败 THEN THE WechatPay_V3 SHALL 返回错误信息并记录日志
+
+### Requirement 6: V3 订单关闭
+
+**User Story:** As a 系统, I want 使用 V3 接口关闭未支付订单, so that 释放库存和资源。
+
+#### Acceptance Criteria
+
+1. WHEN 关闭订单且商户配置为 V3 THEN THE WechatPay_V3 SHALL 调用 V3 订单关闭接口
+2. WHEN 构建关闭请求 THEN THE WechatPay_V3 SHALL 使用商户订单号作为路径参数并包含 mchid
+3. WHEN 关闭成功 THEN THE WechatPay_V3 SHALL 返回成功状态(HTTP 204)
+4. IF 关闭失败 THEN THE WechatPay_V3 SHALL 返回错误信息并记录日志
+
+### Requirement 7: V3 退款接口
+
+**User Story:** As a 系统管理员, I want 使用 V3 接口发起退款, so that 处理用户退款请求。
+
+#### Acceptance Criteria
+
+1. WHEN 发起退款且商户配置为 V3 THEN THE WechatPay_V3 SHALL 调用 V3 退款接口
+2. WHEN 构建退款请求 THEN THE WechatPay_V3 SHALL 包含:out_trade_no、out_refund_no、reason、notify_url、amount
+3. WHEN 退款成功 THEN THE WechatPay_V3 SHALL 返回退款单号和状态
+4. THE WechatPay_V3 SHALL 支持部分退款(退款金额小于订单金额)
+5. IF 退款失败 THEN THE WechatPay_V3 SHALL 返回错误信息并记录日志
diff --git a/.kiro/specs/wechat-pay-v3-upgrade/tasks.md b/.kiro/specs/wechat-pay-v3-upgrade/tasks.md
new file mode 100644
index 00000000..5c675747
--- /dev/null
+++ b/.kiro/specs/wechat-pay-v3-upgrade/tasks.md
@@ -0,0 +1,154 @@
+# Implementation Plan: 微信支付 V3 升级
+
+## Overview
+
+本实现计划将微信支付从 V2 升级到 V3,采用增量开发方式,确保 V2 功能不受影响。实现顺序:配置模型 → V3 服务 → 回调处理 → 后台管理页面。
+
+## Tasks
+
+- [ ] 1. 扩展配置模型支持 V3 字段
+ - [ ] 1.1 扩展 WeixinPayMerchant 模型添加 V3 字段
+ - 在 `HoneyBox.Admin.Business/Models/Config/ConfigModels.cs` 中添加 V3 字段
+ - 字段:PayVersion、ApiV3Key、CertSerialNo、PrivateKeyPath、WechatPublicKeyId、WechatPublicKeyPath
+ - _Requirements: 1.1, 1.2, 1.3_
+ - [ ] 1.2 扩展 WechatPayMerchantConfig 模型添加 V3 字段
+ - 在 `HoneyBox.Model/Models/Payment/PaymentModels.cs` 中添加对应字段
+ - _Requirements: 1.1, 1.2_
+ - [ ] 1.3 更新 WechatPayConfigService 支持 V3 配置映射
+ - 在配置加载时映射 V3 字段
+ - _Requirements: 1.4, 1.5_
+ - [ ] 1.4 编写配置序列化 round-trip 属性测试
+ - **Property 1: 配置序列化 Round-Trip**
+ - **Validates: Requirements 1.4, 1.5**
+
+- [ ] 2. 创建 V3 支付数据模型
+ - [ ] 2.1 创建 WechatPayV3Models.cs 文件
+ - 在 `HoneyBox.Model/Models/Payment/` 目录下创建
+ - 包含:WechatPayV3JsapiRequest、WechatPayV3Amount、WechatPayV3Payer、WechatPayV3JsapiResponse
+ - _Requirements: 3.2_
+ - [ ] 2.2 创建 V3 回调通知模型
+ - 包含:WechatPayV3Notification、WechatPayV3Resource、WechatPayV3PaymentResult
+ - _Requirements: 4.3, 4.4_
+ - [ ] 2.3 创建 V3 查询、关闭、退款结果模型
+ - 包含:WechatPayV3QueryResult、WechatPayV3CloseResult、WechatPayV3RefundResult、WechatPayV3RefundRequest
+ - _Requirements: 5.3, 6.3, 7.3_
+
+- [ ] 3. 实现 V3 支付服务核心功能
+ - [ ] 3.1 创建 IWechatPayV3Service 接口
+ - 在 `HoneyBox.Core/Interfaces/` 目录下创建
+ - 定义:CreateJsapiOrderAsync、QueryOrderAsync、CloseOrderAsync、RefundAsync
+ - _Requirements: 3.1, 5.1, 6.1, 7.1_
+ - [ ] 3.2 实现 V3 签名生成方法
+ - 实现 RSA-SHA256 签名算法
+ - 签名字符串格式:HTTP方法\nURL\n时间戳\n随机串\n请求体\n
+ - _Requirements: 3.3_
+ - [ ] 3.3 编写签名确定性属性测试
+ - **Property 5: V3 请求签名正确性**
+ - **Validates: Requirements 3.3**
+ - [ ] 3.4 实现 CreateJsapiOrderAsync 方法
+ - 构建 V3 JSAPI 下单请求
+ - 调用微信 V3 API
+ - 返回小程序支付参数
+ - _Requirements: 3.2, 3.4_
+ - [ ] 3.5 编写请求字段完整性属性测试
+ - **Property 6: V3 请求字段完整性**
+ - **Validates: Requirements 3.2**
+
+- [ ] 4. Checkpoint - 确保 V3 下单功能测试通过
+ - 运行所有测试,确保通过
+ - 如有问题请询问用户
+
+- [ ] 5. 实现 V3 回调处理
+ - [ ] 5.1 实现回调签名验证方法
+ - 使用微信支付公钥验证 Wechatpay-Signature 头
+ - _Requirements: 4.2_
+ - [ ] 5.2 实现 AES-256-GCM 解密方法
+ - 解密 resource.ciphertext 字段
+ - 使用 APIv3 密钥作为解密密钥
+ - _Requirements: 4.3_
+ - [ ] 5.3 编写解密 round-trip 属性测试
+ - **Property 9: V3 回调解密 Round-Trip**
+ - **Validates: Requirements 4.3**
+ - [ ] 5.4 实现回调格式自动识别
+ - JSON 格式且包含 resource 字段 → V3 流程
+ - XML 格式 → V2 流程
+ - _Requirements: 4.1, 4.5_
+ - [ ] 5.5 编写回调格式识别属性测试
+ - **Property 8: 回调格式识别正确性**
+ - **Validates: Requirements 4.1, 4.5**
+ - [ ] 5.6 更新 PaymentNotifyService 支持 V3 回调
+ - 在现有回调处理中添加 V3 分支
+ - _Requirements: 4.4, 4.6_
+
+- [ ] 6. 实现 V3 订单查询和关闭
+ - [ ] 6.1 实现 QueryOrderAsync 方法
+ - 调用 V3 订单查询接口
+ - 解析订单状态
+ - _Requirements: 5.1, 5.2, 5.3_
+ - [ ] 6.2 实现 CloseOrderAsync 方法
+ - 调用 V3 订单关闭接口
+ - 处理 HTTP 204 响应
+ - _Requirements: 6.1, 6.2, 6.3_
+
+- [ ] 7. 实现 V3 退款接口
+ - [ ] 7.1 实现 RefundAsync 方法
+ - 调用 V3 退款接口
+ - 支持部分退款
+ - _Requirements: 7.1, 7.2, 7.3, 7.4_
+ - [ ] 7.2 编写部分退款金额属性测试
+ - **Property 12: 部分退款金额正确性**
+ - **Validates: Requirements 7.4**
+
+- [ ] 8. 实现版本路由逻辑
+ - [ ] 8.1 更新 WechatPayService 支持版本路由
+ - 根据商户配置的 PayVersion 选择 V2 或 V3 服务
+ - _Requirements: 3.1, 3.5_
+ - [ ] 8.2 编写版本路由属性测试
+ - **Property 4: 版本路由正确性**
+ - **Validates: Requirements 3.1, 3.5**
+ - [ ] 8.3 注册 V3 服务到依赖注入容器
+ - 在 ServiceModule.cs 中注册 IWechatPayV3Service
+ - _Requirements: 3.1_
+
+- [ ] 9. Checkpoint - 确保后端 V3 功能完整
+ - 运行所有测试,确保通过
+ - 如有问题请询问用户
+
+- [ ] 10. 更新后台管理页面
+ - [ ] 10.1 更新前端配置接口类型定义
+ - 在 `admin-web/src/api/business/config.ts` 中添加 V3 字段
+ - _Requirements: 2.1_
+ - [ ] 10.2 更新微信商户配置表单组件
+ - 在 `admin-web/src/views/business/config/components/WeixinMerchantForm.vue` 中添加 V3 配置项
+ - 添加支付版本选择(V2/V3)
+ - 根据版本显示/隐藏对应配置项
+ - _Requirements: 2.1, 2.2, 2.3_
+ - [ ] 10.3 实现配置验证逻辑
+ - V3 版本时验证必填字段
+ - _Requirements: 2.4_
+ - [ ] 10.4 测试配置保存和回显
+ - 确保配置正确保存到数据库
+ - 确保页面加载时正确回显
+ - _Requirements: 2.4, 2.5_
+
+- [ ] 11. 准备证书文件
+ - [ ] 11.1 创建证书目录结构
+ - 创建 `server/HoneyBox/certs/1738725801/` 目录
+ - _Requirements: 1.2_
+ - [ ] 11.2 解压并放置证书文件
+ - 从 `微信支付商户号/商户API证书/` 解压获取 apiclient_key.pem
+ - 从 `微信支付商户号/微信支付公钥/` 复制 pub_key.pem
+ - _Requirements: 1.2_
+
+- [ ] 12. Final Checkpoint - 完整功能验证
+ - 运行所有测试,确保通过
+ - 验证 V2 功能不受影响
+ - 如有问题请询问用户
+
+## Notes
+
+- 所有任务均为必需,包括属性测试任务
+- 每个任务都引用了具体的需求条款以便追溯
+- Checkpoint 任务用于阶段性验证
+- 属性测试验证通用正确性属性
+- 单元测试验证具体示例和边界情况
diff --git a/honey_box/common/env.js b/honey_box/common/env.js
index 13f1ca9d..f192d080 100644
--- a/honey_box/common/env.js
+++ b/honey_box/common/env.js
@@ -11,8 +11,8 @@
// 测试环境配置 - .NET 10 后端
const testing = {
- // baseUrl: 'https://app.zpc-xy.com/honey/api',
- baseUrl: 'http://192.168.1.24:5238',
+ baseUrl: 'https://app.zpc-xy.com/honey/api',
+ // baseUrl: 'http://192.168.1.24:5238',
imageUrl: 'https://youdas-1308826010.cos.ap-shanghai.myqcloud.com',
loginPage: '',
wxAppId: ''
diff --git a/honey_box/common/platform/BasePlatform.js b/honey_box/common/platform/BasePlatform.js
index 1789787e..0a0b09e9 100644
--- a/honey_box/common/platform/BasePlatform.js
+++ b/honey_box/common/platform/BasePlatform.js
@@ -212,6 +212,32 @@ class BasePlatform {
* @param {Object} item 菜单项
*/
navigateToPath(item) {
+ // 需要登录才能访问的页面路径
+ const needLoginPaths = [
+ '/pages/other/order_list', // 消费记录
+ '/package/mine/collect', // 我的收藏
+ '/pages/user/coupon', // 优惠券
+ '/pages/user/tui-guang', // 邀请好友
+ '/pages/user/cancel-account-page', // 注销账号
+ ];
+
+ // 检查是否需要登录
+ const needLogin = needLoginPaths.some(path => item.path.startsWith(path));
+ if (needLogin) {
+ const token = uni.getStorageSync('token');
+ if (!token) {
+ uni.setStorageSync('redirect', item.path);
+ uni.showToast({
+ title: '请先登录',
+ icon: 'none'
+ });
+ setTimeout(() => {
+ navigateTo('/pages/user/login');
+ }, 100);
+ return;
+ }
+ }
+
navigateTo(item.path);
}
diff --git a/honey_box/common/request.js b/honey_box/common/request.js
index a6c44d35..57de238f 100644
--- a/honey_box/common/request.js
+++ b/honey_box/common/request.js
@@ -400,19 +400,32 @@ class RequestManager {
// 处理 HTTP 401 未授权(Token 过期或无效)
if (res.statusCode === 401) {
- console.log('Token过期或无效,尝试自动刷新');
+ console.log('Token过期或无效');
- // 白名单接口不进行自动刷新,直接拒绝
+ // 白名单接口直接返回错误,不处理
if (RequestManager.isUrlInWhitelist(requestUrl)) {
reject({ status: -1, msg: '登录已过期' });
return;
}
+ // 检查是否有 token(用户是否曾经登录过)
+ const currentToken = uni.getStorageSync('token');
+ if (!currentToken) {
+ // 用户从未登录过,直接返回错误,不跳转
+ console.log('用户未登录,返回错误');
+ reject({ status: -1, msg: '请先登录' });
+ return;
+ }
+
// 检查是否有 refreshToken
const refreshToken = uni.getStorageSync('refreshToken');
if (!refreshToken) {
- console.log('没有 refreshToken,直接跳转登录页');
- RequestManager.clearTokensAndRedirect();
+ console.log('没有 refreshToken,清除token并返回错误');
+ // 清除过期的token,但不跳转登录页
+ uni.removeStorageSync('token');
+ uni.removeStorageSync('accessToken');
+ uni.removeStorageSync('tokenExpireTime');
+ uni.removeStorageSync('userinfo');
reject({ status: -1, msg: '登录已过期' });
return;
}
@@ -443,9 +456,13 @@ class RequestManager {
// 处理队列中的其他请求
RequestManager.processRefreshQueue(true);
} else {
- console.log('Token 刷新失败,跳转登录页');
- // 刷新失败,清除 Token 并跳转登录页
- RequestManager.clearTokensAndRedirect();
+ console.log('Token 刷新失败');
+ // 刷新失败,清除 Token,但不跳转登录页
+ uni.removeStorageSync('token');
+ uni.removeStorageSync('accessToken');
+ uni.removeStorageSync('refreshToken');
+ uni.removeStorageSync('tokenExpireTime');
+ uni.removeStorageSync('userinfo');
reject({ status: -1, msg: '登录已过期' });
// 拒绝队列中的所有请求
@@ -455,7 +472,11 @@ class RequestManager {
.catch(error => {
console.error('Token 刷新异常:', error);
RequestManager.isRefreshing = false;
- RequestManager.clearTokensAndRedirect();
+ uni.removeStorageSync('token');
+ uni.removeStorageSync('accessToken');
+ uni.removeStorageSync('refreshToken');
+ uni.removeStorageSync('tokenExpireTime');
+ uni.removeStorageSync('userinfo');
reject({ status: -1, msg: '登录已过期' });
RequestManager.processRefreshQueue(false);
});
@@ -516,55 +537,22 @@ class RequestManager {
}
}
-
- // 获取当前页面路径和参数
- var currentPage = pages[pages.length - 1];
- if (currentPage) {
- var currentRoute = currentPage.route;
- var currentParams = currentPage.options || {};
-
- // 只有非登录页面才保存重定向信息
- if (currentRoute && currentRoute !== 'pages/user/login') {
- // 构建完整的重定向URL
- var redirectPath = '/' + currentRoute;
-
- // 如果有参数,拼接参数
- if (Object.keys(currentParams).length > 0) {
- var paramString = Object.keys(currentParams)
- .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(currentParams[key])}`)
- .join('&');
- redirectPath += '?' + paramString;
- }
-
- // 保存重定向URL到缓存
- console.log('保存重定向URL:', redirectPath);
- uni.setStorageSync('redirect', redirectPath);
- }
- }
-
+ // 白名单接口直接返回错误,不跳转登录页
console.log(requestUrl);
if (RequestManager.isUrlInWhitelist(requestUrl)) {
reject(res.data)
return;
}
- setTimeout(() => {
- uni.showToast({
- title: '请先登录',
- icon: 'none'
- })
- }, 100)
+
// 清除所有Token相关存储
uni.removeStorageSync('token');
uni.removeStorageSync('accessToken');
uni.removeStorageSync('refreshToken');
uni.removeStorageSync('tokenExpireTime');
uni.removeStorageSync('userinfo');
- // 使用新的路由守卫方法进行跳转
- RouterManager.navigateTo('/pages/user/login', {}, 'navigateTo')
- .catch(err => {
- console.error('登录页面跳转失败:', err);
- });
+ // 不再自动跳转登录页,只返回错误让调用方处理
+ // 调用方可以根据业务需要决定是否跳转登录页
reject(res.data)
} else {
reject(res.data)
diff --git a/honey_box/common/router.js b/honey_box/common/router.js
index 9b9778c9..23d57150 100644
--- a/honey_box/common/router.js
+++ b/honey_box/common/router.js
@@ -98,29 +98,9 @@ export function routerTo(options) {
url += (url.indexOf('?') === -1 ? '?' : '&') + queryString;
}
- // 检查是否需要登录
- const needLogin = !isInWhiteList(url);
-
- if (needLogin && !isLogin()) {
- // 需要登录但未登录,跳转到登录页面
- // 先保存当前URL用于登录后重定向
- uni.setStorageSync('redirect', url);
-
- // 使用navigateTo而非redirectTo,保留页面栈
- uni.navigateTo({
- url: '/pages/user/login',
- success: () => {
- console.log('跳转到登录页面成功,保存的重定向地址:', url);
- },
- fail: (err) => {
- console.error('跳转到登录页面失败:', err);
- reject(err);
- }
- });
-
- // 拒绝当前的导航请求
- return reject(new Error('需要登录'));
- }
+ // 移除路由层面的登录拦截
+ // 允许用户浏览所有页面,只在需要执行特定操作时才要求登录
+ // 登录检查应该在具体的业务操作中进行(如抽奖、下单等)
// 根据type选择跳转方式
if (type) {
@@ -251,5 +231,53 @@ export default {
navigateBack,
collectWhitePath,
getCollectedWhitePaths,
- clearCollectedWhitePaths
-};
\ No newline at end of file
+ clearCollectedWhitePaths,
+ requireLogin,
+ isLogin
+};
+
+/**
+ * 检查登录状态,未登录则跳转登录页
+ * 用于需要登录才能执行的操作(如抽奖、下单等)
+ * @param {String} message 提示消息,可选
+ * @returns {Boolean} true表示已登录,false表示未登录(会跳转登录页)
+ */
+export function requireLogin(message = '请先登录') {
+ if (isLogin()) {
+ return true;
+ }
+
+ // 保存当前页面用于登录后跳转
+ const pages = getCurrentPages();
+ const currentPage = pages[pages.length - 1];
+ if (currentPage) {
+ const currentRoute = currentPage.route;
+ const currentParams = currentPage.options || {};
+
+ if (currentRoute && currentRoute !== 'pages/user/login') {
+ let redirectPath = '/' + currentRoute;
+ if (Object.keys(currentParams).length > 0) {
+ const paramString = Object.keys(currentParams)
+ .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(currentParams[key])}`)
+ .join('&');
+ redirectPath += '?' + paramString;
+ }
+ uni.setStorageSync('redirect', redirectPath);
+ }
+ }
+
+ // 显示提示
+ uni.showToast({
+ title: message,
+ icon: 'none'
+ });
+
+ // 跳转登录页
+ setTimeout(() => {
+ uni.navigateTo({
+ url: '/pages/user/login'
+ });
+ }, 100);
+
+ return false;
+}
\ No newline at end of file
diff --git a/honey_box/pages/user/index.vue b/honey_box/pages/user/index.vue
index 55201c18..b58e6d84 100644
--- a/honey_box/pages/user/index.vue
+++ b/honey_box/pages/user/index.vue
@@ -51,25 +51,25 @@
-
+
{{ $config.getAppSetting('currency1_name') }}
{{ formatNumber(userinfo.integral) }}
-
+
{{ $config.getAppSetting('currency2_name') }}
{{ formatNumber(userinfo.money2) }}
-
+
{{ $config.getAppSetting('balance_name') }}
- 充值
+ 充值
{{ formatNumber(userinfo.money) }}
@@ -367,6 +367,25 @@
})
}
},
+ /**
+ * 跳转到财务相关页面(需要登录)
+ * @param {String} url - 页面路径
+ */
+ toFinancePage(url) {
+ const token = uni.getStorageSync('token');
+ if (!token) {
+ uni.setStorageSync('redirect', '/pages/user/index');
+ uni.showToast({
+ title: '请先登录',
+ icon: 'none'
+ });
+ setTimeout(() => {
+ this.$c.nav('/pages/user/login');
+ }, 100);
+ return;
+ }
+ this.$c.to({ url });
+ },
/**
* 格式化数字,如果小数部分是.00则只显示整数部分
* @param {Number|String} num - 要格式化的数字
diff --git a/server/HoneyBox/微信支付商户号/1738725801.txt b/server/HoneyBox/微信支付商户号/1738725801.txt
new file mode 100644
index 00000000..b87733b8
--- /dev/null
+++ b/server/HoneyBox/微信支付商户号/1738725801.txt
@@ -0,0 +1 @@
+商户号:1738725801
\ No newline at end of file
diff --git a/server/HoneyBox/微信支付商户号/微信支付公钥/pub_key.pem b/server/HoneyBox/微信支付商户号/微信支付公钥/pub_key.pem
new file mode 100644
index 00000000..d32530b0
--- /dev/null
+++ b/server/HoneyBox/微信支付商户号/微信支付公钥/pub_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0KeKMd6Yxovf4kPI0c1Q
+Islyq9fi/Wg60dodzPNkRRoraqmqbbW7uQcKHkHvIZi5Z9fK8SGkezyhcjiR3o8z
+uwnH5QiFuMw6P+1XB1koFfbxxCc6Eh0iuRI5BqNfyRwXwn9wIEUNwfF/SAPJGTkk
+hCzViil3tOmnJDMxQUJitt4RsnL6BvQ3afWcm7oqt7MLlcIhIW8jAsSFeWPuZcW5
+Hj+o2udrTUaTRkw7AEsHr9xyePhsqYjGxbi9fTlghkUYnRUNikSydtQoHbGHP70Q
+tz4HbPqH4gpsCqabPVuANFGH5a8uidOH3XKq2iPLggbPci1nFI8xMmHMaT88u/o5
+GQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/server/HoneyBox/微信支付商户号/微信支付公钥/公钥ID.txt b/server/HoneyBox/微信支付商户号/微信支付公钥/公钥ID.txt
new file mode 100644
index 00000000..dca63aa5
--- /dev/null
+++ b/server/HoneyBox/微信支付商户号/微信支付公钥/公钥ID.txt
@@ -0,0 +1 @@
+PUB_KEY_ID_0117387258012026012500291641000801
\ No newline at end of file
diff --git a/server/HoneyBox/微信支付商户号/解密回调APIv3密钥/解密回调APIV3密钥.txt b/server/HoneyBox/微信支付商户号/解密回调APIv3密钥/解密回调APIV3密钥.txt
new file mode 100644
index 00000000..2daa7419
--- /dev/null
+++ b/server/HoneyBox/微信支付商户号/解密回调APIv3密钥/解密回调APIV3密钥.txt
@@ -0,0 +1 @@
+d1cxc0vXCUH2984901DxddPJMYqcwcnd
\ No newline at end of file