227 lines
6.4 KiB
PHP
227 lines
6.4 KiB
PHP
<?php
|
|
|
|
namespace app\util;
|
|
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use GuzzleHttp\Psr7\Response;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
|
|
class HttpClient
|
|
{
|
|
/**
|
|
* @var Client Guzzle客户端实例
|
|
*/
|
|
private static $client;
|
|
|
|
/**
|
|
* 获取Guzzle客户端单例
|
|
* @return Client
|
|
*/
|
|
private static function getClient(): Client
|
|
{
|
|
if (!self::$client) {
|
|
self::$client = new Client([
|
|
'timeout' => 10, // 默认超时时间10秒
|
|
'verify' => false, // 不验证SSL证书(生产环境建议设为true)
|
|
'http_errors' => false, // 不抛出HTTP异常,自己处理
|
|
]);
|
|
}
|
|
return self::$client;
|
|
}
|
|
|
|
/**
|
|
* 发送GET请求
|
|
* @param string $url 请求地址
|
|
* @param array $query 查询参数
|
|
* @param array $headers 请求头
|
|
* @return array
|
|
*/
|
|
public static function get(string $url, array $query = [], array $headers = []): array
|
|
{
|
|
$options = [
|
|
'query' => $query,
|
|
'headers' => $headers
|
|
];
|
|
return self::request('GET', $url, $options);
|
|
}
|
|
|
|
/**
|
|
* 发送POST请求
|
|
* @param string $url 请求地址
|
|
* @param array|string $data 请求数据
|
|
* @param array $headers 请求头
|
|
* @param string $contentType 内容类型(form/json/xml)
|
|
* @return array
|
|
*/
|
|
public static function post(string $url, $data = [], array $headers = [], string $contentType = 'form'): array
|
|
{
|
|
$options = ['headers' => $headers];
|
|
|
|
switch ($contentType) {
|
|
case 'json':
|
|
$options['json'] = $data;
|
|
$options['headers']['Content-Type'] = 'application/json';
|
|
break;
|
|
/*case 'xml':
|
|
$options['body'] = is_array($data) ? self::arrayToXml($data) : $data;
|
|
$options['headers']['Content-Type'] = 'application/xml';
|
|
break;*/
|
|
default: // form
|
|
$options['form_params'] = $data;
|
|
$options['headers']['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
}
|
|
|
|
return self::request('POST', $url, $options);
|
|
}
|
|
|
|
/**
|
|
* 发送PUT请求
|
|
* @param string $url 请求地址
|
|
* @param array|string $data 请求数据
|
|
* @param array $headers 请求头
|
|
* @return array
|
|
*/
|
|
public static function put(string $url, $data = [], array $headers = []): array
|
|
{
|
|
$options = [
|
|
'json' => $data,
|
|
'headers' => $headers
|
|
];
|
|
return self::request('PUT', $url, $options);
|
|
}
|
|
|
|
/**
|
|
* 发送DELETE请求
|
|
* @param string $url 请求地址
|
|
* @param array $data 请求数据
|
|
* @param array $headers 请求头
|
|
* @return array
|
|
*/
|
|
public static function delete(string $url, array $data = [], array $headers = []): array
|
|
{
|
|
$options = [
|
|
'json' => $data,
|
|
'headers' => $headers
|
|
];
|
|
return self::request('DELETE', $url, $options);
|
|
}
|
|
|
|
/**
|
|
* 发送HTTP请求
|
|
* @param string $method 请求方法
|
|
* @param string $url 请求地址
|
|
* @param array $options 请求选项
|
|
* @return array
|
|
*/
|
|
public static function request(string $method, string $url, array $options = []): array
|
|
{
|
|
try {
|
|
$response = self::getClient()->request($method, $url, $options);
|
|
return self::formatResponse($response);
|
|
} catch (GuzzleException $e) {
|
|
return [
|
|
'status' => false,
|
|
'code' => $e->getCode(),
|
|
'message' => $e->getMessage(),
|
|
'data' => null
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传文件
|
|
* @param string $url 请求地址
|
|
* @param array $files 文件数组 [['name' => 'field_name', 'path' => 'file_path']]
|
|
* @param array $form 其他表单数据
|
|
* @param array $headers 请求头
|
|
* @return array
|
|
*/
|
|
public static function upload(string $url, array $files, array $form = [], array $headers = []): array
|
|
{
|
|
$multipart = [];
|
|
|
|
// 添加文件
|
|
foreach ($files as $file) {
|
|
if (file_exists($file['path'])) {
|
|
$multipart[] = [
|
|
'name' => $file['name'],
|
|
'contents' => fopen($file['path'], 'r'),
|
|
'filename' => basename($file['path'])
|
|
];
|
|
}
|
|
}
|
|
|
|
// 添加其他表单数据
|
|
foreach ($form as $name => $value) {
|
|
$multipart[] = [
|
|
'name' => $name,
|
|
'contents' => $value
|
|
];
|
|
}
|
|
|
|
$options = [
|
|
'multipart' => $multipart,
|
|
'headers' => $headers
|
|
];
|
|
|
|
return self::request('POST', $url, $options);
|
|
}
|
|
|
|
/**
|
|
* 格式化响应
|
|
* @param ResponseInterface $response
|
|
* @return array
|
|
*/
|
|
private static function formatResponse(ResponseInterface $response): array
|
|
{
|
|
$contents = $response->getBody()->getContents();
|
|
$contentType = $response->getHeaderLine('Content-Type');
|
|
|
|
$data = $contents;
|
|
if (strpos($contentType, 'application/json') !== false) {
|
|
$data = json_decode($contents, true) ?? $contents;
|
|
}
|
|
|
|
return [
|
|
'status' => $response->getStatusCode() === 200,
|
|
'code' => $response->getStatusCode(),
|
|
'message' => $response->getReasonPhrase(),
|
|
'data' => $data,
|
|
'headers' => $response->getHeaders()
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 数组转XML
|
|
* @param array $data
|
|
* @param string $rootNode
|
|
* @return string
|
|
*/
|
|
private static function arrayToXml(array $data, string $rootNode = 'root'): string
|
|
{
|
|
$xml = new \SimpleXMLElement('<' . $rootNode . '/>');
|
|
self::addDataToXml($xml, $data);
|
|
return $xml->asXML();
|
|
}
|
|
|
|
/**
|
|
* 递归添加数据到XML
|
|
* @param \SimpleXMLElement $xml
|
|
* @param array $data
|
|
*/
|
|
private static function addDataToXml(\SimpleXMLElement $xml, array $data)
|
|
{
|
|
foreach ($data as $key => $value) {
|
|
if (is_array($value)) {
|
|
if (is_numeric($key)) {
|
|
$key = 'item';
|
|
}
|
|
$subNode = $xml->addChild($key);
|
|
self::addDataToXml($subNode, $value);
|
|
} else {
|
|
$xml->addChild($key, htmlspecialchars($value));
|
|
}
|
|
}
|
|
}
|
|
} |