Răsfoiți Sursa

refactor(transfer): 重构划转模块的手续费计算逻辑

- 移除了 TransferFeeDto 中的冗余方法
- 重构了 FeeCalculatedEvent 和 FeeCalculatingListener
- 优化了 TransferLogic 中的订单创建逻辑
- 重新设计了 TransferThirdPartyService 的手续费计算方法
- 调整了 UrsCheckWebhook 中的余额检查流程
notfff 6 luni în urmă
părinte
comite
428fa490db

+ 40 - 66
ThirdParty/Urs/Webhook/UrsCheckWebhook.php

@@ -93,6 +93,7 @@ class UrsCheckWebhook extends WebhookReceiver
 
             /**
              * 三方应用ID
+             *
              * @var int $thirdPartyAppId
              */
             $thirdPartyAppId = $this->service->id;
@@ -103,124 +104,97 @@ class UrsCheckWebhook extends WebhookReceiver
             if (!$farmUserId) {
                 Log::warning("URS余额检查失败:未找到用户映射关系", [
                     'urs_user_id' => $userId,
-                    'amount' => $amount,
+                    'amount'      => $amount,
                 ]);
 
                 return [
-                    'check' => false,
+                    'check'           => false,
                     'diamond_balance' => '0.0000',
                     'principal_total' => $amount,
-                    'fee_total' => '0.0000',
-                    'required_total' => $amount,
-                    'message' => '用户未进入农场系统'
+                    'fee_total'       => '0.0000',
+                    'required_total'  => $amount,
+                    'message'         => '用户未进入农场系统'
                 ];
             }
 
             // 2. 获取用户钻石余额
-            $userFundService = new \App\Module\Fund\Services\FundService($farmUserId, 2); // 2是钻石的fund_id
-            $diamondBalance = $userFundService->balance();
+            $userFundService         = new \App\Module\Fund\Services\FundService($farmUserId, 2); // 2是钻石的fund_id
+            $diamondBalance          = $userFundService->balance();
             $diamondBalanceFormatted = number_format($diamondBalance, 4); // 直接格式化,无需转换
 
             // 3. 特殊处理:如果金额为0,只返回余额信息,不计算手续费
             if (bccomp($amount, '0', 4) === 0) {
                 Log::info("URS余额查询(金额为0)", [
-                    'urs_user_id' => $userId,
-                    'farm_user_id' => $farmUserId,
+                    'urs_user_id'     => $userId,
+                    'farm_user_id'    => $farmUserId,
                     'diamond_balance' => $diamondBalanceFormatted,
                 ]);
 
                 return [
-                    'check' => true,
+                    'check'           => true,
                     'diamond_balance' => $diamondBalanceFormatted,
                     'principal_total' => '0.0000',
-                    'fee_total' => '0.0000',
-                    'required_total' => '0.0000',
-                    'message' => '余额查询成功'
-                ];
-            }
-
-            // 4. 获取转账应用配置以获取汇率
-            $transferApp = \App\Module\Transfer\Services\TransferThirdPartyService::getTransferAppByThirdPartyId($thirdPartyAppId);
-            if (!$transferApp) {
-                Log::warning("URS余额检查失败:未找到对应的划转应用配置", [
-                    'urs_user_id' => $userId,
-                    'farm_user_id' => $farmUserId,
-                    'third_party_app_id' => $thirdPartyAppId,
-                    'amount' => $amount
-                ]);
-
-                return [
-                    'check' => false,
-                    'diamond_balance' => $diamondBalanceFormatted,
-                    'principal_total' => $amount,
-                    'fee_total' => '0.0000',
-                    'required_total' => $amount,
-                    'message' => '未找到对应的划转应用配置'
+                    'fee_total'       => '0.0000',
+                    'required_total'  => '0.0000',
+                    'message'         => '余额查询成功'
                 ];
             }
 
