Payping::verify()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 41
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 21
c 3
b 0
f 0
nc 3
nop 0
dl 0
loc 41
rs 9.584
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Payping;
4
5
use GuzzleHttp\Client;
6
use Shetabit\Multipay\Abstracts\Driver;
7
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
8
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
9
use Shetabit\Multipay\Contracts\ReceiptInterface;
10
use Shetabit\Multipay\Invoice;
11
use Shetabit\Multipay\Receipt;
12
use Shetabit\Multipay\RedirectionForm;
13
use Shetabit\Multipay\Request;
14
15
class Payping extends Driver
16
{
17
    /**
18
     * Payping 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
     * Payping constructor.
40
     * Construct the class with the relevant settings.
41
     *
42
     * @param Invoice $invoice
43
     * @param $settings
44
     * @throws InvalidPaymentException
45
     */
46
    public function __construct(Invoice $invoice, $settings)
47
    {
48
        $this->invoice($invoice);
49
        $this->settings = (object) $settings;
50
        $this->client = new Client();
51
    }
52
53
    /**
54
     * Retrieve data from details using its name.
55
     *
56
     * @return string
57
     */
58
    private function extractDetails($name)
59
    {
60
        return empty($this->invoice->getDetails()[$name]) ? null : $this->invoice->getDetails()[$name];
61
    }
62
63
    /**
64
     * Purchase Invoice.
65
     *
66
     * @return string
67
     *
68
     * @throws PurchaseFailedException
69
     * @throws \GuzzleHttp\Exception\GuzzleException
70
     */
71
    public function purchase()
72
    {
73
        $name = $this->extractDetails('name');
74
        $mobile = $this->extractDetails('mobile');
75
        $email = $this->extractDetails('email');
76
        $description = $this->extractDetails('description');
77
78
        $data = array(
79
            "amount" => $this->invoice->getAmount() / ($this->settings->currency == 'T' ? 1 : 10), // convert to toman
80
            "returnUrl" => $this->settings->callbackUrl,
81
            "payerIdentity" => $mobile ?? $email,
82
            "payerName" => $name,
83
            "description" => $description,
84
            "clientRefId" => $this->invoice->getUuid(),
85
        );
86
87
        $response = $this
88
            ->client
89
            ->request(
90
                'POST',
91
                $this->settings->apiPurchaseUrl,
92
                [
93
                    "json" => $data,
94
                    "headers" => [
95
                        "Accept" => "application/json",
96
                        "Authorization" => "bearer ".$this->settings->merchantId,
97
                    ],
98
                    "http_errors" => false,
99
                ]
100
            );
101
102
        $responseBody = mb_strtolower($response->getBody()->getContents());
103
        $body = @json_decode($responseBody, true);
104
        $statusCode = (int) $response->getStatusCode();
105
106
        if ($statusCode !== 200) {
107
            // some error has happened
108
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
109
110
            throw new PurchaseFailedException($message);
111
        }
112
113
        $this->invoice->transactionId($body['paymentCode']);
114
115
116
        // return the transaction's id
117
        return $this->invoice->getTransactionId();
118
    }
119
120
    /**
121
     * Pay the Invoice
122
     *
123
     * @return RedirectionForm
124
     */
125
    public function pay() : RedirectionForm
126
    {
127
        $payUrl = $this->settings->apiPaymentUrl.$this->invoice->getTransactionId();
128
129
        return $this->redirectWithForm($payUrl, [], 'GET');
130
    }
131
132
    /**
133
     * Verify payment
134
     *
135
     * @return ReceiptInterface
136
     *
137
     * @throws InvalidPaymentException
138
     * @throws \GuzzleHttp\Exception\GuzzleException
139
     */
140
    public function verify() : ReceiptInterface
141
    {
142
        $refId = Request::input('refid');
143
        $data = [
144
                'paymentRefId' => $refId
145
        ];
146
147
148
149
        $response = $this->client->request(
150
            'POST',
151
            $this->settings->apiVerificationUrl,
152
            [
153
                'json' => $data,
154
                "headers" => [
155
                    "Accept" => "application/json",
156
                    "Authorization" => "bearer ".$this->settings->merchantId,
157
                ],
158
                "http_errors" => false,
159
            ]
160
        );
161
162
        $responseBody = mb_strtolower($response->getBody()->getContents());
163
        $body = @json_decode($responseBody, true);
164
165
        $statusCode = (int) $response->getStatusCode();
166
167
        if ($statusCode !== 200) {
168
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
169
170
            $this->notVerified($message, $statusCode);
171
        }
172
173
        $receipt = $this->createReceipt($refId);
174
175
        $receipt->detail([
176
            "cardNumber" => $body['cardnumber'],
177
        ]);
178
179
180
        return $receipt;
181
    }
182
183
    /**
184
     * Generate the payment's receipt
185
     *
186
     * @param $referenceId
187
     *
188
     * @return Receipt
189
     */
190
    protected function createReceipt($referenceId)
191
    {
192
        $receipt = new Receipt('payping', $referenceId);
193
194
        return $receipt;
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
     * Retrieve related message to given status code
211
     *
212
     * @param $statusCode
213
     *
214
     * @return string
215
     */
216
    private function convertStatusCodeToMessage(int $statusCode) : string
217
    {
218
        $messages = [
219
            400 => 'مشکلی در ارسال درخواست وجود دارد',
220
            401 => 'عدم دسترسی',
221
            403 => 'دسترسی غیر مجاز',
222
            404 => 'آیتم درخواستی مورد نظر موجود نمی باشد',
223
            500 => 'مشکلی در سرور درگاه پرداخت رخ داده است',
224
            503 => 'سرور درگاه پرداخت در حال حاضر قادر به پاسخگویی نمی باشد',
225
        ];
226
227
        $unknown = 'خطای ناشناخته ای در درگاه پرداخت رخ داده است';
228
229
        return $messages[$statusCode] ?? $unknown;
230
    }
231
}
232