findOrFail($id); // 验证记录状态 abort_if($record->audit_state !== WithdrawAuditStatus::PENDING->value, 400, '提现申请状态异常'); // 获取用户钱包 $wallet = $record->wallet; abort_if(!$wallet, 404, '钱包信息不存在'); // 验证冻结金额 abort_if($wallet->frozen_amount < $record->amount, 400, '钱包冻结金额异常'); if ($status === WithdrawAuditStatus::APPROVED->value) { // 审核通过,发起自动打款 $this->processApproved($record, $remark); } else { // 审核拒绝,解冻余额 $this->processRejected($record, $remark); } // 记录审核信息 $record->auditor = auth()->user()->name; $record->audit_time = now(); $record->audit_remark = $remark; $record->audit_state = $status; $record->save(); // 记录日志 Log::info('提现申请审核完成', [ 'withdraw_id' => $record->id, 'external_no' => $record->external_no, 'status' => $status, 'remark' => $remark, 'auditor' => $record->auditor ]); }); } /** * 处理审核通过 */ private function processApproved(WalletWithdrawRecord $record, ?string $remark): void { try { // 1. 更新提现记录状态为处理中 $record->state = WithdrawStatus::PROCESSING->value; $record->save(); // 获取钱包当前余额 $wallet = $record->wallet; $currentBalance = $wallet->available_amount; $currentRechargeBalance = $wallet->recharge_amount; // 2. 创建转账记录 $transRecord = WalletTransRecord::create([ 'trans_no' => $this->generateTransNo(), 'wallet_id' => $record->wallet_id, 'owner_id' => $record->id, 'owner_type' => 'withdraw', // 业务类型:提现 'trans_type' => 2, // 交易类型:支出 'amount' => $record->amount, 'before_balance' => $currentBalance, 'after_balance' => $currentBalance - $record->amount, 'before_recharge_balance' => $currentRechargeBalance, 'after_recharge_balance' => $currentRechargeBalance, 'trans_time' => now(), 'remark' => '提现打款', 'state' => TransactionStatus::PROCESSING->value, 'province' => $record->area_code ? substr($record->area_code, 0, 2) . '0000' : null, 'city' => $record->area_code ? substr($record->area_code, 0, 4) . '00' : null, 'district' => $record->area_code ]); // 3. 调用支付服务发起转账 // TODO: 对接实际的支付服务 $paymentResult = $this->processPayment($record); if ($paymentResult['success']) { // 4. 打款成功 // 4.1 更新提现记录状态 $record->state = WithdrawStatus::SUCCESS->value; $record->withdraw_time = now(); $record->trans_no = $paymentResult['trade_no']; $record->remark = '打款成功'; $record->save(); // 4.2 更新转账记录状态 $transRecord->state = TransactionStatus::SUCCESS->value; $transRecord->trans_no = $paymentResult['trade_no']; $transRecord->save(); // 4.3 扣除钱包冻结金额 $record->wallet->decrement('frozen_amount', $record->amount); } else { // 5. 打款失败 throw new \Exception($paymentResult['message'] ?? '打款失败'); } } catch (\Exception $e) { // 6. 处理异常 Log::error('提现打款失败', [ 'withdraw_id' => $record->id, 'error' => $e->getMessage() ]); // 6.1 更新提现记录状态 $record->state = WithdrawStatus::FAILED->value; $record->remark = $e->getMessage(); $record->save(); // 6.2 更新转账记录状态 if (isset($transRecord)) { $transRecord->state = TransactionStatus::FAILED->value; $transRecord->save(); } // 6.3 解冻余额 $this->unfreezeBalance($record); throw $e; } } /** * 处理审核拒绝 */ private function processRejected(WalletWithdrawRecord $record, ?string $remark): void { // 1. 更新提现记录状态 $record->state = WithdrawStatus::FAILED->value; $record->save(); // 2. 解冻余额 $this->unfreezeBalance($record); // 3. 记录日志 Log::info('提现申请已拒绝', [ 'withdraw_id' => $record->id, 'external_no' => $record->external_no, 'amount' => $record->amount, 'remark' => $remark ]); } /** * 解冻余额 */ private function unfreezeBalance(WalletWithdrawRecord $record): void { $wallet = $record->wallet; // 获取当前余额 $currentBalance = $wallet->available_amount; $currentRechargeBalance = $wallet->recharge_amount; // 从冻结金额中减少 $wallet->decrement('frozen_amount', $record->amount); // 增加可用余额 $wallet->increment('available_amount', $record->amount); // 记录解冻操作 WalletTransRecord::create([ 'trans_no' => $this->generateTransNo(), 'wallet_id' => $wallet->id, 'owner_id' => $record->id, 'owner_type' => 'withdraw', 'trans_type' => 1, // 交易类型:收入 'amount' => $record->amount, 'before_balance' => $currentBalance, 'after_balance' => $currentBalance + $record->amount, 'before_recharge_balance' => $currentRechargeBalance, 'after_recharge_balance' => $currentRechargeBalance, 'trans_time' => now(), 'remark' => '提现拒绝解冻', 'state' => TransactionStatus::SUCCESS->value ]); } /** * 生成交易流水号 */ private function generateTransNo(): string { return 'T' . date('YmdHis') . str_pad(random_int(1, 9999), 4, '0', STR_PAD_LEFT); } /** * 处理实际打款 * TODO: 对接实际支付服务 */ private function processPayment(WalletWithdrawRecord $record): array { // 模拟打款成功 return [ 'success' => true, 'trade_no' => 'PAY' . time() . random_int(1000, 9999), 'message' => '打款成功' ]; } }