-            // 5. 将外部金额转换为内部金额(提现:外部金额转内部金额)
-            $internalAmount = bcmul($amount, (string) $transferApp->exchange_rate, 4);
 
             // 6. 使用TransferThirdPartyService计算提取费用,传递用户ID以便URS推广模块计算正确的手续费率
             $feeDto = \App\Module\Transfer\Services\TransferThirdPartyService::calculateWithdrawFeeWithContext(
                 $thirdPartyAppId,
                 $amount,
-                ['user_id' => $farmUserId] // 传递农场用户ID,让URS推广模块能够根据房屋等级和达人等级计算手续费
+                [ 'user_id' => $farmUserId ] // 传递农场用户ID,让URS推广模块能够根据房屋等级和达人等级计算手续费
             );
 
             if ($feeDto->hasError) {
                 Log::warning("URS余额检查失败:无法计算手续费", [
-                    'urs_user_id' => $userId,
-                    'farm_user_id' => $farmUserId,
-                    'amount' => $amount,
-                    'internal_amount' => $internalAmount,
-                    'error' => $feeDto->errorMessage
+                    'urs_user_id'     => $userId,
+                    'farm_user_id'    => $farmUserId,
+                    'amount'          => $amount,
+                    'internal_amount' => $feeDto->feeRate,
+                    'error'           => $feeDto->errorMessage
                 ]);
 
                 return [
-                    'check' => false,
+                    'check'           => false,
                     'diamond_balance' => $diamondBalanceFormatted,
-                    'principal_total' => $internalAmount,
-                    'fee_total' => '0.0000',
-                    'required_total' => $internalAmount,
-                    'message' => $feeDto->errorMessage
+                    'principal_total' => $feeDto->actualAmount,
+                    'fee_total'       => '0.0000',
+                    'required_total'  => $feeDto->totleAmount,
+                    'message'         => $feeDto->errorMessage
                 ];
             }
 
-            // 7. 计算所需总金额(内部本金 + 手续费)
-            $principalAmount = $internalAmount; // 使用内部金额作为本金
-            $feeAmount = $feeDto->feeAmount;
-            $requiredTotal = bcadd($principalAmount, $feeAmount, 4);
-
             // 6. 检查余额是否足够(直接比较小数值)
-            $isAllowed = bccomp($diamondBalance, $requiredTotal, 10) >= 0;
+            $isAllowed = bccomp($diamondBalance, $feeDto->totleAmount, 10) >= 0;
 
             Log::info("URS余额检查完成", [
-                'urs_user_id' => $userId,
-                'farm_user_id' => $farmUserId,
-                'amount' => $amount,
+                'urs_user_id'     => $userId,
+                'farm_user_id'    => $farmUserId,
+                'amount'          => $amount,
                 'diamond_balance' => $diamondBalanceFormatted,
-                'fee_amount' => $feeAmount,
-                'required_total' => $requiredTotal,
-                'is_allowed' => $isAllowed
+                'fee_amount'      => $feeDto->feeAmount,
+                'required_total'  => $feeDto->totleAmount,
+                'is_allowed'      => $isAllowed
             ]);
 
             return [
-                'check' => $isAllowed,
+                'check'           => $isAllowed,
                 'diamond_balance' => $diamondBalanceFormatted,
-                'principal_total' => $principalAmount,
-                'fee_total' => $feeAmount,
-                'required_total' => $requiredTotal,
-                'message' => $isAllowed ? '余额充足,允许提取' : '余额不足,无法提取'
+                'principal_total' => $feeDto->actualAmount,
+                'fee_total'       => $feeDto->feeAmount,
+                'required_total'  => $feeDto->totleAmount,
+                'message'         => $isAllowed ? '余额充足,允许提取' : '余额不足,无法提取'
             ];
 
         } catch (\Exception $e) {
             Log::error("URS余额检查处理异常", [
                 'urs_user_id' => $userId ?? 'unknown',
-                'amount' => $amount ?? 'unknown',
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'amount'      => $amount ?? 'unknown',
+                'error'       => $e->getMessage(),
+                'trace'       => $e->getTraceAsString()
             ]);
             throw $e;
         }

+ 2 - 1
UCore/Dto/BaseDto.php

@@ -15,6 +15,7 @@ use Serializable;
  * 2. JSON序列化
  * 3. 从数组创建对象
  * 4. PHP序列化支持,便于缓存
+ * 不要在构造函数定义属性
  */
 abstract class BaseDto implements Arrayable, JsonSerializable, Jsonable, Serializable
 {
@@ -240,7 +241,7 @@ abstract class BaseDto implements Arrayable, JsonSerializable, Jsonable, Seriali
         }
     }
 
