PaymentGateway::verifyRequest()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 5
Ratio 62.5 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 5
loc 8
ccs 3
cts 4
cp 0.75
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 3
crap 2.0625
1
<?php
2
/**
3
 * @link https://github.com/yiiviet/yii2-payment
4
 * @copyright Copyright (c) 2017 Yii Viet
5
 * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php)
6
 */
7
8
namespace yiiviet\payment\nganluong;
9
10
use GatewayClients\DataInterface;
11
12
use yii\base\NotSupportedException;
13
14
use yiiviet\payment\BasePaymentGateway;
15
16
use vxm\gatewayclients\RequestEvent;
17
18
/**
19
 * Lớp PaymentGateway hổ trợ việc kết nối đến Ngân Lượng.
20
 * Hiện tại nó hỗ trợ 100% tính năng của Ngân Lượng v3.1, v3.2
21
 *
22
 * @method ResponseData purchase(array $data, $clientId = null)
23
 * @method ResponseData queryDR(array $data, $clientId = null)
24
 * @method VerifiedData verifyRequestPurchaseSuccess(\yii\web\Request $request = null, $clientId = null)
25
 * @method PaymentClient getClient($id = null)
26
 * @method PaymentClient getDefaultClient()
27
 *
28
 * @property PaymentClient $client
29
 * @property PaymentClient $defaultClient
30
 * @property bool $seamless
31
 *
32
 * @author Vuong Minh <[email protected]>
33
 * @since 1.0
34
 */
