Completed
Pull Request — master (#666)
by
unknown
06:44
created

API::getSandboxSignKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
/**
13
 * API.php.
14
 *
15
 * @author    overtrue <[email protected]>
16
 * @copyright 2015 overtrue <[email protected]>
17
 *
18
 * @see      https://github.com/overtrue
19
 * @see      http://overtrue.me
20
 */
21
22
namespace EasyWeChat\Payment;
23
24
use EasyWeChat\Core\AbstractAPI;
25
use EasyWeChat\Support\Collection;
26
use EasyWeChat\Support\XML;
27
use Psr\Http\Message\ResponseInterface;
28
29
/**
30
 * Class API.
31
 */
32
class API extends AbstractAPI
33
{
34
    /**
35
     * Merchant instance.
36
     *
37
     * @var Merchant
38
     */
39
    protected $merchant;
40
41
    /**
42
     * Sandbox box mode.
43
     *
44
     * @var bool
45
     */
46
    protected $sandboxEnabled = false;
47
48
    const API_HOST = 'https://api.mch.weixin.qq.com';
49
50
    // api
51
    const API_PAY_ORDER = '/pay/micropay';
52
    const API_PREPARE_ORDER = '/pay/unifiedorder';
53
    const API_QUERY = '/pay/orderquery';
54
    const API_CLOSE = '/pay/closeorder';
55
    const API_REVERSE = '/secapi/pay/reverse';
56
    const API_REFUND = '/secapi/pay/refund';
57
    const API_QUERY_REFUND = '/pay/refundquery';
58
    const API_DOWNLOAD_BILL = '/pay/downloadbill';
59
    const API_REPORT = '/payitil/report';
60
61
    const API_URL_SHORTEN = 'https://api.mch.weixin.qq.com/tools/shorturl';
62
    const API_AUTH_CODE_TO_OPENID = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid';
63
    const API_SANDBOX_SIGN_KEY = 'https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey';
64
65
    // order id types.
66
    const TRANSACTION_ID = 'transaction_id';
67
    const OUT_TRADE_NO = 'out_trade_no';
68
    const OUT_REFUND_NO = 'out_refund_no';
69
    const REFUND_ID = 'refund_id';
70
71
    // bill types.
72
    const BILL_TYPE_ALL = 'ALL';
73
    const BILL_TYPE_SUCCESS = 'SUCCESS';
74
    const BILL_TYPE_REFUND = 'REFUND';
75
    const BILL_TYPE_REVOKED = 'REVOKED';
76
77
    /**
78
     * API constructor.
79
     *
80
     * @param \EasyWeChat\Payment\Merchant $merchant
81
     */
82 12
    public function __construct(Merchant $merchant)
83
    {
84 12
        $this->merchant = $merchant;
85 12
    }
86
87
    /**
88
     * Pay the order.
89
     *
90
     * @param Order $order
91
     *
92
     * @return \EasyWeChat\Support\Collection
93
     */
94 1
    public function pay(Order $order)
95
    {
96 1
        return $this->request($this->wrapApi(self::API_PAY_ORDER), $order->all());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($this->wr...ORDER), $order->all()); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 96 which is incompatible with the return type documented by EasyWeChat\Payment\API::pay of type EasyWeChat\Support\Collection.
Loading history...
97
    }
98
99
    /**
100
     * Prepare order to pay.
101
     *
102
     * @param Order $order
103
     *
104
     * @return \EasyWeChat\Support\Collection
105
     */
106 1
    public function prepare(Order $order)
107
    {
108 1
        $order->notify_url = $order->get('notify_url', $this->merchant->notify_url);
109 1
        if (is_null($order->spbill_create_ip)) {
110 1
            $order->spbill_create_ip = ($order->trade_type === Order::NATIVE) ? get_server_ip() : get_client_ip();
111 1
        }
112
113 1
        return $this->request($this->wrapApi(self::API_PREPARE_ORDER), $order->all());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($this->wr...ORDER), $order->all()); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 113 which is incompatible with the return type documented by EasyWeChat\Payment\API::prepare of type EasyWeChat\Support\Collection.
Loading history...
114
    }
115
116
    /**
117
     * Query order.
118
     *
119
     * @param string $orderNo
120
     * @param string $type
121
     *
122
     * @return \EasyWeChat\Support\Collection
123
     */