-    
+
 
     /**
      * 从对象创建新实例

+ 49 - 127
app/Module/Transfer/Dtos/TransferFeeDto.php

@@ -6,63 +6,72 @@ use UCore\Dto\BaseDto;
 
 /**
  * 划转手续费计算结果数据传输对象
- * 
+ *
  * 用于表示手续费计算的结果,包含手续费率、手续费金额、实际到账金额等信息
  */
 class TransferFeeDto extends BaseDto
 {
+
     /**
      * 构造函数
-     * 
+     *
      * @param float $feeRate 手续费率(小数形式,如 0.01 表示 1%)
      * @param string $feeAmount 手续费金额(字符串格式,保持精度)
-     * @param string $actualAmount 实际到账金额(字符串格式,保持精度)
-     * @param string $originalAmount 原始金额(字符串格式,保持精度)
+     * @param string $actualAmount 实际到账金额(字符串格式,保持精度),本金
+     * @param string $totleAmount 总需金额(字符串格式,保持精度)
+     * @param string $originalAmount 原始金额(字符串格式,保持精度),外部金额
      * @param bool $hasError 是否有错误
      * @param string|null $errorMessage 错误信息
      * @param array $additionalInfo 额外信息
      */
     public function __construct(
-        public readonly float $feeRate,
-        public readonly string $feeAmount,
-        public readonly string $actualAmount,
-        public readonly string $originalAmount,
-        public readonly bool $hasError = false,
+        public readonly float   $feeRate,
+        public readonly string  $feeAmount,
+        public readonly string  $actualAmount,
+        public readonly string  $totleAmount,
+        public readonly string  $originalAmount,
+        public readonly bool    $hasError = false,
         public readonly ?string $errorMessage = null,
-        public readonly array $additionalInfo = []
-    ) {}
+        public readonly array   $additionalInfo = []
+    )
+    {
+    }
 
     /**
      * 创建成功的手续费计算结果
-     * 
+     *
      * @param string $originalAmount 原始金额
      * @param float $feeRate 手续费率
      * @param string $feeAmount 手续费金额
      * @param string $actualAmount 实际到账金额
+     * @param string $totleAmount 总支付金额
      * @param array $additionalInfo 额外信息
      * @return self
      */
     public static function success(
         string $originalAmount,
-        float $feeRate,
+        float  $feeRate,
         string $feeAmount,
         string $actualAmount,
-        array $additionalInfo = []
-    ): self {
+        string $totleAmount,
+        array  $additionalInfo = []
+    ): self
+    {
         return new self(
-            feeRate: $feeRate,
-            feeAmount: $feeAmount,
-            actualAmount: $actualAmount,
+            feeRate:        $feeRate,
+            feeAmount:      $feeAmount,
+            actualAmount:   $actualAmount,
             originalAmount: $originalAmount,
-            hasError: false,
-            errorMessage: null,
+            totleAmount:    $totleAmount,
+            hasError:       false,
+            errorMessage:   null,
             additionalInfo: $additionalInfo
         );
     }
 
     /**
      * 创建错误的手续费计算结果
-     * 
+     *
      * @param string $originalAmount 原始金额
      * @param string $errorMessage 错误信息
      * @param array $additionalInfo 额外信息
@@ -71,121 +80,50 @@ class TransferFeeDto extends BaseDto
     public static function error(
         string $originalAmount,
         string $errorMessage,
-        array $additionalInfo = []
-    ): self {
+        array  $additionalInfo = []
+    ): self
+    {
         return new self(
-            feeRate: 0.0000,
-            feeAmount: '0.0000',
-            actualAmount: $originalAmount,
+            feeRate:        0.0000,
+            feeAmount:      '0.0000',
+            actualAmount:   $originalAmount,
             originalAmount: $originalAmount,
-            hasError: true,
-            errorMessage: $errorMessage,
+            totleAmount:    0,
+            hasError:       true,
+            errorMessage:   $errorMessage,
             additionalInfo: $additionalInfo
         );
     }
 
-    /**
-     * 从数组创建DTO(兼容旧的数组格式)
-     *
-     * @param array $data 数组数据
-     * @param string $originalAmount 原始金额
-     * @return self
-     */
-    public static function fromLegacyArray(array $data, string $originalAmount = ''): self
-    {
-        // 检查是否有错误
-        if (isset($data['error'])) {
-            return self::error(
-                originalAmount: $originalAmount,
-                errorMessage: $data['error'],
-                additionalInfo: array_diff_key($data, array_flip(['error']))
-            );
-        }
-
-        return self::success(
-            originalAmount: $originalAmount,
-            feeRate: (float) ($data['fee_rate'] ?? 0.0000),
-            feeAmount: (string) ($data['fee_amount'] ?? '0.0000'),
-            actualAmount: (string) ($data['actual_amount'] ?? $originalAmount),
-            additionalInfo: array_diff_key($data, array_flip(['fee_rate', 'fee_amount', 'actual_amount']))
-        );
-    }
 
     /**
-     * 转换为数组(保持向后兼容)
-     * 
+     * 转换为数组
+     *
      * @return array
      */
     public function toArray(): array
     {
         $result = [
-            'fee_rate' => $this->feeRate,
-            'fee_amount' => $this->feeAmount,
-            'actual_amount' => $this->actualAmount,
+            'fee_rate'        => $this->feeRate,
+            'fee_amount'      => $this->feeAmount,
+            'actual_amount'   => $this->actualAmount,
             'original_amount' => $this->originalAmount,
-            'has_error' => $this->hasError,
+            'has_error'       => $this->hasError,
         ];
 
-        // 如果有错误,添加错误信息
-        if ($this->hasError && $this->errorMessage) {
-            $result['error'] = $this->errorMessage;
-        }
 
-        // 添加额外信息
-        if (!empty($this->additionalInfo)) {
-            $result = array_merge($result, $this->additionalInfo);
-        }
+        $result['error'] = $this->errorMessage;
 
-        return $result;
-    }
 
