feat: add withdraw request functionality and UI components
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user