Vandar::purchase()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 44
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 29
c 2
b 0
f 0
nc 4
nop 0
dl 0
loc 44
rs 9.456
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Vandar;
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 Vandar extends Driver
16
{
17
    /**
18
     * Vandar 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
    const PAYMENT_STATUS_FAILED = 'FAILED';
39
    const PAYMENT_STATUS_OK = 'OK';
40
41
    public function __construct(Invoice $invoice, $settings)
42
    {
43
        $this->invoice($invoice);
44
        $this->settings = (object) $settings;
45
        $this->client = new Client();
46
    }
47
48
    /**
49
     * Retrieve data from details using its name.
50
     *
51
     * @return string
52
     */
53
    private function extractDetails($name)
54
    {
55
        return empty($this->invoice->getDetails()[$name]) ? null : $this->invoice->getDetails()[$name];
56
    }
57
58
    /**
59
     * @return string
60
     * @throws \GuzzleHttp\Exception\GuzzleException
61
     * @throws \Shetabit\Multipay\Exceptions\PurchaseFailedException
62
     */
63
    public function purchase()
64
    {
65
        $mobile = $this->extractDetails('mobile');
66
        $description = $this->extractDetails('description');
67
        $nationalCode = $this->extractDetails('national_code');
68
        $validCard = $this->extractDetails('valid_card_number');
69
        $factorNumber = $this->extractDetails('factorNumber');
70
71
        $data = [
72
            'api_key' => $this->settings->merchantId,
73
            'amount' => $this->invoice->getAmount() / ($this->settings->currency == 'T' ? 1 : 10), // convert to toman
74
            'callback_url' => $this->settings->callbackUrl,
75
            'description' => $description,
76
            'mobile_number' => $mobile,
77
            'national_code' => $nationalCode,
78
            'valid_card_number' => $validCard,
79
            'factorNumber' => $factorNumber,
80
        ];
81
82
        $response = $this->client
83
            ->request(
84
                'POST',
85
                $this->settings->apiPurchaseUrl,
86
                [
87
                    'json' => $data,
88
                    'headers' => [
89
                        "Accept" => "application/json",
90
                    ],
91
                    'http_errors' => false,
92
                ]
93
            );
94
95
        $responseBody = json_decode($response->getBody()->getContents(), true);
96
        $statusCode = (int) $responseBody['status'];
97
98
        if ($statusCode !== 1) {
99
            $errors = array_pop($responseBody['errors']);
100
101
            throw new PurchaseFailedException($errors);
102
        }
103
104
        $this->invoice->transactionId($responseBody['token']);
105
106
        return $this->invoice->getTransactionId();
107
    }
108
109
    /**
110
     * @return \Shetabit\Multipay\RedirectionForm
111
     */
112
    public function pay(): RedirectionForm
113
    {
114
        $url = $this->settings->apiPaymentUrl . $this->invoice->getTransactionId();
115
116
        return $this->redirectWithForm($url, [], 'GET');
117
    }
118
119
    /**
120
     * @return ReceiptInterface
121
     *
122
     * @throws \GuzzleHttp\Exception\GuzzleException
123
     * @throws \Shetabit\Multipay\Exceptions\InvalidPaymentException
124
     */
125
    public function verify(): ReceiptInterface
126
    {
127
        $token = Request::get('token');
128
        $paymentStatus = Request::get('payment_status');
129
        $data = [
130
            'api_key' => $this->settings->merchantId,
131
            'token' => $token
132
        ];
133
134
        if ($paymentStatus == self::PAYMENT_STATUS_FAILED) {
135
            $this->notVerified('پرداخت با شکست مواجه شد.');
136
        }
137
138
        $response = $this->client
139
            ->request(
140
                'POST',
141
                $this->settings->apiVerificationUrl,
142
                [
143
                    'json' => $data,
144
                    'headers' => [
145
                        "Accept" => "application/json",
146
                    ],
147
                    'http_errors' => false,
148
                ]
149
            );
150
151
        $responseBody = json_decode($response->getBody()->getContents(), true);
152
        $statusCode = (int) $responseBody['status'];
153
154
        if ($statusCode !== 1) {
155
            if (isset($responseBody['error'])) {
156
                $message = is_array($responseBody['error']) ? array_pop($responseBody['error']) : $responseBody['error'];
157
            }
158
159
            if (isset($responseBody['errors']) and is_array($responseBody['errors'])) {
160
                $message = array_pop($responseBody['errors']);
161
            }
162
163
            $this->notVerified($message ?? '', $statusCode);
164
        }
165
166
        $receipt = $this->createReceipt($token);
167
168
        $receipt->detail([
169
            "amount" => $responseBody['amount'],
170
            "realAmount" => $responseBody['realAmount'],
171
            "wage" => $responseBody['wage'],
172
            "cardNumber" => $responseBody['cardNumber'],
173
        ]);
174
175
        return $receipt;
176
    }
177
178
    /**
179
     * Generate the payment's receipt
180
     *
181
     * @param $referenceId
182
     *
183
     * @return Receipt
184
     */
185
    protected function createReceipt($referenceId)
186
    {
187
        $receipt = new Receipt('vandar', $referenceId);
188
189
        return $receipt;
190
    }
191
192
    /**
193
     * @param $message
194
     * @throws \Shetabit\Multipay\Exceptions\InvalidPaymentException
195
     */
196
    protected function notVerified($message, $status = 0)
197
    {
198
        if (empty($message)) {
199
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.', (int)$status);
200
        } else {
201
            throw new InvalidPaymentException($message, (int)$status);
202
        }
203
    }
204
}
205