85 lines
2.6 KiB
PHP
85 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Payment;
|
|
|
|
use App\Enums\PaymentStatusEnum;
|
|
use App\Models\Payment;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\Http;
|
|
use RuntimeException;
|
|
|
|
class ZibalPaymentService
|
|
{
|
|
protected const API_URL = 'https://gateway.zibal.ir/v1';
|
|
protected const START_URL = 'https://gateway.zibal.ir/start';
|
|
|
|
public function request(User $payer, int $amount, string $orderId, array $attributes = []): Payment
|
|
{
|
|
$response = Http::post(self::API_URL . '/request', [
|
|
'merchant' => $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');
|
|
}
|
|
}
|