mockPayment($user, $amount, $description); } $callbackUrl = config('ifnex.zarinpal_callback_url', url('/payment/callback')); $response = Http::post('https://api.zarinpal.com/pg/v4/payment/request', [ 'merchant_id' => $merchantId, 'amount' => (int) ($amount * 10), 'callback_url' => $callbackUrl, 'description' => $description ?? 'شارچ کیف پول IFNEX', 'metadata' => [ 'user_id' => $user->id, 'email' => $user->email, ], ]); $data = $response->json(); if (($data['data']['code'] ?? 0) !== 100) { Log::error('ZarinPal payment request failed', ['response' => $data]); return [ 'success' => false, 'message' => 'خطا در درخواست پرداخت.', 'code' => $data['data']['code'] ?? 0, ]; } $authority = $data['data']['authority']; $this->payment->create([ 'user_id' => $user->id, 'gateway' => 'zarinpal', 'merchant_id' => $merchantId, 'authority' => $authority, 'amount' => (int) ($amount * 10), 'currency' => 'IRR', 'status' => 'pending', 'description' => $description, ]); return [ 'success' => true, 'authority' => $authority, 'payment_url' => "https://www.zarinpal.com/pg/StartPay/{$authority}", ]; } public function verifyPayment(string $authority, string $refId = null): array { $merchantId = config('ifnex.zarinpal_merchant_id'); $payment = $this->payment->where('authority', $authority)->first(); if (!$payment) { return [ 'success' => false, 'message' => 'تراکنش پیدا نشد.', ]; } if ($payment->status !== 'pending') { return [ 'success' => false, 'message' => 'این تراکنش قبلاً بررسی شده است.', ]; } if (!$merchantId || $merchantId === 'change-me') { return $this->mockVerify($payment); } $response = Http::post("https://api.zarinpal.com/pg/v4/payment/verify/{$merchantId}", [ 'merchant_id' => $merchantId, 'authority' => $authority, 'amount' => $payment->amount, ]); $data = $response->json(); if (($data['data']['code'] ?? 0) !== 100) { $payment->update(['status' => 'failed']); return [ 'success' => false, 'message' => 'تأیید پرداخت ناموفق بود.', 'code' => $data['data']['code'] ?? 0, ]; } $refId = $data['data']['ref_id'] ?? null; $payment->update([ 'status' => 'completed', 'ref_id' => $refId, 'paid_at' => now(), ]); if ($payment->wallet_id) { $wallet = Wallet::find($payment->wallet_id); if ($wallet) { $wallet->increment('balance', $payment->amount); } } return [ 'success' => true, 'message' => 'پرداخت با موفقیت تأیید شد.', 'ref_id' => $refId, 'amount' => $payment->amount, ]; } public function checkPayment(string $authority): array { $payment = $this->payment->where('authority', $authority)->first(); if (!$payment) { return [ 'success' => false, 'message' => 'تراکنش پیدا نشد.', ]; } return [ 'success' => true, 'status' => $payment->status, 'amount' => $payment->amount, 'ref_id' => $payment->ref_id, 'paid_at' => $payment->paid_at?->toIso8601String(), ]; } private function mockPayment(User $user, float $amount, string $description = null): array { $this->payment->create([ 'user_id' => $user->id, 'gateway' => 'zarinpal', 'amount' => (int) ($amount * 10), 'currency' => 'IRR', 'status' => 'completed', 'description' => $description, 'paid_at' => now(), ]); $user->wallet()->updateOrCreate( [], ['balance' => 0] ); $wallet = $user->wallet()->first(); $wallet->increment('balance', (int) ($amount * 10)); return [ 'success' => true, 'authority' => 'MOCK-' . strtoupper(uniqid()), 'payment_url' => null, 'mock' => true, ]; } private function mockVerify(Payment $payment): array { $payment->update([ 'status' => 'completed', 'ref_id' => 'MOCK-' . strtoupper(uniqid()), 'paid_at' => now(), ]); if ($payment->wallet_id) { $wallet = Wallet::find($payment->wallet_id); if ($wallet) { $wallet->increment('balance', $payment->amount); } } return [ 'success' => true, 'message' => 'پرداخت موقت تأیید شد (sandbox).', 'ref_id' => $payment->ref_id, 'amount' => $payment->amount, ]; } }