validated(); // 获取应用配置 $app = TransferApp::findOrFail($data['transfer_app_id']); if (!$app->is_enabled) { throw new \Exception('应用已禁用'); } // 计算金额 $outAmount = (string) $data['amount']; $amount = bcmul($outAmount, (string) $app->exchange_rate, 10); // 生成外部订单ID $outOrderId = self::generateOutOrderId('OUT'); // 创建订单 $order = TransferOrder::create([ 'transfer_app_id' => $app->id, 'out_id' => $app->out_id2 ?? 0, 'out_order_id' => $outOrderId, 'out_user_id' => $data['out_user_id'] ?? null, 'user_id' => $data['user_id'], 'currency_id' => $app->currency_id, 'fund_id' => $app->fund_id, 'type' => TransferType::OUT, 'status' => TransferStatus::CREATED, 'out_amount' => $outAmount, 'amount' => $amount, 'exchange_rate' => $app->exchange_rate, 'callback_data' => $data['callback_data'] ?? [], 'remark' => $data['remark'] ?? null, ]); // 扣除用户资金 $fundResult = FundService::decrease( $data['user_id'], $app->fund_id, $amount, "转出到{$app->title}", "transfer_out:{$order->id}" ); if (!$fundResult) { $order->updateStatus(TransferStatus::FAILED, '资金扣除失败'); throw new \Exception('余额不足或资金操作失败'); } // 判断是否为农场内部模式 if ($app->isInternalMode()) { // 内部模式直接完成 $order->updateStatus(TransferStatus::COMPLETED); } else { // 外部模式,调用外部API OrderLogic::processTransferOut($order); } return $order; } /** * 创建转入订单 * * @param array $data 订单数据 * @return TransferOrder * @throws \Exception */ public static function createTransferIn(array $data): TransferOrder { // 验证请求数据 $validation = new TransferInValidation($data); $validation->validated(); // 获取应用配置 $app = TransferApp::findOrFail($data['transfer_app_id']); if (!$app->is_enabled) { throw new \Exception('应用已禁用'); } // 检查外部订单ID是否已存在 $existingOrder = TransferOrder::where('out_order_id', $data['business_id']) ->where('out_id', $app->out_id2 ?? 0) ->first(); if ($existingOrder) { throw new \Exception('订单已存在'); } // 计算金额 $outAmount = (string) $data['amount']; $amount = bcdiv($outAmount, (string) $app->exchange_rate, 10); // 创建订单 $order = TransferOrder::create([ 'transfer_app_id' => $app->id, 'out_id' => $app->out_id2 ?? 0, 'out_order_id' => $data['business_id'], 'out_user_id' => $data['out_user_id'] ?? null, 'user_id' => $data['user_id'], 'currency_id' => $app->currency_id, 'fund_id' => $app->fund_id, 'type' => TransferType::IN, 'status' => TransferStatus::CREATED, 'out_amount' => $outAmount, 'amount' => $amount, 'exchange_rate' => $app->exchange_rate, 'callback_data' => $data['callback_data'] ?? [], 'remark' => $data['remark'] ?? null, ]); // 向用户账户转入资金 $fundResult = FundService::increase( $data['user_id'], $app->fund_id, $amount, "从{$app->title}转入", "transfer_in:{$order->id}" ); if (!$fundResult) { $order->updateStatus(TransferStatus::FAILED, '资金转入失败'); throw new \Exception('资金操作失败'); } // 判断是否为农场内部模式 if ($app->isInternalMode()) { // 内部模式直接完成 $order->updateStatus(TransferStatus::COMPLETED); } else { // 外部模式,更新状态为处理中 $order->updateStatus(TransferStatus::PROCESSING); // 发送回调通知 if ($app->supportsCallback()) { CallbackLogic::sendCallback($order); } } return $order; } /** * 处理回调结果 * * @param array $callbackData 回调数据 * @return bool */ public static function processCallback(array $callbackData): bool { // 查找订单 $order = TransferOrder::where('out_order_id', $callbackData['business_id']) ->where('out_id', $callbackData['out_id']) ->first(); if (!$order) { \Log::warning('Transfer callback order not found', $callbackData); return false; } // 更新订单状态 $status = $callbackData['success'] ? TransferStatus::COMPLETED : TransferStatus::FAILED; $message = $callbackData['message'] ?? null; return $order->updateStatus($status, $message); } /** * 生成外部订单ID * * @param string $prefix 前缀 * @return string */ private static function generateOutOrderId(string $prefix = 'TR'): string { return $prefix . date('YmdHis') . Str::random(6); } /** * 重试订单处理 * * @param int $orderId 订单ID * @return bool */ public static function retryOrder(int $orderId): bool { $order = TransferOrder::findOrFail($orderId); if (!$order->canRetry()) { throw new \Exception('订单状态不允许重试'); } // 重置状态为已创建 $order->updateStatus(TransferStatus::CREATED); // 根据订单类型重新处理 if ($order->isTransferOut()) { OrderLogic::processTransferOut($order); } else { // 转入订单重试主要是重新发送回调 if ($order->transferApp->supportsCallback()) { CallbackLogic::sendCallback($order); } } return true; } /** * 手动完成订单 * * @param int $orderId 订单ID * @param string $remark 备注 * @return bool */ public static function manualComplete(int $orderId, string $remark = ''): bool { $order = TransferOrder::findOrFail($orderId); if ($order->isFinalStatus()) { throw new \Exception('订单已处于最终状态'); } // 更新状态为已完成 $order->updateStatus(TransferStatus::COMPLETED, $remark); return true; } }