Passed
Push — master ( 8679ac...a8b1e8 )
by i
03:51
created

Wechat::setAppId()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 17
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 18.9628

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 7
nop 1
dl 0
loc 17
ccs 6
cts 16
cp 0.375
crap 18.9628
rs 8.2222
c 0
b 0
f 0
1
<?php
2
3
namespace Nilnice\Payment;
4
5
use Illuminate\Config\Repository;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Str;
8
use Nilnice\Payment\Exception\GatewayException;
9
use Symfony\Component\HttpFoundation\Request;
10
11
/**
12
 * @method Wechat\AppPayment app(array $array)
13
 * @method Wechat\WapPayment wap(array $array)
14
 * @method Wechat\ScanPayment scan(array $array)
15
 */
16
class Wechat implements GatewayInterface
17
{
18
    use LogTrait;
19
20
    /**
21
     * @var \Illuminate\Contracts\Config\Repository
22
     */
23
    protected $config;
24
25
    /**
26
     * @var array
27
     */
28
    protected $payload;
29
30
    /**
31
     * @var string
32
     */
33
    protected $gateway;
34
35
    /**
36
     * Wechat constructor.
37
     *
38
     * @param array $config
39
     *
40
     * @throws \Exception
41
     */
42 6
    public function __construct(array $config)
43
    {
44 6
        $this->config = new Repository($config);
45 6
        $env = $this->config->get('env', 'pro');
46 6
        $this->gateway = self::getGatewayUrl($env);
47 6
        $this->payload = [
48
            // 公众账号 ID - 微信分配的公众账号 ID
49 6
            'appid'            => '',
50
51
            // 商户号 - 微信支付分配的商户号
52 6
            'mch_id'           => $this->config->get('mch_id', ''),
53
54
            // 随机字符串	 - 随机字符串,不长于32位
55 6
            'nonce_str'        => Str::random(),
56
57
            // 签名
58 6
            'sign'             => '',
59
60
            // 终端 IP - 必须传正确的客户端 IP
61 6
            'spbill_create_ip' => Request::createFromGlobals()->getClientIp(),
62
63
            // 通知地址 - 接收微信支付异步通知回调地址,通知 url 必须为直接可访问的 url,不能携带参数
64 6
            'notify_url'       => $this->config->get('notify_url'),
65
66
            // 交易类型 - H5 支付的交易类型为 MWEB
67 6
            'trade_type'       => '',
68
        ];
69
70 6
        if ($this->config->has('log.file')) {
71
            $this->registerLogger($this->config, 'Wxpay');
72
        }
73 6
    }
74
75
    /**
76
     * @param string $method
77
     * @param array  $arguments
78
     *
79
     * @return mixed
80
     *
81
     * @throws \Nilnice\Payment\Exception\GatewayException
82
     */
83 3
    public function __call(string $method, array $arguments)
84
    {
85 3
        $this->setAppId($method);
86
87 3
        return $this->dispatcher($method, ...$arguments);
0 ignored issues
show
Bug introduced by
$arguments is expanded, but the parameter $array of Nilnice\Payment\Wechat::dispatcher() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

87
        return $this->dispatcher($method, /** @scrutinizer ignore-type */ ...$arguments);
Loading history...
88
    }
89
90
    /**
91
     * Query an order information.
92
     *
93
     * @param array|string $order
94
     *
95
     * @return \Illuminate\Support\Collection
96
     *
97
     * @throws \InvalidArgumentException
98
     * @throws \Nilnice\Payment\Exception\GatewayException
99
     * @throws \Nilnice\Payment\Exception\InvalidSignException
100
     * @throws \RuntimeException
101
     */
102
    public function query($order) : Collection
103
    {
104
        $this->setAppId();
105
        $this->payload = self::filterPayload(
0 ignored issues
show
Bug introduced by
The method filterPayload() does not exist on Nilnice\Payment\Wechat. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        /** @scrutinizer ignore-call */ 
106
        $this->payload = self::filterPayload(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
106
            $this->payload,
107
            $order,
108
            $this->config
109
        );
110
        $gateway = Constant::WX_PAY_QUERY;
111
112
        return $this->send($gateway, $this->payload, $this->config->get('key'));
0 ignored issues
show
Bug introduced by
The method send() does not exist on Nilnice\Payment\Wechat. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

112
        return $this->/** @scrutinizer ignore-call */ send($gateway, $this->payload, $this->config->get('key'));
Loading history...
113
    }
114
115
    /**
116
     * Close an order.
117
     *
118
     * @param array|string $order
119
     *
120
     * @return \Illuminate\Support\Collection
121
     *
122
     * @throws \InvalidArgumentException
123
     * @throws \Nilnice\Payment\Exception\GatewayException
124
     * @throws \Nilnice\Payment\Exception\InvalidSignException
125
     * @throws \RuntimeException
126
     */
127
    public function close($order) : Collection
128
    {
129
        $this->setAppId();
130
        unset($this->payload['spbill_create_ip']);
131
        $this->payload = self::filterPayload(
132
            $this->payload,
133
            $order,
134
            $this->config
135
        );
136
        $gateway = Constant::WX_PAY_CLOSE;
137
138
        return $this->send($gateway, $this->payload, $this->config->get('key'));
139
    }
140
141
    /**
142
     * Cancel an order.
143
     *
144
     * @param array|string $order
145
     *
146
     * @return \Illuminate\Support\Collection
147
     */
148
    public function cancel($order) : Collection
149
    {
150
        trigger_error('Wechat did not cancel API, please use close API.');
151
152
        return new Collection();
153
    }
154
155
    /**
156
     * Refund an order.
157
     *
158
     * @param array|string $order
159
     *
160
     * @return \Illuminate\Support\Collection
161
     *
162
     * @throws \InvalidArgumentException
163
     * @throws \Nilnice\Payment\Exception\GatewayException
164
     * @throws \Nilnice\Payment\Exception\InvalidSignException
165
     * @throws \RuntimeException
166
     */
167
    public function refund($order) : Collection
168
    {
169
        $this->payload = self::filterPayload(
170
            $this->payload,
171
            $order,
172
            $this->config
173
        );
174
175
        return $this->send(
176
            Constant::WX_PAY_REFUND,
177
            $this->payload,
178
            $this->config->get('key'),
179
            $this->config->get('cert_client'),
180
            $this->config->get('cert_key')
181
        );
182
    }
183
184
    /**
185
     * To pay.
186
     *
187
     * @param string $gateway
188
     *
189
     * @return mixed
190
     *
191
     * @throws \Nilnice\Payment\Exception\GatewayException
192
     */
193 3
    protected function toPay(string $gateway)
194
    {
195 3
        $class = new $gateway($this->config); // Instantiate different gateways.
196
197 3
        if ($class instanceof PaymentInterface) {
198 3
            return $class->toPay($this->gateway, $this->payload);
199
        }
200
201
        throw new GatewayException(
202
            "Pay gateway [{$gateway}] must be an instance of the GatewayInterface.",
203
            2
204
        );
205
    }
206
207
    /**
208
     * Pay dispatcher.
209
     *
210
     * @param string $gateway
211
     * @param array  $array
212
     *
213
     * @return mixed
214
     *
215
     * @throws \Nilnice\Payment\Exception\GatewayException
216
     */
217 3
    private function dispatcher(string $gateway, array $array = [])
218
    {
219 3
        $this->payload = array_merge($this->payload, $array);
220 3
        $class = \get_class($this) . '\\' . Str::studly($gateway) . 'Payment';
221
222 3
        if (class_exists($class)) {
223 3
            return $this->toPay($class);
224
        }
225
226
        throw new GatewayException("Pay gateway [{$gateway}] not exists", 1);
227
    }
228
229
    /**
230
     * Set app identify.
231
     *
232
     * @param string $method
233
     */
234 3
    private function setAppId($method = 'wap')
235
    {
236 1
        switch ($method) {
237 2
            case 'app': // APP 支付
238
                $this->payload['appid'] = $this->config->get('app_appid');
239
                break;
240 2
            case 'wap': // H5 支付
241
            case 'bar': // 刷卡支付
242
            case 'scan': // 扫码支付
243 3
                $this->payload['appid'] = $this->config->get('app_id');
244 3
                break;
245
            case 'pub': // 公众号支付
246
                $this->payload['appid'] = $this->config->get('pub_appid');
247
                break;
248
            case 'xcx': // 小程序支付
249
                $this->payload['appid'] = $this->config->get('xcx_appid');
250
                break;
251
        }
252 3
    }
253
254
    /**
255
     * Get gateway url.
256
     *
257
     * @param string $env
258
     *
259
     * @return string
260
     */
261 6
    private static function getGatewayUrl($env = '') : string
262
    {
263 6
        $uri = '';
264 2
        switch ($env) {
265 4
            case 'pro':
266 3
                $uri = Constant::WX_PAY_PRO_URI;
267 3
                break;
268 2
            case 'dev':
269 3
                $uri = Constant::WX_PAY_DEV_URI;
270 3
                break;
271
            case 'hk':
272
                $uri = Constant::WX_PAY_PRO_HK_URI;
273
                break;
274
            default:
275
                break;
276
        }
277
278 6
        return $uri;
279
    }
280
}
281