Files
2026-09-21 14:57:50 +08:00

325 lines
9.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\common\service;
use think\Log;
use think\Env;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\TransferException;
class ToolService
{
/**
* get请求
* @param $url
* @param array $queryData
* @param array $headers
* @param bool $json
* @return mixed|string
*/
public static function httpGet($url, $queryData = [], $headers = [], $json = true)
{
try {
$client = new Client(['timeout' => 10]);
$response = $client->request('GET', $url, array_filter([
'query' => $queryData,
'headers' => $headers,
'verify' => false
]));
$body = (string)$response->getBody();
return $json ? json_decode($body, true) : $body;
} catch (RequestException $e) {
return false;
}
}
/**
* post请求
* @param $url
* @param array $postData
* @param array $headers
* @param bool $json
* @return mixed|string
*/
public static function httpPost($url, $postData = [], $headers = [], $json = true)
{
try {
$client = new Client(['timeout' => 10]);
$response = $client->request('POST', $url, array_filter([
'form_params' => $postData,
'headers' => $headers,
'verify' => false
]));
$body = (string)$response->getBody();
return $json ? json_decode($body, true) : $body;
} catch (RequestException $e) {
Log::info('httpPost-error:' . $e->getMessage());
return false;
}
}
/**
* @param $method
* @param $url
* @param array $data
* @param array $headers
* @param bool $jsonRequest
* @param bool $jsonDecode
* @return mixed|string
* @throws \Exception
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public static function httpRequest($method, $url, $data = [], $headers = [], $jsonRequest = false, $jsonDecode = true)
{
try {
$method = strtoupper($method);
$client = new Client(['verify' => false]);
$methodMap = [
'GET' => 'query',
'POST' => 'form_params',
];
$type = $jsonRequest ? 'json' : $methodMap[$method] ?? 'query';
$param = [$type => $data];
if ($headers) {
$param['headers'] = $headers;
}
$response = $client->request($method, $url, $param);
$body = (string)$response->getBody();
return $jsonDecode ? json_decode($body, true) : $body;
} catch (TransferException $e) {
throw new \Exception($e->getMessage(), $e->getCode());
}
}
/**
* 输出xml字符
* @param $values
* @return string
* @throws \Exception
*/
public static function ToXml($values)
{
if (!is_array($values) || count($values) <= 0) {
throw new \Exception("数组数据异常!");
}
$xml = "<xml>";
foreach ($values as $key => $val) {
if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>";
return $xml;
}
/**
* 将xml转为array
* @param $xml
* @return mixed
* @throws \Exception
*/
public static function FromXml($xml)
{
if (!$xml) {
throw new \Exception("xml数据异常!");
}
//将XML转为array
//禁止引用外部xml实体(libxml 2.9+已默认禁用,PHP8起该函数已废弃)
if (PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(true);
}
$values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $values;
}
/**
* 格式化参数格式化成url参数
* @param $values
* @return string
*/
public static function ToUrlParams($values)
{
$buff = "";
foreach ($values as $k => $v) {
if ($k != "sign" && $v != "" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* 生成签名
* @param $values
* @param $key
* @return string
*/
public static function MakeSign($values, $key = '')
{
unset($values['sign']);
//签名步骤一:按字典序排序参数
ksort($values);
$string = self::ToUrlParams($values);
//签名步骤二:在string后加入KEY
!$key && $key = Env::get('wechat.api_key');
$string = $string . "&key=" . $key;
//签名步骤三:MD5加密或者HMAC-SHA256
if (isset($values['sign_type']) && $values['sign_type'] == 'HMAC-SHA256') {
$sign = hash_hmac("sha256", $string, $key);
} else {
$sign = md5($string);
}
//签名步骤四:所有字符转为大写
$result = strtoupper($sign);
Log::info('通用工具签名-MakeSign:' . json_encode(['values' => $values, 'string' => $string, 'sign' => $sign]));
return $result;
}
/**
* 验证签名是否正确
* @param $values
* @param $sign
* @param $key
* @return bool
*/
public static function CheckSign($values, $sign, $key = '')
{
$localSign = self::MakeSign($values, $key);
Log::info('通用工具签名信息-Tool-CheckSign' . json_encode(['data' => $values, 'sign' => $sign, 'localSign' => $localSign]));
if ($localSign == $sign) {
//签名正确
return true;
}
return false;
}
/**
* 打包签名数据
* @param $values
* @return mixed
*/
public static function packSign($values)
{
if (!isset($values['nonce_str'])) {
$values['nonce_str'] = uniqid();
}
if (!isset($values['time_stamp'])) {
$values['time_stamp'] = time();
}
//签名步骤四:所有字符转为大写
$values['sign'] = self::MakeSign($values, Env::get('app.token_key'));
return $values;
}
/**
* @param $array
* @return mixed
*/
public static function changeArrayKey($array)
{
foreach ($array as &$value) {
if (isset($value['name'])) {
$value['text'] = $value['name'];
unset($value['name']);
}
if (isset($value['subItems'])) {
foreach ($value['subItems'] as &$v) {
$v['text'] = $v['name'];
unset($v['name']);
}
$value['children'] = $value['subItems'];
unset($value['subItems']);
}
}
return $array;
}
/**
* 解析字符串数组
* @param $string
* @param $data
* @return mixed
*/
public static function parseArrStr($string, $data)
{
$fieldArr = explode('.', str_replace(['{', '}'], '', $string));
foreach ($fieldArr as $field) {
$data = $data[$field] ?? '';
}
return $data;
}
/**
* @param $value
* @param $data
* @return string
*/
public static function parseTempData($value, $data)
{
if (preg_match_all('/\{.*?\}/', $value, $matches)) {
$str = '';
foreach ($matches as $match){
$str .= ToolService::parseArrStr($match, $data);
}
$value = $str;
}
return $value;
}
/**
* 获取请求缓存Key
* @param $url
* @param $param
* @return mixed
*/
public static function httpCacheKey($url, $param)
{
$query = http_build_query($param);
$parse = parse_url($url);
$urls = implode(':', ['http-cache', $parse['host'], $parse['path'], $query]);
$key = preg_replace('/[^a-zA-Z0-9_\-:]/', '', $urls);
return $key;
}
/**
* 递归实现无限极分类
* @param array $array 分类数据
* @param int $pid 父ID
* @param int $level 分类级别
* @return array 分好类的数组 直接遍历即可 $level可以用来遍历缩进
*/
public static function getTree($array, $pid = 0, $level = 0)
{
//声明静态数组,避免递归调用时,多次声明导致数组覆盖
static $list = [];
foreach ($array as $key => $value) {
//第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点
if ($value['parent_id'] == $pid) {
//父节点为根节点的节点,级别为0,也就是第一级
$value['level'] = $level;
$value['name'] = str_repeat('--', $level) . $value['name'];
//把数组放到list中
$list[] = $value;
//把这个节点从数组中移除,减少后续递归消耗
unset($array[$key]);
//开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
self::getTree($array, $value['id'], $level + 1);
}
}
return $list;
}
}