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)); } } } }