# Transfer模块 - 划转系统 Transfer模块是农场游戏系统的资金划转核心模块,负责处理用户与外部系统之间的资金转入转出操作。 ## 📋 目录 - [核心概念](#核心概念) - [架构设计](#架构设计) - [金额转换逻辑](#金额转换逻辑) - [手续费机制](#手续费机制) - [手续费统计](#手续费统计) ⭐ - [第三方应用集成](#第三方应用集成) - [API接口](#api接口) - [数据库设计](#数据库设计) - [配置说明](#配置说明) - [使用示例](#使用示例) - [故障排除](#故障排除) ## 🎯 核心概念 ### 基本术语 | 术语 | 说明 | 示例 | |------|------|------| | **转入订单** | 用户充值/存入资金到农场系统 | URS用户充值100元到农场 | | **转出订单** | 用户提现/转出资金到外部系统 | 农场用户提现30000钻石到URS | | **外部金额** | 第三方系统的金额单位 | URS系统的100元 | | **内部金额** | 农场系统的钻石数量 | 农场系统的30000钻石 | | **汇率** | 外部金额与内部金额的转换比例 | 1元 = 300钻石 | ### 订单状态 ```php enum TransferStatus: int { case CREATED = 100; // 已创建 case PROCESSING = 200; // 处理中 case COMPLETED = 300; // 已完成 case FAILED = 400; // 失败 case CANCELLED = 500; // 已取消 } ``` ### 订单类型 ```php enum TransferType: int { case IN = 1; // 转入 case OUT = 2; // 转出 } ``` ## 🏗️ 架构设计 ### 模块结构 ``` app/Module/Transfer/ ├── Controllers/ # 后台管理控制器 ├── Dtos/ # 数据传输对象 ├── Enums/ # 枚举类 ├── Events/ # 事件类 ├── Handlers/ # API处理器 ├── Logics/ # 业务逻辑层 ├── Models/ # 数据模型 ├── Repositories/ # 数据仓库层 ├── Services/ # 服务层 ├── Validations/ # 验证类 └── Validators/ # 验证器 ``` ### 核心类说明 | 类名 | 职责 | 说明 | |------|------|------| | `TransferLogic` | 核心业务逻辑 | 处理转入转出订单创建和执行 | | `TransferThirdPartyService` | 第三方服务 | 专门处理第三方应用集成 | | `TransferApp` | 应用配置模型 | 管理划转应用配置和手续费计算 | | `TransferOrder` | 订单模型 | 划转订单数据模型 | | `OrderLogic` | 订单处理逻辑 | 处理订单状态变更和外部API调用 | | `CallbackLogic` | 回调处理逻辑 | 处理外部系统回调通知 | | `FeeStatisticsService` | 手续费统计服务 | 处理手续费统计、验证和数据分析 | | `TransferFeeDailyStats` | 手续费统计模型 | 手续费每日统计数据模型 | ## 💱 金额转换逻辑 ### 转换规则 #### 第三方应用转出 ``` 外部金额 × 汇率 = 内部金额 示例:100元 × 300 = 30000钻石 ``` #### 普通应用转出 ``` 内部金额 ÷ 汇率 = 外部金额 示例:30000钻石 ÷ 300 = 100元 ``` #### 转入操作 ``` 外部金额 × 汇率 = 内部金额 示例:50元 × 300 = 15000钻石 ``` ### 重要原则 1. **避免双重转换**:只在`TransferLogic`层进行一次转换 2. **精度处理**:使用`bcmath`函数确保计算精度 3. **汇率验证**:确保汇率大于0,避免计算异常 ## 💰 手续费机制 ### 手续费模式 #### 转出:手续费额外收取 ```php 用户想转出:3000钻石 手续费:10钻石 用户总扣除:3010钻石 外部实际收到:3000钻石(完整金额) ``` #### 转入:手续费从金额中扣除 ```php 外部转入:3000钻石 手续费:10钻石 用户实际收到:2990钻石 ``` ### 手续费计算 ```php // 按比例计算 $feeAmount = $amount * $feeRate; // 应用最低限制 if ($feeAmount < $minFee) { $feeAmount = $minFee; } // 应用最高限制 if ($maxFee > 0 && $feeAmount > $maxFee) { $feeAmount = $maxFee; } ``` ### 手续费配置 | 字段 | 说明 | 示例 | |------|------|------| | `fee_out_rate` | 转出手续费率 | 0.01 (1%) | | `fee_out_min` | 转出最低手续费 | 0.5钻石 | | `fee_out_max` | 转出最高手续费 | 10钻石 | | `fee_in_rate` | 转入手续费率 | 0.005 (0.5%) | | `fee_in_min` | 转入最低手续费 | 1钻石 | | `fee_in_max` | 转入最高手续费 | 50钻石 | ## 📊 手续费统计 ### 统计功能概述 Transfer模块提供完整的手续费统计功能,支持每日自动统计、数据验证、重新统计等操作。 ### 核心特性 - **🔄 增量统计**:基于订单ID的增量统计,避免重复统计 - **⏰ 定时执行**:每天22:00自动执行统计 - **✅ 数据验证**:验证统计数据与实际订单数据一致性 - **🔧 重新统计**:支持删除并重新计算指定日期数据 - **📈 多维分析**:支持按应用、日期范围、月度等多维度查询 - **🖥️ 管理界面**:提供后台管理界面和命令行工具 ### 统计数据结构 ```sql -- 手续费每日统计表 CREATE TABLE `kku_transfer_fee_daily_stats` ( `stat_date` date NOT NULL COMMENT '统计日期', `transfer_app_id` int unsigned NOT NULL COMMENT '划转应用ID', -- 转入统计 `in_order_count` int unsigned NOT NULL COMMENT '转入订单数量', `in_total_amount` decimal(30,10) NOT NULL COMMENT '转入总金额', `in_fee_amount` decimal(30,10) NOT NULL COMMENT '转入手续费总额', -- 转出统计 `out_order_count` int unsigned NOT NULL COMMENT '转出订单数量', `out_total_amount` decimal(30,10) NOT NULL COMMENT '转出总金额', `out_fee_amount` decimal(30,10) NOT NULL COMMENT '转出手续费总额', -- 汇总统计 `total_order_count` int unsigned NOT NULL COMMENT '总订单数量', `total_amount` decimal(30,10) NOT NULL COMMENT '总交易金额', `total_fee_amount` decimal(30,10) NOT NULL COMMENT '总手续费金额', `avg_fee_rate` decimal(8,5) NOT NULL COMMENT '平均手续费率' ); ``` ### 命令行工具 ```bash # 执行每日统计(默认统计昨天) php artisan transfer:fee-statistics # 统计指定日期 php artisan transfer:fee-statistics --date=2025-06-24 # 统计指定应用 php artisan transfer:fee-statistics --app-id=2 # 验证统计数据完整性 php artisan transfer:fee-statistics --validate --date=2025-06-24 # 重新统计(删除原数据重新计算) php artisan transfer:fee-statistics --rerun --date=2025-06-24 # 清理过期统计数据 php artisan transfer:fee-statistics --cleanup --retention-days=365 ``` ### 后台管理 - **访问路径**:`/admin/transfer/fee-statistics` - **功能特性**: - 统计数据列表展示 - 按应用、日期筛选 - 按手续费金额排序 - 详细统计信息查看 - 统计概览和趋势分析 ### 服务接口 ```php use App\Module\Transfer\Services\FeeStatisticsService; // 执行每日统计 $result = FeeStatisticsService::runDailyStatistics('2025-06-24'); // 获取日期范围统计 $stats = FeeStatisticsService::getStatsByDateRange('2025-06-01', '2025-06-30', 2); // 获取月度统计 $monthlyStats = FeeStatisticsService::getMonthlyStats(2025, 6, 2); // 获取应用汇总 $appSummary = FeeStatisticsService::getAppSummary(); // 验证数据完整性 $validation = FeeStatisticsService::validateStatistics('2025-06-24'); ``` ### 统计示例 ``` 统计日期:2025-06-24 处理应用数:2 总订单数:7 总手续费:11.2500000000 +--------+----------+--------+------------+----------------+----------+ | 应用ID | 应用名称 | 订单数 | 手续费金额 | 最后处理订单ID | 状态 | +--------+----------+--------+------------+----------------+----------+ | 2 | urs | 5 | 8.5 | 109 | 统计完成 | | 11 | URS_TEST | 2 | 2.75 | 111 | 统计完成 | +--------+----------+--------+------------+----------------+----------+ ``` ### 定时任务配置 ```php // 每天22:00自动执行 Schedule::command('transfer:fee-statistics') ->dailyAt('22:00') ->description('Transfer模块手续费每日统计') ->withoutOverlapping() // 防止重复执行 ->runInBackground(); // 后台运行 ``` ## 🔌 第三方应用集成 ### 核心服务 `TransferThirdPartyService`专门处理第三方应用需求: ```php // 创建提现订单 $result = TransferThirdPartyService::createWithdrawOrder( thirdPartyAppId: 11, farmUserId: 39027, thirdPartyUserId: '10002', thirdPartyAmount: '100', // 外部金额 remark: 'URS提取', callbackData: ['operation_type' => 'withdraw'] ); // 创建充值订单 $result = TransferThirdPartyService::createDepositOrder( thirdPartyAppId: 11, farmUserId: 39027, thirdPartyUserId: '10002', thirdPartyAmount: '50', // 外部金额 remark: 'URS充值', callbackData: ['operation_type' => 'deposit'] ); ``` ### 特殊功能 1. **跳过密码验证**:第三方应用无需用户输入密码 2. **自动金额转换**:自动处理外部金额与内部金额转换 3. **回调支持**:支持状态变更回调通知 4. **权限控制**:独立控制转入/转出操作权限 ## 📡 API接口 ### 转出接口 ```http POST /api/transfer/out Content-Type: application/json { "transfer_app_id": 1, "amount": "30000", "password": "123456", "out_user_id": "user123", "remark": "提现到银行卡" } ``` ### 转入接口 ```http POST /api/transfer/in Content-Type: application/json { "transfer_app_id": 1, "out_order_id": "ORDER_20250619001", "amount": "15000", "out_user_id": "user123", "remark": "银行卡充值" } ``` ### 回调接口 ```http POST /api/transfer/callback Content-Type: application/json { "out_order_id": "ORDER_20250619001", "out_id": 1, "success": true, "message": "处理成功" } ``` ## 🗄️ 数据库设计 ### 主要数据表 #### transfer_apps - 划转应用配置表 ```sql CREATE TABLE `kku_transfer_apps` ( `id` int NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL COMMENT '应用名称', `exchange_rate` decimal(10,4) NOT NULL DEFAULT '1.0000' COMMENT '汇率', `allow_transfer_in` tinyint(1) NOT NULL DEFAULT '1' COMMENT '允许转入', `allow_transfer_out` tinyint(1) NOT NULL DEFAULT '1' COMMENT '允许转出', `fee_out_rate` decimal(8,6) NOT NULL DEFAULT '0.000000' COMMENT '转出手续费率', `fee_out_min` decimal(20,10) NOT NULL DEFAULT '0.0000000000' COMMENT '转出最低手续费', `fee_out_max` decimal(20,10) NOT NULL DEFAULT '0.0000000000' COMMENT '转出最高手续费', -- 更多字段... PRIMARY KEY (`id`) ); ``` #### transfer_orders - 划转订单表 ```sql CREATE TABLE `kku_transfer_orders` ( `id` int NOT NULL AUTO_INCREMENT, `transfer_app_id` int NOT NULL COMMENT '划转应用ID', `out_order_id` varchar(100) NOT NULL COMMENT '外部订单ID', `user_id` int NOT NULL COMMENT '用户ID', `type` tinyint NOT NULL COMMENT '类型:1转入,2转出', `status` int NOT NULL COMMENT '状态', `out_amount` decimal(30,10) NOT NULL COMMENT '外部金额', `amount` decimal(30,10) NOT NULL COMMENT '内部金额', `exchange_rate` decimal(10,4) NOT NULL COMMENT '汇率', `fee_amount` decimal(30,10) NOT NULL DEFAULT '0.0000000000' COMMENT '手续费', `actual_amount` decimal(30,10) NOT NULL COMMENT '实际金额', -- 更多字段... PRIMARY KEY (`id`) ); ``` #### transfer_fee_daily_stats - 手续费每日统计表 ```sql CREATE TABLE `kku_transfer_fee_daily_stats` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `stat_date` date NOT NULL COMMENT '统计日期', `transfer_app_id` int unsigned NOT NULL COMMENT '划转应用ID', `last_processed_order_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '最后处理的订单ID', `in_order_count` int unsigned NOT NULL DEFAULT 0 COMMENT '转入订单数量', `in_total_amount` decimal(30,10) NOT NULL DEFAULT 0.0000000000 COMMENT '转入总金额', `in_fee_amount` decimal(30,10) NOT NULL DEFAULT 0.0000000000 COMMENT '转入手续费总额', `out_order_count` int unsigned NOT NULL DEFAULT 0 COMMENT '转出订单数量', `out_total_amount` decimal(30,10) NOT NULL DEFAULT 0.0000000000 COMMENT '转出总金额', `out_fee_amount` decimal(30,10) NOT NULL DEFAULT 0.0000000000 COMMENT '转出手续费总额', `total_order_count` int unsigned NOT NULL DEFAULT 0 COMMENT '总订单数量', `total_amount` decimal(30,10) NOT NULL DEFAULT 0.0000000000 COMMENT '总交易金额', `total_fee_amount` decimal(30,10) NOT NULL DEFAULT 0.0000000000 COMMENT '总手续费金额', `avg_fee_rate` decimal(8,5) NOT NULL DEFAULT 0.00000 COMMENT '平均手续费率', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_stat_date_app` (`stat_date`, `transfer_app_id`) ); ``` ## ⚙️ 配置说明 ### 应用配置 在后台管理界面配置划转应用: 1. **基本信息**:应用名称、描述 2. **汇率设置**:外部金额与内部金额转换比例 3. **权限控制**:允许转入/转出操作 4. **手续费配置**:费率、最低/最高限制 5. **账户配置**:转入来源账户、转出目标账户 6. **API配置**:外部API地址、回调URL ### 环境配置 ```env # Transfer模块配置 TRANSFER_DEFAULT_FEE_ACCOUNT_UID=1 TRANSFER_CALLBACK_TIMEOUT=30 TRANSFER_API_TIMEOUT=60 ``` ## 📝 使用示例 ### 基本转出操作 ```php use App\Module\Transfer\Services\TransferService; // 创建转出订单 $order = TransferService::createTransferOut( transferAppId: 1, userId: 12345, amount: '30000', password: '123456', outUserId: 'user123', remark: '提现到银行卡' ); echo "订单ID: {$order->id}"; echo "外部订单ID: {$order->out_order_id}"; echo "状态: {$order->status->name}"; ``` ### URS第三方集成示例 ```php use App\Module\Transfer\Services\TransferThirdPartyService; // URS提现 $result = TransferThirdPartyService::createWithdrawOrder( thirdPartyAppId: 11, farmUserId: 39027, thirdPartyUserId: '10002', thirdPartyAmount: '100', remark: 'URS提取', callbackData: [ 'operation_type' => 'withdraw', 'urs_order_id' => 'URS_20250619001' ] ); if (is_string($result)) { echo "创建失败: {$result}"; } else { echo "创建成功,订单ID: {$result->id}"; } ``` ## 🔧 故障排除 ### 常见问题 #### 1. 金额转换错误 **问题**:外部金额2500变成内部金额2500 **原因**:双重转换问题 **解决**:确保只在TransferLogic层进行一次转换 #### 2. 手续费计算异常 **问题**:手续费从转出金额中扣除,用户困惑 **原因**:手续费模式理解错误 **解决**:转出使用额外收取模式,转入使用扣除模式 #### 3. 余额验证失败 **问题**:用户余额充足但验证失败 **原因**:验证逻辑与执行逻辑不一致 **解决**:确保验证器检查转出金额+手续费总和 #### 4. 事务级别错误 **问题**:transaction level is 0错误 **原因**:Fund模块trade方法需要在事务中执行 **解决**:在调用前开启事务 ### 调试工具 ```bash # 重现错误请求 php artisan debug:reproduce-error {request_log_id} # 检查订单状态 php artisan transfer:order:status {order_id} # 重试失败订单 php artisan transfer:order:retry {order_id} # 手续费统计相关 php artisan transfer:fee-statistics --validate --date=2025-06-24 php artisan transfer:fee-statistics --rerun --date=2025-06-24 ``` --- **版本**: v1.1 **最后更新**: 2025-06-25 **维护者**: AI Assistant ### 更新日志 #### v1.1 (2025-06-25) - ✅ 新增手续费统计功能 - ✅ 支持每日自动统计和数据验证 - ✅ 提供命令行工具和后台管理界面 - ✅ 基于订单ID的增量统计机制 - ✅ 支持多维度数据查询和分析 #### v1.0 (2025-06-19) - ✅ 基础转入转出功能 - ✅ 第三方应用集成 - ✅ 手续费计算机制 - ✅ 后台管理界面