124 1 View Code Duplication
    public function query($orderNo, $type = self::OUT_TRADE_NO)
125
    {
126
        $params = [
127 1
            $type => $orderNo,
128 1
        ];
129
130 1
        return $this->request($this->wrapApi(self::API_QUERY), $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($this->wr...::API_QUERY), $params); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 130 which is incompatible with the return type documented by EasyWeChat\Payment\API::query of type EasyWeChat\Support\Collection.
Loading history...
131
    }
132
133
    /**
134
     * Query order by transaction_id.
135
     *
136
     * @param string $transactionId
137
     *
138
     * @return \EasyWeChat\Support\Collection
139
     */
140 1
    public function queryByTransactionId($transactionId)
141
    {
142 1
        return $this->query($transactionId, self::TRANSACTION_ID);
143
    }
144
145
    /**
146
     * Close order by out_trade_no.
147
     *
148
     * @param $tradeNo
149
     *
150
     * @return \EasyWeChat\Support\Collection
151
     */
152 1
    public function close($tradeNo)
153
    {
154
        $params = [
155 1
            'out_trade_no' => $tradeNo,
156 1
        ];
157
158 1
        return $this->request($this->wrapApi(self::API_CLOSE), $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($this->wr...::API_CLOSE), $params); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 158 which is incompatible with the return type documented by EasyWeChat\Payment\API::close of type EasyWeChat\Support\Collection.
Loading history...
159
    }
160
161
    /**
162
     * Reverse order.
163
     *
164
     * @param string $orderNo
165
     * @param string $type
166
     *
167
     * @return \EasyWeChat\Support\Collection
168
     */
169 1
    public function reverse($orderNo, $type = self::OUT_TRADE_NO)
170
    {
171
        $params = [
172 1
            $type => $orderNo,
173 1
        ];
174
175 1
        return $this->safeRequest($this->wrapApi(self::API_REVERSE), $params);
176
    }
177
178
    /**
179
     * Reverse order by transaction_id.
180
     *
181
     * @param int $transactionId
182
     *
183
     * @return \EasyWeChat\Support\Collection
184
     */
185
    public function reverseByTransactionId($transactionId)
186
    {
187
        return $this->reverse($transactionId, self::TRANSACTION_ID);
188
    }
189
190
    /**
191
     * Make a refund request.
192
     *
193
     * @param string $orderNo
194
     * @param float  $totalFee
195
     * @param float  $refundFee
196
     * @param string $opUserId
197
     * @param string $type
198
     * @param string $refundAccount
199
     *
200
     * @return \EasyWeChat\Support\Collection
201
     */
202 1
    public function refund(
203
        $orderNo,
204
        $refundNo,
205
        $totalFee,
206
        $refundFee = null,
207
        $opUserId = null,
208
        $type = self::OUT_TRADE_NO,
209
        $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS'
210
        ) {
211
        $params = [
212 1
            $type => $orderNo,
213 1
            'out_refund_no' => $refundNo,
214 1
            'total_fee' => $totalFee,
215 1
            'refund_fee' => $refundFee ?: $totalFee,
216 1
            'refund_fee_type' => $this->merchant->fee_type,
217 1
            'refund_account' => $refundAccount,
218 1
            'op_user_id' => $opUserId ?: $this->merchant->merchant_id,
219 1
        ];
220
221 1
        return $this->safeRequest($this->wrapApi(self::API_REFUND), $params);
222
    }
223
224
    /**
225
     * Refund by transaction id.
226
     *
227
     * @param string $orderNo
228
     * @param float  $totalFee
229
     * @param float  $refundFee
230
     * @param string $opUserId
231
     * @param string $refundAccount
232
     *
233
     * @return \EasyWeChat\Support\Collection
234
     */
235
    public function refundByTransactionId(
236
        $orderNo,
237
        $refundNo,
238
        $totalFee,
239
        $refundFee = null,
240
        $opUserId = null,
241
        $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS'
242
        ) {
243
        return $this->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, self::TRANSACTION_ID, $refundAccount);
244
    }
