Sepordeh   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 73
c 1
b 0
f 0
dl 0
loc 207
rs 10
wmc 14

8 Methods

Rating   Name   Duplication   Size   Complexity  
A pay() 0 7 2
A createReceipt() 0 6 1
A extractDetails() 0 3 2
A verify() 0 37 2
A convertStatusCodeToMessage() 0 14 1
A __construct() 0 5 1
A purchase() 0 41 4
A notVerified() 0 3 1
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Sepordeh;
4
5
use GuzzleHttp\Client;
6
use Shetabit\Multipay\Abstracts\Driver;
7
use Shetabit\Multipay\Contracts\ReceiptInterface;
8
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
9
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
10
use Shetabit\Multipay\Invoice;
11
use Shetabit\Multipay\Receipt;
12
use Shetabit\Multipay\RedirectionForm;
13
use Shetabit\Multipay\Request;
14
15
class Sepordeh extends Driver
16
{
17
    /**
18
     * Sepordeh Client.
19
     *
20
     * @var object
21
     */
22
    protected $client;
23
24
    /**
25
     * Invoice
26
     *
27
     * @var Invoice
28
     */
29
    protected $invoice;
30
31
    /**
32
     * Driver settings
33
     *
34
     * @var object
35
     */
36
    protected $settings;
37
38
    /**
39
     * Sepordeh constructor.
40
     * Construct the class with the relevant settings.
41
     *
42
     * @param Invoice $invoice
43
     * @param $settings
44
     */
45
    public function __construct(Invoice $invoice, $settings)
46
    {
47
        $this->invoice($invoice);
48
        $this->settings = (object)$settings;
49
        $this->client = new Client();
50
    }
51
52
    /**
53
     * Purchase Invoice.
54
     *
55
     * @return string
56
     *
57
     * @throws PurchaseFailedException
58
     * @throws \GuzzleHttp\Exception\GuzzleException
59
     */
60
    public function purchase()
61
    {
62
        $orderId = $this->extractDetails('orderId');
63
        $phone = $this->extractDetails('phone');
64
        $description = $this->extractDetails('description') ?: $this->settings->description;
65
66
        $data = [
67
            "merchant" => $this->settings->merchantId,
68
            "amount" => $this->invoice->getAmount() / ($this->settings->currency == 'T' ? 1 : 10), // convert to toman
69
            "phone" => $phone,
70
            "orderId" => $orderId,
71
            "callback" => $this->settings->callbackUrl,
72
            "description" => $description,
73
        ];
74
75
        $response = $this
76
            ->client
77
            ->request(
78
                'POST',
79
                $this->settings->apiPurchaseUrl,
80
                [
81
                    "form_params" => $data,
82
                    "http_errors" => false,
83
                    'verify' => false,
84
                ]
85
            );
86
87
        $responseBody = mb_strtolower($response->getBody()->getContents());
88
        $body = @json_decode($responseBody, true);
89
        $statusCode = (int)$body['status'];
90
91
        if ($statusCode !== 200) {
92
            // some error has happened
93
            $message = $body['message'] ?? $this->convertStatusCodeToMessage($statusCode);
94
95
            throw new PurchaseFailedException($message);
96
        }
97
98
        $this->invoice->transactionId($body['information']['invoice_id']);
99
100
        return $this->invoice->getTransactionId();
101
    }
102
103
    /**
104
     * Retrieve data from details using its name.
105
     *
106
     * @return string
107
     */
108
    private function extractDetails($name)
109
    {
110
        return empty($this->invoice->getDetails()[$name]) ? null : $this->invoice->getDetails()[$name];
111
    }
112
113
    /**
114
     * Retrieve related message to given status code
115
     *
116
     * @param $statusCode
117
     *
118
     * @return string
119
     */
120
    private function convertStatusCodeToMessage(int $statusCode): string
121
    {
122
        $messages = [
123
            400 => 'مشکلی در ارسال درخواست وجود دارد',
124
            401 => 'عدم دسترسی',
125
            403 => 'دسترسی غیر مجاز',
126
            404 => 'آیتم درخواستی مورد نظر موجود نمی باشد',
127
            500 => 'مشکلی در سرور درگاه پرداخت رخ داده است',
128
            503 => 'سرور درگاه پرداخت در حال حاضر قادر به پاسخگویی نمی باشد',
129
        ];
130
131
        $unknown = 'خطای ناشناخته ای در درگاه پرداخت رخ داده است';
132
133
        return $messages[$statusCode] ?? $unknown;
134
    }
135
136
    /**
137
     * Pay the Invoice
138
     *
139
     * @return RedirectionForm
140
     */
141
    public function pay(): RedirectionForm
142
    {
143
        $basePayUrl = $this->settings->mode == 'normal' ? $this->settings->apiPaymentUrl
144
            : $this->settings->apiDirectPaymentUrl;
145
        $payUrl =  $basePayUrl . $this->invoice->getTransactionId();
146
147
        return $this->redirectWithForm($payUrl, [], 'GET');
148
    }
149
150
    /**
151
     * Verify payment
152
     *
153
     * @return ReceiptInterface
154
     *
155
     * @throws InvalidPaymentException
156
     * @throws \GuzzleHttp\Exception\GuzzleException
157
     */
158
    public function verify(): ReceiptInterface
159
    {
160
        $authority = $this->invoice->getTransactionId() ?? Request::input('authority');
161
        $data = [
162
            'merchant' => $this->settings->merchantId,
163
            'authority' => $authority,
164
        ];
165
166
        $response = $this->client->request(
167
            'POST',
168
            $this->settings->apiVerificationUrl,
169
            [
170
                'form_params' => $data,
171
                "headers" => [
172
                    "http_errors" => false,
173
                ],
174
                'verify' => false,
175
            ]
176
        );
177
178
        $responseBody = mb_strtolower($response->getBody()->getContents());
179
        $body = @json_decode($responseBody, true);
180
        $statusCode = (int)$body['status'];
181
182
        if ($statusCode !== 200) {
183
            $message = $body['message'] ?? $this->convertStatusCodeToMessage($statusCode);
184
185
            $this->notVerified($message, $statusCode);
186
        }
187
188
        $refId = $body['information']['invoice_id'];
189
        $detail = [
190
            'card' => $body['information']['card'],
191
            'orderId' => Request::input('orderId')
192
        ];
193
194
        return $this->createReceipt($refId, $detail);
195
    }
196
197
    /**
198
     * Trigger an exception
199
     *
200
     * @param $message
201
     *
202
     * @throws InvalidPaymentException
203
     */
204
    private function notVerified($message, $status)
205
    {
206
        throw new InvalidPaymentException($message, (int)$status);
207
    }
208
209
    /**
210
     * Generate the payment's receipt
211
     *
212
     * @param $referenceId
213
     *
214
     * @return Receipt
215
     */
216
    protected function createReceipt($referenceId, $detail = [])
217
    {
218
        $receipt = new Receipt('sepordeh', $referenceId);
219
        $receipt->detail($detail);
220
221
        return $receipt;
222
    }
223
}
224