35
class PaymentGateway extends BasePaymentGateway
36
{
37
    /**
38
     * Lệnh `authenticate` yêu cầu Ngân Lượng xác minh OTP của khách có hợp lệ hay không.
39
     * Nó được sử dụng ở version 3.2 phương thức seamless checkout.
40
     */
41
    const RC_AUTHENTICATE = 'authenticate';
42
43
    /**
44
     * @event RequestEvent được gọi trước khi thực hiện yêu cầu Ngân Lượng xác minh OTP của khách.
45
     */
46
    const EVENT_BEFORE_AUTHENTICATE = 'beforeAuthenticate';
47
48
    /**
49
     * @event RequestEvent được gọi sau khi thực hiện yêu cầu Ngân Lượng xác minh OTP của khách.
50
     */
51
    const EVENT_AFTER_AUTHENTICATE = 'afterAuthenticate';
52
53
    /**
54
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là Ngân Lượng,
55
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
56
     */
57
    const PAYMENT_METHOD_NL = 'NL';
58
59
    /**
60
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là QR Code,
61
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
62
     */
63
    const PAYMENT_METHOD_QR_CODE = 'QRCODE';
64
65
    /**
66
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là tại ngân hàng,
67
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
68
     */
69
    const PAYMENT_METHOD_BANK_OFFLINE = 'NH_OFFLINE';
70
71
    /**
72
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là thẻ tín dụng trả trước,
73
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
74
     */
75
    const PAYMENT_METHOD_CREDIT_CARD_PREPAID = 'CREDIT_CARD_PREPAID';
76
77
    /**
78
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là thẻ VISA,
79
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
80
     */
81
    const PAYMENT_METHOD_VISA = 'VISA';
82
83
    /**
84
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là ATM Online,
85
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
86
     */
87
    const PAYMENT_METHOD_ATM_ONLINE = 'ATM_ONLINE';
88
89
    /**
90
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là ATM Offline,
91
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
92
     */
93
    const PAYMENT_METHOD_ATM_OFFLINE = 'ATM_OFFLINE';
94
95
    /**
96
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là Internet Banking,
97
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
98
     */
99
    const PAYMENT_METHOD_INTERNET_BANKING = 'IB_ONLINE';
100
101
    /**
102
     * Hằng khai báo giúp Ngân Lượng xác định phương thức thanh toán là thanh toán tại shop,
103
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
104
     * @since 1.0.3
105
     */
106
    const PAYMENT_METHOD_CASH_IN_SHOP = 'CASH_IN_SHOP';
107
108
    /**
109
     * Hằng khai báo giúp Ngân Lượng xác định phương thức giao dịch là trực tiếp (trực tiếp nhận tiền),
110
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
111
     */
112
    const PAYMENT_TYPE_REDIRECT = 1;
113
    /**
114
     * Hằng khai báo giúp Ngân Lượng xác định phương thức giao dịch là tạm giữ (tạm giữ tiền),
115
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
116
     */
117
    const PAYMENT_TYPE_SAFE = 2;
118
119
    /**
120
     * Hằng khai báo giúp bạn xác định trạng thái giao dịch thành công,
121
     * khi khởi tạo lệnh [[VRC_PURCHASE_SUCCESS]] hoặc [[RC_QUERY_DR]] tại phương thức [[request()]] hoặc [[verifyRequest()]].
122
     */
123
    const TRANSACTION_STATUS_SUCCESS = '00';
124
125
    /**
126
     * Hằng khai báo giúp bạn xác định trạng thái giao dịch thàng công nhưng Ngân Lượng tạm giữ,
127
     * khi khởi tạo lệnh [[VRC_PURCHASE_SUCCESS]] hoặc [[RC_QUERY_DR]] tại phương thức [[request()]] hoặc [[verifyRequest()]].
128
     */
129
    const TRANSACTION_STATUS_PENDING = '01';
130
131
    /**
132
     * Hằng khai báo giúp bạn xác định trạng thái giao dịch thất bại khách hàng không thanh toán hoặc lỗi,
133
     * khi khởi tạo lệnh [[VRC_PURCHASE_SUCCESS]] hoặc [[RC_QUERY_DR]] tại phương thức [[request()]] hoặc [[verifyRequest()]].
134
     */
135
    const TRANSACTION_STATUS_ERROR = '02';
136
137
    /**
138
     * Hằng khai báo giúp xác nhận thuộc tính `auth_site` trong kết quả nhận được từ `purchase` version 3.2 là xác nhận OTP thông qua
139
     * phương thức [[authenticate()]].
140
     */
141
    const AUTH_NL = 'NL';
142
143
    /**
144
     * Hằng khai báo giúp xác nhận thuộc tính `auth_site` trong kết quả nhận được từ `purchase` version 3.2 là xác nhận OTP thông qua
145
     * ngân hàng, bạn phải `redirect` khách đến trang `auth_url` để xác minh `OTP`.
146
     */
147
    const AUTH_BANK = 'BANK';
148
149
    /**
150
     * Hằng cho biết gateway ở version 3.1
151
     */
152
    const VERSION_3_1 = '3.1';
153
154
    /**
155
     * Hằng cho biết gateway ở version 3.2
156
     */
157
    const VERSION_3_2 = '3.2';
158
159
    /**
160
     * @inheritdoc
161
     */
162
    public $clientConfig = ['class' => PaymentClient::class];
163
164
    /**
165
     * @inheritdoc
166
     */
167
    public $requestDataConfig = ['class' => RequestData::class];
168
169
    /**
170
     * @inheritdoc
171
     */
172
    public $responseDataConfig = ['class' => ResponseData::class];
173
174
    /**
175
     * @inheritdoc
176
     */
177
    public $verifiedDataConfig = ['class' => VerifiedData::class];
178
179
    /**
180
     * @inheritdoc
181
     */
182 4
    public function getBaseUrl(): string
183
    {
184 4
        return ($this->sandbox ? 'https://sandbox.nganluong.vn:8088/nl30' : 'https://www.nganluong.vn') . '/checkout.api.nganluong.post.php';
185
    }
186
187
    /**
188
     * @inheritdoc
189
     * @since 1.0.3
190
     */
191 4
    public function requestCommands(): array
192
    {
193 4
        return [self::RC_PURCHASE, self::RC_QUERY_DR, self::RC_AUTHENTICATE];
194
    }
195
196
    /**
197
     * @inheritdoc
198
     */
199 2
    public function getSupportedVersions(): array
200
    {
201 2
        return [self::VERSION_3_1, self::VERSION_3_2];
202
    }
203
204
    /**
205
     * Phương thức yêu cầu Ngân Lượng xác minh OTP.
206
     * Đây là phương thức ánh xạ của [[request()]] sử dụng lệnh [[RC_AUTHENTICATE]]. Nó chỉ được hổ trợ ở version 3.2.
207
     *
208
     * @param array $data Dữ liệu yêu cầu xác minh.
209
     * @param null $clientId Client id sử dụng để tạo yêu. Nếu không thiết lập [[getDefaultClient()]] sẽ được gọi để xác định client.
210
     * @return ResponseData|DataInterface Trả về [[ResponseData]] là dữ liệu từ Ngân Lượng phản hồi.
211
     * @throws \yii\base\InvalidConfigException|NotSupportedException|\ReflectionException
212
     */
213 1
    public function authenticate(array $data, $clientId = null)
214
    {
215 1
        return $this->request(self::RC_AUTHENTICATE, $data, $clientId);
216
    }
217
218
    /**
219
     * Phương thức dùng để nhận biết gateway có phải đang sử dụng chế độ `seamless checkout` hay không (version 3.2).
220
     *
221
     * @return bool Return TRUE if current mode is seamless.
222
     */
223 4
    public function getSeamless(): bool
224
    {
225 4
        return $this->getVersion() === self::VERSION_3_2;
226
    }
227
228
    /**
229
     * Phương thức dùng để thiết lập `seamless checkout` (version 3.2).
230
     *
231
     * @param bool $seamless Mode seamless or not.
232
     * @return bool Return TRUE if seamless mode is turn on.
233
     * @throws NotSupportedException
234
     */
235
    public function setSeamless(bool $seamless): bool
236
    {
237
        return $this->setVersion($seamless ? self::VERSION_3_2 : self::VERSION_3_1);
238
    }
239
240
    /**
241
     * @inheritdoc
242
     * @throws NotSupportedException
243
     */
244 4
    public function request($command, array $data, $clientId = null): DataInterface
245
    {
246 4 View Code Duplication
        if ($command === self::RC_AUTHENTICATE && !$this->getSeamless()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
247
            throw new NotSupportedException('Authenticate command only support in `seamless` mode!');
248
        } else {
249 4
            return parent::request($command, $data, $clientId);
250
        }
251
    }
252
253
    /**
254
     * @inheritdoc
255
     * @throws NotSupportedException
256
     */
257 1
    public function verifyRequest($command, \yii\web\Request $request = null, $clientId = null)
258
    {
259 1 View Code Duplication
        if ($command === self::VRC_IPN) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
260
            throw new NotSupportedException('IPN is not supported in Ngan Luong gateway!');
261
        } else {
262 1
            return parent::verifyRequest($command, $request, $clientId);
263
        }
264
    }
