Files
code-bang/backend/application/common/service/ToolService.php
T

325 lines
9.3 KiB
PHP
Raw Normal View History

2026-09-17 16:25:31 +08:00
<?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
2026-09-21 14:57:50 +08:00
//禁止引用外部xml实体(libxml 2.9+已默认禁用,PHP8起该函数已废弃)
if (PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(true);
}
2026-09-17 16:25:31 +08:00
$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;
}
}