AI Assistant ad53f3dc2e 实现getTeamANumber方法:获取三级内活跃用户数量 6 ماه پیش
..
AdminControllers f67fa2f59f 实现Transfer模块手续费统计功能 6 ماه پیش
Casts 9fe44d8b03 Revert "1" 6 ماه پیش
Commands f5d7cf3bc9 手续费统计 6 ماه پیش
Config 336f3f951c refactor(transfer): 将 business_id 重命名为 out_order_id- 在配置文件、API 文档、代码逻辑、测试用例等多处将 business_id 替换为 out_order_id 6 ماه پیش
Database f5d7cf3bc9 手续费统计 6 ماه پیش
Databases ad53f3dc2e 实现getTeamANumber方法:获取三级内活跃用户数量 6 ماه پیش
Docs f5d7cf3bc9 手续费统计 6 ماه پیش
Dtos 428fa490db refactor(transfer): 重构划转模块的手续费计算逻辑 6 ماه پیش
Enums 9fe44d8b03 Revert "1" 6 ماه پیش
Events 848f699662 1 6 ماه پیش
Exceptions 9fe44d8b03 Revert "1" 6 ماه پیش
Jobs 35173d8fe1 1 6 ماه پیش
Listeners 428fa490db refactor(transfer): 重构划转模块的手续费计算逻辑 6 ماه پیش
Logics 097548e7e1 1 6 ماه پیش
Models ad53f3dc2e 实现getTeamANumber方法:获取三级内活跃用户数量 6 ماه پیش
Repositories 9fe44d8b03 Revert "1" 6 ماه پیش
Routes 9fe44d8b03 Revert "1" 6 ماه پیش
Services 097548e7e1 1 6 ماه پیش
Tests 336f3f951c refactor(transfer): 将 business_id 重命名为 out_order_id- 在配置文件、API 文档、代码逻辑、测试用例等多处将 business_id 替换为 out_order_id 6 ماه پیش
Validations 7ecbbf2fe0 l1 6 ماه پیش
Validators 336f3f951c refactor(transfer): 将 business_id 重命名为 out_order_id- 在配置文件、API 文档、代码逻辑、测试用例等多处将 business_id 替换为 out_order_id 6 ماه پیش
README.md f5d7cf3bc9 手续费统计 6 ماه پیش
TransferServiceProvider.php 993136bb30 1 6 ماه پیش

README.md

Transfer模块 - 划转系统

Transfer模块是农场游戏系统的资金划转核心模块,负责处理用户与外部系统之间的资金转入转出操作。

📋 目录

🎯 核心概念

基本术语

术语 说明 示例
转入订单 用户充值/存入资金到农场系统 URS用户充值100元到农场
转出订单 用户提现/转出资金到外部系统 农场用户提现30000钻石到URS
外部金额 第三方系统的金额单位 URS系统的100元
内部金额 农场系统的钻石数量 农场系统的30000钻石
汇率 外部金额与内部金额的转换比例 1元 = 300钻石

订单状态

enum TransferStatus: int
{
    case CREATED = 100;     // 已创建
    case PROCESSING = 200;  // 处理中
    case COMPLETED = 300;   // 已完成
    case FAILED = 400;      // 失败
    case CANCELLED = 500;   // 已取消
}

订单类型

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,避免计算异常

💰 手续费机制

手续费模式

转出:手续费额外收取

用户想转出:3000钻石
手续费:10钻石
用户总扣除:3010钻石
外部实际收到:3000钻石(完整金额)

转入:手续费从金额中扣除

外部转入:3000钻石
手续费:10钻石
用户实际收到:2990钻石

手续费计算

// 按比例计算
$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自动执行统计
  • ✅ 数据验证:验证统计数据与实际订单数据一致性
  • 🔧 重新统计:支持删除并重新计算指定日期数据
  • 📈 多维分析:支持按应用、日期范围、月度等多维度查询
  • 🖥️ 管理界面:提供后台管理界面和命令行工具

统计数据结构

-- 手续费每日统计表
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 '平均手续费率'
);

命令行工具

# 执行每日统计(默认统计昨天)
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
  • 功能特性
    • 统计数据列表展示
    • 按应用、日期筛选
    • 按手续费金额排序
    • 详细统计信息查看
    • 统计概览和趋势分析

服务接口

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            | 统计完成 |
+--------+----------+--------+------------+----------------+----------+

定时任务配置

// 每天22:00自动执行
Schedule::command('transfer:fee-statistics')
    ->dailyAt('22:00')
    ->description('Transfer模块手续费每日统计')
    ->withoutOverlapping() // 防止重复执行
    ->runInBackground(); // 后台运行

🔌 第三方应用集成

核心服务

TransferThirdPartyService专门处理第三方应用需求:

// 创建提现订单
$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接口

转出接口

POST /api/transfer/out
Content-Type: application/json

{
    "transfer_app_id": 1,
    "amount": "30000",
    "password": "123456",
    "out_user_id": "user123",
    "remark": "提现到银行卡"
}

转入接口

POST /api/transfer/in
Content-Type: application/json

{
    "transfer_app_id": 1,
    "out_order_id": "ORDER_20250619001",
    "amount": "15000",
    "out_user_id": "user123",
    "remark": "银行卡充值"
}

回调接口

POST /api/transfer/callback
Content-Type: application/json

{
    "out_order_id": "ORDER_20250619001",
    "out_id": 1,
    "success": true,
    "message": "处理成功"
}

🗄️ 数据库设计

主要数据表

transfer_apps - 划转应用配置表

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 - 划转订单表

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 - 手续费每日统计表

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

环境配置

# Transfer模块配置
TRANSFER_DEFAULT_FEE_ACCOUNT_UID=1
TRANSFER_CALLBACK_TIMEOUT=30
TRANSFER_API_TIMEOUT=60

📝 使用示例

基本转出操作

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第三方集成示例

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方法需要在事务中执行
解决:在调用前开启事务

调试工具

# 重现错误请求
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)

  • ✅ 基础转入转出功能
  • ✅ 第三方应用集成
  • ✅ 手续费计算机制
  • ✅ 后台管理界面