Issues (1482)

src/service/curl/HttpService.php (5 issues)

1
<?php
2
3
// +----------------------------------------------------------------------
4
// | ThinkLibrary 6.0 for ThinkPhP 6.0
5
// +----------------------------------------------------------------------
6
// | 版权所有 2017~2020 [ https://www.dtapp.net ]
7
// +----------------------------------------------------------------------
8
// | 官方网站: https://gitee.com/liguangchun/ThinkLibrary
9
// +----------------------------------------------------------------------
10
// | 开源协议 ( https://mit-license.org )
11
// +----------------------------------------------------------------------
12
// | gitee 仓库地址 :https://gitee.com/liguangchun/ThinkLibrary
13
// | github 仓库地址 :https://github.com/GC0202/ThinkLibrary
14
// | Packagist 地址 :https://packagist.org/packages/liguangchun/think-library
15
// +----------------------------------------------------------------------
16
17
namespace DtApp\ThinkLibrary\service\curl;
18
19
use DtApp\ThinkLibrary\Service;
20
use think\exception\HttpException;
21
22
/**
23
 * 通用网络请求
24
 * Class HttpService
25
 * @package DtApp\ThinkLibrary\service\curl
26
 */
27
class HttpService extends Service
28
{
29
    /**
30
     * @var
31
     */
32
    private $url, $data, $cert, $output;
33
34
    /**
35
     * @var int
36
     */
37
    private $timeout = 60;
38
39
    /**
40
     * @var string
41
     */
42
    private $method = 'GET';
43
44
    /**
45
     * @var string
46
     */
47
    private $headers = 'application/json;charset=utf-8';
48
49
    /**
50
     * 配置网络请求接口
51
     * @param string $str
52
     * @return $this
53
     */
54
    public function url(string $str): self
55
    {
56
        $this->url = $str;
57
        return $this;
58
    }
59
60
    /**
61
     * 需要请求的数据
62
     * @param $str
63
     * @return $this
64
     */
65
    public function data($str): self
66
    {
67
        if (is_array($str)) {
68
            $this->data = json_encode($str, JSON_UNESCAPED_UNICODE);
69
        } else {
70
            $this->data = $str;
71
        }
72
        return $this;
73
    }
74
75
    /**
76
     * 请求头
77
     * @param $str
78
     * @return $this
79
     */
80
    public function headers(string $str): self
81
    {
82
        $this->headers = $str;
83
        return $this;
84
    }
85
86
    /**
87
     * 超时,默认60s
88
     * @param int $int
89
     * @return $this
90
     */
91
    public function timeout(int $int): self
92
    {
93
        $this->timeout = $int;
94
        return $this;
95
    }
96
97
    /**
98
     * 证书
99
     * @param string $sslCertPath
100
     * @param string $sslKeyPath
101
     * @return $this
102
     */
103
    public function cert(string $sslCertPath, string $sslKeyPath): self
104
    {
105
        $this->cert = [
106
            'key' => $sslKeyPath,
107
            'cert' => $sslCertPath,
108
        ];
109
        return $this;
110
    }
111
112
    /**
113
     * GET请求方式
114
     * @return $this
115
     */
116
    public function get(): self
117
    {
118
        $this->method = 'GET';
119
        return $this;
120
    }
121
122
    /**
123
     * POST请求方式
124
     * @return $this
125
     */
126
    public function post(): self
127
    {
128
        $this->method = 'POST';
129
        return $this;
130
    }
131
132
    /**
133
     * XML请求方式
134
     * @return $this
135
     */
136
    public function xml(): self
137
    {
138
        $this->method = 'XML';
139
        return $this;
140
    }
141
142
    /**
143
     * XML请求方式
144
     * @return $this
145
     */
146
    public function file(): self
147
    {
148
        $this->method = 'FILE';
149
        return $this;
150
    }
151
152
    /**
153
     * 返回数组数据
154
     * @param bool $is
155
     * @return array|bool|mixed|string
156
     */
157
    public function toArray(bool $is = true)
158
    {
159
        //首先检测是否支持curl
160
        if (!extension_loaded("curl")) {
161
            throw new HttpException(404, '请开启curl模块!');
162
        }
163
        if ($this->method === 'GET') {
164
            $this->httpGet();
165
        } else if ($this->method === 'POST') {
166
            $this->httpPost();
167
        } else if ($this->method === 'XML') {
168
            $this->httpXml();
169
        } else if ($this->method === 'FILE') {
170
            $this->httpFile();
171
        } else {
172
            throw new HttpException(404, '请求方式异常');
173
        }
174
        if (empty($is)) {
175
            return $this->output;
176
        }
177
        if (is_array($this->output)) {
0 ignored issues
show
The condition is_array($this->output) is always false.
Loading history...
178
            return $this->output;
179
        }
180
        return json_decode($this->output, true);
0 ignored issues
show
It seems like $this->output can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

180
        return json_decode(/** @scrutinizer ignore-type */ $this->output, true);
Loading history...
181
    }
182
183
    /**
184
     * 发送GET请求
185
     * @return bool|mixed|string
186
     */
187
    private function httpGet()
188
    {
189
        $curl = curl_init();
190
        curl_setopt($curl, CURLOPT_URL, $this->url);
191
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
192
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
193
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
194
        if (!empty($this->data)) {
195
            curl_setopt($curl, CURLOPT_POST, 1);
196
            curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
197
        }
198
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
199
        $output = curl_exec($curl);
200
        curl_close($curl);
201
        $this->output = $output;
202
        return $this;
203
    }
204
205
    /**
206
     * 发送Post请求
207
     * @return array|bool|mixed|string
208
     */
209
    private function httpPost()
210
    {
211
        $ch = curl_init();
212
        curl_setopt($ch, CURLOPT_URL, $this->url);
213
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: ' . $this->headers));
214
        curl_setopt($ch, CURLOPT_HEADER, 0);
215
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
216
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
217
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
218
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  // 从证书中检查SSL加密算法是否存在
219
        curl_setopt($ch, CURLOPT_POST, 1);
220
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->data);
221
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
222
        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
223
        $content = curl_exec($ch);
224
        curl_close($ch);
225
        $this->output = $content;
226
        return $this;
227
    }
