Completed
Push — master ( 02e31a...ea780f )
by Vuong
06:21
created

PaymentGateway::getHttpClientConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 12
Ratio 100 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 12
loc 12
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 0
crap 1
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_ONLINE';
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 giao dịch là trực tiếp (trực tiếp nhận tiền),
103
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
104
     */
105
    const PAYMENT_TYPE_REDIRECT = 1;
106
    /**
107
     * 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),
108
     * khi khởi tạo lệnh [[RC_PURCHASE]] tại phương thức [[request()]].
109
     */
110
    const PAYMENT_TYPE_SAFE = 2;
111
112
    /**
113
     * Hằng khai báo giúp bạn xác định trạng thái giao dịch thành công,
114
     * 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()]].
115
     */
116
    const TRANSACTION_STATUS_SUCCESS = '00';
117
118
    /**
119
     * 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ữ,
120
     * 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()]].
121
     */
122
    const TRANSACTION_STATUS_PENDING = '01';
123
124
    /**
125
     * 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,
126
     * 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()]].
127
     */
128
    const TRANSACTION_STATUS_ERROR = '02';
129
130
    /**
131
     * 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
132
     * phương thức [[authenticate()]].
133
     */
134
    const AUTH_NL = 'NL';
135
136
    /**
137
     * 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
138
     * ngân hàng, bạn phải `redirect` khách đến trang `auth_url` để xác minh `OTP`.
139
     */
140
    const AUTH_BANK = 'BANK';
141
142
    /**
143
     * Hằng cho biết gateway ở version 3.1
144
     */
145
    const VERSION_3_1 = '3.1';
146
147
    /**
148
     * Hằng cho biết gateway ở version 3.2
149
     */
150
    const VERSION_3_2 = '3.2';
151
152
    /**
153
     * @inheritdoc
154
     */
155
    public $clientConfig = ['class' => PaymentClient::class];
156
157
    /**
158
     * @inheritdoc
159
     */
160
    public $requestDataConfig = ['class' => RequestData::class];
161
162
    /**
163
     * @inheritdoc
164
     */
165
    public $responseDataConfig = ['class' => ResponseData::class];
166
167
    /**
168
     * @inheritdoc
169
     */
170
    public $verifiedDataConfig = ['class' => VerifiedData::class];
171
172
    /**
173
     * @inheritdoc
174
     */
175 4
    public function getBaseUrl(): string
176
    {
177 4
        return ($this->sandbox ? 'https://sandbox.nganluong.vn:8088/nl30' : 'https://www.nganluong.vn') . '/checkout.api.nganluong.post.php';
178
    }
179
180
    /**
181
     * @inheritdoc
182
     */
183 2
    public function getSupportedVersions(): array
184
    {
185 2
        return [self::VERSION_3_1, self::VERSION_3_2];
186
    }
187
188
    /**
189
     * Phương thức yêu cầu Ngân Lượng xác minh OTP.
190
     * Đâ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.
191
     *
192
     * @param array $data Dữ liệu yêu cầu xác minh.
193
     * @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.
194
     * @return ResponseData|DataInterface Trả về [[ResponseData]] là dữ liệu từ Ngân Lượng phản hồi.
195
     * @throws \yii\base\InvalidConfigException|NotSupportedException|\ReflectionException
196
     */
197 1
    public function authenticate(array $data, $clientId = null)
198
    {
199 1
        return $this->request(self::RC_AUTHENTICATE, $data, $clientId);
200
    }
201
202
    /**
203
     * 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).
204
     *
205
     * @return bool Return TRUE if current mode is seamless.
206
     */
207 4
    public function getSeamless(): bool
208
    {
209 4
        return $this->getVersion() === self::VERSION_3_2;
210
    }
211
212
    /**
213
     * Phương thức dùng để thiết lập `seamless checkout` (version 3.2).
214
     *
215
     * @param bool $seamless Mode seamless or not.
216
     * @return bool Return TRUE if seamless mode is turn on.
217
     * @throws NotSupportedException
218
     */
219
    public function setSeamless(bool $seamless): bool
220
    {
221
        return $this->setVersion($seamless ? self::VERSION_3_2 : self::VERSION_3_1);
222
    }
223
224
    /**
225
     * @inheritdoc
226
     * @throws NotSupportedException
227
     */
228 4
    public function request($command, array $data, $clientId = null): DataInterface
229
    {
230 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...
231
            throw new NotSupportedException('Authenticate command only support in `seamless` mode!');
232
        } else {
233 4
            return parent::request($command, $data, $clientId);
234
        }
235
    }
236
237
    /**
238
     * @inheritdoc
239
     * @throws NotSupportedException
240
     */
241 1
    public function verifyRequest($command, \yii\web\Request $request = null, $clientId = null)
242
    {
243 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...
244
            throw new NotSupportedException('IPN is not supported in Ngan Luong gateway!');
245
        } else {
246 1
            return parent::verifyRequest($command, $request, $clientId);
247
        }
248
    }
249
250
    /**
251
     * @inheritdoc
252
     */
253 2
    protected function defaultVersion(): string
254
    {
255 2
        return self::VERSION_3_1;
256
    }
257
258
    /**
259
     * @inheritdoc
260
     * @throws \yii\base\InvalidConfigException
261
     */
262 6
    protected function initSandboxEnvironment()
263
    {
264 6
        $clientConfig = require(__DIR__ . '/sandbox-client.php');
265 6
        $this->setClient($clientConfig);
266 6
    }
267
268
    /**
269
     * @inheritdoc
270
     */
271 4
    public function beforeRequest(RequestEvent $event)
272
    {
273 4
        if ($event->command === self::RC_AUTHENTICATE) {
274 1
            $this->trigger(self::EVENT_BEFORE_AUTHENTICATE, $event);
275
        }
276
277 4
        parent::beforeRequest($event);
278 4
    }
279
280
    /**
281
     * @inheritdoc
282
     */
283 3
    public function afterRequest(RequestEvent $event)
284
    {
285 3
        if ($event->command === self::RC_AUTHENTICATE) {
286 1
            $this->trigger(self::EVENT_AFTER_AUTHENTICATE, $event);
287
        }
288
289 3
        parent::afterRequest($event);
290 3
    }
291
292
    /**
293
     * @inheritdoc
294
     * @throws \yii\base\InvalidConfigException|\yii\httpclient\Exception
295
     */
296 4
    protected function requestInternal(\vxm\gatewayclients\RequestData $requestData, \yii\httpclient\Client $httpClient): array
297
    {
298 4
        $data = $requestData->get();
299
300 3
        return $httpClient->post('', $data)->send()->getData();
301
    }
302
303
    /**
304
     * @inheritdoc
305
     */
306 1
    protected function getVerifyRequestData($command, \yii\web\Request $request): array
307
    {
308
        return [
309 1
            'token' => $request->get('token')
310
        ];
311
    }
312
313
}
314