265
266
    /**
267
     * @inheritdoc
268
     */
269 2
    protected function defaultVersion(): string
270
    {
271 2
        return self::VERSION_3_1;
272
    }
273
274
    /**
275
     * @inheritdoc
276
     * @throws \yii\base\InvalidConfigException
277
     */
278 9
    protected function initSandboxEnvironment()
279
    {
280 9
        $clientConfig = require(__DIR__ . '/sandbox-client.php');
281 9
        $this->setClient($clientConfig);
282 9
    }
283
284
    /**
285
     * @inheritdoc
286
     */
287 4
    public function beforeRequest(RequestEvent $event)
288
    {
289 4
        if ($event->command === self::RC_AUTHENTICATE) {
290 1
            $this->trigger(self::EVENT_BEFORE_AUTHENTICATE, $event);
291
        }
292
293 4
        parent::beforeRequest($event);
294 4
    }
295
296
    /**
297
     * @inheritdoc
298
     */
299 3
    public function afterRequest(RequestEvent $event)
300
    {
301 3
        if ($event->command === self::RC_AUTHENTICATE) {
302 1
            $this->trigger(self::EVENT_AFTER_AUTHENTICATE, $event);
303
        }
304
305 3
        parent::afterRequest($event);
306 3
    }
307
308
    /**
309
     * @inheritdoc
310
     * @throws \yii\base\InvalidConfigException|\yii\httpclient\Exception
311
     */
312 4
    protected function requestInternal(\vxm\gatewayclients\RequestData $requestData, \yii\httpclient\Client $httpClient): array
313
    {
314 4
        $data = $requestData->get();
315
316 3
        return $httpClient->post('', $data)->send()->getData();
317
    }
318
319
    /**
320
     * @inheritdoc
321
     */
322 1
    protected function getVerifyRequestData($command, \yii\web\Request $request): array
323
    {
324
        return [
325 1
            'token' => $request->get('token')
326
        ];
327
    }
328
329
}
330