|
|
6 ماه پیش | |
|---|---|---|
| .. | ||
| AdminControllers | 6 ماه پیش | |
| Casts | 6 ماه پیش | |
| Commands | 6 ماه پیش | |
| Config | 6 ماه پیش | |
| Database | 6 ماه پیش | |
| Databases | 6 ماه پیش | |
| Docs | 6 ماه پیش | |
| Dtos | 6 ماه پیش | |
| Enums | 6 ماه پیش | |
| Events | 6 ماه پیش | |
| Exceptions | 6 ماه پیش | |
| Jobs | 6 ماه پیش | |
| Listeners | 6 ماه پیش | |
| Logics | 6 ماه پیش | |
| Models | 6 ماه پیش | |
| Repositories | 6 ماه پیش | |
| Routes | 6 ماه پیش | |
| Services | 6 ماه پیش | |
| Tests | 6 ماه پیش | |
| Validations | 6 ماه پیش | |
| Validators | 6 ماه پیش | |
| README.md | 6 ماه پیش | |
| TransferServiceProvider.php | 6 ماه پیش | |
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钻石
TransferLogic层进行一次转换bcmath函数确保计算精度用户想转出: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模块提供完整的手续费统计功能,支持每日自动统计、数据验证、重新统计等操作。
-- 手续费每日统计表
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-statisticsuse 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']
);
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": "处理成功"
}
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`)
);
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`)
);
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`)
);
在后台管理界面配置划转应用:
# 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}";
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}";
}
问题:外部金额2500变成内部金额2500
原因:双重转换问题
解决:确保只在TransferLogic层进行一次转换
问题:手续费从转出金额中扣除,用户困惑
原因:手续费模式理解错误
解决:转出使用额外收取模式,转入使用扣除模式
问题:用户余额充足但验证失败
原因:验证逻辑与执行逻辑不一致
解决:确保验证器检查转出金额+手续费总和
问题: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