API::request()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 2
nop 5
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace YEntWeChat\Payment;
4
5
use YEntWeChat\Core\AbstractAPI;
6
use YEntWeChat\Support\Collection;
7
use YEntWeChat\Support\XML;
8
use Psr\Http\Message\ResponseInterface;
9
10
/**
11
 * Class API.
12
 */
13
class API extends AbstractAPI
14
{
15
    /**
16
     * Merchant instance.
17
     *
18
     * @var Merchant
19
     */
20
    protected $merchant;
21
22
    // api
23
    const API_PAY_ORDER = 'https://api.mch.weixin.qq.com/pay/micropay';
24
    const API_PREPARE_ORDER = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
25
    const API_QUERY = 'https://api.mch.weixin.qq.com/pay/orderquery';
26
    const API_CLOSE = 'https://api.mch.weixin.qq.com/pay/closeorder';
27
    const API_REVERSE = 'https://api.mch.weixin.qq.com/secapi/pay/reverse';
28
    const API_REFUND = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
29
    const API_QUERY_REFUND = 'https://api.mch.weixin.qq.com/pay/refundquery';
30
    const API_DOWNLOAD_BILL = 'https://api.mch.weixin.qq.com/pay/downloadbill';
31
    const API_REPORT = 'https://api.mch.weixin.qq.com/payitil/report';
32
    const API_URL_SHORTEN = 'https://api.mch.weixin.qq.com/tools/shorturl';
33
    const API_AUTH_CODE_TO_OPENID = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid';
34
35
    // order id types.
36
    const TRANSACTION_ID = 'transaction_id';
37
    const OUT_TRADE_NO = 'out_trade_no';
38
    const OUT_REFUND_NO = 'out_refund_no';
39
    const REFUND_ID = 'refund_id';
40
41
    // bill types.
42
    const BILL_TYPE_ALL = 'ALL';
43
    const BILL_TYPE_SUCCESS = 'SUCCESS';
44
    const BILL_TYPE_REFUND = 'REFUND';
45
    const BILL_TYPE_REVOKED = 'REVOKED';
46
47
    /**
48
     * API constructor.
49
     *
50
     * @param \EntWeChat\Payment\Merchant $merchant
51
     */
52
    public function __construct(Merchant $merchant)
53
    {
54
        $this->merchant = $merchant;
55
    }
56
57
    /**
58
     * Pay the order.
59
     *
60
     * @param Order $order
61
     *
62
     * @return \EntWeChat\Support\Collection
63
     */
64
    public function pay(Order $order)
65
    {
66
        return $this->request(self::API_PAY_ORDER, $order->all());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API..._ORDER, $order->all()); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 66 which is incompatible with the return type documented by YEntWeChat\Payment\API::pay of type EntWeChat\Support\Collection.
Loading history...
67
    }
68
69
    /**
70
     * Prepare order to pay.
71
     *
72
     * @param Order $order
73
     *
74
     * @return \EntWeChat\Support\Collection
75
     */
76
    public function prepare(Order $order)
77
    {
78
        $order->notify_url = $order->get('notify_url', $this->merchant->notify_url);
0 ignored issues
show
Documentation introduced by
The property notify_url does not exist on object<YEntWeChat\Payment\Merchant>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
79
        if (is_null($order->spbill_create_ip)) {
80
            $order->spbill_create_ip = ($order->trade_type === Order::NATIVE) ? get_server_ip() : get_client_ip();
81
        }
82
83
        return $this->request(self::API_PREPARE_ORDER, $order->all());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API..._ORDER, $order->all()); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 83 which is incompatible with the return type documented by YEntWeChat\Payment\API::prepare of type EntWeChat\Support\Collection.
Loading history...
84
    }
85
86
    /**
87
     * Query order.
88
     *
89
     * @param string $orderNo
90
     * @param string $type
91
     *
92
     * @return \EntWeChat\Support\Collection
93
     */
94
    public function query($orderNo, $type = self::OUT_TRADE_NO)
95
    {
96
        $params = [
97
            $type => $orderNo,
98
        ];
99
100
        return $this->request(self::API_QUERY, $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API_QUERY, $params); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 100 which is incompatible with the return type documented by YEntWeChat\Payment\API::query of type EntWeChat\Support\Collection.
Loading history...
101
    }
102
103
    /**
104
     * Query order by transaction_id.
105
     *
106
     * @param string $transactionId
107
     *
108
     * @return \EntWeChat\Support\Collection
109
     */
110
    public function queryByTransactionId($transactionId)
111
    {
112
        return $this->query($transactionId, self::TRANSACTION_ID);
113
    }
114
115
    /**
116
     * Close order by out_trade_no.
117
     *
118
     * @param $tradeNo
119
     *
120
     * @return \EntWeChat\Support\Collection
121
     */
122
    public function close($tradeNo)
