user(); if (!$user) { return response()->json(['message' => 'Unauthorized'], 401); } $validated = $request->validate([ 'amount' => ['required', 'numeric', 'min:10000'], // حداقل ۱۰ هزار ریال 'description' => ['nullable', 'string', 'max:500'], 'frontend_callback' => ['nullable', 'url', 'max:500'], // URL فرانت‌اند برای redirect بعد از پرداخت ]); $wallet = $user->wallet ?? Wallet::create([ 'user_id' => $user->id, 'balance' => 0, ]); // بررسی مسدود نبودن کیف پول if ($wallet->isFrozen()) { return response()->json([ 'message' => 'کیف پول شما مسدود است. لطفاً با پشتیبانی تماس بگیرید.', ], 403); } try { // ایجاد تراکنش pending $transaction = $this->walletService->requestDeposit( wallet: $wallet, amount: $validated['amount'], description: $validated['description'] ?? 'شارژ آنلاین کیف پول', user: $user, gateway: PaymentGateway::ZARINPAL ); // دریافت لینک پرداخت از زرین‌پال $paymentData = $this->zarinpalService->requestPayment( amount: $validated['amount'], description: $validated['description'] ?? 'شارژ کیف پول IFNEX', mobile: $user->phone, email: $user->email ); // ذخیره authority و frontend_callback در metadata $metadata = $transaction->metadata ?? []; $metadata['zarinpal_authority'] = $paymentData['authority']; $metadata['frontend_callback'] = $validated['frontend_callback'] ?? null; $transaction->update(['metadata' => $metadata]); return response()->json([ 'success' => true, 'message' => 'در حال انتقال به درگاه پرداخت...', 'payment_url' => $paymentData['payment_url'], 'transaction_id' => $transaction->id, 'authority' => $paymentData['authority'], 'amount' => $paymentData['amount'], ]); } catch (\Exception $e) { Log::error('Payment gateway error', [ 'user_id' => $user->id, 'error' => $e->getMessage(), ]); return response()->json([ 'success' => false, 'message' => 'خطا در ارتباط با درگاه پرداخت: ' . $e->getMessage(), ], 500); } } /** * Callback از درگاه پرداخت (بعد از بازگشت کاربر) */ public function callback(Request $request): RedirectResponse { $authority = $request->input('Authority'); $status = $request->input('Status'); // OK یا NOK // پیدا کردن تراکنش بر اساس authority $transaction = WalletTransaction::whereJsonContains('metadata->zarinpal_authority', $authority)->first(); if (!$transaction) { Log::warning('Payment callback: transaction not found', ['authority' => $authority]); return redirect(config('ifnex.zarinpal.frontend_failure_url', '/payment/failed')); } $frontendCallback = $transaction->metadata['frontend_callback'] ?? config('ifnex.zarinpal.frontend_failure_url', '/payment/failed'); // کاربر پرداخت را لغو کرده if ($status !== 'OK') { $this->walletService->failTransaction($transaction, 'کاربر پرداخت را لغو کرد یا پرداخت ناموفق بود.'); $failureUrl = $frontendCallback . '?' . http_build_query([ 'status' => 'failed', 'transaction_id' => $transaction->id, 'message' => 'پرداخت ناموفق بود', ]); return redirect($failureUrl); } try { // بررسی صحت پرداخت $verification = $this->zarinpalService->verifyPayment( authority: $authority, expectedAmount: $transaction->amount ); if (!$verification['success']) { $this->walletService->failTransaction( $transaction, 'تأیید درگاه ناموفق بود: ' . ($verification['error_message'] ?? 'نامشخص') ); $failureUrl = $frontendCallback . '?' . http_build_query([ 'status' => 'failed', 'transaction_id' => $transaction->id, 'message' => 'تأیید پرداخت ناموفق بود', ]); return redirect($failureUrl); } // تأیید تراکنش و افزایش موجودی $this->walletService->completeDeposit( transaction: $transaction, gatewayReferenceId: $verification['ref_id'] ?? $authority ); $successUrl = config('ifnex.zarinpal.frontend_success_url', '/payment/success') . '?' . http_build_query([ 'status' => 'success', 'transaction_id' => $transaction->id, 'ref_id' => $verification['ref_id'] ?? '', 'amount' => $transaction->amount, ]); return redirect($successUrl); } catch (\Exception $e) { Log::error('Payment callback error', [ 'transaction_id' => $transaction->id, 'error' => $e->getMessage(), ]); $this->walletService->failTransaction($transaction, 'خطای سیستمی: ' . $e->getMessage()); $failureUrl = $frontendCallback . '?' . http_build_query([ 'status' => 'failed', 'transaction_id' => $transaction->id, 'message' => 'خطای سیستمی در پردازش پرداخت', ]); return redirect($failureUrl); } } /** * استعلام وضعیت یک پرداخت */ public function checkStatus(Request $request, $transactionId): JsonResponse { $user = $request->user(); $transaction = WalletTransaction::where('id', $transactionId) ->whereHas('wallet', fn ($q) => $q->where('user_id', $user->id)) ->first(); if (!$transaction) { return response()->json(['message' => 'تراکنش یافت نشد'], 404); } return response()->json([ 'transaction_id' => $transaction->id, 'status' => $transaction->status->label(), 'status_code' => $transaction->status->value, 'amount' => $transaction->amount, 'description' => $transaction->description, 'reference_id' => $transaction->gateway_reference_id, 'created_at' => $transaction->created_at->toIso8601String(), ]); } }