-    /**
-     * 转换为兼容旧格式的数组
-     * 
-     * @return array
-     */
-    public function toLegacyArray(): array
-    {
-        if ($this->hasError) {
-            return [
-                'error' => $this->errorMessage,
-                'fee_rate' => $this->feeRate,
-                'fee_amount' => $this->feeAmount,
-                'actual_amount' => $this->actualAmount,
-            ];
-        }
-
-        return [
-            'fee_rate' => $this->feeRate,
-            'fee_amount' => $this->feeAmount,
-            'actual_amount' => $this->actualAmount,
-        ];
-    }
+        $result['additionalInfo'] = $this->additionalInfo;
 
-    /**
-     * 获取手续费率百分比格式
-     * 
-     * @param int $decimals 小数位数
-     * @return string
-     */
-    public function getFeeRatePercent(int $decimals = 2): string
-    {
-        return number_format($this->feeRate * 100, $decimals) . '%';
+        return $result;
     }
 
-    /**
-     * 判断是否有手续费
-     * 
-     * @return bool
-     */
-    public function hasFee(): bool
-    {
-        return bccomp($this->feeAmount, '0', 10) > 0;
-    }
 
     /**
      * 判断是否计算成功
-     * 
+     *
      * @return bool
      */
     public function isSuccess(): bool
@@ -193,21 +131,5 @@ class TransferFeeDto extends BaseDto
         return !$this->hasError;
     }
 
-    /**
-     * 获取格式化的手续费信息
-     * 
-     * @return string
-     */
-    public function getFormattedFeeInfo(): string
-    {
-        if ($this->hasError) {
-            return "计算失败: {$this->errorMessage}";
-        }
 
-        if (!$this->hasFee()) {
-            return "无手续费";
-        }
-
-        return "手续费: {$this->feeAmount} ({$this->getFeeRatePercent()})";
-    }
 }

+ 1 - 36
app/Module/Transfer/Events/FeeCalculatedEvent.php

@@ -8,7 +8,7 @@ use Illuminate\Queue\SerializesModels;
 
 /**
  * 手续费计算完成事件
- * 
+ *
  * 在手续费计算完成后触发,用于记录日志、统计等
  */
 class FeeCalculatedEvent
@@ -174,42 +174,7 @@ class FeeCalculatedEvent
         return $this->type === 'out';
     }
 
-    /**
-     * 获取手续费节省金额(如果被减免)
-     *
-     * @return string
-     */
-    public function getFeeSavings(): string
-    {
-        if (!$this->isModified) {
-            return '0.0000';
-        }
-
-        // 计算原始手续费(基于应用配置)
-        $originalFee = $this->type === 'in' 
-            ? $this->app->calculateInFee($this->amount)['fee_amount']
-            : $this->app->calculateOutFee($this->amount)['fee_amount'];
-
-        return bcsub($originalFee, $this->feeAmount, 4);
-    }
 
-    /**
-     * 获取手续费增加金额(如果被增加)
-     *
-     * @return string
-     */
-    public function getFeeIncrease(): string
-    {
-        if (!$this->isModified) {
-            return '0.0000';
-        }
 
-        // 计算原始手续费(基于应用配置)
-        $originalFee = $this->type === 'in' 
-            ? $this->app->calculateInFee($this->amount)['fee_amount']
-            : $this->app->calculateOutFee($this->amount)['fee_amount'];
 
-        $increase = bcsub($this->feeAmount, $originalFee, 4);
-        return bccomp($increase, '0', 4) > 0 ? $increase : '0.0000';
-    }
 }

+ 10 - 9
app/Module/Transfer/Listeners/FeeCalculatingListener.php