245
246
    /**
247
     * Query refund status.
248
     *
249
     * @param string $orderNo
250
     * @param string $type
251
     *
252
     * @return \EasyWeChat\Support\Collection
253
     */
254 1 View Code Duplication
    public function queryRefund($orderNo, $type = self::OUT_TRADE_NO)
255
    {
256
        $params = [
257 1
            $type => $orderNo,
258 1
        ];
259
260 1
        return $this->request($this->wrapApi(self::API_QUERY_REFUND), $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($this->wr...UERY_REFUND), $params); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 260 which is incompatible with the return type documented by EasyWeChat\Payment\API::queryRefund of type EasyWeChat\Support\Collection.
Loading history...
261
    }
262
263
    /**
264
     * Query refund status by out_refund_no.
265
     *
266
     * @param string $refundNo
267
     *
268
     * @return \EasyWeChat\Support\Collection
269
     */
270
    public function queryRefundByRefundNo($refundNo)
271
    {
272
        return $this->queryRefund($refundNo, self::OUT_REFUND_NO);
273
    }
274
275
    /**
276
     * Query refund status by transaction_id.
277
     *
278
     * @param string $transactionId
279
     *
280
     * @return \EasyWeChat\Support\Collection
281
     */
282
    public function queryRefundByTransactionId($transactionId)
283
    {
284
        return $this->queryRefund($transactionId, self::TRANSACTION_ID);
285
    }
286
287
    /**
288
     * Query refund status by refund_id.
289
     *
290
     * @param string $refundId
291
     *
292
     * @return \EasyWeChat\Support\Collection
293
     */
294
    public function queryRefundByRefundId($refundId)
295
    {
296
        return $this->queryRefund($refundId, self::REFUND_ID);
297
    }
298
299
    /**
300
     * Download bill history as a table file.
301
     *
302
     * @param string $date
303
     * @param string $type
304
     *
305
     * @return \Psr\Http\Message\ResponseInterface
306
     */
307 1
    public function downloadBill($date, $type = self::BILL_TYPE_ALL)
308
    {
309
        $params = [
310 1
            'bill_date' => $date,
311 1
            'bill_type' => $type,
312 1
        ];
313
314 1
        return $this->request($this->wrapApi(self::API_DOWNLOAD_BILL), $params, 'post', [\GuzzleHttp\RequestOptions::STREAM => true], true)->getBody();
0 ignored issues
show
Bug introduced by
The method getBody does only exist in Psr\Http\Message\ResponseInterface, but not in EasyWeChat\Support\Collection.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
315
    }
316
317
    /**
318
     * Convert long url to short url.
319
     *
320
     * @param string $url
321
     *
322
     * @return \EasyWeChat\Support\Collection
323
     */
324 1
    public function urlShorten($url)
325
    {
326 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 326 which is incompatible with the return type documented by EasyWeChat\Payment\API::urlShorten of type EasyWeChat\Support\Collection.
Loading history...
327
    }
328
329
    /**
330
     * Report API status to WeChat.
331
     *
332
     * @param string $api
333
     * @param int    $timeConsuming
334
     * @param string $resultCode
335
     * @param string $returnCode
336
     * @param array  $other         ex: err_code,err_code_des,out_trade_no,user_ip...
337
     *
338
     * @return \EasyWeChat\Support\Collection
339
     */
340
    public function report($api, $timeConsuming, $resultCode, $returnCode, array $other = [])
341
    {
342
        $params = array_merge([
343
            'interface_url' => $api,
344
            'execute_time_' => $timeConsuming,
345
            'return_code' => $returnCode,
346
            'return_msg' => null,
347
            'result_code' => $resultCode,
348
            'user_ip' => get_client_ip(),
349
            'time' => time(),
350
        ], $other);
351
352
        return $this->request($this->wrapApi(self::API_REPORT), $params);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request($this->wr...:API_REPORT), $params); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 352 which is incompatible with the return type documented by EasyWeChat\Payment\API::report of type EasyWeChat\Support\Collection.
Loading history...
353
    }
354
355
    /**
356
     * Get openid by auth code.
357
     *
358
     * @param string $authCode
359
     *
360
     * @return \EasyWeChat\Support\Collection
361
     */
362 1
    public function authCodeToOpenId($authCode)
