Issues (9)

src/Alipay/Traits/RequestTrait.php (1 issue)

Severity
1
<?php
2
3
namespace Nilnice\Payment\Alipay\Traits;
4
5
use GuzzleHttp\Client;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Collection;
8
use Nilnice\Payment\Constant;
9
use Nilnice\Payment\Exception\GatewayException;
10
use Nilnice\Payment\Exception\InvalidSignException;
11
use Nilnice\Payment\Log;
12
use Psr\Http\Message\ResponseInterface;
13
14
trait RequestTrait
15
{
16
    /**
17
     * Send a Alipay interface request.
18
     *
19
     * @param array  $array
20
     * @param string $key
21
     *
22
     * @return \Illuminate\Support\Collection
23
     *
24
     * @throws \Nilnice\Payment\Exception\GatewayException
25
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
26
     * @throws \Nilnice\Payment\Exception\InvalidSignException
27
     * @throws \RuntimeException
28
     */
29
    public function send(array $array, string $key) : Collection
30
    {
31
        $method = Arr::get($array, 'method');
32
        $method = str_replace('.', '_', $method) . '_response';
33
        $result = $this->post('', $array);
34
        $result = mb_convert_encoding($result, 'UTF-8', 'GB2312');
35
        $result = json_decode($result, true);
36
37
        $data = Arr::get($result, $method);
38
        $sign = Arr::get($result, 'sign');
39
        if (! self::verifySign($data, $key, true, $sign)) {
40
            Log::warning('Alipay sign verify failed:', $data);
41
42
            throw new InvalidSignException(
43
                'Invalid Alipay [signature] verify.',
44
                3
45
            );
46
        }
47
48
        if ('10000' === $code = Arr::get($result, "{$method}.code")) {
49
            return new Collection($data);
50
        }
51
52
        Log::warning('Alipay business failed:', $data);
53
54
        throw new GatewayException(
55
            "Gateway Alipay [{$data['msg']}] error.",
56
            $code
57
        );
58
    }
59
60
    /**
61
     * Send a post request.
62
     *
63
     * @param string $gateway
64
     * @param mixed  $parameter
65
     * @param array  ...$options
66
     *
67
     * @return mixed
68
     *
69
     * @throws \RuntimeException
70
     */
71
    public function post(
72
        string $gateway,
73
        $parameter = null,
74
        ...$options
75
    ) {
76
        $options = $options[0] ?? [];
77
        if (\is_array($parameter)) {
78
            $options['form_params'] = $parameter;
79
        } else {
80
            $options['body'] = $parameter;
81
        }
82
83
        return $this->request('post', $gateway, $options);
84
    }
85
86
    /**
87
     * Send a request.
88
     *
89
     * @param string $method
90
     * @param string $gateway
91
     * @param array  $options
92
     *
93
     * @return mixed
94
     *
95
     * @throws \RuntimeException
96
     */
97
    public function request(
98
        string $method,
99
        string $gateway,
100
        array $options = []
101
    ) {
102
        if (property_exists($this, 'config')) {
103
            $baseuri = $this->config->get('env') === 'dev'
104
                ? Constant::ALI_PAY_DEV_URI
105
                : Constant::ALI_PAY_PRO_URI;
106
        }
107
        $baseuri = $baseuri ?? '';
108
        $timeout = property_exists($this, 'timeout') ? $this->timeout : 5.0;
109
        $config = ['base_uri' => $baseuri, 'timeout' => $timeout];
110
111
        $client = new Client($config);
112
        $response = $client->{$method}($gateway, $options);
113
114
        return $this->jsonResponse($response);
115
    }
116
117
    /**
118
     * Decodes a json/javascript/xml response contents.
119
     *
120
     * @param \Psr\Http\Message\ResponseInterface $response
121
     *
122
     * @return mixed
123
     *
124
     * @throws \RuntimeException
125
     */
126
    protected function jsonResponse(ResponseInterface $response)
127
    {
128
        $type = $response->getHeaderLine('Content-Type');
129
        $content = $response->getBody()->getContents();
130
131
        if (false !== self::contains($type, 'json')) {
0 ignored issues
show
The condition false !== self::contains($type, 'json') can never be false.
Loading history...
132
            $content = json_decode($content, true);
133
        }
134
135
        return $content;
136
    }
137
138
    /**
139
     * Find the position of the first occurrence of a substring in a string.
140
     *
141
     * @param string $needle
142
     * @param string $haystack
143
     * @param bool   $isStrict
144
     *
145
     * @return bool|int
146
     */
147
    private static function contains(
148
        string $needle,
149
        string $haystack,
150
        bool $isStrict = false
151
    ) {
152
        return $isStrict
153
            ? strpos($haystack, $needle)
154
            : stripos($haystack, $needle);
155
    }
156
}
157