$this->merchant(), 'amount' => $amount * 10, 'callbackUrl' => $this->callbackUrl(), 'orderId' => $orderId, ])->json(); if (($response['result'] ?? null) !== 100) { throw new RuntimeException('خطا در ایجاد درخواست پرداخت: ' . ($response['message'] ?? 'پاسخ نامعتبر از درگاه')); } return Payment::create(array_merge([ 'track_id' => (string) $response['trackId'], 'amount' => $amount, 'status' => PaymentStatusEnum::Pending->value, 'payer_id' => $payer->id, ], $attributes)); } public function paymentUrl(Payment $payment): string { return self::START_URL . '/' . $payment->track_id; } public function verify(Payment $payment): Payment { if ($payment->status !== PaymentStatusEnum::Pending) { return $payment; } $response = Http::post(self::API_URL . '/verify', [ 'merchant' => $this->merchant(), 'trackId' => $payment->track_id, ])->json(); if (in_array($response['result'] ?? null, [100, 201], true)) { $payment->update([ 'status' => PaymentStatusEnum::Paid->value, 'ref_number' => $response['refNumber'] ?? null, 'verified_at' => now(), ]); } else { $payment->update(['status' => PaymentStatusEnum::Failed->value]); } return $payment; } public function markFailed(Payment $payment): Payment { if ($payment->status === PaymentStatusEnum::Pending) { $payment->update(['status' => PaymentStatusEnum::Failed->value]); } return $payment; } protected function merchant(): string { return config('services.zibal.sandbox') ? 'zibal' : config('services.zibal.merchant'); } protected function callbackUrl(): string { return config('services.zibal.callback_url') ?: route('dashboard.payments.callback'); } }