228
229
230
    /**
231
     * 发送Xml数据
232
     * @return string
233
     */
234
    private function httpXml()
235
    {
236
        //初始一个curl会话
237
        $ch = curl_init();
238
        //设置超时
239
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
240
        curl_setopt($ch, CURLOPT_URL, $this->url);
241
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
242
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
243
        //设置header
244
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
245
        //要求结果为字符串且输出到屏幕上
246
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
247
        //post提交方式
248
        curl_setopt($ch, CURLOPT_POST, TRUE);
249
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->data);
250
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
251
        curl_setopt($ch, CURLOPT_TIMEOUT, 40);
252
        set_time_limit(0);
253
        if (!empty($this->headers)) {
254
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: ' . $this->headers));
255
        }
256
        //运行curl
257
        $data = curl_exec($ch);
258
        curl_close($ch);
259
        $this->output = $data;
260
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type DtApp\ThinkLibrary\service\curl\HttpService which is incompatible with the documented return type string.
Loading history...
261
    }
262
263
    /**
264
     * 上传图片
265
     * @return false|string
266
     */
267
    private function httpFile()
268
    {
269
        //初始一个curl会话
270
        $ch = curl_init();
271
        curl_setopt($ch, CURLOPT_URL, $this->url);
272
        //设置超时
273
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
274
        if (empty($this->cert)) {
275
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
276
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
277
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
278
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
279
            curl_setopt($ch, CURLOPT_SSLCERT, $this->cert['cert']);
280
            curl_setopt($ch, CURLOPT_SSLKEY, $this->cert['key']);
281
        } else if (strpos($this->url, 'https') === 0) {
282
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
283
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名
284
        }
285
        if (!empty($this->headers)) {
286
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('content-type: ' . $this->headers));
287
        }
288
        curl_setopt($ch, CURLOPT_HEADER, true);    // 是否需要响应 header
289
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
290
        $output = curl_exec($ch);
291
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);    // 获得响应结果里的:头大小
292
        $response_body = substr($output, $header_size);
0 ignored issues
show
It seems like $output can also be of type true; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

292
        $response_body = substr(/** @scrutinizer ignore-type */ $output, $header_size);
Loading history...
293
        curl_close($ch);
294
        $this->output = $response_body;
295
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type DtApp\ThinkLibrary\service\curl\HttpService which is incompatible with the documented return type false|string.
Loading history...
296
    }
297
}
298