123
    {
124
        $params = [
125
            'out_trade_no' => $tradeNo,
126
        ];
127
128
        return $this->request(self::API_CLOSE, $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API_CLOSE, $params); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 128 which is incompatible with the return type documented by YEntWeChat\Payment\API::close of type EntWeChat\Support\Collection.
Loading history...
129
    }
130
131
    /**
132
     * Reverse order.
133
     *
134
     * @param string $orderNo
135
     * @param string $type
136
     *
137
     * @return \EntWeChat\Support\Collection
138
     */
139
    public function reverse($orderNo, $type = self::OUT_TRADE_NO)
140
    {
141
        $params = [
142
            $type => $orderNo,
143
        ];
144
145
        return $this->safeRequest(self::API_REVERSE, $params);
146
    }
147
148
    /**
149
     * Reverse order by transaction_id.
150
     *
151
     * @param int $transactionId
152
     *
153
     * @return \EntWeChat\Support\Collection
154
     */
155
    public function reverseByTransactionId($transactionId)
156
    {
157
        return $this->reverse($transactionId, self::TRANSACTION_ID);
158
    }
159
160
    /**
161
     * Make a refund request.
162
     *
163
     * @param string $orderNo
164
     * @param float  $totalFee
165
     * @param float  $refundFee
166
     * @param string $opUserId
167
     * @param string $type
168
     * @param string $refundAccount
169
     *
170
     * @return \EntWeChat\Support\Collection
171
     */
172
    public function refund(
173
        $orderNo,
174
        $refundNo,
175
        $totalFee,
176
        $refundFee = null,
177
        $opUserId = null,
178
        $type = self::OUT_TRADE_NO,
179
        $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS'
180
    ) {
181
        $params = [
182
            $type             => $orderNo,
183
            'out_refund_no'   => $refundNo,
184
            'total_fee'       => $totalFee,
185
            'refund_fee'      => $refundFee ?: $totalFee,
186
            'refund_fee_type' => $this->merchant->fee_type,
187
            'refund_account'  => $refundAccount,
188
            'op_user_id'      => $opUserId ?: $this->merchant->merchant_id,
189
        ];
190
191
        return $this->safeRequest(self::API_REFUND, $params);
192
    }
193
194
    /**
195
     * Refund by transaction id.
196
     *
197
     * @param string $orderNo
198
     * @param float  $totalFee
199
     * @param float  $refundFee
200
     * @param string $opUserId
201
     * @param string $refundAccount
202
     *
203
     * @return \EntWeChat\Support\Collection
204
     */
205
    public function refundByTransactionId(
206
        $orderNo,
207
        $refundNo,
208
        $totalFee,
209
        $refundFee = null,
210
        $opUserId = null,
211
        $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS'
212
    ) {
213
        return $this->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, self::TRANSACTION_ID, $refundAccount);
214
    }
215
216
    /**
217
     * Query refund status.
218
     *
219
     * @param string $orderNo
220
     * @param string $type
221
     *
222
     * @return \EntWeChat\Support\Collection
223
     */
224
    public function queryRefund($orderNo, $type = self::OUT_TRADE_NO)
225
    {
226
        $params = [
227
            $type => $orderNo,
228
        ];
229
230
        return $this->request(self::API_QUERY_REFUND, $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API_QUERY_REFUND, $params); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 230 which is incompatible with the return type documented by YEntWeChat\Payment\API::queryRefund of type EntWeChat\Support\Collection.
Loading history...
231
    }
232
233
    /**
234
     * Query refund status by out_refund_no.
235
     *
236
     * @param string $refundNo
237
     *
238
     * @return \EntWeChat\Support\Collection
239
     */
240
    public function queryRefundByRefundNo($refundNo)
241
    {
242
        return $this->queryRefund($refundNo, self::OUT_REFUND_NO);
243
    }
244
245
    /**
246
     * Query refund status by transaction_id.
247
     *
248
     * @param string $transactionId
249
     *
250
     * @return \EntWeChat\Support\Collection
251
     */
252
    public function queryRefundByTransactionId($transactionId)
253
    {
254
        return $this->queryRefund($transactionId, self::TRANSACTION_ID);
255
    }
256
257
    /**
258
     * Query refund status by refund_id.
259
     *
260
     * @param string $refundId
261
     *
262
     * @return \EntWeChat\Support\Collection
263
     */
264
    public function queryRefundByRefundId($refundId)
265
    {
266
        return $this->queryRefund($refundId, self::REFUND_ID);
267
    }
268
269
    /**
270
     * Download bill history as a table file.
271
     *
272
     * @param string $date
273
     * @param string $type
274
     *
275
     * @return \Psr\Http\Message\ResponseInterface
276
     */
277
    public function downloadBill($date, $type = self::BILL_TYPE_ALL)
278
    {
279
        $params = [
280
            'bill_date' => $date,
281
            'bill_type' => $type,
282
        ];
283
284
        return $this->request(self::API_DOWNLOAD_BILL, $params, 'post', [\GuzzleHttp\RequestOptions::STREAM => true], true)->getBody();
285
    }
