Completed
Pull Request — master (#243)
by Carlos
05:12 queued 01:51
created

API::sendNormal()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 7
Ratio 100 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 7
loc 7
rs 9.4286
cc 2
eloc 4
nc 2
nop 1
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    tianyong90 <[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\LuckyMoney;
22
23
use EasyWeChat\Core\AbstractAPI;
24
use EasyWeChat\Payment\Merchant;
25
use EasyWeChat\Support\Collection;
26
use EasyWeChat\Support\XML;
27
use Psr\Http\Message\ResponseInterface;
28
29
/**
30
 * Class API.
31
 */
32 View Code Duplication
class API extends AbstractAPI
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type EasyWeChat\Payment\LuckyMoney\API has been defined more than once; this definition is ignored, only the first definition in src/Payment/luckymoney/API.php (L32-211) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Comprehensibility Best Practice introduced by
The type EasyWeChat\Payment\LuckyMoney\API has been defined more than once; this definition is ignored, only the first definition in src/Payment/luckymoney/API.php (L32-211) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Duplication introduced by
This class seems to be duplicated in 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...
Duplication introduced by
This class seems to be duplicated in 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...
Duplication introduced by
This class seems to be duplicated in 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...
33
{
34
    /**
35
     * Merchant instance.
36
     *
37
     * @var Merchant
38
     */
39
    protected $merchant;
40
41
    // api
42
    const API_SEND = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
43
    const API_SEND_GROUP = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack';
44
    const API_QUERY = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo';
45
    const API_PREPARE = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/hbpreorder';
46
47
    // LuckyMoney type
48
    const TYPE_NORMAL = 'NORMAL';
49
    const TYPE_GROUP = 'GROUP';
50
51
    // Risk control type.
52
    const RISK_NORMAL = 'NORMAL';
53
    const RISK_IGN_FREQ_LMT = 'IGN_FREQ_LMT';
54
    const RISK_IGN_DAY_LMT = 'IGN_DAY_LMT';
55
    const RISK_IGN_FREQ_DAY_LMT = 'IGN_FREQ_DAY_LMT';
56
57
    /**
58
     * API constructor.
59
     *
60
     * @param \EasyWeChat\Payment\Merchant $merchant
61
     */
62
    public function __construct(Merchant $merchant)
63
    {
64
        $this->merchant = $merchant;
65
    }
66
67
    /**
68
     * Prepare luckymoney.
69
     *
70
     *
71
     * @return Collection
72
     */
73
    public function prepare(array $params)
74
    {
75
        $params['wxappid'] = $this->merchant->app_id;
76
77
        //This parameter is fixed and can not be changed.
78
        $params['auth_mchid'] = '1000052601';
79
        //This parameter is fixed and can not be changed.
80
        $params['auth_appid'] = 'wxbf42bd79c4391863';
81
82
        $params['amt_type'] = 'ALL_RAND';
83
84
        return $this->request(self::API_PREPARE, $params);
85
    }
86
87
    /**
88
     * Query luckymoney.
89
     *
90
     * @param string $mchBillNo
0 ignored issues
show
Bug introduced by
There is no parameter named $mchBillNo. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
Bug introduced by
There is no parameter named $mchBillNo. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
Bug introduced by
There is no parameter named $mchBillNo. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
91
     */
92
    public function query($orderNo)
93
    {
94
        $params = [
95
            'appid' => $this->merchant->app_id,
96
            'mch_billno' => $orderNo,
97
            'bill_type' => 'MCHT',
98
        ];
99
100
        return $this->request(self::API_QUERY, $params);
101
    }
102
103
    /**
104
     * Send Luckymoney.
105
     *
106
     * @param array  $params
107
     * @param string $type
108
     */
109
    public function send(array $params, $type = self::TYPE_NORMAL)
110
    {
111
        if ($type === self::TYPE_NORMAL) {
112
            $api = self::API_SEND;
113
        } else {
114
            $api = self::API_SEND_GROUP;
115
        }
116
117
        $params['wxappid'] = $this->merchant->app_id;
118
119
        return $this->request($api, $params);
120
    }
121
122
    /**
123
     * Send normal lucnymoney.
124
     *
125
     * @param array $params
126
     *
127
     * @return Collection
128
     */
129
    public function sendNormal($params)
0 ignored issues
show
Coding Style introduced by
sendNormal uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
sendNormal uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
sendNormal uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
130
    {
131
        $params['total_num'] = 1;
132
        $params['client_ip'] = $params['client_ip'] ?: $_SERVER['HTTP_CLIENT_IP'];
133
134
        return $this->send($params, self::TYPE_NORMAL);
135
    }
136
137
    /**
138
     * Send group luckymoney.
139
     *
140
     * @param array $params
141
     *
142
     * @return Collection
143
     */
144
    public function sendGroup($params)
0 ignored issues
show
Coding Style introduced by
sendGroup uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
sendGroup uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
sendGroup uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
145
    {
146
        $params['amt_type'] = 'ALL_RAND';
147
        $params['client_ip'] = $params['client_ip'] ?: $_SERVER['HTTP_CLIENT_IP'];
148
149
        return $this->send($params, self::TYPE_GROUP);
150
    }
151
152
    /**
153
     * Merchant setter.
154
     *
155
     * @param Merchant $merchant
156
     *
157
     * @return $this
158
     */
159
    public function setMerchant(Merchant $merchant)
160
    {
161
        $this->merchant = $merchant;
162
    }
163
164
    /**
165
     * Merchant getter.
166
     *
167
     * @return Merchant
168
     */
169
    public function getMerchant()
170
    {
171
        return $this->merchant;
172
    }
173
174
    /**
175
     * Make a API request.
176
     *
177
     * @param string $api
178
     * @param array  $params
179
     * @param string $method
180
     *
181
     * @return Collection
182
     */
183
    protected function request($api, array $params, $method = 'post')
184
    {
185
        $params['mch_id'] = $this->merchant->merchant_id;
186
        $params['nonce_str'] = uniqid();
187
        $params['sign'] = \EasyWeChat\Payment\generate_sign($params, $this->merchant->key, 'md5');
188
189
        $options['body'] = XML::build($params);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
190
        $options['cert'] = $this->merchant->get('cert_path');
191
        $options['ssl_key'] = $this->merchant->get('key_path');
192
193
        return $this->parseResponse($this->getHttp()->request($api, $method, $options));
0 ignored issues
show
Documentation introduced by
$this->getHttp()->reques...api, $method, $options) is of type object<Psr\Http\Message\ResponseInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$this->getHttp()->reques...api, $method, $options) is of type object<Psr\Http\Message\ResponseInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$this->getHttp()->reques...api, $method, $options) is of type object<Psr\Http\Message\ResponseInterface>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
194
    }
195
196
    /**
197
     * Parse Response XML to array.
198
     *
199
     * @param string $response
200
     *
201
     * @return Collection
202
     */
203
    protected function parseResponse($response)
204
    {
205
        if ($response instanceof ResponseInterface) {
206
            $response = $response->getBody();
207
        }
208
209
        return new Collection((array) XML::parse($response));
210
    }
211
}
212