190211-URS余额检查汇率转换修复.md 4.4 KB

URS余额检查汇率转换修复

时间: 2025年06月19日 02:11:14 CST
任务: 修复URS余额检查中汇率转换导致的单位不一致问题

问题描述

用户报告请求68993679,金额1,配置汇率300时:

  • 返回结果: "principal_total": "1", "fee_total": "3.0000", "required_total": "4.0000"
  • 期望结果: 最少300个内部币

问题分析

根本原因

ThirdParty/Urs/Webhook/UrsCheckWebhook.phpprocessCheck 方法中存在单位不一致问题:

  1. 汇率转换正确: calculateWithdrawFee 方法中正确将外部金额1转换为内部金额300
  2. 手续费计算正确: 基于内部金额300计算手续费3.0000
  3. 本金使用错误: principalAmount = $amount 使用的是外部金额1,而不是内部金额300
  4. 单位混乱: 本金用外部金额,手续费用内部金额,导致总额计算错误

问题流程

外部金额1 → 汇率300 → 内部金额300
                    ↓
                手续费计算(基于内部金额300) → 3.0000
                    ↓
本金1(外部) + 手续费3.0000(内部) = 4.0000 ❌

正确流程

外部金额1 → 汇率300 → 内部金额300
                    ↓
                手续费计算(基于内部金额300) → 3.0000
                    ↓
本金300(内部) + 手续费3.0000(内部) = 303.0000 ✅

修复方案

1. 获取汇率信息

在计算手续费前先获取转账应用配置:

// 4. 获取转账应用配置以获取汇率
$transferApp = \App\Module\Transfer\Services\TransferThirdPartyService::getTransferAppByThirdPartyId($thirdPartyAppId);

2. 计算内部金额

// 5. 将外部金额转换为内部金额(提现:外部金额转内部金额)
$internalAmount = bcmul($amount, (string) $transferApp->exchange_rate, 4);

3. 使用内部金额作为本金

// 7. 计算所需总金额(内部本金 + 手续费)
$principalAmount = $internalAmount; // 使用内部金额作为本金
$feeAmount = $feeDto->feeAmount;
$requiredTotal = bcadd($principalAmount, $feeAmount, 4);

修复验证

测试数据

  • 用户ID: 10002
  • 外部金额: 1
  • 汇率: 300
  • 手续费率: 1%

修复前结果

{
    "check": true,
    "diamond_balance": "499,781.0000",
    "principal_total": "1",           // ❌ 外部金额
    "fee_total": "3.0000",           // 基于内部金额计算
    "required_total": "4.0000",      // ❌ 单位不一致
    "message": "余额充足,允许提取"
}

修复后结果

{
    "check": true,
    "diamond_balance": "499,781.0000",
    "principal_total": "300.0000",   // ✅ 内部金额
    "fee_total": "3.0000",          // 基于内部金额计算
    "required_total": "303.0000",   // ✅ 单位一致
    "message": "余额充足,允许提取"
}

验证结果

  • 本金差异: +299 (1 × 300汇率 - 1 = 299)
  • 总额差异: +299 (303 - 4 = 299)
  • 单位一致: 本金、手续费、总额都使用内部金额

测试文件

1. test_urs_fix_verification.php

  • 使用原始请求数据验证修复效果
  • 对比修复前后的响应差异
  • 验证汇率转换和单位一致性

2. test_urs_check_fix.php

  • 通过反射调用Webhook处理器
  • 测试不同金额的手续费计算
  • 验证DTO属性和计算逻辑

3. test_webhook_api.php

  • 直接调用HTTP API测试
  • 验证完整的请求响应流程

影响范围

修改文件

  • ThirdParty/Urs/Webhook/UrsCheckWebhook.php

影响功能

  • URS余额检查API (/thirdParty/webhook/urs/check)
  • 所有依赖该API的URS提现功能

向后兼容性

  • ✅ 不影响API接口结构
  • ✅ 只修复计算逻辑,不改变字段定义
  • ⚠️ 返回值会发生变化(principal_total和required_total会增大)

部署注意事项

  1. 数据一致性: 修复后的返回值会显著增大,需要确保调用方能正确处理
  2. 余额检查: 用户余额需要足够支付内部金额,而不是外部金额
  3. 监控告警: 可能会触发余额不足的告警,这是正常现象

总结

此次修复解决了URS余额检查中汇率转换导致的单位不一致问题,确保:

  • 本金使用正确的内部金额(外部金额 × 汇率)
  • 手续费基于内部金额计算
  • 总额计算基于统一的内部金额单位
  • 提高了系统的准确性和一致性