where('is_enabled', true) ->first(); if (!$transferApp) { return '未找到对应的划转应用配置或应用已禁用'; } // 检查应用是否支持转入 if (!$transferApp->supportsTransferIn()) { return '该应用不支持充值功能或充值功能已被禁用'; } // 生成业务订单ID(使用时间戳+随机字符串) // 调用Transfer模块的转入逻辑 $order = TransferLogic::createTransferIn( transferAppId: $transferApp->id, userId: $farmUserId, out_order_id: $order_id, 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_user_id' => $thirdPartyUserId, 'amount' => $thirdPartyAmount, 'error' => $e->getMessage() ]); return $e->getMessage(); } } /** * 创建提现单(转出订单) * * @param int $thirdPartyAppId 三方应用ID * @param int $farmUserId 农场用户ID * @param string $thirdPartyUserId 三方用户ID * @param string $thirdPartyAmount 三方金额(外部金额) * @param string|null $remark 备注 * @param array $callbackData 回调数据 * @return TransferOrderDto|string 成功返回DTO,失败返回错误信息 * @throws \Exception */ public static function createWithdrawOrder( int $thirdPartyAppId, int $farmUserId, string $thirdPartyUserId, string $order_id, string $thirdPartyAmount, ?string $remark = null, array $callbackData = [] ): TransferOrderDto|string { try { // 根据三方应用ID查找对应的Transfer应用配置 $transferApp = TransferApp::where('out_id3', $thirdPartyAppId) ->where('is_enabled', true) ->first(); if (!$transferApp) { return '未找到对应的划转应用配置或应用已禁用'; } // 检查应用是否支持转出 if (!$transferApp->supportsTransferOut()) { return '该应用不支持提现功能或提现功能已被禁用'; } // 调用Transfer模块的第三方转出逻辑(跳过密码验证) // 注意:这里传递的是外部金额,createTransferOutForThirdParty内部会进行金额转换 $order = TransferLogic::createTransferOutForThirdParty( transferAppId: $transferApp->id, userId: $farmUserId, amount: $thirdPartyAmount, // 传递外部金额 outUserId: $thirdPartyUserId, out_order_id: $order_id, 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_user_id' => $thirdPartyUserId, 'third_party_amount' => $thirdPartyAmount, 'error' => $e->getMessage() ]); return $e->getMessage(); } } /** * 根据三方应用ID获取Transfer应用配置 * * @param int $thirdPartyAppId 三方应用ID * @return TransferApp|null */ public static function getTransferAppByThirdPartyId(int $thirdPartyAppId): ?TransferApp { return TransferApp::where('out_id3', $thirdPartyAppId) ->where('is_enabled', true) ->first(); } /** * 检查三方应用是否支持充值 * * @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 ], ]; } return [ '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, 'enabled' => $transferApp->isFeeEnabled('out'), ], 'exchange_rate' => $transferApp->exchange_rate, 'currency_id' => $transferApp->currency_id, 'fund_id' => $transferApp->fund_id, ]; } /** * 计算提现手续费(带上下文信息) * * @param int $thirdPartyAppId 三方应用ID * @param string $amount 提现金额(外部金额) * @param array $context 上下文信息(包含用户ID等,用于URS推广模块计算手续费率) * @return TransferFeeDto */ public static function calculateWithdrawFeeWithContext(int $thirdPartyAppId, string $amount, array $context = []): TransferFeeDto { $transferApp = self::getTransferAppByThirdPartyId($thirdPartyAppId); if (!$transferApp) { return TransferFeeDto::error( originalAmount: $amount, errorMessage: '未找到对应的划转应用配置' ); } // 将三方金额转换为农场内部金额(提现:外部金额转内部金额) $internalAmount = bcmul($amount, (string)$transferApp->exchange_rate, 10); // 获取手续费计算结果,传递上下文信息以便URS推广模块计算正确的手续费率 $FeeCalculatedEvent = \App\Module\Transfer\Services\FeeService::calculateOutFee($transferApp, $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::success( originalAmount: $amount, feeRate: $FeeCalculatedEvent->feeRate, feeAmount: $FeeCalculatedEvent->feeAmount, actualAmount: $internalAmount, totleAmount: $FeeCalculatedEvent->totleAmount, additionalInfo: [] ); } }