286
287
    /**
288
     * Convert long url to short url.
289
     *
290
     * @param string $url
291
     *
292
     * @return \EntWeChat\Support\Collection
293
     */
294
    public function urlShorten($url)
295
    {
296
        return $this->request(self::API_URL_SHORTEN, ['long_url' => $url]);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API...y('long_url' => $url)); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 296 which is incompatible with the return type documented by YEntWeChat\Payment\API::urlShorten of type EntWeChat\Support\Collection.
Loading history...
297
    }
298
299
    /**
300
     * Report API status to WeChat.
301
     *
302
     * @param string $api
303
     * @param int    $timeConsuming
304
     * @param string $resultCode
305
     * @param string $returnCode
306
     * @param array  $other         ex: err_code,err_code_des,out_trade_no,user_ip...
307
     *
308
     * @return \EntWeChat\Support\Collection
309
     */
310
    public function report($api, $timeConsuming, $resultCode, $returnCode, array $other = [])
311
    {
312
        $params = array_merge([
313
            'interface_url' => $api,
314
            'execute_time_' => $timeConsuming,
315
            'return_code'   => $returnCode,
316
            'return_msg'    => null,
317
            'result_code'   => $resultCode,
318
            'user_ip'       => get_client_ip(),
319
            'time'          => time(),
320
        ], $other);
321
322
        return $this->request(self::API_REPORT, $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API_REPORT, $params); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 322 which is incompatible with the return type documented by YEntWeChat\Payment\API::report of type EntWeChat\Support\Collection.
Loading history...
323
    }
324
325
    /**
326
     * Get openid by auth code.
327
     *
328
     * @param string $authCode
329
     *
330
     * @return \EntWeChat\Support\Collection
331
     */
332
    public function authCodeToOpenId($authCode)
333
    {
334
        return $this->request(self::API_AUTH_CODE_TO_OPENID, ['auth_code' => $authCode]);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API...h_code' => $authCode)); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 334 which is incompatible with the return type documented by YEntWeChat\Payment\API::authCodeToOpenId of type EntWeChat\Support\Collection.
Loading history...
335
    }
336
337
    /**
338
     * Merchant setter.
339
     *
340
     * @param Merchant $merchant
341
     *
342
     * @return $this
343
     */
344
    public function setMerchant(Merchant $merchant)
345
    {
346
        $this->merchant = $merchant;
347
    }
348
349
    /**
350
     * Merchant getter.
351
     *
352
     * @return Merchant
353
     */
354
    public function getMerchant()
355
    {
356
        return $this->merchant;
357
    }
358
359
    /**
360
     * Make a API request.
361
     *
362
     * @param string $api
363
     * @param array  $params
364
     * @param string $method
365
     * @param array  $options
366
     * @param bool   $returnResponse
367
     *
368
     * @return \EntWeChat\Support\Collection|\Psr\Http\Message\ResponseInterface
369
     */
370
    protected function request($api, array $params, $method = 'post', array $options = [], $returnResponse = false)
371
    {
372
        $params = array_merge($params, $this->merchant->only(['sub_appid', 'sub_mch_id']));
373
374
        $params['appid'] = $this->merchant->app_id;
375
        $params['mch_id'] = $this->merchant->merchant_id;
376
        $params['device_info'] = $this->merchant->device_info;
377
        $params['nonce_str'] = uniqid();
378
        $params = array_filter($params);
379
        $params['sign'] = generate_sign($params, $this->merchant->key, 'md5');
380
381
        $options = array_merge([
382
            'body' => XML::build($params),
383
        ], $options);
384
385
        $response = $this->getHttp()->request($api, $method, $options);
386
387
        return $returnResponse ? $response : $this->parseResponse($response);
388
    }
389
390
    /**
391
     * Request with SSL.
392
     *
393
     * @param string $api
394
     * @param array  $params
395
     * @param string $method
396
     *
397
     * @return \EntWeChat\Support\Collection
398
     */
399
    protected function safeRequest($api, array $params, $method = 'post')
400
    {
401
        $options = [
402
            'cert'    => $this->merchant->get('cert_path'),
403
            'ssl_key' => $this->merchant->get('key_path'),
404
        ];
405
406
        return $this->request($api, $params, $method, $options);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($api, $params, $method, $options); of type EntWeChat\Support\Collec...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 406 which is incompatible with the return type documented by YEntWeChat\Payment\API::safeRequest of type EntWeChat\Support\Collection.
Loading history...
407
    }
408
409
    /**
410
     * Parse Response XML to array.
411
     *
412
     * @param ResponseInterface $response
413
     *
414
     * @return \EntWeChat\Support\Collection
415
     */
416
    protected function parseResponse($response)
417
    {
418
        if ($response instanceof ResponseInterface) {
419
            $response = $response->getBody();
420
        }
421
422
        return new Collection((array) XML::parse($response));
423
    }
424
}
425