EXCHANGE_RATE_CONCEPT.md 5.4 KB

Transfer模块汇率概念说明

汇率定义

在Transfer模块中,汇率(exchange_rate)表示"1个外部币能兑换多少内部币"

📊 汇率公式

汇率 = 内部币数量 / 外部币数量

🔄 转换公式

转出(内部币 → 外部币)

外部金额 = 内部金额 ÷ 汇率

转入(外部币 → 内部币)

内部金额 = 外部金额 × 汇率

实际示例

示例1:汇率 = 1.0450

假设汇率为1.0450,表示1个外部币可以兑换1.0450个内部币。

转出场景

  • 用户要转出100个内部币
  • 外部金额 = 100 ÷ 1.0450 ≈ 95.69个外部币

转入场景

  • 用户要转入100个外部币
  • 内部金额 = 100 × 1.0450 = 104.50个内部币

示例2:汇率 = 0.9568

假设汇率为0.9568,表示1个外部币可以兑换0.9568个内部币。

转出场景

  • 用户要转出100个内部币
  • 外部金额 = 100 ÷ 0.9568 ≈ 104.52个外部币

转入场景

  • 用户要转入100个外部币
  • 内部金额 = 100 × 0.9568 = 95.68个内部币

代码实现

TransferLogic.php

转出订单创建

// 计算金额(转出:内部金额转换为外部金额)
$amount = (string) $data['amount']; // 内部金额
$outAmount = bcdiv($amount, (string) $app->exchange_rate, 10); // 外部金额 = 内部金额 ÷ 汇率

转入订单创建

// 计算金额(转入:外部金额转换为内部金额)
$outAmount = (string) $data['amount']; // 外部金额
$amount = bcmul($outAmount, (string) $app->exchange_rate, 10); // 内部金额 = 外部金额 × 汇率

TransferThirdPartyService.php

充值费用计算

// 将三方金额转换为农场内部金额(充值:外部金额转内部金额)
$internalAmount = bcmul($amount, (string) $transferApp->exchange_rate, 10);

提现费用计算

// 将三方金额转换为农场内部金额(提现:外部金额转内部金额)
$internalAmount = bcmul($amount, (string) $transferApp->exchange_rate, 10);

业务场景理解

内部币 vs 外部币

  • 内部币: 农场系统内部使用的虚拟货币(如钻石、金币等)
  • 外部币: 第三方应用使用的货币单位(如游戏币、积分等)

汇率的经济含义

汇率 > 1.0

  • 表示外部币比内部币"值钱"
  • 1个外部币可以兑换超过1个内部币
  • 例如:汇率1.05表示1游戏币=1.05钻石

汇率 < 1.0

  • 表示内部币比外部币"值钱"
  • 1个外部币只能兑换不到1个内部币
  • 例如:汇率0.95表示1游戏币=0.95钻石

汇率 = 1.0

  • 表示内部币和外部币等值
  • 1个外部币=1个内部币

数据库存储

transfer_apps表

`exchange_rate` decimal(10,4) NOT NULL DEFAULT '1.0000' COMMENT '汇率(1个外部币能兑换多少内部币)'

transfer_orders表

`exchange_rate` decimal(10,4) NOT NULL COMMENT '使用汇率(1外部币=N内部币)'

测试验证

单元测试示例

public function testExchangeRateConversion()
{
    // 设置汇率为2.0(1外部币=2内部币)
    $app = TransferApp::factory()->create(['exchange_rate' => 2.0]);

    // 测试转出:100内部币应该转换为50外部币
    $outOrder = TransferLogic::createOutOrder($app, ['amount' => '100.00']);
    $this->assertEquals('50.0000000000', $outOrder->out_amount);

    // 测试转入:100外部币应该转换为200内部币
    $inOrder = TransferLogic::createInOrder($app, ['amount' => '100.00']);
    $this->assertEquals('200.0000000000', $inOrder->amount);
}

常见错误

❌ 错误理解

认为汇率表示"1个内部币能兑换多少外部币",导致:

  • 转出时使用:外部金额 = 内部金额 × 汇率(错误)
  • 转入时使用:内部金额 = 外部金额 ÷ 汇率(错误)

✅ 正确理解

汇率表示"1个外部币能兑换多少内部币",因此:

  • 转出时使用:外部金额 = 内部金额 ÷ 汇率(正确)
  • 转入时使用:内部金额 = 外部金额 × 汇率(正确)

实际应用场景

游戏充值

  1. 用户在游戏中购买100游戏币(外部币)
  2. 汇率为0.95(1游戏币=0.95钻石)
  3. 系统计算:100 × 0.95 = 95钻石(内部币)
  4. 用户农场账户增加95钻石

游戏提现

  1. 用户要提现100钻石(内部币)到游戏
  2. 汇率为0.95(1游戏币=0.95钻石)
  3. 系统计算:100 ÷ 0.95 ≈ 105.26游戏币(外部币)
  4. 用户游戏账户增加105.26游戏币

配置建议

汇率设置原则

  1. 市场汇率: 根据内外部货币的实际价值比例设置
  2. 手续费考虑: 可以在汇率中包含一定的手续费成本
  3. 精度控制: 使用4位小数精度,满足大部分业务需求
  4. 动态调整: 根据市场变化定期调整汇率

监控指标

  1. 汇率变化: 监控汇率调整频率和幅度
  2. 转换量: 统计内外部币种的转换量
  3. 差异分析: 分析理论汇率与实际汇率的差异

总结

Transfer模块的汇率概念明确定义为"1个外部币能兑换多少内部币",这个定义:

  1. 符合经济学常识: 与传统外汇汇率概念一致
  2. 便于理解: 直观表达内外部货币的兑换关系
  3. 计算简单: 转出乘法,转入除法,逻辑清晰
  4. 测试验证: 通过单元测试确保实现正确性

所有相关代码已经按照这个概念进行了修正和注释,确保实现的一致性和正确性。