| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- <?php
- namespace App\Module\Transfer\Logics;
- use App\Module\Transfer\Enums\TransferStatus;
- use App\Module\Transfer\Enums\TransferType;
- use App\Module\Transfer\Models\TransferApp;
- use App\Module\Transfer\Models\TransferOrder;
- use App\Module\Transfer\Validations\TransferInValidation;
- use App\Module\Transfer\Validations\TransferOutValidation;
- use App\Module\Fund\Service\FundService;
- use Illuminate\Support\Str;
- /**
- * Transfer模块核心业务逻辑
- */
- class TransferLogic
- {
- /**
- * 创建转出订单
- *
- * @param array $data 订单数据
- * @return TransferOrder
- * @throws \Exception
- */
- public static function createTransferOut(array $data): TransferOrder
- {
- // 验证请求数据
- $validation = new TransferOutValidation($data);
- $validation->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;
- }
- }
|