Completed
Push — master ( d3395c...6ce6f6 )
by i
03:50
created

Alipay::cancel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
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 Monolog\Formatter\LineFormatter;
9
use Monolog\Handler\StreamHandler;
10
use Monolog\Logger;
11
use Nilnice\Payment\Alipay\Traits\RequestTrait;
12
use Nilnice\Payment\Alipay\Traits\SecurityTrait;
13
use Nilnice\Payment\Exception\GatewayException;
14
15
/**
16
 * @method Alipay\BarPayment bar(array $array)
17
 * @method Alipay\ScanPayment scan(array $array)
18
 * @method Alipay\AppPayment app(array $array)
19
 * @method Alipay\WapPayment wap(array $array)
20
 * @method Alipay\WebPayment web(array $array)
21
 */
22
class Alipay implements GatewayInterface
23
{
24
    use RequestTrait;
25
    use SecurityTrait;
26
27
    /**
28
     * @var \Illuminate\Contracts\Config\Repository
29
     */
30
    protected $config;
31
32
    /**
33
     * @var array
34
     */
35
    protected $payload;
36
37
    /**
38
     * @var string
39
     */
40
    protected $gateway;
41
42
    /**
43
     * Alipay constructor.
44
     *
45
     * @param array $config
46
     *
47
     * @throws \Exception
48
     */
49 9
    public function __construct(array $config)
50
    {
51 9
        $this->config = new Repository($config);
52 9
        $env = $this->config->get('env', 'pro');
53 9
        $this->gateway = self::getGatewayUrl($env);
54 9
        $this->payload = [
55
            // 支付宝分配给开发者的应用 ID
56 9
            'app_id'      => $this->config->get('app_id'),
57
58
            // 接口名称
59 9
            'method'      => '',
60
61
            // 数据格式,仅支持 JSON
62 9
            'format'      => 'JSON',
63
64
            // 同步返回地址,HTTP/HTTPS 开头字符串
65 9
            'return_url'  => $this->config->get('return_url'),
66
67
            // 请求使用的编码格式,如:UTF-8, GBK, GB2312 等
68 9
            'charset'     => 'UTF-8',
69
70
            // 商户生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA,推荐使用 RSA2
71 9
            'sign_type'   => 'RSA2',
72
73
            // 商户请求参数的签名串,详见签名
74 9
            'sign'        => '',
75
76
            // 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
77 9
            'timestamp'   => date('Y-m-d H:i:s'),
78
79
            // 调用的接口版本,固定为:1.0
80 9
            'version'     => '1.0',
81
82
            // 支付宝服务器主动通知商户服务器里指定的页面 http/https 路径
83 9
            'notify_url'  => $this->config->get('notify_url'),
84
85
            // 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档
86 9
            'biz_content' => '',
87
        ];
88
89 9
        ! $this->config->has('log.file') ?: $this->registerLogger();
90 9
    }
91
92
    /**
93
     * @param string $method
94
     * @param array  $arguments
95
     *
96
     * @return mixed
97
     * @throws \Nilnice\Payment\Exception\GatewayException
98
     */
99 6
    public function __call(string $method, array $arguments)
100
    {
101 6
        return $this->dispatcher($method, ...$arguments);
0 ignored issues
show
Bug introduced by
$arguments is expanded, but the parameter $array of Nilnice\Payment\Alipay::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

101
        return $this->dispatcher($method, /** @scrutinizer ignore-type */ ...$arguments);
Loading history...
102
    }
103
104
    /**
105
     * Query an order information.
106
     *
107
     * @param array|string $order
108
     *
109
     * @return \Illuminate\Support\Collection
110
     * @throws \Nilnice\Payment\Exception\GatewayException
111
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
112
     * @throws \Nilnice\Payment\Exception\InvalidSignException
113
     * @throws \RuntimeException
114
     */
115
    public function query($order) : Collection
116
    {
117
        return $this->getOrderResult($order);
118
    }
119
120
    /**
121
     * Close an order.
122
     *
123
     * @param array|string $order
124
     *
125
     * @return \Illuminate\Support\Collection
126
     * @throws \Nilnice\Payment\Exception\GatewayException
127
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
128
     * @throws \Nilnice\Payment\Exception\InvalidSignException
129
     * @throws \RuntimeException
130
     */
131
    public function close($order) : Collection
132
    {
133
        return $this->getOrderResult($order, __FUNCTION__);
134
    }
135
136
    /**
137
     * Cancel an order.
138
     *
139
     * @param array|string $order
140
     *
141
     * @return \Illuminate\Support\Collection
142
     * @throws \Nilnice\Payment\Exception\GatewayException
143
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
144
     * @throws \Nilnice\Payment\Exception\InvalidSignException
145
     * @throws \RuntimeException
146
     */
147
    public function cancel($order) : Collection
148
    {
149
        return $this->getOrderResult($order, __FUNCTION__);
150
    }
151
152
    /**
153
     * Refund an order.
154
     *
155
     * @param array|string $order
156
     *
157
     * @return \Illuminate\Support\Collection
158
     * @throws \Nilnice\Payment\Exception\GatewayException
159
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
160
     * @throws \Nilnice\Payment\Exception\InvalidSignException
161
     * @throws \RuntimeException
162
     */
163
    public function refund($order) : Collection
164
    {
165
        return $this->getOrderResult($order, __FUNCTION__);
166
    }
167
168
    /**
169
     * To pay.
170
     *
171
     * @param string $gateway
172
     *
173
     * @return mixed
174
     * @throws \Nilnice\Payment\Exception\GatewayException
175
     */
176 3
    protected function toPay(string $gateway)
177
    {
178 3
        $class = new $gateway($this->config); // Instantiate different gateways.
179
180 3
        if ($class instanceof PaymentInterface) {
181 3
            return $class->toPay($this->gateway, $this->payload);
182
        }
183
184
        throw new GatewayException(
185
            "Pay gateway [{$gateway}] must be an instance of the GatewayInterface.",
186
            2
187
        );
188
    }
189
190
    /**
191
     * @throws \Exception
192
     */
193
    protected function registerLogger()
194
    {
195
        $handler = new StreamHandler(
196
            $this->config->get('log.file'),
197
            $this->config->get('log.level', Logger::WARNING)
198
        );
199
        $formatter = new LineFormatter();
200
        $handler->setFormatter($formatter);
201
202
        $logger = new Logger('Alipay');
203
        $logger->pushHandler($handler);
204
        Log::setLogger($logger);
205
    }
206
207
    /**
208
     * Pay dispatcher.
209
     *
210
     * @param string $gateway
211
     * @param array  $array
212
     *
213
     * @return mixed
214
     * @throws \Nilnice\Payment\Exception\GatewayException
215
     */
216 6
    private function dispatcher(string $gateway, array $array = [])
217
    {
218 6
        $this->payload['biz_content'] = $array;
219 6
        $class = \get_class($this) . '\\' . Str::studly($gateway) . 'Payment';
220
221 6
        if (class_exists($class)) {
222 3
            return $this->toPay($class);
223
        }
224
225 3
        throw new GatewayException("Pay gateway [{$gateway}] not exists.", 1);
226
    }
227
228
    /**
229
     * Get order result.
230
     *
231
     * @param array|string $order
232
     * @param string       $type
233
     *
234
     * @return \Illuminate\Support\Collection
235
     * @throws \Nilnice\Payment\Exception\GatewayException
236
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
237
     * @throws \Nilnice\Payment\Exception\InvalidSignException
238
     * @throws \RuntimeException
239
     */
240
    private function getOrderResult($order, $type = 'query') : Collection
241
    {
242
        $order = \is_array($order) ? $order : ['out_trade_no' => $order];
243
        switch (trim($type)) {
244
            case 'close':
245
                $method = Constant::ALI_PAY_CLOSE;
246
                break;
247
            case 'cancel':
248
                $method = Constant::ALI_PAY_CANCEL;
249
                break;
250
            case 'refund':
251
                $method = Constant::ALI_PAY_REFUND;
252
                break;
253
            default:
254
                $method = Constant::ALI_PAY_QUERY;
255
                break;
256
        }
257
        $this->payload['method'] = $method;
258
        $this->payload['biz_content'] = json_encode($order);
259
        $this->payload['sign'] = self::generateSign(
260
            $this->payload,
261
            $this->config->get('private_key')
262
        );
263
        Log::debug(ucfirst($type) . ' an order:', [
264
            $this->gateway,
265
            $this->payload,
266
        ]);
267
268
        return $this->send($this->payload, $this->config->get('public_key'));
269
    }
270
271
    /**
272
     * Get gateway url.
273
     *
274
     * @param string $env
275
     *
276
     * @return string
277
     */
278 9
    private static function getGatewayUrl($env = '') : string
279
    {
280 9
        $uri = '';
281 9
        if ($env === 'pro') {
282 6
            $uri = Constant::ALI_PAY_PRO_URI;
283 3
        } elseif ($env === 'dev') {
284 3
            $uri = Constant::ALI_PAY_DEV_URI;
285
        }
286
287 9
        return $uri;
288
    }
289
}
290