hasSufficientBalance($shipment->total_fee)) { return [ 'success' => false, 'message' => 'موجودی کیف پول کافی نیست.', 'required' => $shipment->total_fee, 'available' => $wallet->balance, ]; } try { return DB::transaction(function () use ($shipment, $wallet) { // ۱. ثبت تراکنش کسر از کیف پول $transaction = WalletTransaction::create([ 'wallet_id' => $wallet->id, 'amount' => -$shipment->total_fee, 'balance_before' => $wallet->balance, 'balance_after' => $wallet->balance - $shipment->total_fee, 'type' => TransactionType::ORDER_PAYMENT, 'status' => TransactionStatus::COMPLETED, 'gateway' => PaymentGateway::WALLET, 'description' => "پرداخت سفارش {$shipment->awb_no}", 'transactionable_type' => Shipment::class, 'transactionable_id' => $shipment->id, 'ip_address' => request()->ip(), 'user_agent' => request()->userAgent(), ]); // ۲. به‌روزرسانی موجودی کیف پول $wallet->update([ 'balance' => $wallet->balance - $shipment->total_fee, 'total_withdrawn' => $wallet->total_withdrawn + $shipment->total_fee, ]); // ۳. تغییر status سفارش به processed $shipment->update(['status' => ShipmentStatus::Processed]); // ۴. ثبت tracking event (با همه فیلدهای احتمالی) $this->createTrackingEvent($shipment, 'پرداخت تکمیل شد (از کیف پول)'); Log::info('Order paid from wallet', [ 'shipment_id' => $shipment->id, 'awb_no' => $shipment->awb_no, 'amount' => $shipment->total_fee, 'wallet_id' => $wallet->id, ]); return [ 'success' => true, 'message' => 'پرداخت با موفقیت انجام شد.', 'transaction_id' => $transaction->id, 'new_status' => 'processed', ]; }); } catch (\Exception $e) { Log::error('Wallet payment failed', [ 'shipment_id' => $shipment->id, 'error' => $e->getMessage(), ]); return [ 'success' => false, 'message' => 'خطا در پرداخت: ' . $e->getMessage(), ]; } } /** * شروع پرداخت از درگاه */ public function initiateGatewayPayment(Shipment $shipment, Wallet $wallet): array { try { // ۱. ایجاد تراکنش pending $transaction = WalletTransaction::create([ 'wallet_id' => $wallet->id, 'amount' => $shipment->total_fee, 'balance_before' => $wallet->balance, 'balance_after' => $wallet->balance, 'type' => TransactionType::ORDER_PAYMENT, 'status' => TransactionStatus::PENDING, 'gateway' => PaymentGateway::ZARINPAL, 'description' => "پرداخت سفارش {$shipment->awb_no}", 'transactionable_type' => Shipment::class, 'transactionable_id' => $shipment->id, 'ip_address' => request()->ip(), 'user_agent' => request()->userAgent(), 'metadata' => [ 'shipment_id' => $shipment->id, 'awb_no' => $shipment->awb_no, 'is_order_payment' => true, ], ]); // ۲. درخواست به درگاه $gatewayService = app()->make(\App\Services\ZarinpalService::class); if (config('ifnex.zarinpal.merchant_id') === 'fake-merchant-id-for-testing' || config('ifnex.zarinpal.sandbox', true)) { $gatewayService = app()->make(\App\Services\MockZarinpalService::class); } $paymentData = $gatewayService->requestPayment( amount: $shipment->total_fee, description: "پرداخت سفارش {$shipment->awb_no}", mobile: $shipment->user->phone, email: $shipment->user->email ); // ۳. ذخیره authority در metadata $metadata = $transaction->metadata ?? []; $metadata['zarinpal_authority'] = $paymentData['authority']; $transaction->update(['metadata' => $metadata]); return [ 'success' => true, 'payment_url' => $paymentData['payment_url'], 'transaction_id' => $transaction->id, 'authority' => $paymentData['authority'], ]; } catch (\Exception $e) { Log::error('Gateway payment initiation failed', [ 'shipment_id' => $shipment->id, 'error' => $e->getMessage(), ]); return [ 'success' => false, 'message' => 'خطا در اتصال به درگاه: ' . $e->getMessage(), ]; } } /** * تکمیل پرداخت بعد از callback موفق */ public function completeGatewayPayment(WalletTransaction $transaction): bool { try { return DB::transaction(function () use ($transaction) { $shipment = Shipment::find($transaction->transactionable_id); if (!$shipment || $shipment->status !== ShipmentStatus::Approved) { return false; } // ۱. به‌روزرسانی تراکنش $transaction->update([ 'status' => TransactionStatus::COMPLETED, 'balance_after' => $transaction->wallet->balance, ]); // ۲. تغییر status سفارش $shipment->update(['status' => ShipmentStatus::Processed]); // ۳. ثبت tracking event $this->createTrackingEvent($shipment, 'پرداخت تکمیل شد (از درگاه بانکی)'); Log::info('Order paid via gateway', [ 'shipment_id' => $shipment->id, 'awb_no' => $shipment->awb_no, 'transaction_id' => $transaction->id, ]); return true; }); } catch (\Exception $e) { Log::error('Complete gateway payment failed', [ 'transaction_id' => $transaction->id, 'error' => $e->getMessage(), ]); return false; } } /** * ساخت Tracking Event با ساختار دقیق جدول */ private function createTrackingEvent(Shipment $shipment, string $description): void { try { ShipmentTrackingEvent::create([ 'shipment_id' => $shipment->id, 'event_date' => now()->toDateString(), // YYYY-MM-DD 'event_time' => now()->format('H:i:s'), // HH:MM:SS ← فیلد جدید 'event_description' => $description, 'location' => 'سیستم', 'delivery_status' => 'processed', // ← اصلاح شد (status وجود نداشت) 'source' => 'manual', // مقدار معتبر enum TrackingSource ]); } catch (\Exception $e) { // اگر tracking event ثبت نشد، فقط لاگ کن (تراکنش را خراب نکن) Log::warning('Failed to create tracking event', [ 'shipment_id' => $shipment->id, 'error' => $e->getMessage(), ]); } } }