Completed
Push — master ( 633dec...01bc99 )
by Carlos
02:51
created

API::setMerchant()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
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
 * @link      https://github.com/overtrue
19
 * @link      http://overtrue.me
20
 */
21
namespace EasyWeChat\Payment;
22
23
use EasyWeChat\Core\AbstractAPI;
24
use EasyWeChat\Support\Collection;
25
use EasyWeChat\Support\XML;
26
use Psr\Http\Message\ResponseInterface;
27
28
/**
29
 * Class API.
30
 */
31
class API extends AbstractAPI
32
{
33
    /**
34
     * Merchant instance.
35
     *
36
     * @var Merchant
37
     */
38
    protected $merchant;
39
40
    // api
41
    const API_PAY_ORDER = 'https://api.mch.weixin.qq.com/pay/micropay';
42
    const API_PREPARE_ORDER = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
43
    const API_QUERY = 'https://api.mch.weixin.qq.com/pay/orderquery';
44
    const API_CLOSE = 'https://api.mch.weixin.qq.com/pay/closeorder';
45
    const API_REVERSE = 'https://api.mch.weixin.qq.com/secapi/pay/reverse';
46
    const API_REFUND = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
47
    const API_QUERY_REFUND = 'https://api.mch.weixin.qq.com/pay/refundquery';
48
    const API_DOWNLOAD_BILL = 'https://api.mch.weixin.qq.com/pay/downloadbill';
49
    const API_REPORT = 'https://api.mch.weixin.qq.com/payitil/report';
50
    const API_URL_SHORTEN = 'https://api.mch.weixin.qq.com/tools/shorturl';
51
    const API_AUTH_CODE_TO_OPENID = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid';
52
53
    // order id types.
54
    const TRANSACTION_ID = 'transaction_id';
55
    const OUT_TRADE_NO = 'out_trade_no';
56
    const OUT_REFUND_NO = 'out_refund_no';
57
    const REFUND_ID = 'refund_id';
58
59
    // bill types.
60
    const BILL_TYPE_ALL = 'ALL';
61
    const BILL_TYPE_SUCCESS = 'SUCCESS';
62
    const BILL_TYPE_REFUND = 'REFUND';
63
    const BILL_TYPE_REVOKED = 'REVOKED';
64
65
    /**
66
     * API constructor.
67
     *
68
     * @param \EasyWeChat\Payment\Merchant $merchant
69
     */
70 12
    public function __construct(Merchant $merchant)
71
    {
72 12
        $this->merchant = $merchant;
73 12
    }
74
75
    /**
76
     * Pay the order.
77
     *
78
     * @param Order $order
79
     *
80
     * @return \EasyWeChat\Support\Collection
81
     */
82 1
    public function pay(Order $order)
83
    {
84 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 84 which is incompatible with the return type documented by EasyWeChat\Payment\API::pay of type EasyWeChat\Support\Collection.
Loading history...
85
    }
86
87
    /**
88
     * Prepare order to pay.
89
     *
90
     * @param Order $order
91
     *
92
     * @return \EasyWeChat\Support\Collection
93
     */
94 1
    public function prepare(Order $order)
95
    {
96 1
        $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<EasyWeChat\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...
97 1
        $order->spbill_create_ip = ($order->trade_type === Order::NATIVE) ? get_server_ip() : get_client_ip();
98
99 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 99 which is incompatible with the return type documented by EasyWeChat\Payment\API::prepare of type EasyWeChat\Support\Collection.
Loading history...
100
    }
101
102
    /**
103
     * Query order.
104
     *
105
     * @param string $orderNo
106
     * @param string $type
107
     *
108
     * @return \EasyWeChat\Support\Collection
109
     */
110 1
    public function query($orderNo, $type = self::OUT_TRADE_NO)
111
    {
112
        $params = [
113 1
            $type => $orderNo,
114 1
        ];
115
116 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 116 which is incompatible with the return type documented by EasyWeChat\Payment\API::query of type EasyWeChat\Support\Collection.
Loading history...
117
    }
118
119
    /**
120
     * Query order by transaction_id.
121
     *
122
     * @param string $transactionId
123
     *
124
     * @return \EasyWeChat\Support\Collection
125
     */
126 1
    public function queryByTransactionId($transactionId)
127
    {
128 1
        return $this->query($transactionId, self::TRANSACTION_ID);
129
    }
130
131
    /**
132
     * Close order by out_trade_no.
133
     *
134
     * @param $tradeNo
135
     *
136
     * @return \EasyWeChat\Support\Collection
137
     */
138 1
    public function close($tradeNo)
139
    {
140
        $params = [
141 1
            'out_trade_no' => $tradeNo,
142 1
        ];
143
144 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 144 which is incompatible with the return type documented by EasyWeChat\Payment\API::close of type EasyWeChat\Support\Collection.
Loading history...
145
    }
146
147
    /**
148
     * Reverse order.
149
     *
150
     * @param string $orderNo
151
     * @param string $type
152
     *
153
     * @return \EasyWeChat\Support\Collection
154
     */
155 1
    public function reverse($orderNo, $type = self::OUT_TRADE_NO)
156
    {
157
        $params = [
158 1
            $type => $orderNo,
159 1
        ];
160
161 1
        return $this->safeRequest(self::API_REVERSE, $params);
162
    }
163
164
    /**
165
     * Reverse order by transaction_id.
166
     *
167
     * @param int $transactionId
168
     *
169
     * @return \EasyWeChat\Support\Collection
170
     */
171
    public function reverseByTransactionId($transactionId)
172
    {
173
        return $this->reverse($transactionId, self::TRANSACTION_ID);
174
    }
175
176
    /**
177
     * Make a refund request.
178
     *
179
     * @param string $orderNo
180
     * @param float  $totalFee
181
     * @param float  $refundFee
182
     * @param string $opUserId
183
     * @param string $type
184
     * @param string $refundAccount
185
     *
186
     * @return \EasyWeChat\Support\Collection
187
     */
188 1
    public function refund(
189
        $orderNo,
190
        $refundNo,
191
        $totalFee,
192
        $refundFee = null,
193
        $opUserId = null,
194
        $type = self::OUT_TRADE_NO,
195
        $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS'
196
        ) {
197
        $params = [
198 1
            $type => $orderNo,
199 1
            'out_refund_no' => $refundNo,
200 1
            'total_fee' => $totalFee,
201 1
            'refund_fee' => $refundFee ?: $totalFee,
202 1
            'refund_fee_type' => $this->merchant->fee_type,
203 1
            'refund_account' => $refundAccount,
204 1
            'op_user_id' => $opUserId ?: $this->merchant->merchant_id,
205 1
        ];
206
207 1
        return $this->safeRequest(self::API_REFUND, $params);
208
    }
209
210
    /**
211
     * Refund by transaction id.
212
     *
213
     * @param string $orderNo
214
     * @param float  $totalFee
215
     * @param float  $refundFee
216
     * @param string $opUserId
217
     * @param string $refundAccount
218
     *
219
     * @return \EasyWeChat\Support\Collection
220
     */
221
    public function refundByTransactionId(
222
        $orderNo,
223
        $refundNo,
224
        $totalFee,
225
        $refundFee = null,
226
        $opUserId = null,
227
        $refundAccount = 'REFUND_SOURCE_UNSETTLED_FUNDS'
228
        ) {
229
        return $this->refund($orderNo, $refundNo, $totalFee, $refundFee, $opUserId, self::TRANSACTION_ID, $refundAccount);
230
    }
231
232
    /**
233
     * Query refund status.
234
     *
235
     * @param string $orderNo
236
     * @param string $type
237
     *
238
     * @return \EasyWeChat\Support\Collection
239
     */
240 1
    public function queryRefund($orderNo, $type = self::OUT_TRADE_NO)
241
    {
242
        $params = [
243 1
            $type => $orderNo,
244 1
        ];
245
246 1
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 246 which is incompatible with the return type documented by EasyWeChat\Payment\API::queryRefund of type EasyWeChat\Support\Collection.
Loading history...
247
    }
248
249
    /**
250
     * Query refund status by out_refund_no.
251
     *
252
     * @param string $refundNo
253
     *
254
     * @return \EasyWeChat\Support\Collection
255
     */
256
    public function queryRefundByRefundNo($refundNo)
257
    {
258
        return $this->queryRefund($refundNo, self::OUT_REFUND_NO);
259
    }
260
261
    /**
262
     * Query refund status by transaction_id.
263
     *
264
     * @param string $transactionId
265
     *
266
     * @return \EasyWeChat\Support\Collection
267
     */
268
    public function queryRefundByTransactionId($transactionId)
269
    {
270
        return $this->queryRefund($transactionId, self::TRANSACTION_ID);
271
    }
272
273
    /**
274
     * Query refund status by refund_id.
275
     *
276
     * @param string $refundId
277
     *
278
     * @return \EasyWeChat\Support\Collection
279
     */
280
    public function queryRefundByRefundId($refundId)
281
    {
282
        return $this->queryRefund($refundId, self::REFUND_ID);
283
    }
284
285
    /**
286
     * Download bill history as a table file.
287
     *
288
     * @param string $date
289
     * @param string $type
290
     *
291
     * @return \Psr\Http\Message\ResponseInterface
292
     */
293 1
    public function downloadBill($date, $type = self::BILL_TYPE_ALL)
294
    {
295
        $params = [
296 1
            'bill_date' => $date,
297 1
            'bill_type' => $type,
298 1
        ];
299
300 1
        return $this->request(self::API_DOWNLOAD_BILL, $params, 'post', [], 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...
301
    }
302
303
    /**
304
     * Convert long url to short url.
305
     *
306
     * @param string $url
307
     *
308
     * @return \EasyWeChat\Support\Collection
309
     */
310 1
    public function urlShorten($url)
311
    {
312 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 312 which is incompatible with the return type documented by EasyWeChat\Payment\API::urlShorten of type EasyWeChat\Support\Collection.
Loading history...
313
    }
314
315
    /**
316
     * Report API status to WeChat.
317
     *
318
     * @param string $api
319
     * @param int    $timeConsuming
320
     * @param string $resultCode
321
     * @param string $returnCode
322
     * @param array  $other         ex: err_code,err_code_des,out_trade_no,user_ip...
323
     *
324
     * @return \EasyWeChat\Support\Collection
325
     */
326
    public function report($api, $timeConsuming, $resultCode, $returnCode, array $other = [])
327
    {
328
        $params = array_merge([
329
            'interface_url' => $api,
330
            'execute_time_' => $timeConsuming,
331
            'return_code' => $returnCode,
332
            'return_msg' => null,
333
            'result_code' => $resultCode,
334
            'user_ip' => get_client_ip(),
335
            'time' => time(),
336
        ], $other);
337
338
        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 EasyWeChat\Support\Colle...ssage\ResponseInterface adds the type Psr\Http\Message\ResponseInterface to the return on line 338 which is incompatible with the return type documented by EasyWeChat\Payment\API::report of type EasyWeChat\Support\Collection.
Loading history...
339
    }
340
341
    /**
342
     * Get openid by auth code.
343
     *
344
     * @param string $authCode
345
     *
346
     * @return \EasyWeChat\Support\Collection
347
     */
348 1
    public function authCodeToOpenId($authCode)
349
    {
350 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 350 which is incompatible with the return type documented by EasyWeChat\Payment\API::authCodeToOpenId of type EasyWeChat\Support\Collection.
Loading history...
351
    }
352
353
    /**
354
     * Merchant setter.
355
     *
356
     * @param Merchant $merchant
357
     *
358
     * @return $this
359
     */
360 1
    public function setMerchant(Merchant $merchant)
361
    {
362 1
        $this->merchant = $merchant;
363 1
    }
364
365
    /**
366
     * Merchant getter.
367
     *
368
     * @return Merchant
369
     */
370 1
    public function getMerchant()
371
    {
372 1
        return $this->merchant;
373
    }
374
375
    /**
376
     * Make a API request.
377
     *
378
     * @param string $api
379
     * @param array  $params
380
     * @param string $method
381
     * @param array  $options
382
     * @param bool   $returnResponse
383
     *
384
     * @return \EasyWeChat\Support\Collection|\Psr\Http\Message\ResponseInterface
385
     */
386 10
    protected function request($api, array $params, $method = 'post', array $options = [], $returnResponse = false)
387
    {
388 10
        $params = array_merge($params, $this->merchant->only(['sub_appid', 'sub_mch_id']));
389
390 10
        $params['appid'] = $this->merchant->app_id;
391 10
        $params['mch_id'] = $this->merchant->merchant_id;
392 10
        $params['device_info'] = $this->merchant->device_info;
393 10
        $params['nonce_str'] = uniqid();
394 10
        $params = array_filter($params);
395 10
        $params['sign'] = generate_sign($params, $this->merchant->key, 'md5');
396
397 10
        $options = array_merge([
398 10
            'body' => XML::build($params),
399 10
        ], $options);
400
401 10
        $response = $this->getHttp()->request($api, $method, $options);
402
403 10
        return $returnResponse ? $response : $this->parseResponse($response);
404
    }
405
406
    /**
407
     * Request with SSL.
408
     *
409
     * @param string $api
410
     * @param array  $params
411
     * @param string $method
412
     *
413
     * @return \EasyWeChat\Support\Collection
414
     */
415 2
    protected function safeRequest($api, array $params, $method = 'post')
416
    {
417
        $options = [
418 2
            'cert' => $this->merchant->get('cert_path'),
419 2
            'ssl_key' => $this->merchant->get('key_path'),
420 2
        ];
421
422 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 422 which is incompatible with the return type documented by EasyWeChat\Payment\API::safeRequest of type EasyWeChat\Support\Collection.
Loading history...
423
    }
424
425
    /**
426
     * Parse Response XML to array.
427
     *
428
     * @param ResponseInterface $response
429
     *
430
     * @return \EasyWeChat\Support\Collection
431
     */
432 9
    protected function parseResponse($response)
433
    {
434 9
        if ($response instanceof ResponseInterface) {
435
            $response = $response->getBody();
436
        }
437
438 9
        return new Collection((array) XML::parse($response));
439
    }
440
}
441