363
    {
364 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 364 which is incompatible with the return type documented by EasyWeChat\Payment\API::authCodeToOpenId of type EasyWeChat\Support\Collection.
Loading history...
365
    }
366
367
    /**
368
     * Merchant setter.
369
     *
370
     * @param Merchant $merchant
371
     *
372
     * @return $this
373
     */
374 1
    public function setMerchant(Merchant $merchant)
375
    {
376 1
        $this->merchant = $merchant;
377 1
    }
378
379
    /**
380
     * Merchant getter.
381
     *
382
     * @return Merchant
383
     */
384 1
    public function getMerchant()
385
    {
386 1
        return $this->merchant;
387
    }
388
389
    /**
390
     * Set sandbox mode.
391
     *
392
     * @param bool $enabled
393
     *
394
     * @return $this
395
     */
396 10
    public function sandboxMode($enabled = false)
397
    {
398 10
        $this->sandboxEnabled = $enabled;
399
400 10
        return $this;
401
    }
402
403
    /**
404
     * Make a API request.
405
     *
406
     * @param string $api
407
     * @param array  $params
408
     * @param string $method
409
     * @param array  $options
410
     * @param bool   $returnResponse
411
     *
412
     * @return \EasyWeChat\Support\Collection|\Psr\Http\Message\ResponseInterface
413
     */
414 10
    protected function request($api, array $params, $method = 'post', array $options = [], $returnResponse = false)
415
    {
416 10
        $params = array_merge($params, $this->merchant->only(['sub_appid', 'sub_mch_id']));
417
418 10
        $params['appid'] = $this->merchant->app_id;
419 10
        $params['mch_id'] = $this->merchant->merchant_id;
420 10
        $params['device_info'] = $this->merchant->device_info;
421 10
        $params['nonce_str'] = uniqid();
422 10
        $params = array_filter($params);
423 10
        $params['sign'] = generate_sign($params, $this->merchant->key, 'md5');
424
425 10
        $options = array_merge([
426 10
            'body' => XML::build($params),
427 10
        ], $options);
428
429 10
        $response = $this->getHttp()->request($api, $method, $options);
430
431 10
        return $returnResponse ? $response : $this->parseResponse($response);
432
    }
433
434
    /**
435
     * Request with SSL.
436
     *
437
     * @param string $api
438
     * @param array  $params
439
     * @param string $method
440
     *
441
     * @return \EasyWeChat\Support\Collection
442
     */
443 2
    protected function safeRequest($api, array $params, $method = 'post')
444
    {
445
        $options = [
446 2
            'cert' => $this->merchant->get('cert_path'),
447 2
            'ssl_key' => $this->merchant->get('key_path'),
448 2
        ];
449
450 2
        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 Psr\Http\Message\Respons...Chat\Support\Collection adds the type Psr\Http\Message\ResponseInterface to the return on line 450 which is incompatible with the return type documented by EasyWeChat\Payment\API::safeRequest of type EasyWeChat\Support\Collection.
Loading history...
451
    }
452
453
    /**
454
     * Parse Response XML to array.
455
     *
456
     * @param ResponseInterface $response
457
     *
458
     * @return \EasyWeChat\Support\Collection
459
     */
460 9
    protected function parseResponse($response)
461
    {
462 9
        if ($response instanceof ResponseInterface) {
463
            $response = $response->getBody();
464
        }
465
466 9
        return new Collection((array) XML::parse($response));
467
    }
468
469
    /**
470
     * Wrap API.
471
     *
472
     * @param string $resource
473
     *
474
     * @return string
475
     */
476 8
    protected function wrapApi($resource)
477
    {
478 8
        return self::API_HOST.($this->sandboxEnabled ? '/sandboxnew' : '').$resource;
479
    }
480
481
    /**
482
     * Get sandbox sign key
483
     *
484
     * @return \EasyWeChat\Support\Collection
485
     */
486
    public function getSandboxSignKey()
487
    {
488
      return $this->request(self::API_SANDBOX_SIGN_KEY, []);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->request(self::API...BOX_SIGN_KEY, array()); of type EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 488 which is incompatible with the return type documented by EasyWeChat\Payment\API::getSandboxSignKey of type EasyWeChat\Support\Collection.
Loading history...
489
    }
490
}
491