diff --git a/README-FA.md b/README-FA.md
index ab177a1..989b530 100644
--- a/README-FA.md
+++ b/README-FA.md
@@ -34,6 +34,7 @@
- [آیدی پی](https://idpay.ir)
- [زیبال](https://zibal.ir)
- [شبکه پرداخت پی](https://pay.ir)
+- [پی استار](https://paystar.ir)
## نصب
diff --git a/README.md b/README.md
index ea46578..dda2bd7 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,8 @@ Supports laravel **v8.0+** and requires php **v8.1+**
- [IDPay](https://idpay.ir)
- [Pay.ir](https://pay.ir)
- [Zibal](https://zibal.ir)
+- [PayStar](https://paystar.ir)
+
## Installation & Configuration
diff --git a/config/gateway_paystar.php b/config/gateway_paystar.php
new file mode 100644
index 0000000..68aed9a
--- /dev/null
+++ b/config/gateway_paystar.php
@@ -0,0 +1,29 @@
+ Omalizadeh\MultiPayment\Drivers\Paystar\Paystar::class,
+
+ /**
+ * gateway configurations.
+ */
+ 'main' => [
+ 'gateway_id' => '',
+ 'secret_key' => '', // If you use sign is true fill this value, It's your gateway secret key for generate sign
+ 'type' => '', // Type is required => direct | pardakht
+ 'use_sign' => false,
+ 'callback' => 'https://yoursite.com/path/to',
+ 'description' => 'payment using Paystar',
+ ],
+ 'other' => [
+ 'gateway_id' => '',
+ 'secret_key' => '',
+ 'type' => '',
+ 'use_sign' => false,
+ 'callback' => 'https://yoursite.com/path/to',
+ 'description' => 'payment using Paystar',
+ ],
+];
diff --git a/config/multipayment.php b/config/multipayment.php
index 326d8df..a3053aa 100644
--- a/config/multipayment.php
+++ b/config/multipayment.php
@@ -6,7 +6,7 @@
* set default gateway.
*
* valid pattern --> GATEWAY_NAME.GATEWAY_CONFIG_KEY
- * valid GATEWAY_NAME --> zarinpal, saman, mellat, novin, parsian, pasargad, zibal, payir, idpay
+ * valid GATEWAY_NAME --> zarinpal, saman, mellat, novin, parsian, pasargad, zibal, payir, idpay, paystar
*/
'default_gateway' => env('DEFAULT_PAYMENT_GATEWAY', 'zarinpal.main'),
diff --git a/resources/views/redirect_to_gateway.blade.php b/resources/views/redirect_to_gateway.blade.php
index b45b64f..cea082b 100644
--- a/resources/views/redirect_to_gateway.blade.php
+++ b/resources/views/redirect_to_gateway.blade.php
@@ -1,22 +1,25 @@
-
+
+
- انتقال به درگاه پرداخت
+
+ درحال انتقال به درگاه پرداخت
-
-در حال انتقال به درگاه پرداخت. لطفا چند ثانیه صبر کنید...
+
+
-
+
+ function countdown() {
+ seconds = seconds - 1;
+ if (seconds <= 0) {
+ // submit the form
+ submitForm();
+ } else {
+ // Update remaining seconds
+ document.getElementById("countdown").innerHTML = seconds;
+ // Count down using javascript
+ window.setTimeout("countdown()", 1000);
+ }
+ }
+
+ // Run countdown function
+ countdown();
+
+
diff --git a/src/Drivers/Paystar/Paystar.php b/src/Drivers/Paystar/Paystar.php
new file mode 100644
index 0000000..353c90a
--- /dev/null
+++ b/src/Drivers/Paystar/Paystar.php
@@ -0,0 +1,249 @@
+getPurchaseData();
+ $response = $this->callApi($this->getPurchaseUrl(), $this->getPurchaseData());
+
+ if ($response['status'] !== $this->getSuccessResponseStatusCode()) {
+ $message = $response['message'] ?? $this->getStatusMessage($response['status']);
+
+ throw new PurchaseFailedException($message, $response['status'], $purchaseData);
+ }
+
+ $this->getInvoice()->setToken($response['data']['token']);
+ $this->getInvoice()->setTransactionId($response['data']['ref_num']);
+ $this->getInvoice()->setInvoiceId($response['data']['order_id']);
+
+ return $this->getInvoice()->getTransactionId();
+ }
+
+ public function pay(): RedirectionForm
+ {
+ $token = $this->getInvoice()->getToken();
+ $paymentUrl = $this->getPaymentUrl();
+
+ return $this->redirect($paymentUrl, ['token' => $token]);
+ }
+
+ /**
+ * @throws PaymentFailedException
+ * @throws HttpRequestFailedException
+ * @throws InvalidConfigurationException
+ */
+ public function verify(): Receipt
+ {
+ $success = (int) request('status');
+
+ if ($success !== $this->getSuccessResponseStatusCode()) {
+ throw new PaymentFailedException('عملیات پرداخت ناموفق بود یا توسط کاربر لغو شد.');
+ }
+
+ $response = $this->callApi($this->getVerificationUrl(), $this->getVerificationData());
+
+ if ($response['status'] !== $this->getSuccessResponseStatusCode()) {
+ $message = $response['message'] ?? $this->getStatusMessage($response['status']);
+
+ throw new PaymentFailedException($message, $response['status']);
+ }
+
+ $this->getInvoice()->setTransactionId($response['data']['ref_num']);
+
+ return new Receipt(
+ $this->getInvoice(),
+ $response['data']['ref_num'],
+ null,
+ $response['data']['card_number'],
+ );
+ }
+
+ /**
+ * @throws InvalidConfigurationException
+ * @throws \Exception
+ * @throws \Exception
+ */
+ protected function getPurchaseData(): array
+ {
+ if (empty($this->settings['gateway_id'])) {
+ throw new InvalidConfigurationException('gateway_id key has not been set.');
+ }
+
+ if (empty($this->settings['type'])) {
+ throw new InvalidConfigurationException('type key has not been set.');
+ }
+
+ $description = $this->getInvoice()->getDescription() ?? $this->settings['description'];
+
+ $mobile = $this->getInvoice()->getPhoneNumber();
+ $email = $this->getInvoice()->getEmail();
+
+ if ($this->settings['use_sign']) {
+ if (empty($this->settings['secret_key'])) {
+ throw new InvalidConfigurationException('secret_key key has not been set.');
+ }
+
+ $sign = hash_hmac('sha512', $this->getInvoice()->getAmount().'#'.$this->getInvoice()->getInvoiceId().'#'.$this->settings['callback'], $this->settings['secret_key']);
+ }
+
+ if (! empty($mobile)) {
+ $mobile = $this->checkPhoneNumberFormat($mobile);
+ }
+
+ $callback = $this->getInvoice()->getCallbackUrl() ?: $this->settings['callback'];
+ if ($this->settings['use_sign']) {
+ return [
+ 'amount' => $this->getInvoice()->getAmount(),
+ 'callback' => $callback,
+ 'mobile' => $mobile,
+ 'email' => $email ?? '',
+ 'order_id' => $this->getInvoice()->getInvoiceId(),
+ 'description' => $description,
+ 'sign' => $sign ?? '',
+ ];
+ }
+
+ return [
+ 'amount' => $this->getInvoice()->getAmount(),
+ 'callback' => $callback,
+ 'mobile' => $mobile,
+ 'email' => $email ?? '',
+ 'order_id' => $this->getInvoice()->getInvoiceId(),
+ 'description' => $description,
+ ];
+
+ }
+
+ /**
+ * @throws InvalidConfigurationException
+ */
+ protected function getVerificationData(): array
+ {
+ $cartNumber = request('card_number');
+ $trackingCode = request('tracking_code');
+ if ($this->settings['use_sign']) {
+ if (empty($this->settings['secret_key'])) {
+ throw new InvalidConfigurationException('secret_key key has not been set.');
+ }
+
+ $sign = hash_hmac('sha512', $this->getInvoice()->getAmount().'#'.$this->getInvoice()->getTransactionId().'#'.$cartNumber.'#'.$trackingCode, $this->settings['secret_key']);
+ }
+
+ if ($this->settings['use_sign']) {
+ return [
+ 'ref_num' => $this->getInvoice()->getTransactionId(),
+ 'amount' => $this->getInvoice()->getAmount(),
+ 'sign' => $sign ?? '',
+ ];
+ }
+
+ return [
+ 'ref_num' => $this->getInvoice()->getTransactionId(),
+ 'amount' => $this->getInvoice()->getAmount(),
+ ];
+
+ }
+
+ protected function getStatusMessage(int|string $statusCode): string
+ {
+ $messages = [
+ '-101' => 'درخواست نامعتبر (خطا در پارامترهای ورودی)',
+ '-102' => 'درگاه فعال نیست',
+ '-103' => 'توکن تکراری است',
+ '-104' => 'مبلغ بیشتر از سقف مجاز درگاه است',
+ '-105' => 'شناسه ref_num معتبر نیست',
+ '-106' => 'تراکنش قبلا وریفای شده است',
+ '-107' => 'پارامترهای ارسال شده نامعتبر است',
+ '-108' => 'تراکنش را نمیتوان وریفای کرد',
+ '-109' => 'تراکنش وریفای نشد',
+ '-198' => 'تراکنش ناموفق',
+ '-1' => 'درخواست نامعتبر (خطا در پارامترهای ورودی)',
+ '-2' => 'درگاه فعال نیست',
+ '-3' => 'توکن تکراری است',
+ '-4' => 'مبلغ بیشتر از سقف مجاز درگاه است',
+ '-5' => 'شناسه ref_num معتبر نیست',
+ '-6' => 'تراکنش قبلا وریفای شده است',
+ '-7' => 'پارامترهای ارسال شده نامعتبر است',
+ '-8' => 'تراکنش را نمیتوان وریفای کرد',
+ '-9' => 'تراکنش وریفای نشد',
+ '-98' => 'تراکنش ناموفق',
+ '-99' => 'خطای سامانه',
+ ];
+
+ return array_key_exists($statusCode, $messages) ? $messages[$statusCode] : 'خطای تعریف نشده رخ داده است.';
+ }
+
+ protected function getSuccessResponseStatusCode(): int
+ {
+ return 1;
+ }
+
+ protected function getPurchaseUrl(): string
+ {
+ return 'https://core.paystar.ir/api/'.$this->settings['type'].'/create';
+ }
+
+ protected function getPaymentUrl(): string
+ {
+ return 'https://core.paystar.ir/api/'.$this->settings['type'].'/payment';
+ }
+
+ protected function getVerificationUrl(): string
+ {
+ return 'https://core.paystar.ir/api/'.$this->settings['type'].'/verify';
+ }
+
+ private function getRequestHeaders(): array
+ {
+ return [
+ 'Content-Type' => 'application/json',
+ 'Accept' => 'application/json',
+ ];
+ }
+
+ /**
+ * @throws HttpRequestFailedException
+ */
+ private function callApi(string $url, array $data)
+ {
+ $headers = $this->getRequestHeaders();
+ $response = Http::withHeaders($headers)->withToken($this->settings['gateway_id'])->post($url, $data);
+
+ if ($response->successful()) {
+ return $response->json();
+ }
+
+ throw new HttpRequestFailedException($response->body(), $response->status());
+ }
+
+ private function checkPhoneNumberFormat(string $phoneNumber): string
+ {
+ if (strlen($phoneNumber) === 12 && Str::startsWith($phoneNumber, '98')) {
+ return Str::replaceFirst('98', '0', $phoneNumber);
+ }
+
+ if (strlen($phoneNumber) === 10 && Str::startsWith($phoneNumber, '9')) {
+ return '0'.$phoneNumber;
+ }
+
+ return $phoneNumber;
+ }
+}
diff --git a/src/Providers/MultiPaymentServiceProvider.php b/src/Providers/MultiPaymentServiceProvider.php
index 601bc88..6a3be22 100644
--- a/src/Providers/MultiPaymentServiceProvider.php
+++ b/src/Providers/MultiPaymentServiceProvider.php
@@ -74,6 +74,10 @@ public function boot()
$this->publishes([
__DIR__.'/../../config/gateway_payir.php' => config_path('gateway_payir.php'),
], 'payir-config');
+
+ $this->publishes([
+ __DIR__.'/../../config/gateway_paystar.php' => config_path('gateway_paystar.php'),
+ ], 'paystar-config');
}
}
}