Passed
Pull Request — master (#228)
by
unknown
08:03
created

Digipay::setPaymentUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
4
namespace Shetabit\Multipay\Drivers\Digipay;
5
6
use GuzzleHttp\Client;
7
use GuzzleHttp\Exception\GuzzleException;
8
use GuzzleHttp\RequestOptions;
9
use Shetabit\Multipay\Abstracts\Driver;
10
use Shetabit\Multipay\Contracts\ReceiptInterface;
11
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
12
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
13
use Shetabit\Multipay\Invoice;
14
use Shetabit\Multipay\Receipt;
15
use Shetabit\Multipay\RedirectionForm;
16
use Shetabit\Multipay\Request;
17
18
class Digipay extends Driver
19
{
20
    /**
21
     * Digipay Client.
22
     *
23
     * @var Client
24
     */
25
    protected $client;
26
27
    /**
28
     * Invoice
29
     *
30
     * @var Invoice
31
     */
32
    protected $invoice;
33
34
    /**
35
     * Driver settings
36
     *
37
     * @var object
38
     */
39
    protected $settings;
40
    /**
41
     * Digipay Oauth Token
42
     *
43
     * @var string
44
     */
45
    protected $oauthToken;
46
47
    /**
48
     * Digipay payment url
49
     *
50
     * @var string
51
     */
52
    protected $paymentUrl;
53
54
    /**
55
     * Digipay constructor.
56
     * Construct the class with the relevant settings.
57
     *
58
     * @param Invoice $invoice
59
     * @param $settings
60
     */
61
    public function __construct(Invoice $invoice, $settings)
62
    {
63
        $this->invoice($invoice);
64
        $this->settings= (object) $settings;
65
        $this->client = new Client();
66
        $this->oauthToken = $this->oauth();
67
    }
68
69
    /**
70
     * @throws PurchaseFailedException
71
     */
72
    public function purchase(): string
73
    {
74
        $phone = $this->invoice->getDetail('phone')
75
            ?? $this->invoice->getDetail('cellphone')
76
            ?? $this->invoice->getDetail('mobile');
77
78
        /**
79
         * @see https://docs.mydigipay.com/upg.html#_request_fields_2
80
         */
81
        $data = [
82
            'amount'      => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1),
83
            'cellNumber'  => $phone,
84
            'providerId'  => $this->invoice->getUuid(),
85
            'callbackUrl' => $this->settings->callbackUrl,
86
        ];
87
88
        if (!is_null($basketDetailsDto = $this->invoice->getDetail('basketDetailsDto'))) {
89
            $data['basketDetailsDto'] = $basketDetailsDto;
90
        }
91
92
        if (!is_null($preferredGateway = $this->invoice->getDetail('preferredGateway'))) {
93
            $data['preferredGateway'] = $preferredGateway;
94
        }
95
96
        if (!is_null($splitDetailsList = $this->invoice->getDetail('splitDetailsList'))) {
97
            $data['splitDetailsList'] = $splitDetailsList;
98
        }
99
100
        /**
101
         * @see https://docs.mydigipay.com/upg.html#_query_parameters_2
102
         */
103
        $digipayType = $this->invoice->getDetail('digipayType') ?? 11;
104
105
        $response = $this
106
            ->client
107
            ->request(
108
                'POST',
109
                $this->settings->apiPurchaseUrl,
110
                [
111
                    RequestOptions::BODY  => json_encode($data),
112
                    RequestOptions::QUERY  => ['type' => $digipayType],
113
                    RequestOptions::HEADERS   => [
114
                        'Agent' => $this->invoice->getDetail('agent') ?? 'WEB',
115
                        'Content-Type'  => 'application/json',
116
                        'Authorization' => 'Bearer ' . $this->oauthToken,
117
                        'Digipay-Version' => '2022-02-02',
118
                    ],
119
                    RequestOptions::HTTP_ERRORS => false,
120
                ]
121
            );
122
123
        if ($response->getStatusCode() != 200) {
124
            // error has happened
125
            $message = $body['result']['message'] ?? 'خطا در هنگام درخواست برای پرداخت رخ داده است.';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $body seems to never exist and therefore isset should always be false.
Loading history...
126
            throw new PurchaseFailedException($message);
127
        }
128
129
        $body = json_decode($response->getBody()->getContents(), true);
130
        $this->invoice->transactionId($body['ticket']);
131
        $this->setPaymentUrl($body['redirectUrl']);
132
133
        // return the transaction's id
134
        return $this->invoice->getTransactionId();
135
    }
136
137
    public function pay(): RedirectionForm
138
    {
139
        return $this->redirectWithForm($this->getPaymentUrl(), [], 'GET');
140
    }
141
142
    /**
143
     * @throws InvalidPaymentException
144
     */
145
    public function verify(): ReceiptInterface
146
    {
147
        $tracingId = $this->invoice->getTransactionId() ?? Request::input('trackingCode');
148
149
        $response = $this->client->request(
150
            'POST',
151
            $this->settings->apiVerificationUrl . $tracingId,
152
            [
153
                RequestOptions::BODY => '{}',
154
                RequestOptions::HEADERS => [
155
                    "Accept"        => "application/json",
156
                    "Authorization" => "Bearer " . $this->oauthToken,
157
                ],
158
                RequestOptions::HTTP_ERRORS => false,
159
            ]
160
        );
161
162
        if ($response->getStatusCode() != 200) {
163
            $message = 'تراکنش تایید نشد';
164
165
            throw new InvalidPaymentException($message, (int) $response->getStatusCode());
166
        }
167
168
        $body = json_decode($response->getBody()->getContents(), true);
169
170
        return (new Receipt('digipay', $body["trackingCode"]))->detail($body);
171
    }
172
173
    /**
174
     * @throws PurchaseFailedException
175
     */
176
    protected function oauth()
177
    {
178
        $response = $this
179
            ->client
180
            ->request(
181
                'POST',
182
                $this->settings->apiOauthUrl,
183
                [
184
                    RequestOptions::HEADERS   => [
185
                        'Authorization' => 'Basic ' . base64_encode("{$this->settings->client_id}:{$this->settings->client_secret}"),
186
                    ],
187
                    RequestOptions::MULTIPART   => [
188
                        [
189
                            "name"     => "username",
190
                            "contents" => $this->settings->username,
191
                        ],
192
                        [
193
                            "name"     => "password",
194
                            "contents" => $this->settings->password,
195
                        ],
196
                        [
197
                            "name"     => "grant_type",
198
                            "contents" => 'password',
199
                        ],
200
                    ],
201
                    RequestOptions::HTTP_ERRORS => false,
202
                ]
203
            );
204
205
        if ($response->getStatusCode() != 200) {
206
            if ($response->getStatusCode() == 401) {
207
                throw new PurchaseFailedException("خطا نام کاربری یا رمز عبور شما اشتباه می باشد.");
208
            } else {
209
                throw new PurchaseFailedException("خطا در هنگام احراز هویت.");
210
            }
211
        }
212
213
        $body = json_decode($response->getBody()->getContents(), true);
214
215
        $this->oauthToken = $body['access_token'];
216
        return $body['access_token'];
217
    }
218
219
    /**
220
     * @return string
221
     */
222
    public function getPaymentUrl(): string
223
    {
224
        return $this->paymentUrl;
225
    }
226
227
    /**
228
     * @param string $paymentUrl
229
     */
230
    public function setPaymentUrl(string $paymentUrl): void
231
    {
232
        $this->paymentUrl = $paymentUrl;
233
    }
234
}
235