@@ -7,9 +7,10 @@ use Illuminate\Support\Facades\Log;
 
 /**
  * 手续费计算监听器示例
- * 
+ *
  * 展示如何监听手续费计算事件并修改手续费数额
  * 其他模块可以创建类似的监听器来实现自定义的手续费逻辑
+ * @deprecated  仅作展示,没有监听
  */
 class FeeCalculatingListener
 {
@@ -44,14 +45,14 @@ class FeeCalculatingListener
     {
         // 从上下文获取用户ID
         $userId = $event->getContext('user_id');
-        
+
         if (!$userId) {
             return;
         }
 
         // 检查用户是否为VIP(这里只是示例逻辑)
         $isVip = $this->checkUserVipStatus($userId);
-        
+
         if ($isVip) {
             // VIP用户享受50%手续费减免
             $discountAmount = bcmul($event->feeAmount, '0.5', 4);
@@ -86,11 +87,11 @@ class FeeCalculatingListener
 
         // 大额交易阈值(例如:1000以上)
         $largeAmountThreshold = '1000.0000';
-        
+
         if (bccomp($event->amount, $largeAmountThreshold, 4) >= 0) {
             // 大额交易手续费上限为10
             $maxFee = '10.0000';
-            
+
             if (bccomp($event->feeAmount, $maxFee, 4) > 0) {
                 $event->modifyFeeAmount(
                     newFeeAmount: $maxFee,
@@ -118,7 +119,7 @@ class FeeCalculatingListener
     {
         // 特殊应用ID列表(例如:合作伙伴应用)
         $specialAppIds = [1, 2, 3]; // 示例应用ID
-        
+
         if (in_array($event->app->id, $specialAppIds)) {
             // 合作伙伴应用免手续费
             $event->setFree(
@@ -153,7 +154,7 @@ class FeeCalculatingListener
             // 节假日手续费8折
             $discountRate = '0.2'; // 20%折扣
             $discountAmount = bcmul($event->feeAmount, $discountRate, 4);
-            
+
             $event->reduceFee(
                 discountFee: $discountAmount,
                 reason: '节假日手续费8折优惠',
@@ -180,7 +181,7 @@ class FeeCalculatingListener
     {
         // 这里应该调用实际的用户服务来检查VIP状态
         // 示例:return UserService::isVip($userId);
-        
+
         // 为了演示,这里简单判断用户ID
         return $userId % 10 === 0; // 用户ID是10的倍数就是VIP
     }
@@ -194,7 +195,7 @@ class FeeCalculatingListener
     {
         // 这里应该调用实际的节假日服务来检查
         // 示例:return HolidayService::isHoliday(now());
-        
+
         // 为了演示,这里简单判断周末
         return now()->isWeekend();
     }

+ 7 - 4
app/Module/Transfer/Logics/TransferLogic.php

@@ -101,6 +101,9 @@ class TransferLogic
     public static function createTransferOutFromArrayForThirdParty(array $data): TransferOrder
     {
         // 获取应用配置(需要先获取以便进行金额转换)
+        /**
+         * @var  TransferApp $app
+         */
         $app = TransferApp::findOrFail($data['transfer_app_id']);
         if (!$app->is_enabled) {
             throw new \Exception('应用已禁用');
@@ -562,7 +565,7 @@ class TransferLogic
 
     /**
      * 处理回调结果
-     * 
+     *
      * @param array $callbackData 回调数据
      * @return bool
      */
@@ -587,7 +590,7 @@ class TransferLogic
 
     /**
      * 生成外部订单ID
-     * 
+     *
      * @param string $prefix 前缀
      * @return string
      */
@@ -598,7 +601,7 @@ class TransferLogic
 
     /**
      * 重试订单处理
-     * 
+     *
      * @param int $orderId 订单ID
      * @return bool
      */
@@ -628,7 +631,7 @@ class TransferLogic
 
     /**
      * 手动完成订单
-     * 
+     *
      * @param int $orderId 订单ID
      * @param string $remark 备注
      * @return bool

+ 5 - 36
app/Module/Transfer/Models/TransferApp.php

@@ -7,8 +7,8 @@ use UCore\ModelCore;
 
 /**
  * 划转应用配置模型
- * 
- * field start 
+ *
+ * field start
  * @property  int  $id  主键ID
  * @property  string  $keyname  应用标识符
  * @property  string  $title  应用显示名称
@@ -46,7 +46,7 @@ class TransferApp extends ModelCore
      */
     protected $table = 'transfer_apps';
 
-    // attrlist start 
+    // attrlist start
     protected $fillable = [
         'id',
         'keyname',
@@ -236,6 +236,7 @@ class TransferApp extends ModelCore
      *
      * @param string $amount 转入金额
      * @return array ['fee_rate' => 手续费率, 'fee_amount' => 手续费金额, 'actual_amount' => 实际到账金额]
+     * @deprecated 模型内不应该有逻辑
      */
     public function calculateInFee(string $amount): array
     {
@@ -248,6 +249,7 @@ class TransferApp extends ModelCore
      * @param string $amount 转出金额
      * @param array $context 额外的上下文数据(包含用户ID等信息)
      * @return array ['fee_rate' => 手续费率, 'fee_amount' => 手续费金额, 'actual_amount' => 用户总支付金额]
+     * @deprecated 模型内,不应该有逻辑
      */
     public function calculateOutFee(string $amount, array $context = []): array
     {
@@ -255,41 +257,8 @@ class TransferApp extends ModelCore
         return \App\Module\Transfer\Services\FeeService::calculateOutFee($this, $amount, $context);
     }
 
-    /**
-     * 计算转出手续费的专用方法(额外收取手续费)
-     *
-     * @param string $amount 转出金额
-     * @param float $feeRate 手续费率
-     * @param float $minFee 最低手续费
-     * @param float $maxFee 最高手续费
-     * @return array
-     */
-    private function calculateOutFeeWithExtraCharge(string $amount, float $feeRate, float $minFee, float $maxFee): array
-    {
-        $amountDecimal = bcmul($amount, '1', 4); // 转换为4位小数
-
-        // 按比例计算手续费
-        $feeAmount = bcmul($amountDecimal, (string)$feeRate, 4);
-
-        // 应用最低手续费限制
-        if (bccomp($feeAmount, (string)$minFee, 4) < 0) {
-            $feeAmount = bcmul((string)$minFee, '1', 4);
-        }
-
-        // 应用最高手续费限制(如果设置了)
-        if ($maxFee > 0 && bccomp($feeAmount, (string)$maxFee, 4) > 0) {
-            $feeAmount = bcmul((string)$maxFee, '1', 4);
-        }
 
-        // 计算用户总支付金额(转出金额 + 手续费)
-        $actualAmount = bcadd($amountDecimal, $feeAmount, 4);
 
-        return [
-            'fee_rate' => $feeRate,
-            'fee_amount' => $feeAmount,
-            'actual_amount' => $actualAmount, // 对于转出:用户总支付金额
-        ];
-    }
 
     /**
      * 计算手续费的通用方法(从金额中扣除手续费)

+ 85 - 77
app/Module/Transfer/Services/TransferThirdPartyService.php

@@ -13,9 +13,10 @@ use App\Module\Transfer\Models\TransferApp;
  */
 class TransferThirdPartyService
 {
+
     /**
      * 创建充值单(转入订单)
-     * 
+     *
      * @param int $thirdPartyAppId 三方应用ID
      * @param int $farmUserId 农场用户ID
      * @param string $thirdPartyUserId 三方用户ID
@@ -26,13 +27,14 @@ class TransferThirdPartyService
      * @throws \Exception
      */
     public static function createRechargeOrder(
-        int $thirdPartyAppId,
-        int $farmUserId,
-        string $thirdPartyUserId,
-        string $thirdPartyAmount,
+        int     $thirdPartyAppId,
+        int     $farmUserId,
+        string  $thirdPartyUserId,
+        string  $thirdPartyAmount,
         ?string $remark = null,
-        array $callbackData = []
-    ): TransferOrderDto|string {
+        array   $callbackData = []
+    ): TransferOrderDto|string
+    {
         try {
             // 根据三方应用ID查找对应的Transfer应用配置
             $transferApp = TransferApp::where('out_id3', $thirdPartyAppId)
@@ -54,26 +56,26 @@ class TransferThirdPartyService
             // 调用Transfer模块的转入逻辑
             $order = TransferLogic::createTransferIn(
                 transferAppId: $transferApp->id,
-                userId: $farmUserId,
-                businessId: $businessId,
-                amount: $thirdPartyAmount,
-                outUserId: $thirdPartyUserId,
-                remark: $remark,
-                callbackData: array_merge($callbackData, [
-                    'third_party_app_id' => $thirdPartyAppId,
-                    'third_party_user_id' => $thirdPartyUserId,
-                    'operation_type' => 'recharge'
-                ])
+                userId:        $farmUserId,
+                businessId:    $businessId,
+                amount:        $thirdPartyAmount,
+                outUserId:     $thirdPartyUserId,
+                remark:        $remark,
+                callbackData:  array_merge($callbackData, [
+                                   'third_party_app_id'  => $thirdPartyAppId,
+                                   'third_party_user_id' => $thirdPartyUserId,
+                                   'operation_type'      => 'recharge'
+                               ])
             );
 
             return TransferOrderDto::fromModel($order);
         } catch (\Exception $e) {
             \Illuminate\Support\Facades\Log::error('ThirdParty recharge order creation failed', [
-                'third_party_app_id' => $thirdPartyAppId,
-                'farm_user_id' => $farmUserId,
+                'third_party_app_id'  => $thirdPartyAppId,
+                'farm_user_id'        => $farmUserId,
                 'third_party_user_id' => $thirdPartyUserId,
-                'amount' => $thirdPartyAmount,
-                'error' => $e->getMessage()
+                'amount'              => $thirdPartyAmount,
+                'error'               => $e->getMessage()
             ]);
 
             return $e->getMessage();
@@ -93,13 +95,14 @@ class TransferThirdPartyService
      * @throws \Exception
      */
     public static function createWithdrawOrder(
-        int $thirdPartyAppId,
-        int $farmUserId,
-        string $thirdPartyUserId,
-        string $thirdPartyAmount,
+        int     $thirdPartyAppId,
+        int     $farmUserId,
+        string  $thirdPartyUserId,
+        string  $thirdPartyAmount,
         ?string $remark = null,
-        array $callbackData = []
-    ): TransferOrderDto|string {
+        array   $callbackData = []
+    ): TransferOrderDto|string
+    {
         try {
             // 根据三方应用ID查找对应的Transfer应用配置
             $transferApp = TransferApp::where('out_id3', $thirdPartyAppId)
@@ -119,25 +122,25 @@ class TransferThirdPartyService
             // 注意:这里传递的是外部金额,createTransferOutForThirdParty内部会进行金额转换
             $order = TransferLogic::createTransferOutForThirdParty(
                 transferAppId: $transferApp->id,
-                userId: $farmUserId,
-                amount: $thirdPartyAmount, // 传递外部金额
-                outUserId: $thirdPartyUserId,
-                remark: $remark,
-                callbackData: array_merge($callbackData, [
-                    'third_party_app_id' => $thirdPartyAppId,
-                    'third_party_user_id' => $thirdPartyUserId,
-                    'operation_type' => 'withdraw'
-                ])
+                userId:        $farmUserId,
+                amount:        $thirdPartyAmount, // 传递外部金额
+                outUserId:     $thirdPartyUserId,
+                remark:        $remark,
+                callbackData:  array_merge($callbackData, [
+                                   'third_party_app_id'  => $thirdPartyAppId,
+                                   'third_party_user_id' => $thirdPartyUserId,
+                                   'operation_type'      => 'withdraw'
+                               ])
             );
 
             return TransferOrderDto::fromModel($order);
         } catch (\Exception $e) {
             \Illuminate\Support\Facades\Log::error('ThirdParty withdraw order creation failed', [
-                'third_party_app_id' => $thirdPartyAppId,
-                'farm_user_id' => $farmUserId,
+                'third_party_app_id'  => $thirdPartyAppId,
+                'farm_user_id'        => $farmUserId,
                 'third_party_user_id' => $thirdPartyUserId,
-                'third_party_amount' => $thirdPartyAmount,
-                'error' => $e->getMessage()
+                'third_party_amount'  => $thirdPartyAmount,
+                'error'               => $e->getMessage()
             ]);
 
             return $e->getMessage();
@@ -146,7 +149,7 @@ class TransferThirdPartyService
 
     /**
      * 根据三方应用ID获取Transfer应用配置
-     * 
+     *
      * @param int $thirdPartyAppId 三方应用ID
      * @return TransferApp|null
      */
@@ -159,64 +162,64 @@ class TransferThirdPartyService
 
     /**
      * 检查三方应用是否支持充值
-     * 
+     *
      * @param int $thirdPartyAppId 三方应用ID
      * @return bool
      */
     public static function supportsRecharge(int $thirdPartyAppId): bool
     {
         $transferApp = self::getTransferAppByThirdPartyId($thirdPartyAppId);
-        
+
         return $transferApp && $transferApp->supportsTransferIn();
     }
 
     /**
      * 检查三方应用是否支持提现
-     * 
+     *
      * @param int $thirdPartyAppId 三方应用ID
      * @return bool
      */
     public static function supportsWithdraw(int $thirdPartyAppId): bool
     {
         $transferApp = self::getTransferAppByThirdPartyId($thirdPartyAppId);
-        
+
         return $transferApp && $transferApp->supportsTransferOut();
     }
 
     /**
      * 获取三方应用的手续费配置
-     * 
+     *
      * @param int $thirdPartyAppId 三方应用ID
      * @return array
      */
     public static function getFeeConfig(int $thirdPartyAppId): array
     {
         $transferApp = self::getTransferAppByThirdPartyId($thirdPartyAppId);
-        
+
         if (!$transferApp) {
             return [
-                'error' => '未找到对应的划转应用配置',
-                'recharge' => ['rate' => 0, 'min' => 0, 'max' => 0, 'enabled' => false],
-                'withdraw' => ['rate' => 0, 'min' => 0, 'max' => 0, 'enabled' => false],
+                'error'    => '未找到对应的划转应用配置',
+                'recharge' => [ 'rate' => 0, 'min' => 0, 'max' => 0, 'enabled' => false ],
+                'withdraw' => [ 'rate' => 0, 'min' => 0, 'max' => 0, 'enabled' => false ],
             ];
         }
 
         return [
-            'recharge' => [
-                'rate' => $transferApp->fee_in_rate,
-                'min' => $transferApp->fee_in_min,
-                'max' => $transferApp->fee_in_max,
+            'recharge'      => [
+                'rate'    => $transferApp->fee_in_rate,
+                'min'     => $transferApp->fee_in_min,
+                'max'     => $transferApp->fee_in_max,
                 'enabled' => $transferApp->isFeeEnabled('in'),
             ],
-            'withdraw' => [
-                'rate' => $transferApp->fee_out_rate,
-                'min' => $transferApp->fee_out_min,
-                'max' => $transferApp->fee_out_max,
+            'withdraw'      => [
+                'rate'    => $transferApp->fee_out_rate,
+                'min'     => $transferApp->fee_out_min,
+                'max'     => $transferApp->fee_out_max,
                 'enabled' => $transferApp->isFeeEnabled('out'),
             ],
             'exchange_rate' => $transferApp->exchange_rate,
-            'currency_id' => $transferApp->currency_id,
-            'fund_id' => $transferApp->fund_id,
+            'currency_id'   => $transferApp->currency_id,
+            'fund_id'       => $transferApp->fund_id,
         ];
     }
 
@@ -226,6 +229,7 @@ class TransferThirdPartyService
      * @param int $thirdPartyAppId 三方应用ID
      * @param string $amount 充值金额
      * @return TransferFeeDto
+     * @deprecated  暂时无用,有bug
      */
     public static function calculateRechargeFee(int $thirdPartyAppId, string $amount): TransferFeeDto
     {
@@ -234,31 +238,20 @@ class TransferThirdPartyService
         if (!$transferApp) {
             return TransferFeeDto::error(
                 originalAmount: $amount,
-                errorMessage: '未找到对应的划转应用配置'
+                errorMessage:   '未找到对应的划转应用配置'
             );
         }
 
         // 将三方金额转换为农场内部金额(充值:外部金额转内部金额)
-        $internalAmount = bcmul($amount, (string) $transferApp->exchange_rate, 10);
+        $internalAmount = bcmul($amount, (string)$transferApp->exchange_rate, 10);
 
         // 获取手续费计算结果
         $feeResult = $transferApp->calculateInFee($internalAmount);
 
         // 将结果转换为DTO
-        return TransferFeeDto::fromLegacyArray($feeResult, $amount);
+        return TransferFeeDto::f($feeResult, $amount);
     }
 
-    /**
-     * 计算提现手续费
-     *
-     * @param int $thirdPartyAppId 三方应用ID
-     * @param string $amount 提现金额
-     * @return TransferFeeDto
-     */
-    public static function calculateWithdrawFee(int $thirdPartyAppId, string $amount): TransferFeeDto
-    {
-        return self::calculateWithdrawFeeWithContext($thirdPartyAppId, $amount, []);
-    }
 
     /**
      * 计算提现手续费(带上下文信息)
@@ -275,17 +268,32 @@ class TransferThirdPartyService
         if (!$transferApp) {
             return TransferFeeDto::error(
                 originalAmount: $amount,
-                errorMessage: '未找到对应的划转应用配置'
+                errorMessage:   '未找到对应的划转应用配置'
             );
         }
 
         // 将三方金额转换为农场内部金额(提现:外部金额转内部金额)
-        $internalAmount = bcmul($amount, (string) $transferApp->exchange_rate, 10);
+        $internalAmount = bcmul($amount, (string)$transferApp->exchange_rate, 10);
 
         // 获取手续费计算结果,传递上下文信息以便URS推广模块计算正确的手续费率
         $feeResult = $transferApp->calculateOutFee($internalAmount, $context);
+        // ['fee_rate' => 手续费率, 'fee_amount' => 手续费金额, 'actual_amount' => 用户总支付金额]
+        //  public readonly float   $feeRate,
+        //        public readonly string  $feeAmount,
+        //        public readonly string  $actualAmount,
+        //        public readonly string  $originalAmount,
+        //        public readonly bool    $hasError = false,
+        //        public readonly ?string $errorMessage = null,
 
         // 将结果转换为DTO
-        return TransferFeeDto::fromLegacyArray($feeResult, $amount);
+        return TransferFeeDto::success(
+            originalAmount: $amount,
+            feeRate:        $feeResult['fee_rate'],
+            feeAmount:      $feeResult['fee_amount'],
+            actualAmount:   $internalAmount,
+            totleAmount:    $feeResult['actual_amount'],
+            additionalInfo: []
+        );
     }
+
 }