test
This commit is contained in:
Submodule superadmin/vendor/wanghua/general-utility-tools-php deleted from a64ab59e2d
37
superadmin/vendor/wanghua/general-utility-tools-php/README.en.md
vendored
Normal file
37
superadmin/vendor/wanghua/general-utility-tools-php/README.en.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# general_utility_tools_php
|
||||
|
||||
#### Description
|
||||
php常用工具箱
|
||||
general utility tool for php
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
142
superadmin/vendor/wanghua/general-utility-tools-php/README.md
vendored
Normal file
142
superadmin/vendor/wanghua/general-utility-tools-php/README.md
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
# general_utility_tools_php
|
||||
|
||||
#### 介绍
|
||||
|
||||
[PHP常用通用工具库]
|
||||
|
||||
一、常用验证类库
|
||||
1. 验证手机号是否正确
|
||||
2. 验证邮箱
|
||||
3. 验证身份证号码
|
||||
4. 是否字母或数字
|
||||
5. 是否是小数格式
|
||||
6. 更多功能请参考代码
|
||||
|
||||
二、PHP日期处理工具
|
||||
1. 日期加上N年、月、日、时、分、秒,得到计算后的时间
|
||||
2. 两个日期相减得到天、时、分、秒(没有两个日期相加一说)
|
||||
3. 更多更完善功能敬请期待......
|
||||
|
||||
三、更多类库参考本类库目录
|
||||
1. 每个目录都有使用说明.
|
||||
|
||||
#### 软件架构
|
||||
|
||||
每一种工具独立为一个功能类库。
|
||||
#### 软件要求
|
||||
thinkphp5.0+,PHP7.1+
|
||||
|
||||
|
||||
#### 安装教程
|
||||
composer require wanghua/general-utility-tools-php dev-master
|
||||
|
||||
###### 注意:如果总是安装失败,可切换国内或者国外源;如果是找不到版本则加上dev-master尝试
|
||||
###### 注意:如果总是安装失败,可卸载此包重新安装,卸载指令:composer remove wanghua/general-utility-tools-php
|
||||
###### 注意:如果总是不能提交 vendor下面的一个文件夹(或文件),请参考这篇文章解决:https://blog.csdn.net/qq_15941409/article/details/113184021
|
||||
|
||||
### 一、常用验证类库使用说明
|
||||
##### 初始化
|
||||
|
||||
//静态方法无需实例化直接调用
|
||||
|
||||
##### 验证参数是否是小数格式
|
||||
$str = '1.223';
|
||||
var_dump(Validate::is_float_number($str));
|
||||
|
||||
##### 验证参数是否字母或数字
|
||||
$str = 'qwer#199';
|
||||
var_dump(Validate::is_letter_or_number($str));
|
||||
|
||||
###### 注: 更多功能请参考源码
|
||||
|
||||
### 二、PHP日期处理工具使用说明
|
||||
|
||||
##### 初始化
|
||||
$date = (new Date());
|
||||
$date->date_format = 'Y-m-d H:i:s';//设置格式,默认Y-m-d H:i:s
|
||||
|
||||
##### 日期类型参数(第2个参数)可选项:
|
||||
//分、时、天、周、月、年
|
||||
protected $data_type = [
|
||||
'm' =>'minute',//分钟
|
||||
'minute' =>'minute',//分钟
|
||||
'h' =>'hour',//小时
|
||||
'hour' =>'hour',//小时
|
||||
'd' =>'day',//天
|
||||
'day' =>'day',//天
|
||||
'w' =>'week',//周
|
||||
'week' =>'week',//周
|
||||
'M' =>'month',//月
|
||||
'month' =>'month',//月
|
||||
'y' =>'year',//年
|
||||
'year' =>'year',//年
|
||||
];
|
||||
|
||||
|
||||
##### 在当前时间基础上加3天(第三个参数不传默认使用当前时间)
|
||||
$res = $date->addTime(3, 'd');//支持单词和字母,例如:d表示天,day也表示天
|
||||
dump($res);
|
||||
|
||||
##### 在当前时间基础上加1小时(第三个参数不传默认使用当前时间)
|
||||
$res = $date->addTime(1, 'h');//支持单词和字母,例如:h表示小时,hour也表示小时
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上加1小时
|
||||
$res = $date->addTime(1, 'h', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减1个月 (注意:月是大写M字母,分钟是小写m字母)
|
||||
$res = $date->reduceTime(1, 'M', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减20分钟 (注意:分钟是小写m字母)
|
||||
$res = $date->reduceTime(20, 'm', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减1年
|
||||
$res = $date->reduceTime(1, 'y', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
### 日期时间相减
|
||||
|
||||
//时间相减返回的时间类型 秒、分、时、天 默认返回秒
|
||||
protected $time_type = [
|
||||
's' =>1,//秒
|
||||
'second' =>1,//秒
|
||||
'm' =>60,//分钟
|
||||
'minute' =>60,//分钟
|
||||
'h' =>3600,//小时
|
||||
'hour' =>3600,//小时
|
||||
'd' =>86400,//天
|
||||
'day' =>86400,//天
|
||||
];
|
||||
|
||||
$start_time = '2010-05-01 12:30:00';
|
||||
$end_time = '2010-10-28 12:30:00';
|
||||
|
||||
//结束时间减去开始时间得到秒数 (返回类型参考上方配置)
|
||||
$res = $date->timeReduceTime($end_time, $start_time);
|
||||
dump($res);
|
||||
|
||||
//结束时间减去开始时间得到天数 (返回类型参考上方配置)
|
||||
$res = $date->timeReduceTime($end_time, $start_time, 'day');
|
||||
dump($res);
|
||||
|
||||
###### 注: 更多功能请参考源码
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
25
superadmin/vendor/wanghua/general-utility-tools-php/composer.json
vendored
Normal file
25
superadmin/vendor/wanghua/general-utility-tools-php/composer.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"type": "library",
|
||||
"name": "wanghua/general-utility-tools-php",
|
||||
"homepage": "https://gitee.com/drop_drop/general_utility_tools_php.git",
|
||||
"description": "general utility tools for thinkPHP",
|
||||
"license": "Apache-2.0",
|
||||
"version":"1.0.1",
|
||||
"keywords": ["general-utility-tools","php tool","common tool"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "wanghua",
|
||||
"email": "wanghua@qq.com",
|
||||
"homepage": "https://blog.csdn.net/qq_15941409"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"ext-json": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"wanghua\\general_utility_tools_php\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
396
superadmin/vendor/wanghua/general-utility-tools-php/src/Date.php
vendored
Normal file
396
superadmin/vendor/wanghua/general-utility-tools-php/src/Date.php
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/10/27} {11:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
/**
|
||||
* 日期时间处理类
|
||||
* Class Date
|
||||
* @package libraries
|
||||
*/
|
||||
class Date
|
||||
{
|
||||
//时间默认返回格式
|
||||
public $date_format = 'Y-m-d H:i:s';
|
||||
//分、时、天、周、月、年
|
||||
protected $data_type = [
|
||||
'm' =>'minute',//分钟
|
||||
'minute' =>'minute',//分钟
|
||||
'h' =>'hour',//小时
|
||||
'hour' =>'hour',//小时
|
||||
'd' =>'day',//天
|
||||
'day' =>'day',//天
|
||||
'w' =>'week',//周
|
||||
'week' =>'week',//周
|
||||
'M' =>'month',//月
|
||||
'month' =>'month',//月
|
||||
'y' =>'year',//年
|
||||
'year' =>'year',//年
|
||||
];
|
||||
//秒、分、时、天
|
||||
protected $time_type = [
|
||||
's' =>1,//秒
|
||||
'second' =>1,//秒
|
||||
'm' =>60,//分钟
|
||||
'minute' =>60,//分钟
|
||||
'h' =>3600,//小时
|
||||
'hour' =>3600,//小时
|
||||
'd' =>86400,//天
|
||||
'day' =>86400,//天
|
||||
];
|
||||
/**
|
||||
* desc:日期时间加N
|
||||
*
|
||||
* 【注意】
|
||||
* 请在计算月时使用$date->date_format = 'Y-m'防止跳月份
|
||||
* 例如:2020-03-31月基础上加一个月,在默认$date->date_format='Y-m-d H:i:s'时,会跳到2020-05-01
|
||||
*
|
||||
* author:wh
|
||||
* @param int $times 相加的时间数量 整型
|
||||
* @param string $date_type 要相加的时间类型 可选值:m 分钟;h 小时;d 天;w 周;M 月;y 年
|
||||
* @param int $default_time 时间戳,默认当前时间
|
||||
* @return false|string 返回$this->date_format格式,可根据需要设定格式
|
||||
*/
|
||||
function addTime(int $times, string $date_type, int $default_time=0){
|
||||
return date($this->date_format, strtotime("+{$times} {$this->data_type[$date_type]}", $default_time?$default_time:time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期时间减N
|
||||
*
|
||||
* 【注意】
|
||||
* 请在计算月时使用$date->date_format = 'Y-m'防止跳月份
|
||||
* 例如:2020-03-31月基础上加一个月,在默认$date->date_format='Y-m-d H:i:s'时,会跳到2020-05-01
|
||||
*
|
||||
* author:wh
|
||||
* @param int $times 减去的时间数量 整型
|
||||
* @param string $date_type 要相减的时间类型 可选值:m 分钟;h 小时;d 天;w 周;M 月;y 年
|
||||
* @param int $default_time 时间戳,默认当前时间
|
||||
* @return false|string 返回$this->date_format格式,可根据需要设定格式
|
||||
*/
|
||||
function reduceTime(int $times, string $date_type, int $default_time=0){
|
||||
return date($this->date_format, strtotime("-{$times} {$this->data_type[$date_type]}", $default_time?$default_time:time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期时间相减,通常结束时间大于开始时间
|
||||
* author:wh
|
||||
* @param string $end_time 结束时间
|
||||
* @param string $start_time 开始时间
|
||||
* @param string $return_type 日期时间相减后得到的时间类型,可能是小数。可选值:s 秒;m 分钟;h 小时;d;天
|
||||
* @return float|int 返回计算后的天、时、分、秒数
|
||||
*/
|
||||
function timeReduceTime(string $end_time, string $start_time, string $return_type='s'){
|
||||
return (strtotime($end_time) - strtotime($start_time)) / $this->time_type[$return_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期减日期, 返回月数或年数
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间
|
||||
* @param string $end_time 结束时间
|
||||
* @param string $return_type M 返回一共有多少个月,y 返回有多少个年
|
||||
* @return float|int
|
||||
*/
|
||||
function dateCutDate(string $start_time, string $end_time, string $return_type='M'){
|
||||
$e = date_create($end_time);
|
||||
|
||||
$s = date_create($start_time);
|
||||
|
||||
$diff = date_diff($e, $s);
|
||||
|
||||
//计算月份
|
||||
if ($diff->y > 0) {
|
||||
$m = $diff->y * 12 + $diff->m;
|
||||
}else{
|
||||
$m = $diff->m;
|
||||
}
|
||||
return $return_type=='M'?$m:$diff->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期相减得到月数
|
||||
* 注意:不是计算的时间戳,而是计算的月份差值
|
||||
* author:wh
|
||||
* @param string $start_time
|
||||
* @param string $end_time
|
||||
* @return false|float|int|string
|
||||
*/
|
||||
function dateCutMonth(string $start_time, string $end_time){
|
||||
$start_y = date('Y', strtotime($start_time));
|
||||
$end_y = date('Y', strtotime($end_time));
|
||||
$start_m = date('m', strtotime($start_time));
|
||||
$end_m = date('m', strtotime($end_time));
|
||||
$ym = ($end_y-$start_y) * 12;
|
||||
return $ym - $start_m + $end_m;
|
||||
}
|
||||
/**
|
||||
* desc:日期相减得到年数
|
||||
* 注意:不是计算的时间戳,而是计算的年份差值
|
||||
* author:wh
|
||||
* @param string $start_time
|
||||
* @param string $end_time
|
||||
* @return false|float|int|string
|
||||
*/
|
||||
function dateCutYear(string $start_time, string $end_time){
|
||||
$start_y = date('Y', strtotime($start_time));
|
||||
$end_y = date('Y', strtotime($end_time));
|
||||
return ($end_y-$start_y) * 12;
|
||||
}
|
||||
/**
|
||||
* desc:返回年中第几天
|
||||
* author:wh
|
||||
* @param string $month 指定月份
|
||||
* @param string $day 指定日
|
||||
* @param string $year 指定年份
|
||||
* @return false|string
|
||||
*/
|
||||
function get_day_Year(string $month, string $day, string $year){
|
||||
return date('z',mktime(0,0,0,$month,$day,$year));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:今天的开始时间
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginToday(){
|
||||
return date('Y-m-d').' 00:00:00';
|
||||
}
|
||||
/**
|
||||
* desc:今天的结束时间
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endToday(){
|
||||
return date('Y-m-d').' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:昨天的开始时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function beginYesterday(){
|
||||
return date('Y-m-d', strtotime('-1 day')).' 00:00:00';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:昨天的结束时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function endYesterday(){
|
||||
return date('Y-m-d', strtotime('-1 day')).' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前天的开始时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function beginBeforeYesterday(){
|
||||
return date('Y-m-d', strtotime('-2 day')).' 00:00:00';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前天的结束时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function endBeforeYesterday(){
|
||||
return date('Y-m-d', strtotime('-2 day')).' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* 本周的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginWeek($His = true)
|
||||
{
|
||||
//此代码会跳周、月、年
|
||||
//$timestamp = mktime(0, 0, 0, date('m'), date('d') - date('w') + 1, date('Y'));
|
||||
//return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
|
||||
//改进
|
||||
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
|
||||
$first=1;
|
||||
$sdefaultDate = date("Y-m-d");
|
||||
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
|
||||
$w=date('w',strtotime($sdefaultDate));
|
||||
//是否展示时分秒
|
||||
$week_start = date('Y-m-d',strtotime("$sdefaultDate -".($w ? $w - $first : 6).' days'));
|
||||
//是否展示时分秒
|
||||
if($His){
|
||||
//$week_start
|
||||
return $week_start.' 00:00:00';
|
||||
}
|
||||
//$week_start
|
||||
return $week_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* 本周的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endWeek($His = true)
|
||||
{
|
||||
//此代码会跳周、月、年
|
||||
//$timestamp = mktime(23, 59, 59, date('m'), date('d') - date('w') + 7, date('Y'));
|
||||
//return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
|
||||
//改进
|
||||
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
|
||||
$first=1;
|
||||
$sdefaultDate = date("Y-m-d");
|
||||
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
|
||||
$w=date('w',strtotime($sdefaultDate));
|
||||
//是否展示时分秒
|
||||
$week_start = date('Y-m-d',strtotime("$sdefaultDate -".($w ? $w - $first : 6).' days'));
|
||||
$week_end=date('Y-m-d',strtotime("$week_start +6 days"));
|
||||
//是否展示时分秒
|
||||
return $His?$week_end.' 23:59:59':$week_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上周开始
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginBeforeWeek(){
|
||||
$week = $this->beginWeek();
|
||||
$this->date_format = 'Y-m-d';
|
||||
return $this->reduceTime(7,'d',strtotime($week)) . ' 00:00:00';
|
||||
|
||||
//此代码会跳周、月、年
|
||||
//return date('Y-m-d', strtotime('-1 monday', time())).' 00:00:00';//上周一,无论今天几号,-1 monday为上一个有效周未
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上周结束
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endBeforeWeek(){
|
||||
|
||||
$week = $this->beginWeek();
|
||||
$this->date_format = 'Y-m-d';
|
||||
return $this->reduceTime(1,'d',strtotime($week)) . ' 23:59:59';
|
||||
|
||||
//此代码会跳周、月、年
|
||||
//return date('Y-m-d', strtotime('-1 sunday', time())).' 23:59:59'; //上一个有效周日,同样适用于其它星期
|
||||
}
|
||||
|
||||
/**
|
||||
* 本月的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginMonth($His = true)
|
||||
{
|
||||
return $His ? date('Y-m-').'01 00:00:00' : date('Y-m-').'01';
|
||||
}
|
||||
/**
|
||||
* 本月的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endMonth($His = true)
|
||||
{
|
||||
$timestamp = mktime(23, 59, 59, date('m'), date('t'), date('Y'));
|
||||
return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上月开始时间(上月一日)
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginBeforeMonth(){
|
||||
return date('Y-m-d', strtotime('-1 month', strtotime(date('Y-m', time()) . '-01 00:00:00'))).' 00:00:00'; //本月一日直接strtotime上减一个月
|
||||
}
|
||||
/**
|
||||
* desc:上月结束时间(上月最后一日)
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endBeforeMonth(){
|
||||
return date('Y-m-d', strtotime(date('Y-m', time()) . '-01 00:00:00') - 86400).' 23:59:59'; //本月一日减一天即是上月最后一日
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:七天(一周)以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerWeekDay(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 7 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
/**
|
||||
* desc:一月以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerMonth(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 30 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
/**
|
||||
* desc:一年以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerYear(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 365 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
|
||||
/**
|
||||
* 几年的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginYear($His = true)
|
||||
{
|
||||
$timestamp = date('Y');
|
||||
return $His ? $timestamp.'-01-01 00:00:00' : $timestamp.'-01-01';
|
||||
}
|
||||
|
||||
/**
|
||||
* 几年的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endYear($His = true)
|
||||
{
|
||||
$timestamp = date('Y');
|
||||
return $His ? $timestamp.'-12-31 23:59:59' : $timestamp.'-12-31';
|
||||
}
|
||||
}
|
||||
134
superadmin/vendor/wanghua/general-utility-tools-php/src/Mmodel.php
vendored
Normal file
134
superadmin/vendor/wanghua/general-utility-tools-php/src/Mmodel.php
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/1} {21:28}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* thinkphp5模型快捷方法库
|
||||
* Class Mmodel
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class Mmodel
|
||||
{
|
||||
/**
|
||||
* desc:存在则更新否则插入
|
||||
* author:wh
|
||||
* @param string $table 表名
|
||||
* @param array $where 更新条件(只在更新时有效)
|
||||
* @param array $data 更新或写入数据
|
||||
* @return int 数据主键id
|
||||
*/
|
||||
static function existsUpdateInsert($table,$where,$data){
|
||||
if(empty($where)){
|
||||
return Db::table($table)->insertGetId($data);
|
||||
}
|
||||
$res = Db::table($table)
|
||||
->where($where)
|
||||
->find();
|
||||
if($res){
|
||||
//不修改条件数据
|
||||
$data = array_diff_key($data,$where);//从data中删除where数组中的键值对
|
||||
|
||||
Db::table($table)
|
||||
->where($where)
|
||||
->data($data)
|
||||
->update();
|
||||
return $res['id'];
|
||||
}
|
||||
return Db::table($table)->insertGetId($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 无事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catch($fn){
|
||||
try{
|
||||
//不输出日志,此代码块可能用于内部逻辑
|
||||
//Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
//Tools::log_to_write_txt(['output'=>$res]);
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('操作失败.',$e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 无事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchJson($fn, $is_whrite_log=true){
|
||||
try{
|
||||
!$is_whrite_log?:Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
!$is_whrite_log?:Tools::log_to_write_txt(['output'=>$res]);
|
||||
return json($res);
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return json(Tools::set_fail('操作失败.',$e->getMessage()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 自动事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchTrans($fn, $is_whrite_log=true){
|
||||
Db::startTrans();
|
||||
try{
|
||||
!$is_whrite_log?:Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
!$is_whrite_log?:Tools::log_to_write_txt(['output'=>$res]);
|
||||
Db::commit();
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Db::rollback();
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('操作失败.',$e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 自动事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchTransJson($fn, $is_whrite_log=true){
|
||||
Db::startTrans();
|
||||
try{
|
||||
!$is_whrite_log?:Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
!$is_whrite_log?:Tools::log_to_write_txt(['output'=>$res]);
|
||||
Db::commit();
|
||||
return json($res);
|
||||
}catch (\Exception $e){
|
||||
Db::rollback();
|
||||
Tools::error_txt_log($e);
|
||||
return json(Tools::set_fail('操作失败.',$e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
94
superadmin/vendor/wanghua/general-utility-tools-php/src/PinYin.php
vendored
Normal file
94
superadmin/vendor/wanghua/general-utility-tools-php/src/PinYin.php
vendored
Normal file
File diff suppressed because one or more lines are too long
50
superadmin/vendor/wanghua/general-utility-tools-php/src/SundryConfig.php
vendored
Normal file
50
superadmin/vendor/wanghua/general-utility-tools-php/src/SundryConfig.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2023/12/31} {21:56}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 系统杂项配置
|
||||
*
|
||||
* 读取fa_sundry_config表中的配置
|
||||
*
|
||||
* Class SundryConfig
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class SundryConfig
|
||||
{
|
||||
private static $tablename = 'fa_zc_sundry_config';
|
||||
|
||||
/**
|
||||
* desc:获取配置的值,设置配置的值
|
||||
*
|
||||
* 默认缓存值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
static function val(string $key,string $val=''){
|
||||
$tabname = self::$tablename;
|
||||
if($val){
|
||||
$obj = Db::table($tabname);
|
||||
$obj->where('key',$key);
|
||||
$obj->data(['val'=>$val]);
|
||||
return $obj->update();
|
||||
}
|
||||
$obj = Db::table($tabname);
|
||||
return $obj->where(['key'=>$key])
|
||||
->cache($tabname.'_'.$key,0,$tabname)
|
||||
->value('val');
|
||||
}
|
||||
}
|
||||
360
superadmin/vendor/wanghua/general-utility-tools-php/src/Validate.php
vendored
Normal file
360
superadmin/vendor/wanghua/general-utility-tools-php/src/Validate.php
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/11/1} {15:09}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
class Validate
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:验证手机号是否正确
|
||||
* author:wh
|
||||
* @param $m
|
||||
* @return bool
|
||||
*/
|
||||
static function is_mobile($m) {
|
||||
return preg_match('/^1[3,4,5,6,7,8,9]{1}\d{9}$/', $m) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邮箱
|
||||
* author:wh
|
||||
* @param $email
|
||||
* @return bool
|
||||
*/
|
||||
static function is_email($email){
|
||||
return preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/",$email)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [is_IDCard 验证身份证号码]
|
||||
* @Author
|
||||
* @Date 2019-11-26
|
||||
* @param [string] $string [身份证号]
|
||||
* @return boolean [description]
|
||||
*/
|
||||
static function is_IDCard($string){
|
||||
return preg_match("/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/", $string)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [is_money_times 验证金额是否是100的整数倍]
|
||||
* @Author
|
||||
* @Date 2019-12-12
|
||||
* @param [type] $money [金额]
|
||||
* @return boolean [description]
|
||||
*/
|
||||
static function is_money_times($money){
|
||||
if(!is_numeric($money) || $money <= 0){
|
||||
return false;
|
||||
}
|
||||
return $money%100===0;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是金额
|
||||
* author:wh
|
||||
* @param $money
|
||||
* @return bool
|
||||
*/
|
||||
static function is_money($money){
|
||||
return (preg_match('/^[0-9]+.[0-9]+$/', $money) || preg_match('/^\d+$/', $money))?true:false;
|
||||
}
|
||||
/**
|
||||
* desc:是否是金额,并且最多只有两位小数
|
||||
*
|
||||
* 严格金额格式校验
|
||||
*
|
||||
* author:wh
|
||||
* @param $money
|
||||
* @return bool
|
||||
*/
|
||||
static function is_money_double($money){
|
||||
|
||||
$r = (preg_match('/^[0-9]+.[0-9]+$/', $money) || preg_match('/^\d+$/', $money))?true:false;
|
||||
|
||||
$exp = explode('.',$money);
|
||||
|
||||
if(strpos($money,'.') && preg_match('/^[0-9]+.[0-9]+$/', $money) && strlen($exp[1])>2){
|
||||
//返回false,表示非严格的2位数金额
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是小数格式
|
||||
* author:wh
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
static function is_float_number(string $num){
|
||||
return preg_match('/^[0-9]+.[0-9]+$/', $num)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是数字
|
||||
* author:wh
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
static function is_number(string $num){
|
||||
return preg_match('/^\d+$/', $num)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是字母
|
||||
* author: wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_letter(string $str){
|
||||
return preg_match('/^[a-zA-Z]+$/', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否字母或数字
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_letter_or_number(string $str){
|
||||
return preg_match('/^[a-zA-Z|0-9]+$/', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证数组是否存在空值
|
||||
* 仅针对基本数据类型
|
||||
* 仅针对一维数组
|
||||
* author:wh
|
||||
* @param $array
|
||||
* @return bool
|
||||
*/
|
||||
static function check_array_val_empty($array){
|
||||
$is_empty = false;
|
||||
foreach ($array as $value){
|
||||
if(($value!==0 && $value !=='0') && empty($value)){
|
||||
$is_empty = true;
|
||||
break;
|
||||
}
|
||||
if(is_int($value) && empty(1*$value)){
|
||||
$is_empty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $is_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是url
|
||||
* author:wh
|
||||
* @param $v
|
||||
* @return bool
|
||||
*/
|
||||
static function is_url($v){
|
||||
$pattern="#(http|https)://(.*\.)?.*\..*#i";
|
||||
return preg_match($pattern,$v)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [是否全部大写]
|
||||
*
|
||||
* @param $str
|
||||
* @return bool
|
||||
* @example
|
||||
* @see
|
||||
* @link
|
||||
*/
|
||||
static function is_upper($str){
|
||||
return preg_match('/^[A-Z]+$/', $str)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [是否全部小写]
|
||||
*
|
||||
* @param $str
|
||||
* @return bool
|
||||
* @example
|
||||
* @see
|
||||
* @link
|
||||
*/
|
||||
static function is_lower($str){
|
||||
return preg_match('/^[a-z]+$/', $str)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:验证是微信内还是微信外
|
||||
*
|
||||
* 是否在微信内,是否在微信中
|
||||
*
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
static function is_weixin(){
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否包含特殊字符
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_special_character(string $str){
|
||||
$res = preg_match ( '/[\Q~!@#$%^&*()+-_=.:?<>\E]/', $str );
|
||||
return $res ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证字符串是否全部是中文
|
||||
*
|
||||
* 返回 true表示全部是中文,false表示部分是中文或没有中文
|
||||
*
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_all_chinese(string $str){
|
||||
return preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$str)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证两个浮点数值是否相等
|
||||
*
|
||||
* 例如:
|
||||
* $num1 = 0.1;
|
||||
$num2 = 0.7;
|
||||
|
||||
$res = $num1 + $num2;
|
||||
|
||||
var_dump($res);
|
||||
|
||||
var_dump($res == 0.8);//false 不相等
|
||||
|
||||
var_dump(intval(strval($res)) == intval(strval(0.8)));//true 相等
|
||||
*
|
||||
* author:wh
|
||||
* @param $float_num1
|
||||
* @param $float_num2
|
||||
* @return bool
|
||||
*/
|
||||
static function is_equal_num_val($float_num1, $float_num2){
|
||||
|
||||
return intval(strval($float_num1)) == intval(strval($float_num2));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否包含给定的主域名
|
||||
* author:wh
|
||||
* @param $domain
|
||||
* @param $main_domain
|
||||
* @return bool
|
||||
*/
|
||||
static function is_main_domain($domain,$main_domain){
|
||||
$exp_arr = explode('.',$domain);
|
||||
$str = $exp_arr[count($exp_arr)-2] .'.'. $exp_arr[count($exp_arr)-1];
|
||||
return $str==$main_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:国内国外IP校验,校验IP来源
|
||||
*
|
||||
* author:wh
|
||||
* @param $ip
|
||||
* @return bool
|
||||
*/
|
||||
static function validate_ip($ip) {
|
||||
$chinaStart = ip2long('1.0.1.0'); // 中国大陆起始IP
|
||||
$chinaEnd = ip2long('254.254.254.254'); // 中国大陆结束IP
|
||||
|
||||
$hongKongStart = ip2long('8.36.0.0'); // 香港起始IP
|
||||
$hongKongEnd = ip2long('8.37.255.255'); // 香港结束IP
|
||||
|
||||
$taiwanStart = ip2long('192.168.0.0'); // 台湾起始IP
|
||||
$taiwanEnd = ip2long('192.168.255.255'); // 台湾结束IP
|
||||
|
||||
$ipLong = ip2long($ip);
|
||||
|
||||
if ($ipLong >= $chinaStart && $ipLong <= $chinaEnd ||
|
||||
$ipLong >= $hongKongStart && $ipLong <= $hongKongEnd ||
|
||||
$ipLong >= $taiwanStart && $ipLong <= $taiwanEnd) {
|
||||
return true; // IP属于国内
|
||||
} else {
|
||||
return false; // IP不属于国内
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否移动端访问访问
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function is_mobile_client()
|
||||
{
|
||||
// 如果有HTTP_X_WAP_PROFILE则一定是移动设备
|
||||
if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
|
||||
if (isset($_SERVER['HTTP_VIA'])) {
|
||||
//找不到为flase,否则为true
|
||||
return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
|
||||
}
|
||||
|
||||
//判断手机发送的客户端标志
|
||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||
$clientkeywords = [
|
||||
'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp',
|
||||
'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu',
|
||||
'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi',
|
||||
'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile','alipay'
|
||||
];
|
||||
|
||||
// 从HTTP_USER_AGENT中查找手机浏览器的关键字
|
||||
if (preg_match("/(".implode('|', $clientkeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//协议法,因为有可能不准确,放到最后判断
|
||||
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
||||
// 如果只支持wml并且不支持html那一定是移动设备
|
||||
// 如果支持wml和html但是wml在html之前则是移动设备
|
||||
if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否微信内置浏览器访问
|
||||
* @return bool
|
||||
*/
|
||||
static function is_wx_client()
|
||||
{
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否支付宝内置浏览器访问
|
||||
* @return bool
|
||||
*/
|
||||
static function is_ali_client()
|
||||
{
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'Alipay') !== false;
|
||||
}
|
||||
}
|
||||
121
superadmin/vendor/wanghua/general-utility-tools-php/src/algorithm/Algorithm.php
vendored
Normal file
121
superadmin/vendor/wanghua/general-utility-tools-php/src/algorithm/Algorithm.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/27} {17:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\algorithm;
|
||||
|
||||
|
||||
/**
|
||||
* 常见算法
|
||||
* Class AlgorithmTools
|
||||
* @package wanghua\general_utility_tools_php\tool
|
||||
*/
|
||||
class Algorithm
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:权重随机选择算法
|
||||
*
|
||||
* 使用场景:转盘抽奖等需要指定概率的场景
|
||||
*
|
||||
* author:wh
|
||||
* @param array $weights 权重数组 eg:[1, 9, 30, 70] 概率的总和是100%
|
||||
* return 返回计算后的索引
|
||||
*/
|
||||
static function weightRandom($weights){
|
||||
//$weights = [1, 9, 30, 70]; // 权重数组
|
||||
$totalWeight = array_sum($weights);
|
||||
$min_num = min($weights);//取出数组中最小的值
|
||||
$random = mt_rand($min_num, $totalWeight); // 生成一个最小元素到总权重的随机数
|
||||
|
||||
$cumulativeWeight = 0; // 累积权重
|
||||
$selected = 0; // 选择的索引
|
||||
|
||||
foreach ($weights as $index => $weight) {
|
||||
$cumulativeWeight += $weight; // 累加权重
|
||||
if ($random <= $cumulativeWeight) {
|
||||
$selected = $index; // 根据权重选择索引
|
||||
break;
|
||||
}
|
||||
}
|
||||
//输出选择的索引
|
||||
return $selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:测试权重随机算法概率
|
||||
* author:wh
|
||||
* @param array $weights 权重数组 eg:[1, 9, 30, 70]
|
||||
*/
|
||||
static function testWeightRandom(array $weights){
|
||||
echo json_encode($weights)."\n";
|
||||
|
||||
$trials = 1000; // 试验次数
|
||||
$selectionCounts = array_fill(0, count($weights), 0); // 用于存储每个索引的选择次数
|
||||
|
||||
for ($i = 0; $i < $trials; $i++) {
|
||||
|
||||
$index = self::weightRandom($weights);
|
||||
$selectionCounts[$index]++; // 记录选择次数
|
||||
}
|
||||
|
||||
// 计算每个索引的选择概率
|
||||
$probabilities = [];
|
||||
foreach ($selectionCounts as $index => $count) {
|
||||
$probabilities[$index] = ($count / $trials) * 100; // 转换为百分比
|
||||
}
|
||||
|
||||
// 输出结果
|
||||
echo "After {$trials} trials, the probabilities of selecting each index are:\n";
|
||||
foreach ($probabilities as $index => $probability) {
|
||||
echo "Index {$index}: {$probability}%\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:洗牌算法
|
||||
*
|
||||
* 对数组进行随机排序,实现洗牌算法
|
||||
* author:wh
|
||||
* @param array $items eg: [1, 2, 3, 4, 5]
|
||||
* @return array 返回计算后的数组
|
||||
*/
|
||||
static function shuffle(array $items) {
|
||||
//$items = [1, 2, 3, 4, 5];
|
||||
shuffle($items);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机密码生成算法
|
||||
*
|
||||
* 作用:创建安全的随机密码,常用于用户注册或密码重置
|
||||
* 使用场景:用户账户创建、密码重置链接生成
|
||||
*/
|
||||
static function randomPassword($length = 8) {
|
||||
$password = '';
|
||||
$possibleChars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$password .= substr($possibleChars, mt_rand(0, strlen($possibleChars) - 1), 1);
|
||||
}
|
||||
return $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机颜色生成算法
|
||||
*
|
||||
* 作用:生成随机RGB颜色值,可用于网页设计中动态改变元素颜色
|
||||
* 使用场景:动态网页背景、随机颜色显示的元素
|
||||
*/
|
||||
static function randomColor() {
|
||||
$red = mt_rand(0, 255);
|
||||
$green = mt_rand(0, 255);
|
||||
$blue = mt_rand(0, 255);
|
||||
return [$red, $green, $blue];
|
||||
}
|
||||
}
|
||||
52
superadmin/vendor/wanghua/general-utility-tools-php/src/algorithm/AlgorithmTest.php
vendored
Normal file
52
superadmin/vendor/wanghua/general-utility-tools-php/src/algorithm/AlgorithmTest.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/27} {17:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\algorithm;
|
||||
|
||||
|
||||
/**
|
||||
* 算法测试
|
||||
* Class AlgorithmTest
|
||||
* @package wanghua\general_utility_tools_php\algorithm
|
||||
*/
|
||||
class AlgorithmTest
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:测试权重随机算法概率
|
||||
* author:wh
|
||||
* @param array $weights 权重数组 eg:[1, 9, 30, 70]
|
||||
*/
|
||||
static function testWeightRandom(array $weights){
|
||||
echo json_encode($weights)."\n";
|
||||
|
||||
$trials = 1000; // 试验次数
|
||||
$selectionCounts = array_fill(0, count($weights), 0); // 用于存储每个索引的选择次数
|
||||
|
||||
for ($i = 0; $i < $trials; $i++) {
|
||||
|
||||
$index = Algorithm::weightRandom($weights);
|
||||
$selectionCounts[$index]++; // 记录选择次数
|
||||
}
|
||||
|
||||
// 计算每个索引的选择概率
|
||||
$probabilities = [];
|
||||
foreach ($selectionCounts as $index => $count) {
|
||||
$probabilities[$index] = ($count / $trials) * 100; // 转换为百分比
|
||||
}
|
||||
|
||||
// 输出结果
|
||||
echo "After {$trials} trials, the probabilities of selecting each index are:\n";
|
||||
foreach ($probabilities as $index => $probability) {
|
||||
echo "Index {$index}: {$probability}%\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
1
superadmin/vendor/wanghua/general-utility-tools-php/src/algorithm/README.MD
vendored
Normal file
1
superadmin/vendor/wanghua/general-utility-tools-php/src/algorithm/README.MD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
## 常见实用算法
|
||||
162
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/AlibabaAuth.php
vendored
Normal file
162
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/AlibabaAuth.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/28} {14:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba;
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*
|
||||
* 注意:
|
||||
* 分销自研自用版不需要授权,直接使用永久accessToken
|
||||
* 请把当前账号添加为应用的日常测试账号
|
||||
*
|
||||
* Class Auth
|
||||
* @package app\index\logic\alibaba
|
||||
*/
|
||||
class AlibabaAuth
|
||||
{
|
||||
public $base_url = '';//不同业务线,授权地址不一样
|
||||
public $config = [];
|
||||
public $request_body = [];
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
function trusteeshipAuth(){
|
||||
//待开发
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:授权分为托管式授权和WEB端授权,这里是WEB端授权(后去code临时凭证)
|
||||
*
|
||||
* author:wh
|
||||
* @param string $appKey app注册时,分配给app的唯一标识
|
||||
* @param string $redirect_uri app的入口地址,授权临时令牌会以queryString的形式跟在该url后返回。注意参数中回调地址的域名必须与app注册时填写的回调地址的域名匹配。
|
||||
* @param string $site site参数标识当前授权的站点,直接填写1688
|
||||
* @param string $state 可选,app自定义参数,回跳到redirect_uri时,会原样返回
|
||||
* return 用户输入用户名密码,并确认授权,返回临时授权码code给app,具体返回方式,参照redirect_uri说明
|
||||
*/
|
||||
function webAppAuth($redirect_uri,$site='1688',$state=''){
|
||||
$appKey = $this->config['appkey'];
|
||||
|
||||
$url = "https://auth.1688.com/oauth/authorize?client_id={$appKey}&site={$site}&redirect_uri={$redirect_uri}&state={$state}";
|
||||
|
||||
|
||||
//$res = Curl::curl_post($url,[]);
|
||||
return "<script>location.href='{$url}'</script>";
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:使用code获取令牌【code有效期(2分钟)】
|
||||
*
|
||||
* 注:此接口必须使用POST方法提交;必须使用https
|
||||
getToken接口参数说明:
|
||||
a) grant_type为授权类型,使用authorization_code即可
|
||||
b) need_refresh_token为是否需要返回refresh_token,如果返回了refresh_token,原来获取的refresh_token也不会失效,除非超过半年有效期
|
||||
c) client_id为app唯一标识,即appKey
|
||||
d) client_secret为app密钥
|
||||
e) redirect_uri为app入口地址
|
||||
f) code为授权完成后返回的一次性令牌
|
||||
g) 调用getToken接口不需要签名
|
||||
注:如果超过code有效期(2分钟)或者已经使用code获取了一次令牌,code都将失效,需要返回第二步重新获取code
|
||||
* author:wh
|
||||
*/
|
||||
function getTokenByCode($code,$redirect_uri){
|
||||
$appkey = $this->config['appkey'];
|
||||
$secret = $this->config['appsecret'];
|
||||
$url = "https://gw.open.1688.com/openapi/";
|
||||
$urlPath = "http/1/system.oauth2/getToken/".$appkey;
|
||||
$paramstr = "?grant_type=authorization_code&need_refresh_token=true&client_id={$appkey}&client_secret={$secret}&redirect_uri={$redirect_uri}&code={$code}";
|
||||
|
||||
$url = $url.$urlPath.$paramstr;
|
||||
return Curl::curl_post($url,[]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
*
|
||||
1、 构造urlPath。urlPath是url 中的一部分,从协议开始截取,到“?”为止,包含了协议、namespace、apiName和apiVersion,如urlPath=http/1/system/currentTime/1688
|
||||
|
||||
2、 拼装参数。首先将所有参数按照key+value拼装得到一个字符串数组(如[b1,a2]),然后对数组进行排序([a2,b1]),最后将排序后的数组合并为字符串(a2b1)
|
||||
|
||||
3、 合并。把前两步的字符串拼接(http/1/system/currentTime/1688a2b1)
|
||||
|
||||
4、 执行hmac_sha1算法。 Signature=uppercase (hex (hmac_sha1 (concatString, secretKey)),假设secretKey=test123,那么得到的签名为2F1E96587451DE0E171978F4AAE1A90FF9B2F94B
|
||||
|
||||
a) concatString为合并后的字符串
|
||||
|
||||
b) secretKey为签名密钥,与urlPath中的appKey(1000000)对应
|
||||
|
||||
c) hmac_sha1为通用的hmac_sha1算法,各编程语言一般都对应类库
|
||||
|
||||
d) hex为转为十六进制
|
||||
|
||||
e) uppercase为转为大写字符
|
||||
* author:wh
|
||||
* @param string $urlPath eg: param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/7571561
|
||||
* @param array $params 请求参数
|
||||
* @return string
|
||||
*/
|
||||
public function signature($urlPath,$params)
|
||||
{
|
||||
$accessToken = $this->config['accessToken'];
|
||||
$params['access_token'] = $accessToken;
|
||||
//$url = 'http://gw.open.1688.com/openapi';//1688开放平台使用gw.open.1688.com域名
|
||||
//$appKey = $this->config['appkey'];
|
||||
$appSecret = $this->config['appsecret'];
|
||||
|
||||
//dump('$urlPath: '.$urlPath);
|
||||
//$apiInfo = 'param2/1/system/currentTime/' . $appKey;//此处请用具体api进行替换
|
||||
//$urlPath = $urlPath . $appKey;//此处请用具体api进行替换
|
||||
|
||||
//配置参数,请用apiInfo对应的api参数进行替换
|
||||
$aliParams = array();
|
||||
foreach ($params as $key => $val) {
|
||||
$aliParams[] = $key . $val;
|
||||
}
|
||||
sort($aliParams);
|
||||
$sign_str = join('', $aliParams);
|
||||
$sign_str = $urlPath . $sign_str;
|
||||
$code_sign = strtoupper(bin2hex(hash_hmac("sha1", $sign_str, $appSecret, true)));
|
||||
|
||||
return $code_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:发起请求,自动完成签名并返回结果
|
||||
* author:wh
|
||||
* @param string $urlPath eg: param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/23222222
|
||||
* @param array $request_data 接口请求数据
|
||||
*/
|
||||
function request($urlPath, $request_data){
|
||||
set_time_limit(0);
|
||||
$request_params_str = '';
|
||||
foreach ($request_data as $k=>$v){
|
||||
if($request_params_str == ''){
|
||||
$request_params_str .= $k.'='.$v;
|
||||
}else{
|
||||
$request_params_str .= '&'.$k.'='.$v;
|
||||
}
|
||||
}
|
||||
$accessToken = $this->config['accessToken'];
|
||||
//dump($request_params_str);
|
||||
$_aop_signature = $this->signature($urlPath,$request_data);
|
||||
//dump($_aop_signature);
|
||||
//$request_data['_aop_signature'] = $_aop_signature;
|
||||
|
||||
$url = $this->base_url.$urlPath.'?'.$request_params_str.'&access_token='.$accessToken.'&_aop_signature='.$_aop_signature;
|
||||
//dump($url);
|
||||
$this->request_body = $url;
|
||||
$res = Curl::curl_post($url,[]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
23
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/BaseStrict.php
vendored
Normal file
23
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/BaseStrict.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {12:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes;
|
||||
|
||||
|
||||
class BaseStrict
|
||||
{
|
||||
public $base_url = 'https://gw.open.1688.com/openapi/';
|
||||
//授权对象
|
||||
protected $authObj = null;
|
||||
public function __construct($authObj)
|
||||
{
|
||||
$this->authObj = $authObj;
|
||||
//初始化并设置当前模块的基础url
|
||||
$this->authObj->base_url = $this->base_url;
|
||||
}
|
||||
}
|
||||
3
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/README.MD
vendored
Normal file
3
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/README.MD
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
## distributes 分销模块
|
||||
|
||||
### strict 分销中严选模块(商家自营)
|
||||
158
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/Testexample.php
vendored
Normal file
158
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/Testexample.php
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {12:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use wanghua\general_utility_tools_php\alibaba\AlibabaAuth;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\CustomerService;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictCategory;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictGoods;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictLogistics;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictOrder;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictPay;
|
||||
|
||||
|
||||
/**
|
||||
* 测试案例
|
||||
*
|
||||
* Class Testexample
|
||||
* @package wanghua\general_utility_tools_php\alibaba\distributes
|
||||
*/
|
||||
class Testexample
|
||||
{
|
||||
/**
|
||||
* desc:查询订单是否开通免密支付
|
||||
*/
|
||||
function queryOrderIsNoPassPay(){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictPay($authObj);
|
||||
return $obj->queryOrderIsNoPassPay();
|
||||
}
|
||||
function getLogisticsTemplate(){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictLogistics($authObj);
|
||||
return $obj->getLogisticsTemplate();
|
||||
}
|
||||
//物流模板详情
|
||||
function getLogisticsTemplateDetail($template_id){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictLogistics($authObj);
|
||||
return $obj->getLogisticsTemplateDetail($template_id);
|
||||
}
|
||||
function getGoodsList($where){
|
||||
set_time_limit(0);
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictGoods($authObj);
|
||||
return $obj->getGoodsList($where);
|
||||
}
|
||||
function getGoodsListsPft($where){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictGoods($authObj);
|
||||
return $obj->getGoodsListsPft($where);
|
||||
}
|
||||
function getGoodsDetail(array $itemIds){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictGoods($authObj);
|
||||
return $obj->getGoodsDetail($itemIds);
|
||||
}
|
||||
function getCategoryByCID($category_id){
|
||||
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictCategory($authObj);
|
||||
return $obj->getCategoryByCID($category_id);
|
||||
}
|
||||
function testGetRootCategory(){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictCategory($authObj);
|
||||
return $obj->getRootCategory();
|
||||
}
|
||||
|
||||
function testWebAuth($redirect_uri){
|
||||
$config = config('meebo_supply_config');
|
||||
$res = (new AlibabaAuth($config))->webAppAuth($redirect_uri);
|
||||
return $res;
|
||||
}
|
||||
function getTokenByCode($code,$redirect_uri){
|
||||
$config = config('meebo_supply_config');
|
||||
$res = (new AlibabaAuth($config))->getTokenByCode($code,$redirect_uri);
|
||||
return $res;
|
||||
}
|
||||
//测试创建订单
|
||||
function createOrder(){
|
||||
$order_info = Db::table(TabConf::$fa_order)
|
||||
->where('orderid','mm70wgex1719586377768')
|
||||
->find();
|
||||
$address = Db::table(TabConf::$fa_useraddress)
|
||||
->where('id',$order_info['useraddress_id'])
|
||||
->where('users_id',$order_info['users_id'])
|
||||
->find();
|
||||
$goods = Db::table(TabConf::$fa_goods)
|
||||
->where('id',$order_info['goods_id'])
|
||||
->find();
|
||||
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new StrictOrder($authObj);
|
||||
$order->setAddress($address);
|
||||
$order->setGoods($goods,$order_info['buy_num']);
|
||||
return $order->createOrder($order_info);
|
||||
}
|
||||
|
||||
function previewOrder(){
|
||||
$order_info = Db::table(TabConf::$fa_order)
|
||||
->where('orderid','mm70wgex1719586377768')
|
||||
->find();
|
||||
$address = Db::table(TabConf::$fa_useraddress)
|
||||
->where('id',$order_info['useraddress_id'])
|
||||
->where('users_id',$order_info['users_id'])
|
||||
->find();
|
||||
$goods = Db::table(TabConf::$fa_goods)
|
||||
->where('id',$order_info['goods_id'])
|
||||
->find();
|
||||
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new StrictOrder($authObj);
|
||||
$order->setAddress($address);
|
||||
$order->setGoods($goods,$order_info['buy_num']);
|
||||
return $order->previewOrder();
|
||||
}
|
||||
//查询订单可以支持的支付渠道
|
||||
function queryOrderPayChannel($order_id){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new StrictPay($authObj);
|
||||
return $order->queryOrderPayChannel($order_id);
|
||||
}
|
||||
//组合收银台url获取
|
||||
function getPayUrl(array $orderIds){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new StrictPay($authObj);
|
||||
return $order->getPayUrl($orderIds,'PC');
|
||||
}
|
||||
|
||||
//获取唤起旺旺聊天的链接
|
||||
function getCustomerServiceLink($toOpenUid){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new CustomerService($authObj);
|
||||
return $order->getCustomerServiceLink($toOpenUid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {17:31}
|
||||
*/
|
||||
|
||||
namespace app\index\controller;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use app\index\logic\alibaba\distributes\notify\BaseStrictNotify;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\Testexample;
|
||||
use app\index\logic\alibabanotify\ProductNotify;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 阿里巴巴异步通知控制器类,是消息处理入口类
|
||||
* Class Alibabanotify
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class Alibaba extends BasePublicController
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:通知
|
||||
* index/Alibaba/notify
|
||||
*
|
||||
* 输出message
|
||||
{
|
||||
"data":{
|
||||
"productIds":"107680826",
|
||||
"msgSendTime":"2018-05-30 20:29:37",
|
||||
"memberId":"shyxsscl",
|
||||
"status":"RELATION_VIEW_PRODUCT_REPOST"
|
||||
},
|
||||
"gmtBorn":1720459935606,
|
||||
"msgId":88837491757,
|
||||
"type":"PRODUCT_RELATION_VIEW_PRODUCT_REPOST",
|
||||
"userInfo":"b2b-1881150273"
|
||||
}
|
||||
* author:wh
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
function notify(){
|
||||
return Mmodel::catchJson(function (){
|
||||
Tools::log_to_write_txt(['执行消息处理']);
|
||||
//根据消息类型,选择对应的处理类
|
||||
$message_data = input('message');
|
||||
if(empty($message_data)){
|
||||
return Tools::set_fail('message为空');
|
||||
}
|
||||
$message_data = json_decode($message_data,true);
|
||||
Tools::log_to_write_txt(['消息解码'=>$message_data]);
|
||||
if(empty($message_data['type'])){
|
||||
return Tools::set_fail('type为空');
|
||||
}
|
||||
//$key = strtolower(explode('_',$message_data['type'])[0]);
|
||||
//获取消息类型
|
||||
$fn = strtolower($message_data['type']);//类型即为方法名
|
||||
//消息类型前缀即为类名
|
||||
$class = '\\app\\index\\logic\\alibabanotify\\'.ucfirst(explode('_',$fn)[0]).'Notify';
|
||||
//实例化类
|
||||
return (new $class())->{$fn}($message_data);//调用方法
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:ali采购获取临时授权code
|
||||
*
|
||||
* index/alibaba/webAuthCode
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function webAuthCode(){
|
||||
|
||||
$Testexample = new Testexample();
|
||||
|
||||
$res = $Testexample->testWebAuth(request()->domain().'/index/alibaba/webUserAuth');
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:网页授权,code换取token
|
||||
*
|
||||
* index/alibaba/webUserAuth
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function webUserAuth(){
|
||||
$code = input('code');
|
||||
if(empty($code)){
|
||||
return $this->error('授权失败');
|
||||
}
|
||||
|
||||
$redirect_uri = url('test/test2');
|
||||
$Testexample = new Testexample();
|
||||
$res = $Testexample->getTokenByCode($code,$redirect_uri);
|
||||
if($res['code'] != 200){
|
||||
return $this->error('授权失败.'.$res['msg']);
|
||||
}
|
||||
$data = json_decode($res['data']);
|
||||
$auth_data = [
|
||||
'access_token'=>$data['access_token'],
|
||||
'aliid'=>$data['aliId'],
|
||||
'expires_in'=>$data['expires_in'],
|
||||
'memberid'=>$data['memberId'],
|
||||
'refresh_token'=>$data['refresh_token'],
|
||||
'refresh_token_timeout'=>$data['refresh_token_timeout'],
|
||||
'resource_owner'=>$data['resource_owner'],
|
||||
];
|
||||
//写入数据库
|
||||
Mmodel::existsUpdateInsert(TabConf::$fa_alibaba_user_auth,['access_token'=>$data['access_token']],$auth_data);
|
||||
return '授权成功';
|
||||
}
|
||||
|
||||
//function getCode(){
|
||||
// return Mmodel::catchJson(function (){
|
||||
// //保存code
|
||||
// $code = input('code');
|
||||
//
|
||||
// });
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/25} {0:41}
|
||||
*/
|
||||
|
||||
namespace app\index\logic\alibabanotify;
|
||||
|
||||
|
||||
use app\index\logic\BaseLogic;
|
||||
|
||||
class BaseAlibabaLogic extends BaseLogic
|
||||
{
|
||||
|
||||
//接收消息成功后,只要响应http code是200,则认为消息消费成功
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/25} {1:04}
|
||||
*/
|
||||
|
||||
namespace app\index\logic\alibabanotify;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class LogisticsNotify extends BaseAlibabaLogic
|
||||
{
|
||||
/**
|
||||
* 物流单状态变更(买家视角)
|
||||
*/
|
||||
function logistics_buyer_view_trace($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 物流单号修改消息
|
||||
*/
|
||||
function logistics_mail_no_change($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/25} {0:37}
|
||||
*/
|
||||
namespace app\index\logic\alibabanotify;
|
||||
|
||||
use app\index\logic\BaseLogic;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class OrderNotify extends BaseAlibabaLogic
|
||||
{
|
||||
/**
|
||||
* desc:1688创建订单(买家视角)/order created (buyer view)
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function order_buyer_view_buyer_make($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:1688交易成功(卖家视角)
|
||||
* author:wh
|
||||
*/
|
||||
function order_buyer_view_order_success($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688订单批量支付状态同步消息
|
||||
*/
|
||||
function order_batch_pay($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688交易付款(买家视角)/1688 transaction payment (buyer view)
|
||||
*/
|
||||
function order_buyer_view_order_pay($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688卖家关闭订单(买家视角)/seller closing order (buyer view)
|
||||
*/
|
||||
function order_buyer_view_order_seller_close($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688修改订单价格(买家视角)/order price modification (buyer view)
|
||||
*/
|
||||
function order_buyer_view_order_price_modify($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688订单发货(买家视角)/1688 order delivery (buyer view)
|
||||
*/
|
||||
function order_buyer_view_announce_sendgoods($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688订单部分发货(买家视角)/Partial delivery of 1688 order (buyer view)
|
||||
*/
|
||||
function order_buyer_view_part_part_sendgoods($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 商家修改订单地址(买家视角)
|
||||
*/
|
||||
function order_buyer_view_order_seller_modify_adress($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688订单售中退款(买家视角)
|
||||
*/
|
||||
function order_buyer_view_order_buyer_refund_in_sales($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688订单售后退款(买家视角)
|
||||
*/
|
||||
function order_buyer_view_order_refund_after_sales($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688买家关闭订单(买家视角)/buyer closing order (buyer view)
|
||||
*/
|
||||
function order_buyer_view_order_buyer_close($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688订单确认收货(买家视角)/order receipt confirmation (buyer view)
|
||||
*/
|
||||
function order_buyer_view_order_comfirm_receivegoods($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/25} {1:06}
|
||||
*/
|
||||
|
||||
namespace app\index\logic\alibabanotify;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class ProductNotify extends BaseAlibabaLogic
|
||||
{
|
||||
/**
|
||||
* 1688产品审核下架(关系用户视角)
|
||||
*/
|
||||
function product_relation_view_product_audit($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688产品删除(关系用户视角)
|
||||
*/
|
||||
function product_relation_view_product_delete($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688产品新增或修改(关系用户视角)
|
||||
*/
|
||||
function product_relation_view_product_new_or_modify($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688产品上架(关系用户视角)
|
||||
*/
|
||||
function product_relation_view_product_repost($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688商品库存变更消息(关系用户视角)
|
||||
*/
|
||||
function product_product_inventory_change($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 精选货源商品下架消息
|
||||
*/
|
||||
function product_pft_offer_quit($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 精选货源商品价格变动消息
|
||||
*/
|
||||
function product_pft_offer_price_modify($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 1688产品下架(关系用户视角)
|
||||
*/
|
||||
function product_relation_view_product_expire($message_data){
|
||||
return Mmodel::catch(function ()use($message_data){
|
||||
Tools::log_to_write_txt([__FUNCTION__.'消息入参:'=>$message_data]);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
## 阿里巴巴开放平台消息通知模板
|
||||
|
||||
|
||||
### 特别说明
|
||||
#### Alibaba.php是控制器类(复制可用),是消息通道httpCallback的回调地址类文件。
|
||||
##### eg:http://www.xxx.com/index/alibaba/notify
|
||||
##### 回调地址配置入口:https://open.1688.com/develop/app/detail?spm=a260s.develop-app-list.0.0.4d875bfaS5YzoD&appkey=7571564&appKey=7571564
|
||||
进入页面后找到“日常消息测试”按钮,点击后在弹出的界面中进行配置。
|
||||
### 文件说明
|
||||
#### 按照消息类型前缀分类(复制可用)
|
||||
1. 订单相关 OrderNotify.php
|
||||
2. 产品相关 ProductNotify.php
|
||||
3. 物流相关 LogisticsNotify.php
|
||||
4. 售后相关
|
||||
|
||||
......以此类推,消息类型的小写就是类的方法名。
|
||||
|
||||
这里只是打个样,这几个模板可以直接复制,补充上自己的业务逻辑即可。
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/9} {13:42}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\notify;
|
||||
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 弃用,通知属于业务模块,直接在业务控制器中处理,这里仅作参考
|
||||
* 分销严选消息通知基类
|
||||
*
|
||||
* 初始化该基类,按需调用通知处理类
|
||||
*
|
||||
* Class BaseStrictNotify
|
||||
* @package app\index\logic\alibaba\distributes\notify
|
||||
*/
|
||||
class BaseStrictNotify
|
||||
{
|
||||
|
||||
private $object = null;
|
||||
|
||||
/**
|
||||
* desc:执行消息处理
|
||||
* author:wh
|
||||
* @param $callback
|
||||
* @return array
|
||||
*/
|
||||
function doMessage($callback=null){
|
||||
return Mmodel::catch(function () use ($callback){
|
||||
Tools::log_to_write_txt(['执行消息处理']);
|
||||
//根据消息类型,选择对应的处理类
|
||||
$message_data = input('message');
|
||||
if(empty($message_data)){
|
||||
return Tools::set_fail('message为空');
|
||||
}
|
||||
$message_data = json_decode($message_data,true);
|
||||
Tools::log_to_write_txt(['消息解码'=>$message_data]);
|
||||
if(empty($message_data['type'])){
|
||||
return Tools::set_fail('type为空');
|
||||
}
|
||||
//获取消息类型
|
||||
$fn = strtolower($message_data['type']);//类型即为方法名
|
||||
//消息类型前缀即为类名
|
||||
$class = '\\app\\index\\logic\\alibaba\\distributes\\notify\\'.ucfirst(explode('_',$fn)[0]).'Notify';
|
||||
$this->object = (new $class());//实例化类
|
||||
return $this->object->{$fn}($callback);//调用方法
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/9} {13:25}
|
||||
*/
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\notify;
|
||||
|
||||
use app\index\logic\alibaba\distributes\Testexample;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 弃用,通知属于业务模块,直接在业务控制器中处理,这里仅作参考
|
||||
* 产品 消息通知
|
||||
*
|
||||
* Class ProductNotify
|
||||
* @package app\index\logic\alibaba\distributes\notify
|
||||
*/
|
||||
class ProductNotify extends BaseStrictNotify
|
||||
{
|
||||
|
||||
/**
|
||||
* @deprecated 弃用,通知属于业务模块,直接在业务控制器中处理,这里仅作参考
|
||||
* desc:商品上架通知
|
||||
* author:wh
|
||||
*
|
||||
* 输出message
|
||||
{"message":"{\"data\":{\"productIds\":\"107680826\",\"msgSendTime\":\"2018-05-30 20:29:37\",\"memberId\":\"shyxsscl\",\"status\":\"RELATION_VIEW_PRODUCT_REPOST\"},\"gmtBorn\":1720514151217,\"msgId\":88922343751,\"type\":\"PRODUCT_RELATION_VIEW_PRODUCT_REPOST\",\"userInfo\":\"b2b-1881150273\"}","_aop_signature":"03EB6538BB8864BC141ADB5A4923005BB0204F85"}
|
||||
*/
|
||||
function product_relation_view_product_repost($callback=null)
|
||||
{
|
||||
return Mmodel::catch(function () use ($callback){
|
||||
$message_data = input('message');
|
||||
if(empty($message_data)){
|
||||
return Tools::set_fail('message不能为空');
|
||||
}
|
||||
$message_data = json_decode($message_data,true);
|
||||
if(empty($message_data['data'])){
|
||||
return Tools::set_fail('data不能为空');
|
||||
}
|
||||
$productIds = $data['productIds'];//商品ID集合,至少有一个,用逗号分割
|
||||
$productIdsArr = explode(',',$productIds);
|
||||
});
|
||||
}
|
||||
}
|
||||
3
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/notify/README.MD
vendored
Normal file
3
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/notify/README.MD
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#这是异步通知案例
|
||||
|
||||
##业务逻辑自行编写
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/9} {0:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
class CustomerService extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:获取唤起旺旺聊天的链接
|
||||
* author:wh
|
||||
* @param $toOpenUid
|
||||
* @return mixed
|
||||
*/
|
||||
function getCustomerServiceLink($toOpenUid){
|
||||
$urlPath = "param2/1/com.alibaba.account/account.wangwangUrl.get/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, ['toOpenUid'=>$toOpenUid]);
|
||||
}
|
||||
}
|
||||
4
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/README.MD
vendored
Normal file
4
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/README.MD
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
## 分销严选模块
|
||||
只能使用分销严选方案里的接口
|
||||
DOC:
|
||||
https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.product:alibaba.category.get-1&aopApiCategory=category_new
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {12:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
/**
|
||||
* 根据类目Id查询类目
|
||||
*
|
||||
* 传0获取所有一级类目,循环调用可以获取类目树
|
||||
*
|
||||
* 注意:类目id,必须大于等于0, 如果为0,则查询所有一级类目
|
||||
*
|
||||
* 类目查询。如果需要获取所有1688类目信息,需要从根类目开始遍历获取整个类目树。
|
||||
* 即:先传0获取所有一级类目ID,然后在通过获取到的一级类目ID遍历获取所二级类目,最后通过遍历二级类目ID获取三级类目。
|
||||
* 注意:1688类目仅三级,三级类目即发布商品所需的叶子类目。
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.product:alibaba.category.get-1&aopApiCategory=category_new
|
||||
* Class StrictCategory
|
||||
* @package app\index\logic\alibaba\distributes\strict
|
||||
*/
|
||||
class StrictCategory extends BaseStrict
|
||||
{
|
||||
|
||||
public function __construct($authObj)
|
||||
{
|
||||
parent::__construct($authObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取严选一级分类(顶级分类)
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getRootCategory(){
|
||||
//$base_url = "https://gw.open.1688.com/openapi/";
|
||||
$urlPath = "param2/1/com.alibaba.product/alibaba.category.get/".$this->authObj->config['appkey'];
|
||||
|
||||
$request_data = [];
|
||||
$request_data['categoryID'] = '0';
|
||||
return $this->authObj->request($urlPath,$request_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:根据类目id获取类目信息
|
||||
* author:wh
|
||||
* @param $category_id
|
||||
* @return mixed
|
||||
*/
|
||||
function getCategoryByCID($category_id){
|
||||
$urlPath = "param2/1/com.alibaba.product/alibaba.category.get/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['categoryID'] = $category_id;
|
||||
return $this->authObj->request($urlPath,$request_data);
|
||||
}
|
||||
}
|
||||
164
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictGoods.php
vendored
Normal file
164
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictGoods.php
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/30} {1:54}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
/**
|
||||
* 物流
|
||||
* Class StrictLogistics
|
||||
* @package app\index\logic\alibaba\distributes\strict
|
||||
*/
|
||||
class StrictLogistics extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取物流模板详情
|
||||
*
|
||||
* 根据物流模版ID获取卖家的物流模板。运费模板ID为0表示运费说明,为1表示卖家承担运费
|
||||
*
|
||||
* doc:https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.logistics:alibaba.logistics.myFreightTemplate.list.get-1&aopApiCategory=Logistics_NEW
|
||||
*/
|
||||
function getLogisticsTemplateDetail($template_id){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.logistics.myFreightTemplate.list.get/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, ['templateId'=>$template_id]);
|
||||
}
|
||||
function getLogisticsTemplate(){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.logistics.myFreightTemplate.list.get/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc: 获取物流公司列表
|
||||
*
|
||||
* 物流公司列表-自联物流
|
||||
*
|
||||
* doc:https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.logistics:alibaba.logistics.OpQueryLogisticCompanyList.offline-1&aopApiCategory=Logistics_NEW
|
||||
* author:wh
|
||||
*/
|
||||
function getLogisticsCompanyList(){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.logistics.OpQueryLogisticCompanyList.offline/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, []);
|
||||
}
|
||||
}
|
||||
437
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictOrder.php
vendored
Normal file
437
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictOrder.php
vendored
Normal file
@@ -0,0 +1,437 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/28} {15:11}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
use Exception;
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
/**
|
||||
* 分销订单
|
||||
* Class Order
|
||||
* @package app\index\logic\alibaba\distributes
|
||||
*/
|
||||
class StrictOrder extends BaseStrict
|
||||
{
|
||||
//用户收货地址
|
||||
private $address = [];
|
||||
//商品信息
|
||||
private $goods = [];
|
||||
//发票信息
|
||||
private $invoice = [];
|
||||
//交易类型 由于不同的商品支持的交易方式不同,没有一种交易方式是全局通用的,所以当前下单可使用的交易方式必须通过下单预览接口的tradeModeNameList获取。
|
||||
public $tradeType = '';
|
||||
|
||||
/**
|
||||
* desc:收货地址说明
|
||||
1、使用保存的收货地址传参示例:{"addressId":593861699},其中addressId是调用“买家获取保存的收货地址信息列表”接口获取;
|
||||
2、使用地址编码传参示例:{"address":"桃浦镇 金达路888号贸易8楼","phone": "0517-88990077","mobile": "15251667788","fullName": "张三","postCode": "000000","districtCode": "310107"},其中districtCode需要调用“根据地址解析地区码”接口获取;
|
||||
3、直接使用文本地址示例:{"address":"网商路699号","phone": "0517-88990077","mobile": "15251667788","fullName": "张三","postCode": "000000","areaText": "滨江区","townText": "","cityText": "杭州市","provinceText": "浙江省"},省市区要传文本;
|
||||
4、优先级说明,如果同时传入以上参数,系统按从1至3的优先级获取地址,满足1的条件下不会使用上示2中的参数,满足2的条件下不会使用上示3中的参数;
|
||||
* author:wh
|
||||
* @param $address
|
||||
*/
|
||||
function setAddress($address){
|
||||
//{
|
||||
//"address":"网商路699号",
|
||||
//"phone":"0517-88990077",
|
||||
//"mobile":"15251667788",
|
||||
//"fullName":"张三",
|
||||
//"postCode":"000000",
|
||||
//"areaText":"滨江区",
|
||||
//"townText":"",
|
||||
//"cityText":"杭州市",
|
||||
//"provinceText":"浙江省"
|
||||
//}
|
||||
//用户收货地址
|
||||
$this->address = [
|
||||
//'addressId'=>$address['id'],
|
||||
'address'=>$address['address'],//街道地 网商路699号
|
||||
'phone'=>$address['mobile'],//电话 0517-88990077
|
||||
'mobile'=>$address['mobile'],//手机
|
||||
'fullName'=>$address['name'],
|
||||
'postCode'=>'000000',//邮编 000000
|
||||
'areaText'=>$address['area'],//区文本
|
||||
'townText'=>$address['town'],//镇文本
|
||||
'cityText'=>$address['city'],//市文本
|
||||
'provinceText'=>$address['provice'],//省份文本
|
||||
//'districtCode'=>'000000',//地址编码 310107
|
||||
];
|
||||
|
||||
}
|
||||
function setGoods($goods,$buy_num){
|
||||
$this->goods = [
|
||||
'offerId'=>$goods['offerid'],
|
||||
'quantity'=>$buy_num,//$goods['quantity'],//商品数量(计算金额用)
|
||||
];
|
||||
if(!empty($goods['specid'])){
|
||||
$this->goods['specId'] = $goods['specid'];//商品规格id
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置发票信息
|
||||
* author:wh
|
||||
*/
|
||||
function setInvoice(array $invoice){
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建分销订单 下单
|
||||
*
|
||||
* 获取订单运费,请调用预览订单接口 alibaba.createOrder.preview
|
||||
*
|
||||
* 【优先推荐】
|
||||
* 优先推荐(适用于大部分场景):如果渠道服务的用户在采购过程中,价格是核心决策点,推荐直接使用接口中的"最优价下单“能力,即在订单预览、下单过程中选择flow为空,1688会在所有买家可下单的流程中选择最优价进行下单;
|
||||
* 如果渠道服务的对象以代发群体为主(例如淘卖),需要依赖包邮服务,在分销严选商品下单时,fow选择【boutiquefenxiao】下单,这样即使在采购多件时依然能够保证包邮、48小时发货、7天无理由以及极速退款服务;
|
||||
* 如果渠道服务对象以批发群体为主(例如跨境),对干是否包,邮的服务不是特别敏感,在分销严选商品下单时,fow选择[boutiquepifa】进行下单,使用该接口时,如果只单笔订单购买一件,依然以包邮价进行下单,在单笔多件时会自动切换为批发价+邮费的模式下单,
|
||||
*
|
||||
* @param $order
|
||||
* @param string $flow 下单时必填 boutiquefenxiao(新分销严选包邮) boutiquepifa(分销批发)
|
||||
* author:wh
|
||||
*/
|
||||
function createOrder($order,$flow){
|
||||
if(empty($this->authObj)){
|
||||
throw new Exception('未初始化授权对象');
|
||||
}
|
||||
if(empty($this->address)){
|
||||
throw new Exception('未设置收货地址');
|
||||
}
|
||||
if(empty($this->goods)){
|
||||
throw new Exception('未设置商品信息');
|
||||
}
|
||||
//$base_url = "https://gw.open.1688.com/openapi/";
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/".$this->authObj->config['appkey'];
|
||||
|
||||
if(empty($this->tradeType)){
|
||||
throw new Exception('交易类型必须');
|
||||
}
|
||||
//由于不同的商品支持的交易方式不同,没有一种交易方式是全局通用的,
|
||||
//所以当前下单可使用的交易方式必须通过下单预览接口的tradeModeNameList获取。
|
||||
$request_data = ['tradeType'=>$this->tradeType];
|
||||
|
||||
//boutiquefenxiao(新分销严选)
|
||||
$request_data['flow'] = $flow;//'boutiquefenxiao';
|
||||
$request_data['isvBizTypeStr'] = 'fenxiaoMedia';
|
||||
|
||||
$request_data['message'] = $order['remark'];//买家留言
|
||||
//地址
|
||||
$request_data['addressParam'] = json_encode($this->address,JSON_UNESCAPED_UNICODE);
|
||||
//商品信息
|
||||
$request_data['cargoParamList'] = json_encode($this->goods,JSON_UNESCAPED_UNICODE);
|
||||
//发票信息
|
||||
$request_data['invoiceParam'] = json_encode($this->invoice,JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建订单前预览数据接口
|
||||
*
|
||||
* 【下单的时候flow是必填的。只有在预览的时候不填写flow会返回最优的下单方式】
|
||||
* 【调用预览接口,这个是最准确的。】
|
||||
*
|
||||
* 订单创建只允许购买同一个供应商的商品。
|
||||
* 本接口返回创建订单相关的优惠等信息。
|
||||
* 1、校验商品数据是否允许订购。 2、校验代销关系 3、校验库存、起批量、是否满足混批条件
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.createOrder.preview-1&aopApiCategory=trade_new
|
||||
*/
|
||||
function previewOrder($flow=''){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.createOrder.preview/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//boutiquefenxiao(新分销严选)
|
||||
$request_data['flow'] = $flow;//'boutiquefenxiao';
|
||||
//$request_data['isvBizTypeStr'] = 'fenxiaoMedia';
|
||||
|
||||
//$request_data['message'] = $order['remark'];//买家留言
|
||||
//地址
|
||||
$request_data['addressParam'] = json_encode($this->address,JSON_UNESCAPED_UNICODE);
|
||||
//商品信息
|
||||
$request_data['cargoParamList'] = json_encode($this->goods,JSON_UNESCAPED_UNICODE);
|
||||
//发票信息
|
||||
$request_data['invoiceParam'] = json_encode($this->invoice,JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消交易
|
||||
*
|
||||
* 买家或者卖家取消交易,注意只有特定状态的交易才能取消,1688可用于取消未付款的订单。
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.cancel-1&aopApiCategory=trade_new
|
||||
*
|
||||
* author:wh
|
||||
* @param string $order_id 订单号
|
||||
* @param string $cancelReason 原因描述;buyerCancel:买家取消订单;sellerGoodsLack:卖家库存不足;other:其它
|
||||
*
|
||||
* 返回:{
|
||||
"success": true
|
||||
}
|
||||
*/
|
||||
function cancelOrder($order_id, $cancelReason, $remark=''){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.cancel/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['tradeID'] = $order_id;
|
||||
$request_data['webSite'] = 1688;
|
||||
//原因描述;buyerCancel:买家取消订单;sellerGoodsLack:卖家库存不足;other:其它
|
||||
$request_data['cancelReason'] = $cancelReason;
|
||||
if($remark){
|
||||
$request_data['remark'] = $remark;
|
||||
}
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改订单备忘
|
||||
*
|
||||
* 授权用户为卖家修改卖家备忘,授权用户为买家修改买家备忘 注意:该接口可重复调用,备注内容将覆盖前一次调用
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.order.memoAdd-1&aopApiCategory=trade_new
|
||||
*
|
||||
*/
|
||||
function updateOrderRemark($order_id,$remark){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.order.memoAdd/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $order_id;
|
||||
$request_data['memo'] = $remark;
|
||||
//备忘图标,目前仅支持数字。1位红色图标,2为蓝色图标,3为绿色图标,4为黄色图标
|
||||
$request_data['remarkIcon'] = 2;
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据地址解析地区码
|
||||
*
|
||||
* 根据地址信息,解析地区码
|
||||
*
|
||||
* doc:https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.addresscode.parse-1&aopApiCategory=trade_new
|
||||
*
|
||||
*返回:{
|
||||
"result": {
|
||||
"address": "网商路699号",
|
||||
"addressCode": "330108",
|
||||
"isDefault": false,
|
||||
"latest": false,
|
||||
"postCode": "310051"
|
||||
}
|
||||
}
|
||||
*/
|
||||
function getAreaCode($address){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.addresscode.parse/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//地址信息 eg: 浙江省 杭州市 滨江区网商路699号
|
||||
$request_data['addressInfo'] = $address;
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取交易地址代码表详情
|
||||
*
|
||||
* 获取交易地址代码表,该API会返回输入code的详情和该code的下一级地区code.
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.addresscode.get-1&aopApiCategory=trade_new
|
||||
*
|
||||
* 返回:{
|
||||
"result": {
|
||||
"code": "330108",
|
||||
"name": "滨江区",
|
||||
"parentCode": "330100",
|
||||
"post": "310051",
|
||||
"children": ["330108001",
|
||||
"330108002",
|
||||
"330108003"]
|
||||
}
|
||||
}
|
||||
*/
|
||||
function getAreaCodeDetail($areaCode){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.addresscode.get/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//地址code码 eg: 330108
|
||||
$request_data['areaCode'] = $areaCode;
|
||||
$request_data['webSite'] = 1688;
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单列表查看(买家视角)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.getBuyerOrderList-1&aopApiCategory=trade_new
|
||||
*
|
||||
*/
|
||||
function getOrderList($queryParams=[],$page=1,$pageSize=20){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.getSellerOrderList/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['page'] = $page;
|
||||
$request_data['pageSize'] = $pageSize;
|
||||
|
||||
//业务类型,支持: "cn"(普通订单类型), "ws"(大额批发订单类型), "yp"(普通拿样订单类型), "yf"(一分钱拿样订单类型),
|
||||
// "fs"(倒批(限时折扣)订单类型), "cz"(加工定制订单类型), "ag"(协议采购订单类型), "hp"(伙拼订单类型),
|
||||
// "gc"(国采订单类型), "supply"(供销订单类型), "nyg"(nyg订单类型), "factory"(淘工厂订单类型),
|
||||
// "quick"(快订下单), "xiangpin"(享拼订单), "nest"(采购商城-鸟巢), "f2f"(当面付), "cyfw"(存样服务),
|
||||
// "sp"(代销订单标记), "wg"(微供订单), "factorysamp"(淘工厂打样订单), "factorybig"(淘工厂大货订单)
|
||||
if(isset($queryParams['bizTypes'])){
|
||||
$request_data['bizTypes'] = $queryParams['bizTypes'];
|
||||
}
|
||||
//下单开始时间 20180802211113000+0800
|
||||
if(isset($queryParams['createStartTime'])){
|
||||
$request_data['createStartTime'] = $queryParams['createStartTime'];
|
||||
}
|
||||
//下单结束时间 20180802211113000+0800
|
||||
if(isset($queryParams['createEndTime'])){
|
||||
$request_data['createEndTime'] = $queryParams['createEndTime'];
|
||||
}
|
||||
//是否查询历史订单表,默认查询当前表,即默认值为false
|
||||
if(isset($queryParams['isHis'])){
|
||||
$request_data['isHis'] = $queryParams['isHis'];
|
||||
}
|
||||
//查询修改时间结束 20180802211113000+0800
|
||||
if(isset($queryParams['modifyStartTime'])){
|
||||
$request_data['modifyStartTime'] = $queryParams['modifyStartTime'];
|
||||
}
|
||||
//查询修改时间结束 20180802211113000+0800
|
||||
if(isset($queryParams['modifyEndTime'])){
|
||||
$request_data['modifyEndTime'] = $queryParams['modifyEndTime'];
|
||||
}
|
||||
//订单状态,值有 success, cancel(交易取消,违约金等交割完毕), waitbuyerpay(等待卖家付款),
|
||||
// waitsellersend(等待卖家发货),waitbuyerreceive(等待买家收货 )
|
||||
if(isset($queryParams['orderStatus'])){
|
||||
$request_data['orderStatus'] = $queryParams['orderStatus'];
|
||||
}
|
||||
//查询分页页码,从1开始
|
||||
//if(isset($queryParams['page'])){
|
||||
// $request_data['page'] = $queryParams['page'];
|
||||
//}
|
||||
////查询的每页的数量 20
|
||||
//if(isset($queryParams['pageSize'])){
|
||||
// $request_data['pageSize'] = $queryParams['pageSize'];
|
||||
//}
|
||||
//退款状态,支持: "waitselleragree"(等待卖家同意), "refundsuccess"(退款成功), "refundclose"(退款关闭),
|
||||
// "waitbuyermodify"(待买家修改), "waitbuyersend"(等待买家退货), "waitsellerreceive"(等待卖家确认收货)
|
||||
if(isset($queryParams['refundStatus'])){
|
||||
$request_data['refundStatus'] = $queryParams['refundStatus'];
|
||||
}
|
||||
//卖家memberId b2b-1624961198
|
||||
if(isset($queryParams['sellerMemberId'])){
|
||||
$request_data['sellerMemberId'] = $queryParams['sellerMemberId'];
|
||||
}
|
||||
//卖家loginId alitestforisv02
|
||||
if(isset($queryParams['sellerLoginId'])){
|
||||
$request_data['sellerLoginId'] = $queryParams['sellerLoginId'];
|
||||
}
|
||||
//卖家评价状态 (4:已评价,5:未评价,6;不需要评价)
|
||||
if(isset($queryParams['sellerRateStatus'])){
|
||||
$request_data['sellerRateStatus'] = $queryParams['sellerRateStatus'];
|
||||
}
|
||||
//交易类型: 担保交易(1), 预存款交易(2), ETC境外收单交易(3), 即时到帐交易(4), 保障金安全交易(5), 统一交易流程(6),
|
||||
// 分阶段交易(7), 货到付款交易(8), 信用凭证支付交易(9), 账期支付交易(10), 1688交易4.0,新分阶段交易(50060),
|
||||
// 当面付的交易流程(50070), 服务类的交易流程(50080)
|
||||
if(isset($queryParams['tradeType'])){
|
||||
$request_data['tradeType'] = $queryParams['tradeType'];
|
||||
}
|
||||
//商品名称
|
||||
if(isset($queryParams['productName'])){
|
||||
$request_data['productName'] = $queryParams['productName'];
|
||||
}
|
||||
//是否需要查询买家的详细地址信息和电话 false
|
||||
if(isset($queryParams['needBuyerAddressAndPhone'])){
|
||||
$request_data['needBuyerAddressAndPhone'] = $queryParams['needBuyerAddressAndPhone'];
|
||||
}
|
||||
//是否需要查询备注信息 false
|
||||
if(isset($queryParams['needMemoInfo'])){
|
||||
$request_data['needMemoInfo'] = $queryParams['needMemoInfo'];
|
||||
}
|
||||
//外部订单号,可用于控制幂等 90187872898371
|
||||
if(isset($queryParams['outOrderId'])){
|
||||
$request_data['outOrderId'] = $queryParams['outOrderId'];
|
||||
}
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
/**
|
||||
* 订单详情查看(买家视角)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.get.buyerView-1&aopApiCategory=trade_new
|
||||
*/
|
||||
function getBuyerView(int $orderId,$webSite='1688',$includeFields='',$attributeKeys='',$outOrderId=''){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.get.buyerView/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $orderId;//交易的订单id 1234345
|
||||
$request_data['webSite'] = $webSite;//站点信息,指定调用的API是属于国际站(alibaba)还是1688网站(1688)
|
||||
$request_data['includeFields'] = $includeFields;//查询结果中包含的域,GuaranteesTerms:保障条款,NativeLogistics:物流信息,RateDetail:评价详情,OrderInvoice:发票信息。默认返回GuaranteesTerms、NativeLogistics、OrderInvoice。
|
||||
$request_data['attributeKeys'] = $attributeKeys;//垂直表中的attributeKeys
|
||||
$request_data['outOrderId'] = $outOrderId;//外部订单id,控制幂等
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取交易订单的物流信息(买家视角)
|
||||
*
|
||||
* 该接口需要获得订单买家的授权,获取买家的订单的物流详情,在采购或者分销场景中,作为买家也有获取物流详情的需求。
|
||||
* 该接口能查能根据订单号查看物流详情,包括发件人,收件人,所发货物明细等。由于物流单录入的原因,
|
||||
* 可能跟踪信息的API查询会有延迟。该API需要向开放平台申请权限才能访问。
|
||||
*
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.logistics:alibaba.trade.getLogisticsInfos.buyerView-1&aopApiCategory=Logistics_NEW
|
||||
*/
|
||||
function getLogisticsInfosBuyerView(int $orderId,$webSite='1688',$fields=''){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.trade.getLogisticsInfos.buyerView/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $orderId;//交易的订单id 1234345
|
||||
$request_data['webSite'] = $webSite;//站点信息,指定调用的API是属于国际站是1688业务还是icbu业务 (1688或者alibaba)
|
||||
$request_data['fields'] = $fields;//需要返回的字段,目前有:company.name,sender,receiver,sendgood。返回的字段要用英文逗号分隔开
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
/**
|
||||
* 获取交易订单的物流跟踪信息(买家视角)
|
||||
*
|
||||
* 该接口需要获取订单买家的授权,获取买家的订单的物流跟踪信息,在采购或者分销场景中,作为买家也有获取物流详情的需求。
|
||||
* 该接口能查能根据物流单号查看物流单跟踪信息。由于物流单录入的原因,可能跟踪信息的API查询会有延迟。
|
||||
* 该API需要向开放平台申请权限才能访问。
|
||||
*
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.logistics:alibaba.trade.getLogisticsTraceInfo.buyerView-1&aopApiCategory=Logistics_NEW
|
||||
*/
|
||||
function getLogisticsTraceInfoBuyerView(int $orderId,$webSite='1688',$logisticsId=''){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.trade.getLogisticsTraceInfo.buyerView/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $orderId;//交易的订单id 1234345
|
||||
$request_data['webSite'] = $webSite;//站点信息,指定调用的API是属于国际站是1688业务还是ic
|
||||
$request_data['logisticsId'] = $logisticsId;//该订单下的物流编号 AL8234243
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 买家确认收货
|
||||
*
|
||||
* doc:https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:trade.receivegoods.confirm-1
|
||||
*/
|
||||
function receiveGoodsConfirm(int $orderId,$orderEntryIds=[]){
|
||||
$urlPath = "param2/1/com.alibaba.trade/trade.receivegoods.confirm/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $orderId;//交易的订单id 1234345
|
||||
if($orderEntryIds){
|
||||
$request_data['orderEntryIds'] = json_encode($orderEntryIds,JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
63
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictPay.php
vendored
Normal file
63
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictPay.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/30} {12:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
/**
|
||||
* 支付相关
|
||||
*
|
||||
* Class StrictPay
|
||||
* @package app\index\logic\alibaba\distributes\strict
|
||||
*/
|
||||
class StrictPay extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* desc: 查询订单是否开通免密支付
|
||||
* author:wh
|
||||
*/
|
||||
function queryOrderIsNoPassPay(){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.pay.protocolPay.isopen/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:查询订单可以支持的支付渠道
|
||||
* author:wh
|
||||
* @param string $order_id
|
||||
*/
|
||||
function queryOrderPayChannel(string $order_id){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.payWay.query/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $order_id;
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:组合收银台url获取
|
||||
* author:wh
|
||||
* @param string $orderIds 订单列表 格式参考 字符串格式的数组:["123456789","123456789"]
|
||||
* @param string $payPlatformType PC或WIRELESS
|
||||
* @return mixed
|
||||
*/
|
||||
function getPayUrl(string $orderIds,string $payPlatformType){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.grouppay.url.get/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderIds'] = $orderIds;//json_encode($orderIds);
|
||||
$request_data['payPlatformType'] = $payPlatformType;//PC或WIRELESS
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
257
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictRefund.php
vendored
Normal file
257
superadmin/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/strict/StrictRefund.php
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/23} {22:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class StrictRefund extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* 创建退款退货申请
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.createRefund-1
|
||||
*/
|
||||
function createRefund($params){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.createRefund/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
|
||||
//主订单
|
||||
if(empty($params['orderId'])){
|
||||
return Tools::set_fail('orderId不能为空');
|
||||
}
|
||||
$request_data['orderId'] = $params['orderId'];
|
||||
//子订单 订单接口 productItems- subItemID 就是子订单ID,
|
||||
// 卖家拒绝退款后无法重新申请,需要到1688后台退款单页面 修改退款协议
|
||||
if(empty($params['orderEntryIds'])){
|
||||
return Tools::set_fail('orderEntryIds不能为空');
|
||||
}
|
||||
$request_data['orderEntryIds'] = $params['orderEntryIds'];
|
||||
//退款/退款退货。只有已收到货,才可以选择退款退货 退款:"refund"; 退款退货:"returnRefund"
|
||||
if(empty($params['disputeRequest'])){
|
||||
return Tools::set_fail('disputeRequest不能为空');
|
||||
}
|
||||
$request_data['disputeRequest'] = $params['disputeRequest'];
|
||||
//退款金额(单位:分)。不大于实际付款金额;等待卖家发货时,必须为商品的实际付款金额。
|
||||
if(empty($params['applyPayment'])){
|
||||
return Tools::set_fail('applyPayment不能为空');
|
||||
}
|
||||
$request_data['applyPayment'] = $params['applyPayment'];
|
||||
//退运费金额(单位:分)。
|
||||
if(!isset($params['applyCarriage'])){
|
||||
return Tools::set_fail('applyCarriage不能为空');
|
||||
}
|
||||
$request_data['applyCarriage'] = $params['applyCarriage'];
|
||||
//退款原因id(从API getRefundReasonList获取)
|
||||
if(empty($params['applyReasonId'])){
|
||||
return Tools::set_fail('applyReasonId不能为空');
|
||||
}
|
||||
$request_data['applyReasonId'] = $params['applyReasonId'];
|
||||
//退款申请理由,2-150字
|
||||
if(empty($params['description'])){
|
||||
return Tools::set_fail('description不能为空');
|
||||
}
|
||||
$request_data['description'] = $params['description'];
|
||||
//货物状态 售中等待卖家发货:"refundWaitSellerSend"; 售中等待买家收货:"refundWaitBuyerReceive";
|
||||
// 售中已收货(未确认完成交易):"refundBuyerReceived" 售后未收货:"aftersaleBuyerNotReceived";
|
||||
// 售后已收到货:"aftersaleBuyerReceived"
|
||||
if(empty($params['goodsStatus'])){
|
||||
return Tools::set_fail('goodsStatus不能为空');
|
||||
}
|
||||
$request_data['goodsStatus'] = $params['goodsStatus'];
|
||||
//凭证图片URLs。1-5张,必须使用API uploadRefundVoucher返回的“图片域名/相对路径”
|
||||
if(isset($params['vouchers'])){
|
||||
$request_data['vouchers'] = $params['vouchers'];
|
||||
}
|
||||
//子订单退款数量。仅在售中买家已收货(退款退货)时,可指定退货数量;默认,全部退货。[{"id":586683458996743215,"count":1}]
|
||||
if(isset($params['orderEntryCountList'])){
|
||||
$request_data['orderEntryCountList'] = $params['orderEntryCountList'];
|
||||
}
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款退货原因(用于创建退款退货)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.getRefundReasonList-1
|
||||
*/
|
||||
function getRefundReasonList(int $orderId,array $orderEntryIds,$goodsStatus){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.getRefundReasonList/".$this->authObj->config['appkey'];
|
||||
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $orderId;//主订单id 1234345
|
||||
$request_data['orderEntryIds'] = json_encode($orderEntryIds);//子订单id Long[]
|
||||
//售中等待买家发货:”refundWaitSellerSend"; 售中等待买家收货:"refundWaitBuyerReceive";
|
||||
// 售中已收货(未确认完成交易):"refundBuyerReceived" 售后未收货:"aftersaleBuyerNotReceived";
|
||||
// 售后已收到货:"aftersaleBuyerReceived"
|
||||
$request_data['goodsStatus'] = $goodsStatus;//货物状态
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 【可在前端通过表单提交】
|
||||
*
|
||||
* 上传退款退货凭证
|
||||
*
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.uploadRefundVoucher-1
|
||||
*/
|
||||
function uploadRefundVoucher($imageData){
|
||||
//$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.uploadRefundVoucher/".$this->authObj->config['appkey'];
|
||||
//$request_data = [];
|
||||
//$request_data['imageData'] = $imageData;//凭证图片数据。小于1M,jpg格式。
|
||||
//$res = $this->authObj->request($urlPath, $request_data);
|
||||
//return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款单列表(买家视角)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.refund.buyer.queryOrderRefundList-1&aopApiCategory=trade_new
|
||||
* 买家查看退款单列表,该接口不支持子账号查询,请使用主账号授权后查询
|
||||
*/
|
||||
function queryOrderRefundList($params){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.refund.buyer.queryOrderRefundList/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//订单Id
|
||||
if(isset($params['orderId'])){
|
||||
$request_data['orderId'] = $params['orderId'];
|
||||
}
|
||||
//退款申请时间(起始) 20220926114526000+0800
|
||||
if(isset($params['applyStartTime'])){
|
||||
$request_data['applyStartTime'] = $params['applyStartTime'];
|
||||
}
|
||||
//退款申请时间(截止) 20220926114526000+0800
|
||||
if(isset($params['applyEndTime'])){
|
||||
$request_data['applyEndTime'] = $params['applyEndTime'];
|
||||
}
|
||||
//退款状态列表 等待卖家同意 waitselleragree;退款成功 refundsuccess;退款关闭 refundclose;
|
||||
//待买家修改 waitbuyermodify;等待买家退货 waitbuyersend;等待卖家确认收货 waitsellerreceive
|
||||
if(isset($params['refundStatusSet'])){
|
||||
$request_data['refundStatusSet'] = $params['refundStatusSet'];
|
||||
}
|
||||
//卖家memberId
|
||||
if(isset($params['sellerMemberId'])){
|
||||
$request_data['sellerMemberId'] = $params['sellerMemberId'];
|
||||
}
|
||||
//当前页码
|
||||
if(isset($params['currentPageNum'])){
|
||||
$request_data['currentPageNum'] = $params['currentPageNum'];
|
||||
}
|
||||
//每页条数
|
||||
if(isset($params['pageSize'])){
|
||||
$request_data['pageSize'] = $params['pageSize'];
|
||||
}
|
||||
//退货物流单号(传此字段查询时,需同时传入sellerMemberId)
|
||||
if(isset($params['logisticsNo'])){
|
||||
$request_data['logisticsNo'] = $params['logisticsNo'];
|
||||
if(empty($params['sellerMemberId'])){
|
||||
return Tools::set_fail('logisticsNo必须与sellerMemberId同时传入');
|
||||
}
|
||||
}
|
||||
//退款修改时间(起始) 20220926114526000+0800
|
||||
if(isset($params['modifyStartTime'])){
|
||||
$request_data['modifyStartTime'] = $params['modifyStartTime'];
|
||||
}
|
||||
//退款修改时间(截止) 20220926114526000+0800
|
||||
if(isset($params['modifyEndTime'])){
|
||||
$request_data['modifyEndTime'] = $params['modifyEndTime'];
|
||||
}
|
||||
//1:售中退款,2:售后退款;0:所有退款单
|
||||
if(isset($params['dipsuteType'])){
|
||||
$request_data['dipsuteType'] = $params['dipsuteType'];
|
||||
}
|
||||
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款单详情-根据订单ID(买家视角)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.refund.OpQueryBatchRefundByOrderIdAndStatus-1&aopApiCategory=trade_new
|
||||
*/
|
||||
function queryBatchRefundByOrderIdAndStatus(int $orderId,string $queryType){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.refund.OpQueryBatchRefundByOrderIdAndStatus/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//订单Id
|
||||
$request_data['orderId'] = $orderId;
|
||||
//查询类型 1:活动;3:退款成功(只支持退款中和退款成功)
|
||||
$request_data['queryType'] = $queryType;
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款单操作记录列表(买家视角)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.refund.OpQueryOrderRefundOperationList-1
|
||||
*/
|
||||
function queryOrderRefundOperationList(string $refundId,$pageNo=1,$pageSize=100){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.refund.OpQueryOrderRefundOperationList/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['refundId'] = $refundId;
|
||||
$request_data['pageNo'] = $pageNo;
|
||||
$request_data['pageSize'] = $pageSize;
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
/**
|
||||
* 查询退款单详情-根据退款单ID(买家视角)
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.refund.OpQueryOrderRefund-1&aopApiCategory=trade_new
|
||||
*/
|
||||
function opQueryOrderRefund(string $refundId,$needTimeOutInfo=false,$needOrderRefundOperation=false){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.refund.OpQueryOrderRefund/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['refundId'] = $refundId;
|
||||
if(isset($needTimeOutInfo)){
|
||||
$request_data['needTimeOutInfo'] = $needTimeOutInfo;
|
||||
}
|
||||
if(isset($needOrderRefundOperation)){
|
||||
$request_data['needOrderRefundOperation'] = $needOrderRefundOperation;
|
||||
}
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
/**
|
||||
* 买家提交退款货信息
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.refund.returnGoods-1
|
||||
*/
|
||||
function buyerSubmitRefundGoodsInfo(string $refundId,string $logisticsCompanyNo,string $freightBill,string $description='',string $vouchers=''){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.refund.returnGoods/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['refundId'] = $refundId;
|
||||
$request_data['logisticsCompanyNo'] = $logisticsCompanyNo;
|
||||
$request_data['freightBill'] = $freightBill;
|
||||
if($description){
|
||||
$request_data['description'] = $description;//发货说明,内容在2-200个字之间
|
||||
}
|
||||
//凭证图片URLs,必须使用API alibaba.trade.uploadRefundVoucher返回的“图片域名/相对路径”,
|
||||
//最多可上传 10 张图片 ;单张大小不超过1M;支持jpg、gif、jpeg、png、和bmp格式。
|
||||
// 请上传凭证,以便以后续赔所需(不上传将无法理赔)
|
||||
if($vouchers){
|
||||
$request_data['vouchers'] = $vouchers;//[https://cbu01.alicdn.com/img/ibank/2019/901/930/11848039109.jpg]
|
||||
}
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 取消退款退货申请
|
||||
* https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.cancelRefund-1
|
||||
*/
|
||||
function cancelRefund(string $refundId){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.cancelRefund/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['refundId'] = $refundId;
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
145
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayAuthSDK.php
vendored
Normal file
145
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayAuthSDK.php
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2025/3/14} {16:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class AlipayAuthSDK extends BaseAlipay
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:获取支付宝用户授权信息
|
||||
* author:wh
|
||||
* @param $auth_code
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAuthInfo($auth_code){
|
||||
if(session('session_alipay_system_oauth_token_response')){
|
||||
//到期时间(s)
|
||||
$expires_in = session('session_alipay_system_oauth_token_response.expires_in');
|
||||
$auth_start = session('session_alipay_system_oauth_token_response.auth_start');
|
||||
//这里减去600秒防止刷新token的时候,时间还没到就过期了
|
||||
if(strtotime($auth_start)+$expires_in-600<time()){
|
||||
//过期了,刷新token
|
||||
$grantType = 'refresh_token';
|
||||
$alipay_system_oauth_token_response = $this->authExchangeOpenid($auth_code,$grantType);
|
||||
return $alipay_system_oauth_token_response;
|
||||
}else{
|
||||
return session('session_alipay_system_oauth_token_response');
|
||||
}
|
||||
}else{
|
||||
//实时获取
|
||||
$alipay_system_oauth_token_response = $this->authExchangeOpenid($auth_code);
|
||||
return $alipay_system_oauth_token_response;
|
||||
}
|
||||
}
|
||||
// 第一步:构建授权URL (引导用户跳转)
|
||||
function buildAuthUrl($auth_url)
|
||||
{
|
||||
//Tools::log_to_write_txt(['构建授权URL (引导用户跳转),$url'=>$auth_url]);
|
||||
$redirect_uri = urlencode($auth_url); // 回调地址需在支付宝后台配置
|
||||
$auth_url = "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?" .
|
||||
"app_id={$this->alipayConfig['app_id']}&" .
|
||||
"scope=auth_user&" .
|
||||
"redirect_uri={$redirect_uri}&" .
|
||||
"state=meebo";//自定义防CSRF参数
|
||||
//Tools::log_to_write_txt(['构建授权URL (引导用户跳转),$auth_url:'=>$auth_url]);
|
||||
return $auth_url;
|
||||
}
|
||||
|
||||
// 第二步:获取授权码
|
||||
function authExchangeOpenid($auth_code,$grantType='authorization_code'){
|
||||
$root_path = Tools::get_root_path();
|
||||
require_once($root_path.'library/alipay-sdk-php-all/aop/AopCertClient.php'); // 支付宝官方SDK, 需从开放平台下载
|
||||
//AlipaySystemOauthTokenRequest
|
||||
require_once($root_path.'library/alipay-sdk-php-all/aop/request/AlipaySystemOauthTokenRequest.php');
|
||||
|
||||
/** 初始化 **/
|
||||
$aop = new \AopCertClient;
|
||||
|
||||
/** 支付宝网关 **/
|
||||
$aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
|
||||
|
||||
/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
|
||||
$aop->appId = $this->alipayConfig['app_id'];
|
||||
|
||||
/** 密钥格式为pkcs1,如何获取私钥请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
|
||||
$aop->rsaPrivateKey = $this->alipayConfig['alipay_app_private_key'];
|
||||
|
||||
/** 应用公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$appCertPath = $root_path.$this->alipayConfig['appCertPublicKey'];
|
||||
|
||||
/** 支付宝公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$alipayCertPath = $root_path.$this->alipayConfig['cert_path_alipayCertPublicKey_RSA2'];
|
||||
|
||||
/** 支付宝公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$rootCertPath = $root_path.$this->alipayConfig['cert_path_alipayRootCert'];
|
||||
|
||||
/** 设置签名类型 **/
|
||||
$aop->signType= "RSA2";
|
||||
|
||||
/** 设置请求格式,固定值json **/
|
||||
$aop->format = "json";
|
||||
|
||||
/** 设置编码格式 **/
|
||||
$aop->charset= "utf-8";
|
||||
|
||||
/** 调用getPublicKey从支付宝公钥证书中提取公钥 **/
|
||||
$aop->alipayrsaPublicKey = $aop->getPublicKey($alipayCertPath);
|
||||
|
||||
/** 是否校验自动下载的支付宝公钥证书,如果开启校验要保证支付宝根证书在有效期内 **/
|
||||
$aop->isCheckAlipayPublicCert = true;
|
||||
|
||||
/** 调用getCertSN获取证书序列号 **/
|
||||
$aop->appCertSN = $aop->getCertSN($appCertPath);
|
||||
|
||||
/** 调用getRootCertSN获取支付宝根证书序列号 **/
|
||||
$aop->alipayRootCertSN = $aop->getRootCertSN($rootCertPath);
|
||||
|
||||
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称alipay.system.oauth.token(换取授权访问令牌) **/
|
||||
$request = new \AlipaySystemOauthTokenRequest ();
|
||||
|
||||
/** 值为authorization_code时,代表用code换取;值为refresh_token时,代表用refresh_token换取 **/
|
||||
$request->setGrantType($grantType);
|
||||
|
||||
/** 授权码,用户对应用授权后得到,可参考文档:https://opendocs.alipay.com/open/284/web **/
|
||||
$request->setCode($auth_code);//"4b203fe6c11548bcabd8da5bb087a83b"
|
||||
|
||||
/** 刷新令牌,上次换取访问令牌时得到。见出参的refresh_token字段 **/
|
||||
//$request->setRefreshToken("201208134b203fe6c11548bcabd8da5bb087a83b");
|
||||
|
||||
|
||||
$result = $aop->execute ($request);
|
||||
|
||||
/**第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631 **/
|
||||
//$result = $aop->execute ($request,null,$app_auth_token);
|
||||
|
||||
$json = json_encode($result,JSON_UNESCAPED_UNICODE);
|
||||
//dump($json);;
|
||||
//array(3) {
|
||||
// ["alipay_system_oauth_token_response"] => array(6) {
|
||||
// ["access_token"] => string(40) "authusrB61082f01b2064753b039210cec7ddB44"
|
||||
// ["auth_start"] => string(19) "2025-03-14 14:59:02"
|
||||
// ["expires_in"] => int(1296000)
|
||||
// ["re_expires_in"] => int(2592000)
|
||||
// ["refresh_token"] => string(40) "authusrB85949807a38d4bffbd5c86ae7e797B44"
|
||||
// ["open_id"] => string(47) "0442qO88pZKcduCIdYq7Z4N8y29dGoocWheNow1jt_QW1k4"
|
||||
// }
|
||||
// ["alipay_cert_sn"] => string(32) "9cbb86296783f52af85119eb59308f9a"
|
||||
// ["sign"] => string(344) "qTFAlIaq3DO3L+9cjoXVJVhSipib8v2ot0Vb1cFEDdtVUH99eZsd33vDBDaKobf00XhVUBqx9WbL67GfEbUF94s6cPfGn9kHuYSMDKh5VRCUFF9TI+melq6GAXih9FbsgqUTY/OuAxz5GDfYL974CppSi7+uBodl0KCmt9kC6VgoC0tUe0s8MDC7LRWBEXheAwrfzMn8NzCpbJRSWRfmewRnBzNXC3SVV6KrMlQPaNcj4Wjl9JQxxCOFXRGqeCMF7pDLYPrChFy7TOCVE/ONUbBQcR1p3qqek3MO/QhpeumTB33VsfKTMQOKjWhEEfSYJa7vGxkQBnZ5QVVngzGVHg=="
|
||||
//}
|
||||
$json_arr = json_decode($json,true);
|
||||
$alipay_system_oauth_token_response = $json_arr['alipay_system_oauth_token_response'];
|
||||
session('session_alipay_system_oauth_token_response',$alipay_system_oauth_token_response);
|
||||
//$open_id = $alipay_system_oauth_token_response['open_id'];
|
||||
return $alipay_system_oauth_token_response;
|
||||
}
|
||||
|
||||
}
|
||||
82
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayLogic.php
vendored
Normal file
82
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayLogic.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/24} {10:20}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay;
|
||||
|
||||
|
||||
use app\index\model\AppOrderPayReqRecordModel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 调起支付宝支付
|
||||
*
|
||||
* Class AlipayLogic
|
||||
*
|
||||
* 依赖:
|
||||
* composer require wanghua/general-utility-tools-php dev-master
|
||||
* @deprecated
|
||||
*/
|
||||
class AlipayLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:调起支付
|
||||
* author:wh
|
||||
* @return false|mixed|\SimpleXMLElement|string|\提交表单HTML文本|null
|
||||
* @throws \think\Exception
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
//function pay(string $notify_url,string $return_url=''){
|
||||
|
||||
|
||||
///* *
|
||||
// * 功能:支付宝手机网站支付接口(alipay.trade.wap.pay)接口调试入口页面
|
||||
// * 版本:2.0
|
||||
// * 修改日期:2016-11-01
|
||||
// * 说明:
|
||||
// * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
|
||||
// 请确保项目文件有可写权限,不然打印不了日志。
|
||||
// */
|
||||
//
|
||||
//header("Content-type: text/html; charset=utf-8");
|
||||
//
|
||||
//
|
||||
//require_once Tools::get_root_path().'library/AlipayTradeWapPay/wappay/service/AlipayTradeService.php';
|
||||
//require_once Tools::get_root_path().'library/AlipayTradeWapPay/wappay/buildermodel/AlipayTradeWapPayContentBuilder.php';
|
||||
////require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../config.php';
|
||||
//$config = config('pay_config.alipay');
|
||||
//if(empty($_POST['WIDout_trade_no']) || trim($_POST['WIDout_trade_no'])=="") return null;
|
||||
////商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
//$out_trade_no = input('WIDout_trade_no');
|
||||
//if(empty($out_trade_no)){
|
||||
// return '参数错误';
|
||||
//}
|
||||
//$order = AppOrderPayReqRecordModel::getOrder($out_trade_no);
|
||||
//if(empty($order)){
|
||||
// return '订单错误';
|
||||
//}
|
||||
////超时时间
|
||||
//$timeout_express="1m";
|
||||
//
|
||||
//$payRequestBuilder = new \AlipayTradeWapPayContentBuilder();
|
||||
//$payRequestBuilder->setBody($order['goods_name']);
|
||||
//$payRequestBuilder->setSubject($order['goods_name']);
|
||||
//$payRequestBuilder->setOutTradeNo($out_trade_no);
|
||||
//$payRequestBuilder->setTotalAmount($order['goods_price']);
|
||||
//$payRequestBuilder->setTimeExpress($timeout_express);
|
||||
//
|
||||
//$payResponse = new \AlipayTradeService($config);
|
||||
|
||||
|
||||
//$result = $payResponse->wapPay($payRequestBuilder,$return_url,$notify_url);
|
||||
//return $result;
|
||||
//}
|
||||
}
|
||||
172
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/BaseAlipay.php
vendored
Normal file
172
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/BaseAlipay.php
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2025/2/10} {10:11}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay;
|
||||
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use wanghua\general_utility_tools_php\alipay\transfer\AlipayTransfer;
|
||||
use wanghua\general_utility_tools_php\alipay\transfer\TransferConfig;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 基础通用功能
|
||||
*
|
||||
* 说明:
|
||||
* 支付和转账都能使用的功能
|
||||
*
|
||||
* Class BaseAlipay
|
||||
* @package wanghua\general_utility_tools_php\alipay
|
||||
*/
|
||||
class BaseAlipay
|
||||
{
|
||||
protected array $alipayConfig = [];
|
||||
public function __construct($alipayConfig)
|
||||
{
|
||||
$this->alipayConfig = $alipayConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付宝账户余额
|
||||
*/
|
||||
function queryBalance(){
|
||||
//$transferConfig = new TransferConfig();
|
||||
//$transferConfig->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
//$transferConfig->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
//$transferConfig->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
//$trans_obj = new AlipayTransfer();
|
||||
Factory::setOptions($this->getAlipayOptions());
|
||||
|
||||
$method = 'alipay.fund.account.query';
|
||||
//公共参数
|
||||
$textParams = [
|
||||
'app_id'=>$this->alipayConfig['app_id'],
|
||||
'charset'=>'utf-8',
|
||||
'sign_type'=>'RSA2',
|
||||
'timestamp'=>Tools::get_now_date(),
|
||||
'version'=>'1.0',
|
||||
];
|
||||
|
||||
//请求参数
|
||||
//订单号前缀
|
||||
$biz_content = [
|
||||
'account_type'=>'ACCTRANS_ACCOUNT',
|
||||
];
|
||||
$pay_res = Factory::util()->generic()->execute($method,$textParams,$biz_content);
|
||||
|
||||
return $pay_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:证书模式参数(非证书模式参数需单独获取)
|
||||
* author:wh
|
||||
* @param array $this->alipayConfig 支付宝转账配置(非支付配置)
|
||||
* @return Config
|
||||
*/
|
||||
function getAlipayOptions($notifyUrl='')
|
||||
{
|
||||
$root_path = Tools::get_root_path();
|
||||
$options = new Config();
|
||||
$options->protocol = 'https';
|
||||
$options->gatewayHost = 'openapi.alipay.com';
|
||||
$options->signType = 'RSA2';
|
||||
|
||||
//'<-- 请填写您的AppId,例如:2019022663440152 -->'
|
||||
$options->appId = $this->alipayConfig['app_id'];//'2021002103639985';
|
||||
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
$options->merchantPrivateKey = $this->alipayConfig['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
|
||||
$options->alipayCertPath = $root_path.$this->alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$options->alipayRootCertPath = $root_path.$this->alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$options->merchantCertPath = $root_path.$this->alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
|
||||
|
||||
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
// $options->alipayPublicKey = $this->alipayConfig['alipay_public_key'];//'<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
$options->notifyUrl = $notifyUrl;//"<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->";
|
||||
|
||||
//可设置AES密钥,调用AES加解密相关接口时需要(可选)
|
||||
//$options->encryptKey = "<-- 请填写您的AES密钥,例如:aa4BtZ4tspm2wnXLb1ThQA== -->";
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝退款
|
||||
*
|
||||
* 注意:需要在正式服测,本地会报错
|
||||
*
|
||||
* doc:
|
||||
* https://opendocs.alipay.com/open/3aea9b48_alipay.trade.refund?pathHash=4de421df&scene=common
|
||||
*
|
||||
* 测试结果:
|
||||
* object(Alipay\EasySDK\Util\Generic\Models\AlipayOpenApiGenericResponse)#93 (7) {
|
||||
["_name":protected] => array(5) {
|
||||
["httpBody"] => string(9) "http_body"
|
||||
["code"] => string(4) "code"
|
||||
["msg"] => string(3) "msg"
|
||||
["subCode"] => string(8) "sub_code"
|
||||
["subMsg"] => string(7) "sub_msg"
|
||||
}
|
||||
["httpBody"] => string(826) "{"alipay_trade_refund_response":{"code":"10000","msg":"Success","buyer_logon_id":"150******25","fund_change":"Y","gmt_refund_pay":"2025-02-24 10:06:26","out_trade_no":"h5cqa31h1740360008389","refund_detail_item_list":[{"amount":"0.11","fund_channel":"ALIPAYACCOUNT"}],"refund_fee":"0.11","send_back_fee":"0.11","trade_no":"2025022422001457441416271979","buyer_open_id":"0442qO88pZKcduCIdYq7Z4N8y29dGoocWheNow1jt_QW1k4"},"alipay_cert_sn":"9cbb86296783f52af85119eb59308f9a","sign":"fcmu9CwYw0uziZTNImfGJvaYE9EdO4OoeKjktl/jxn+EGKvybDijKxTsn+jRM99jm9gcvmQmqweTd6OJMkep6cut1Tl5jsktYGy+ri1lLTGc9eNg+ctyO6qylnVaKQstV0QNZkuRo6Y36W3ZXolZk81ppNM1chtupsALHfwoWSirupqJ6Y52iBRG67kN0AxexL8mbOhwGS9vAMbMXoyRKJ7ajLGSmpnhb1sMvHVhFkvXaCBrzn6Nt1TMw6cyelqNHsAsmJ+OSnndVcRaqt9Q+IAwn98vhBhl1J5Vi7cWbsIYeki+TViQZ2ArW09IdBrP+A9qIydeM0BQdElRFWntvg=="}"
|
||||
["code"] => string(5) "10000"
|
||||
["msg"] => string(7) "Success"
|
||||
["subCode"] => NULL
|
||||
["subMsg"] => NULL
|
||||
["_required":protected] => array(0) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
function aliRefund($order_info){
|
||||
$alipayConfig = $this->alipayConfig;
|
||||
//$transferConfig = new TransferConfig();
|
||||
//$transferConfig->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
//$transferConfig->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
//$transferConfig->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
Factory::setOptions($this->getAlipayOptions());
|
||||
|
||||
$method = 'alipay.trade.refund';
|
||||
//公共参数
|
||||
$textParams = [
|
||||
'app_id'=>$alipayConfig['app_id'],
|
||||
'charset'=>'utf-8',
|
||||
'sign_type'=>'RSA2',
|
||||
'timestamp'=>Tools::get_now_date(),
|
||||
'version'=>'1.0',
|
||||
];
|
||||
|
||||
//请求参数 wap/pc/app支付
|
||||
|
||||
//【描述】退分账明细信息。
|
||||
// 注: 1.当面付且非直付通模式无需传入退分账明细,系统自动按退款金额与订单金额的比率,
|
||||
//从收款方和分账收入方退款,不支持指定退款金额与退款方。
|
||||
// 2.直付通模式,电脑网站支付,手机 APP 支付,手机网站支付产品,须在退款请求中明确是否退分账,
|
||||
//从哪个分账收入方退,退多少分账金额;
|
||||
//如不明确,默认从收款方退款,收款方余额不足退款失败。不支持系统按比率退款。
|
||||
$refund_royalty_parameters = [];//如果有分账,此项必填
|
||||
//订单号前缀
|
||||
$biz_content = [
|
||||
//'account_type'=>'ACCTRANS_ACCOUNT',
|
||||
'out_trade_no'=>$order_info['orderid'],
|
||||
'refund_amount'=>$order_info['real_amount'],
|
||||
];
|
||||
if($refund_royalty_parameters){
|
||||
$biz_content['refund_royalty_parameters'] = $refund_royalty_parameters;
|
||||
}
|
||||
$pay_res = Factory::util()->generic()->execute($method,$textParams,$biz_content);
|
||||
|
||||
return $pay_res;
|
||||
|
||||
}
|
||||
}
|
||||
BIN
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/alipay-sdk-php-all.zip
vendored
Normal file
BIN
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/alipay-sdk-php-all.zip
vendored
Normal file
Binary file not shown.
140
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayAppPay.php
vendored
Normal file
140
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayAppPay.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/10/16} {14:07}
|
||||
*/
|
||||
namespace wanghua\general_utility_tools_php\alipay\pay;
|
||||
|
||||
use wanghua\general_utility_tools_php\alipay\BaseAlipay;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
|
||||
/**
|
||||
* 支付宝app支付
|
||||
*
|
||||
* Class AlipayAppPay
|
||||
* @package wanghua\general_utility_tools_php\alipay\pay
|
||||
*/
|
||||
class AlipayAppPay extends BaseAlipay
|
||||
{
|
||||
public $notifyUrl;
|
||||
|
||||
/**
|
||||
* desc:app支付
|
||||
*
|
||||
* [备注]
|
||||
* 需要引入alipay-sdk-php-all官方SDK类库
|
||||
* [使用]
|
||||
* [alipay-sdk-php-all.zip]解压后放在项目中,然后在代码中引入
|
||||
* [流程]
|
||||
* 1、生成订单信息
|
||||
* 2、调用支付接口,生成orderStr,返回给客户端
|
||||
* 3、客户端用浏览器打开,浏览器会自动跳转到支付宝页面,完成支付
|
||||
*
|
||||
* api/alipay/apppay
|
||||
* author:wh
|
||||
*/
|
||||
function apppay($order){
|
||||
$root = Tools::get_root_path();
|
||||
require_once $root.'library/alipay-sdk-php-all/aop/AopClient.php';
|
||||
require_once $root.'library/alipay-sdk-php-all/aop/AopCertClient.php';
|
||||
require_once $root.'library/alipay-sdk-php-all/aop/AopCertification.php';
|
||||
require_once $root.'library/alipay-sdk-php-all/aop/AlipayConfig.php';
|
||||
require_once $root.'library/alipay-sdk-php-all/aop/request/AlipayTradeAppPayRequest.php';
|
||||
|
||||
// 初始化SDK
|
||||
$alipayClient = new \AopClient($this->getAlipayConfig($this->pay_config));
|
||||
// 构造请求参数以调用接口
|
||||
$request = new \AlipayTradeAppPayRequest();
|
||||
$model = array();
|
||||
// 设置商户订单号
|
||||
$model['out_trade_no'] = $order['orderid'];
|
||||
|
||||
// 设置订单总金额
|
||||
$model['total_amount'] = $order['real_amount'];//实付金额
|
||||
|
||||
// 设置订单标题
|
||||
$model['subject'] = $order['remark'];
|
||||
|
||||
//// 设置产品码
|
||||
//$model['product_code'] = "QUICK_MSECURITY_PAY";
|
||||
//
|
||||
////设置订单包含的商品列表信息
|
||||
//$goodsDetail = array();
|
||||
//$goodsDetail0 = array();
|
||||
//$goodsDetail0['goods_name'] = "ipad";
|
||||
//$goodsDetail0['alipay_goods_id'] = "20010001";
|
||||
//$goodsDetail0['quantity'] = 1;
|
||||
//$goodsDetail0['price'] = "2000";
|
||||
//$goodsDetail0['goods_id'] = "apple-01";
|
||||
//$goodsDetail0['goods_category'] = "34543238";
|
||||
//$goodsDetail0['categories_tree'] = "124868003|126232002|126252004";
|
||||
//$goodsDetail0['show_url'] = "http://www.alipay.com/xxx.jpg";
|
||||
//$goodsDetail[] = $goodsDetail0;
|
||||
//$model['goods_detail'] = $goodsDetail;
|
||||
//
|
||||
////设置订单绝对超时时间
|
||||
//$model['time_expire'] = "2016-12-31 10:05:00";
|
||||
//
|
||||
////设置业务扩展参数
|
||||
//$extendParams = array();
|
||||
//$extendParams['sys_service_provider_id'] = "2088511833207846";
|
||||
//$extendParams['hb_fq_seller_percent'] = "100";
|
||||
//$extendParams['hb_fq_num'] = "3";
|
||||
//$extendParams['industry_reflux_info'] = "{\"scene_code\":\"metro_tradeorder\",\"channel\":\"xxxx\",\"scene_data\":{\"asset_name\":\"ALIPAY\"}}";
|
||||
//$extendParams['specified_seller_name'] = "XXX的跨境小铺";
|
||||
//$extendParams['royalty_freeze'] = "true";
|
||||
//$extendParams['card_type'] = "S0JP0000";
|
||||
//$model['extend_params'] = $extendParams;
|
||||
//
|
||||
////设置公用回传参数
|
||||
//$model['passback_params'] = "merchantBizType%3d3C%26merchantBizNo%3d2016010101111";
|
||||
//
|
||||
////设置商户的原始订单号
|
||||
//$model['merchant_order_no'] = "20161008001";
|
||||
//
|
||||
////设置外部指定买家
|
||||
//$extUserInfo = array();
|
||||
//$extUserInfo['cert_type'] = "IDENTITY_CARD";
|
||||
//$extUserInfo['cert_no'] = "362334768769238881";
|
||||
//$extUserInfo['name'] = "李明";
|
||||
//$extUserInfo['mobile'] = "16587658765";
|
||||
//$extUserInfo['min_age'] = "18";
|
||||
//$extUserInfo['need_check_info'] = "F";
|
||||
//$extUserInfo['identity_hash'] = "27bfcd1dee4f22c8fe8a2374af9b660419d1361b1c207e9b41a754a113f38fcc";
|
||||
//$model['ext_user_info'] = $extUserInfo;
|
||||
//
|
||||
////设置通知参数选项
|
||||
//$queryOptions = array();
|
||||
//$queryOptions[] = "hyb_amount";
|
||||
//$queryOptions[] = "enterprise_pay_info";
|
||||
//$model['query_options'] = $queryOptions;
|
||||
|
||||
//dump($pay_config);
|
||||
$request->setBizContent(json_encode($model, JSON_UNESCAPED_UNICODE));
|
||||
$request->setNotifyUrl($this->notifyUrl);
|
||||
// 如果是第三方代调用模式,请设置app_auth_token(应用授权令牌)
|
||||
$authToken = $this->pay_config['app_auth_token'];//"<-- 请填写应用授权令牌 -->"
|
||||
$orderStr = $alipayClient->sdkExecute($request, $authToken);
|
||||
|
||||
return Tools::set_ok('ok',$orderStr);
|
||||
}
|
||||
|
||||
private function getAlipayConfig($pay_config)
|
||||
{
|
||||
$privateKey = $pay_config['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
$alipayPublicKey = $pay_config['alipay_app_public_key'];//'<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
$alipayConfig = new \AlipayConfig();
|
||||
$alipayConfig->setServerUrl('https://openapi.alipay.com/gateway.do');
|
||||
$alipayConfig->setAppId($pay_config['app_id']);//'<-- 请填写您的AppId,例如:2019091767145019 -->'
|
||||
$alipayConfig->setPrivateKey($privateKey);
|
||||
$alipayConfig->setFormat('json');
|
||||
$alipayConfig->setAlipayPublicKey($alipayPublicKey);
|
||||
$alipayConfig->setCharset('UTF-8');
|
||||
$alipayConfig->setSignType('RSA2');
|
||||
return $alipayConfig;
|
||||
}
|
||||
}
|
||||
184
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayScanPay.php
vendored
Normal file
184
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayScanPay.php
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/10} {23:15}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\pay;
|
||||
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use app\common\model\TabConf;
|
||||
use app\common\tools\EmailTool;
|
||||
use app\index\logic\AlipayBarcodePayLogic;
|
||||
use app\index\logic\CheckstandLogic;
|
||||
use app\index\model\OrderModel;
|
||||
use app\index\model\PartnerAccountModel;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\alipay\BaseAlipay;
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝面对面扫码支付(用户出示付款码)
|
||||
*
|
||||
* 【扫码支付专用】
|
||||
*
|
||||
* 依赖:"alipaysdk/easysdk": "^2.2" || composer require alipaysdk/easysdk
|
||||
*
|
||||
* Class AlipayScanPay
|
||||
* @package wanghua\general_utility_tools_php\alipay\transfer
|
||||
*/
|
||||
class AlipayScanPay extends BaseAlipay
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:面对面扫码支付-(扫用户的付款码)
|
||||
*
|
||||
* 注意:
|
||||
* 免密支付是同步返回支付结果,输入密码支付是异步通知支付结果,
|
||||
* 所以需要处理异步支付结果通知。
|
||||
* @param array $order 订单信息
|
||||
* @param string $auth_code 扫码枪扫描后的授权码
|
||||
* @return array 返回支付结果(一维数组)
|
||||
*/
|
||||
function scanPay($order,$auth_code){
|
||||
if(empty($auth_code)){
|
||||
return Tools::set_res(500,'授权码错误');
|
||||
}
|
||||
try {
|
||||
//1. 设置参数(全局只需设置一次)
|
||||
Factory::setOptions($this->getOptions());
|
||||
//2. 发起API调用(以支付能力下的统一收单交易创建接口为例)
|
||||
$result = Factory::payment()->faceToFace()
|
||||
->optional('scene','bar_code')
|
||||
->pay($order['title'], $order['orderid'], $order['real_amount'], $auth_code);
|
||||
|
||||
if($result->code == 10003){
|
||||
return Tools::set_res(230,'交易进行中(提示用户输入密码)'.$result->msg);
|
||||
}
|
||||
//必须解析json
|
||||
$resp = json_decode($result->httpBody, true);
|
||||
//支付宝面对面扫码支付后续流程
|
||||
return Tools::set_ok('ok',$resp['alipay_trade_pay_response']);//返回支付结果(一维数组)
|
||||
} catch (\Exception $e) {
|
||||
$err_data = [
|
||||
'error'=>'支付宝付款码支付错误'.$e->getMessage(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
];
|
||||
Tools::log_to_write_txt($err_data);
|
||||
return Tools::set_fail('错误.'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取支付配置
|
||||
* author:wh
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getOptions()
|
||||
{
|
||||
if(empty($this->pay_config)){
|
||||
throw new Exception('支付宝配置错误');
|
||||
}
|
||||
if(empty($this->pay_config['notifyUrl'])){
|
||||
throw new Exception('支付宝配置错误:notifyUrl通知地址字段必须配置(免密支付是同步返回支付结果,输入密码支付是异步通知支付结果)');
|
||||
}
|
||||
$options = new Config();
|
||||
$options->protocol = 'https';
|
||||
$options->gatewayHost = 'openapi.alipay.com';
|
||||
$options->signType = $this->pay_config['sign_type'];
|
||||
|
||||
$options->appId = $this->pay_config['app_id'];//'<-- 请填写您的AppId,例如:2019022663440152 -->';
|
||||
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
$options->merchantPrivateKey = $this->pay_config['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
|
||||
$options->alipayCertPath = Tools::get_root_path().$this->pay_config['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$options->alipayRootCertPath = Tools::get_root_path().$this->pay_config['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$options->merchantCertPath = Tools::get_root_path().$this->pay_config['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
|
||||
|
||||
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
// $options->alipayPublicKey = '<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
$options->notifyUrl = $this->pay_config['notifyUrl'];//request()->domain().'/index/alipay/notify';//"<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->";
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:支付宝扫码异步通知
|
||||
*
|
||||
* 【通知结果是一维数组】
|
||||
*
|
||||
* {"gmt_create":"2024-06-10 11:53:37","charset":"UTF-8","seller_email":"15023017325",
|
||||
* "subject":"购物消费",
|
||||
* "sign":"oCR3X0ViRrydigLMeOCTrMBNx7O8bSZnEflT0qZYo0gXk2jTI2OVB9mG2UPCkGuSND3wq/pMRFN
|
||||
* ljuz+2r3KMha9a6ArD/ey8w1am3yCKI+FMqUMQSv9TJqfpWdAsc8B45egtr+txBBOA1NMfN41hPnTxM3QzQ82cm
|
||||
* 7VYw6pnYpxJVj/3AsqYxY+wcyMq5+v25eC4TgBo+YJ9pfb3rqaAV91cJBoHRq1Cwh0XEnOzm9zpv7b5cu3r+V0oeW
|
||||
* wTCCi8S1TXW2dfE4H8o63xgASYfJO2fgGIu19YICQdUONkDhu9Tfbf3fFf9SHw3RIw8zrQRqkwAXC32NwfUv4Ru5NqQ==",
|
||||
* "buyer_id":"2088612757425274","invoice_amount":"3258.60","notify_id":"2024061001222115350025271439748729",
|
||||
* "fund_bill_list":"[{\"amount\":\"3258.60\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
|
||||
* "notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"3258.60",
|
||||
* "app_id":"2021004136614333","buyer_pay_amount":"3258.60","sign_type":"RSA2",
|
||||
* "seller_id":"2088642975857443","gmt_payment":"2024-06-10 11:53:50",
|
||||
* "notify_time":"2024-06-10 12:07:40","version":"1.0","out_trade_no":"cs25obpv1717991615660",
|
||||
* "total_amount":"3258.60","trade_no":"2024061022001425271426453509","auth_app_id":"2021004136614333",
|
||||
* "buyer_logon_id":"146***@qq.com","point_amount":"0.00"}
|
||||
*
|
||||
* author:wh
|
||||
* param function $fn 传入订单处理逻辑函数 要求返回success、fail
|
||||
* @return string
|
||||
*/
|
||||
function scanPayNotify($fn){
|
||||
Tools::log_to_write_txt([
|
||||
'支付宝异步通知',
|
||||
'input'=>input()
|
||||
]);
|
||||
|
||||
$out_trade_no = input('out_trade_no');
|
||||
if(empty($out_trade_no)){
|
||||
Tools::log_to_write_txt(['error'=>'out_trade_no为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
//$order = Db::table(TabConf::$fa_order)
|
||||
// ->where('orderid',$out_trade_no)
|
||||
// ->find();
|
||||
//if(empty($order)){
|
||||
// Tools::log_to_write_txt(['error'=>'订单不存在,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
// return '';
|
||||
//}
|
||||
//该字段用于判断成功、失败
|
||||
$trade_status = input('trade_status');
|
||||
if(empty($trade_status)){
|
||||
Tools::log_to_write_txt(['error'=>'trade_status为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
if(empty($this->pay_config['seller_id'])){
|
||||
Tools::log_to_write_txt(['error'=>'卖家seller_id为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
|
||||
//判断来源
|
||||
$seller_id = input('seller_id');
|
||||
if($seller_id != $this->pay_config['seller_id']){
|
||||
Tools::log_to_write_txt(['error'=>'支付通知来源错误','seller_id'=>$seller_id,'config'=>$this->pay_config['seller_id']]);
|
||||
return 'fail';
|
||||
}
|
||||
//支付宝面对面扫码支付后续流程
|
||||
$result = input();
|
||||
//异步通知
|
||||
//$res = CheckstandLogic::alipayScanSuccessFlow($result,$order);
|
||||
//if($res['code'] == 200 || $res['code'] == 230){//成功或进行中
|
||||
// return 'success';
|
||||
//}
|
||||
return $fn($result);//要求返回success、fail
|
||||
}
|
||||
}
|
||||
271
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayWapPay.php
vendored
Normal file
271
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayWapPay.php
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2025/2/24} {20:06}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\pay;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\alipay\BaseAlipay;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝-手机网站支付
|
||||
* Class AlipayWapPay
|
||||
* @package wanghua\general_utility_tools_php\alipay\pay
|
||||
*/
|
||||
class AlipayWapPay extends BaseAlipay
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:移动端wap原生支付宝支付(证书模式-当系统存在转账和支付时,支付必须使用证书模式)
|
||||
*
|
||||
* 支付宝手机网站支付,高内聚,低耦合
|
||||
* author:wh
|
||||
*
|
||||
* @return string html
|
||||
*/
|
||||
function alipayWapH5payCert($order,$notify_url,$pay_end_url){
|
||||
$root_path = Tools::get_root_path();
|
||||
require $root_path.'library/alipay-sdk-php-all/aop/AopCertClient.php';
|
||||
require $root_path.'library/alipay-sdk-php-all/aop/request/AlipayTradeWapPayRequest.php';
|
||||
|
||||
Tools::log_to_write_txt(['支付宝支付(证书模式)-提交支付,参数(出参在回调中):', $order,$notify_url,$pay_end_url]);
|
||||
|
||||
|
||||
//商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
$orderid = $order['orderid'];
|
||||
$total_amount = $order['real_amount'];//交易金额
|
||||
$subject = $order['goods_name']?:"购物消费¥{$total_amount}元";//订单标题
|
||||
|
||||
//$game_admin_domain = any_sys_env_domain_conf('store_outer_api_domain');
|
||||
//这里可以把支付结果通知到其它系统
|
||||
//$notify_url = $game_admin_domain.'/paytool/Alipay/alipayNotify';
|
||||
|
||||
//跳转到支付结果并显示商品推荐
|
||||
//$pay_end_url = url('paytool/recommend/payend','',false,true);//支付结果展示
|
||||
|
||||
//$alipayConfig = aliPayConfPublicAcc();
|
||||
$alipayConfig = $this->alipayConfig;
|
||||
|
||||
/** 初始化 **/
|
||||
$aop = new \AopCertClient();
|
||||
|
||||
/** 支付宝网关 **/
|
||||
$aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
|
||||
|
||||
/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
|
||||
$aop->appId = $alipayConfig['app_id'];
|
||||
|
||||
/** 密钥格式为pkcs1,如何获取私钥请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
|
||||
$aop->rsaPrivateKey = $alipayConfig['alipay_app_private_key'];
|
||||
|
||||
/** 应用公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$appCertPath = $root_path.$alipayConfig['appCertPublicKey'];
|
||||
|
||||
/** 支付宝公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$alipayCertPath = $root_path.$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];
|
||||
|
||||
/** 支付宝公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$rootCertPath = $root_path.$alipayConfig['cert_path_alipayRootCert'];
|
||||
|
||||
/** 设置签名类型 **/
|
||||
$aop->signType= "RSA2";
|
||||
|
||||
/** 设置请求格式,固定值json **/
|
||||
$aop->format = "json";
|
||||
|
||||
/** 设置编码格式 **/
|
||||
$aop->charset= "utf-8";
|
||||
|
||||
/** 调用getPublicKey从支付宝公钥证书中提取公钥 **/
|
||||
$aop->alipayrsaPublicKey = $aop->getPublicKey($alipayCertPath);
|
||||
|
||||
/** 是否校验自动下载的支付宝公钥证书,如果开启校验要保证支付宝根证书在有效期内 **/
|
||||
$aop->isCheckAlipayPublicCert = true;
|
||||
|
||||
/** 调用getCertSN获取证书序列号 **/
|
||||
$aop->appCertSN = $aop->getCertSN($appCertPath);
|
||||
|
||||
/** 调用getRootCertSN获取支付宝根证书序列号 **/
|
||||
$aop->alipayRootCertSN = $aop->getRootCertSN($rootCertPath);
|
||||
|
||||
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.wap.pay **/
|
||||
$request = new \AlipayTradeWapPayRequest();
|
||||
|
||||
/** 设置业务参数 **/
|
||||
$request->setBizContent("{" .
|
||||
|
||||
/** 商户订单号,商户自定义,需保证在商户端不重复,如:20150320010101001 **/
|
||||
"'out_trade_no':'$orderid'," .
|
||||
|
||||
/** 销售产品码,固定值:QUICK_WAP_WAY **/
|
||||
"'product_code':'QUICK_WAP_WAY'," .
|
||||
|
||||
/** 订单金额,精确到小数点后两位 **/
|
||||
"'total_amount':'$total_amount'," .
|
||||
|
||||
/** 订单标题 **/
|
||||
"'subject':'$subject'," .
|
||||
|
||||
/** 业务扩展参数 **/
|
||||
// "'extend_params':{" .
|
||||
/** 系统商编号,填写服务商的PID用于获取返佣,返佣参数传值前提:传值账号需要签约返佣协议,用于isv商户。 **/
|
||||
//"'sys_service_provider_id':'2088511833207846'," .
|
||||
|
||||
/** 花呗分期参数传值前提:必须有该接口花呗收款准入条件,且需签约花呗分期 **/
|
||||
/** 指定可选期数,只支持3/6/12期,还款期数越长手续费越高 **/
|
||||
// "'hb_fq_num':'3'," .
|
||||
|
||||
/** 指定花呗分期手续费承担方式,手续费可以由用户全承担(该值为0),也可以商户全承担(该值为100),但不可以共同承担,即不可取0和100外的其他值。 **/
|
||||
//"'hb_fq_seller_percent':'100'" .
|
||||
// "}," .
|
||||
|
||||
/** 订单描述 **/
|
||||
"'body':'$subject'" .
|
||||
"}");
|
||||
|
||||
/**注:支付结果以异步通知为准,不能以同步返回为准,因为如果实际支付成功,但因为外力因素,如断网、断电等导致页面没有跳转,则无法接收到同步通知;**/
|
||||
/** 支付完成的跳转地址,用于用户视觉感知支付已成功,传值外网可以访问的地址,如果同步未跳转可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602474937 **/
|
||||
$request->setReturnUrl($pay_end_url);
|
||||
|
||||
/** 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/
|
||||
$request->setNotifyUrl($notify_url);
|
||||
|
||||
/** 调用SDK生成支付链接,可在浏览器打开链接进入支付页面 **/
|
||||
$result = $aop->pageExecute ($request,'get');
|
||||
|
||||
/**第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631 **/
|
||||
//$result = $aop->pageExecute($request,'get',"传入获取到的app_auth_token值");
|
||||
|
||||
/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/93 **/
|
||||
//print_r(htmlspecialchars($result));
|
||||
$html = <<<EOF
|
||||
<html><head></head><body style="display: none" onload="javascript:location.href='$result';"></body></html>
|
||||
EOF;
|
||||
return $html;
|
||||
}
|
||||
function alipayWapH5payCertReturnUrl($order,$notify_url,$pay_end_url){
|
||||
$root_path = Tools::get_root_path();
|
||||
require $root_path.'library/alipay-sdk-php-all/aop/AopCertClient.php';
|
||||
require $root_path.'library/alipay-sdk-php-all/aop/request/AlipayTradeWapPayRequest.php';
|
||||
|
||||
Tools::log_to_write_txt(['支付宝支付(证书模式)-提交支付,参数(出参在回调中):', $order,$notify_url,$pay_end_url]);
|
||||
|
||||
|
||||
//商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
$orderid = $order['orderid'];
|
||||
$total_amount = $order['real_amount'];//交易金额
|
||||
$subject = $order['goods_name']?:"购物消费¥{$total_amount}元";//订单标题
|
||||
|
||||
//$game_admin_domain = any_sys_env_domain_conf('store_outer_api_domain');
|
||||
//这里可以把支付结果通知到其它系统
|
||||
//$notify_url = $game_admin_domain.'/paytool/Alipay/alipayNotify';
|
||||
|
||||
//跳转到支付结果并显示商品推荐
|
||||
//$pay_end_url = url('paytool/recommend/payend','',false,true);//支付结果展示
|
||||
|
||||
//$alipayConfig = aliPayConfPublicAcc();
|
||||
$alipayConfig = $this->alipayConfig;
|
||||
|
||||
/** 初始化 **/
|
||||
$aop = new \AopCertClient();
|
||||
|
||||
/** 支付宝网关 **/
|
||||
$aop->gatewayUrl = "https://openapi.alipay.com/gateway.do";
|
||||
|
||||
/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
|
||||
$aop->appId = $alipayConfig['app_id'];
|
||||
|
||||
/** 密钥格式为pkcs1,如何获取私钥请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
|
||||
$aop->rsaPrivateKey = $alipayConfig['alipay_app_private_key'];
|
||||
|
||||
/** 应用公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$appCertPath = $root_path.$alipayConfig['appCertPublicKey'];
|
||||
|
||||
/** 支付宝公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$alipayCertPath = $root_path.$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];
|
||||
|
||||
/** 支付宝公钥证书路径,下载后保存位置的绝对路径 **/
|
||||
$rootCertPath = $root_path.$alipayConfig['cert_path_alipayRootCert'];
|
||||
|
||||
/** 设置签名类型 **/
|
||||
$aop->signType= "RSA2";
|
||||
|
||||
/** 设置请求格式,固定值json **/
|
||||
$aop->format = "json";
|
||||
|
||||
/** 设置编码格式 **/
|
||||
$aop->charset= "utf-8";
|
||||
|
||||
/** 调用getPublicKey从支付宝公钥证书中提取公钥 **/
|
||||
$aop->alipayrsaPublicKey = $aop->getPublicKey($alipayCertPath);
|
||||
|
||||
/** 是否校验自动下载的支付宝公钥证书,如果开启校验要保证支付宝根证书在有效期内 **/
|
||||
$aop->isCheckAlipayPublicCert = true;
|
||||
|
||||
/** 调用getCertSN获取证书序列号 **/
|
||||
$aop->appCertSN = $aop->getCertSN($appCertPath);
|
||||
|
||||
/** 调用getRootCertSN获取支付宝根证书序列号 **/
|
||||
$aop->alipayRootCertSN = $aop->getRootCertSN($rootCertPath);
|
||||
|
||||
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.wap.pay **/
|
||||
$request = new \AlipayTradeWapPayRequest();
|
||||
|
||||
/** 设置业务参数 **/
|
||||
$request->setBizContent("{" .
|
||||
|
||||
/** 商户订单号,商户自定义,需保证在商户端不重复,如:20150320010101001 **/
|
||||
"'out_trade_no':'$orderid'," .
|
||||
|
||||
/** 销售产品码,固定值:QUICK_WAP_WAY **/
|
||||
"'product_code':'QUICK_WAP_WAY'," .
|
||||
|
||||
/** 订单金额,精确到小数点后两位 **/
|
||||
"'total_amount':'$total_amount'," .
|
||||
|
||||
/** 订单标题 **/
|
||||
"'subject':'$subject'," .
|
||||
|
||||
/** 业务扩展参数 **/
|
||||
// "'extend_params':{" .
|
||||
/** 系统商编号,填写服务商的PID用于获取返佣,返佣参数传值前提:传值账号需要签约返佣协议,用于isv商户。 **/
|
||||
//"'sys_service_provider_id':'2088511833207846'," .
|
||||
|
||||
/** 花呗分期参数传值前提:必须有该接口花呗收款准入条件,且需签约花呗分期 **/
|
||||
/** 指定可选期数,只支持3/6/12期,还款期数越长手续费越高 **/
|
||||
// "'hb_fq_num':'3'," .
|
||||
|
||||
/** 指定花呗分期手续费承担方式,手续费可以由用户全承担(该值为0),也可以商户全承担(该值为100),但不可以共同承担,即不可取0和100外的其他值。 **/
|
||||
//"'hb_fq_seller_percent':'100'" .
|
||||
// "}," .
|
||||
|
||||
/** 订单描述 **/
|
||||
"'body':'$subject'" .
|
||||
"}");
|
||||
|
||||
/**注:支付结果以异步通知为准,不能以同步返回为准,因为如果实际支付成功,但因为外力因素,如断网、断电等导致页面没有跳转,则无法接收到同步通知;**/
|
||||
/** 支付完成的跳转地址,用于用户视觉感知支付已成功,传值外网可以访问的地址,如果同步未跳转可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602474937 **/
|
||||
$request->setReturnUrl($pay_end_url);
|
||||
|
||||
/** 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/
|
||||
$request->setNotifyUrl($notify_url);
|
||||
|
||||
/** 调用SDK生成支付链接,可在浏览器打开链接进入支付页面 **/
|
||||
$result = $aop->pageExecute ($request,'get');
|
||||
|
||||
/**第三方调用(服务商模式),传值app_auth_token后,会收款至授权token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631 **/
|
||||
//$result = $aop->pageExecute($request,'get',"传入获取到的app_auth_token值");
|
||||
|
||||
/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/93 **/
|
||||
//print_r(htmlspecialchars($result));
|
||||
// $html = <<<EOF
|
||||
//<html><head></head><body style="display: none" onload="javascript:location.href='$result';"></body></html>
|
||||
//EOF;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
108
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/AlipayTransfer.php
vendored
Normal file
108
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/AlipayTransfer.php
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/09/24} {19:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\transfer;
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use wanghua\general_utility_tools_php\alipay\BaseAlipay;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝转账(独立且区别于支付,连参数都不能用支付参数)
|
||||
*
|
||||
* 注:换句话说,转账是转账的参数,支付是支付的参数,不能混为一谈(以此备注长记性)。
|
||||
*
|
||||
* 环境要求:PHP7.0+,ThinkPHP5.0+
|
||||
*
|
||||
* 依赖:
|
||||
* composer require alipaysdk/easysdk:^2.0
|
||||
*
|
||||
* composer require wanghua/general-utility-tools-php dev-master
|
||||
*
|
||||
* 重要说明:
|
||||
*
|
||||
* 支付宝开放平台可能有多个应用,可能存在一个默认应用(应用名称:应用2.0签约2020102692466480),转账配置就用此应用的参数,而不是其它应用的配置!
|
||||
*
|
||||
*/
|
||||
class AlipayTransfer extends BaseAlipay
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:转账到支付宝(证书模式)
|
||||
* author:wh
|
||||
* @param $transferData TransferConfig.php
|
||||
* @return mixed
|
||||
*
|
||||
* 使用案例:
|
||||
*
|
||||
function transfer(array $trans_data){
|
||||
$alipayConfig = \config('pay_config.alipay_transfer');//转账配置
|
||||
|
||||
$trans_config = new TransferConfig();
|
||||
$trans_config->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$trans_config->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$trans_config->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
$order_prefix = 'trs';
|
||||
$order_id = Tools::to_create_order_no($order_prefix);
|
||||
$trans_config->order_id = $order_id;//订单号 必须
|
||||
$trans_config->timestamp = Tools::get_now_date();//请求时间 eg:2020-01-08 10:12:50
|
||||
$trans_config->trans_amount = $trans_data['trans_amount'];//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
$trans_config->order_title = $trans_data['order_title'];//订单标题 可选
|
||||
$trans_config->phone = $trans_data['phone'];//支付宝登录手机号 必须
|
||||
$trans_config->name = $trans_data['name'];//支付宝真实姓名 必须
|
||||
$trans_config->remark = $trans_data['remark'];//支付备注 可选
|
||||
|
||||
|
||||
$trans = new AlipayTransfer($alipayConfig);
|
||||
Tools::log_to_write_txt(['转账到支付宝,入参:'=>input(), 'trans_config'=>$trans_config]);
|
||||
$pay_res = $trans->alitransfer($trans_config);
|
||||
Tools::log_to_write_txt(['转账到支付宝,出参:'=>$pay_res]);
|
||||
//直接返回转账结果,自主验证成功失败的status。code=10000表示操作成功,status=SUCCESS表示转账成功
|
||||
//由于是同步响应,所以不需要对结果验签
|
||||
return $pay_res;
|
||||
}
|
||||
*
|
||||
*/
|
||||
function alitransfer($transferData){
|
||||
Factory::setOptions($this->getAlipayOptions());
|
||||
|
||||
$method = 'alipay.fund.trans.uni.transfer';
|
||||
//公共参数
|
||||
$textParams = [
|
||||
'app_id'=>$this->alipayConfig['app_id'],
|
||||
'charset'=>'utf-8',
|
||||
'sign_type'=>'RSA2',
|
||||
'timestamp'=>$transferData->timestamp,
|
||||
'version'=>'1.0',
|
||||
];
|
||||
|
||||
//请求参数
|
||||
//订单号前缀
|
||||
$biz_content = [
|
||||
'out_biz_no'=>$transferData->order_id,//商家支付订单号
|
||||
'trans_amount'=>$transferData->trans_amount,
|
||||
'product_code'=>'TRANS_ACCOUNT_NO_PWD',
|
||||
'biz_scene'=>'DIRECT_TRANSFER',
|
||||
'order_title'=>$transferData->order_title,
|
||||
'payee_info'=>[
|
||||
'identity'=>$transferData->phone,//手机号
|
||||
'identity_type'=>'ALIPAY_LOGON_ID',
|
||||
'name'=>$transferData->name,//参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。
|
||||
],
|
||||
'remark'=>$transferData->remark,
|
||||
];
|
||||
$pay_res = Factory::util()->generic()->execute($method,$textParams,$biz_content);
|
||||
|
||||
return $pay_res;
|
||||
}
|
||||
|
||||
}
|
||||
63
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/TransferConfig.php
vendored
Normal file
63
superadmin/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/TransferConfig.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/09/24} {20:07}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\transfer;
|
||||
|
||||
|
||||
/**
|
||||
* 调用转账之前请配置此参数
|
||||
*
|
||||
* 配置示例:
|
||||
*
|
||||
$alipayConfig = \config('pay_config.alipay_transfer');//转账配置
|
||||
|
||||
$trans_config = new TransferConfig();
|
||||
$trans_config->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$trans_config->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$trans_config->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
$order_prefix = 'trs';
|
||||
$order_id = Tools::to_create_order_no($order_prefix);
|
||||
$trans_config->order_id = $order_id;//订单号 必须
|
||||
$trans_config->timestamp = Tools::get_now_date();//请求时间 eg:2020-01-08 10:12:50
|
||||
$trans_config->trans_amount = '0.21';//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
$trans_config->order_title = '代理提现';//订单标题 可选
|
||||
$trans_config->phone = '18290416033';//支付宝登录手机号 必须
|
||||
$trans_config->name = '王华';//支付宝真实姓名 必须
|
||||
$trans_config->remark = '代理提现到支付宝';//支付备注 可选
|
||||
|
||||
$trans = new AlipayTransfer();
|
||||
$pay_res = $trans->alitransfer($alipayConfig, $trans_config);
|
||||
|
||||
dump($pay_res);
|
||||
*
|
||||
*/
|
||||
class TransferConfig
|
||||
{
|
||||
//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
public $cert_path_alipayCertPublicKey_RSA2 = '';//必须
|
||||
//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
public $cert_path_alipayRootCert = '';//必须
|
||||
//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
public $appCertPublicKey = '';//必须
|
||||
|
||||
public $notifyUrl = '';//接收异步通知(可选)
|
||||
|
||||
|
||||
//业务参数
|
||||
public $order_id = '';//订单号 必须
|
||||
public $timestamp = '';//请求时间 必须 eg:2020-01-08 10:12:50
|
||||
public $trans_amount = '';//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
public $order_title = '';//订单标题 可选
|
||||
public $phone = '';//支付宝登录手机号 必须
|
||||
public $name = '';//支付宝真实姓名 必须
|
||||
public $remark = '';//支付备注 可选
|
||||
|
||||
|
||||
}
|
||||
425
superadmin/vendor/wanghua/general-utility-tools-php/src/api/Api.php
vendored
Normal file
425
superadmin/vendor/wanghua/general-utility-tools-php/src/api/Api.php
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {11:21}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\mysql\lib\Table;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Api extends BaseLibApi
|
||||
{
|
||||
private $apidir = '';
|
||||
private $namespace = 'app\api\controller';
|
||||
|
||||
private $table_obj = null;
|
||||
|
||||
//一维数组
|
||||
private $functions_arr = [];//要创建的初始方法
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//默认api目录
|
||||
$this->apidir = Tools::get_root_path().'application/api/controller/';
|
||||
if(!$this->table_obj)
|
||||
$this->table_obj = new Table();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api目录
|
||||
* author:wh
|
||||
* @param string $dir api创建目录,格式必须按照例子填写 eg: application/api/controller/
|
||||
*/
|
||||
function setapidir(string $dir){
|
||||
$this->apidir = $dir;
|
||||
$nsp = str_replace('application','app',substr($dir,0,strlen($dir)-2));
|
||||
$this->namespace = str_replace('/','\\',$nsp);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:替换表前缀
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return false|string
|
||||
*/
|
||||
function replaceTablePrefix($tablename){
|
||||
$prefix = config('database.prefix');
|
||||
if($prefix){
|
||||
return substr($tablename,strlen($prefix));
|
||||
}
|
||||
$tmp_prefix = 't_';
|
||||
if(false !== strpos($tablename,$tmp_prefix)){
|
||||
return substr($tablename,strlen($tmp_prefix));
|
||||
}
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置方法名称
|
||||
*
|
||||
* author:wh
|
||||
* @param array $functions_arr
|
||||
*/
|
||||
function setApiFunctionsName(array $functions_arr){
|
||||
$this->functions_arr = array_merge($functions_arr,$this->functions_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:动态创建方法
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function syncCreateFunction(array $func_name_arr){
|
||||
$code = '';
|
||||
foreach ($func_name_arr as $func_name=>$func_remark){ //接口方法公共代码模块
|
||||
$commonFunctionCodeModule = $this->commonFunctionCodeModule($func_remark);
|
||||
$code .= <<<EOF
|
||||
|
||||
/**
|
||||
* desc:{$func_remark}
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
function {$func_name}(){
|
||||
{$commonFunctionCodeModule}
|
||||
}
|
||||
EOF;
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建查询接口的代码体
|
||||
*
|
||||
* 本接口只针对简单查询逻辑
|
||||
*
|
||||
* and
|
||||
* like%,%like%,
|
||||
* >, <, >=, <=, !=
|
||||
* between
|
||||
* in
|
||||
*
|
||||
* author:wh
|
||||
* @param array $select_in_params eg:
|
||||
* [
|
||||
* 'gameid'=>['and'],
|
||||
* 'nickname'=>['like%'],
|
||||
* 'reg_time'=>['between'],//时间区间查询
|
||||
* 'audit_time'=>['2015-01-3','eq'],//时间区间查询
|
||||
* ]
|
||||
*
|
||||
*/
|
||||
function setQueryCodeBody(array $select_in_params){
|
||||
$code = '';
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:写入查询接口的代码体
|
||||
*
|
||||
* author:wh
|
||||
* @param array $insert_params
|
||||
* @return string
|
||||
*/
|
||||
function setInsertCodeBody(array $insert_params){
|
||||
$code = '';
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:快速构建api代码
|
||||
*
|
||||
* 本方法不验证接口名称是否重复
|
||||
*
|
||||
* author:wh
|
||||
* @param string $tablename 数据表名称
|
||||
* @param array $func_name_arr 方法名称数组 eg:['getData'=>'获取数据','function_aaa'=>'function_注释aaa']
|
||||
*/
|
||||
function buildApi(string $tablename, array $func_name_arr){
|
||||
//deal table name
|
||||
$tablename = $this->replaceTablePrefix($tablename);
|
||||
|
||||
//基础 start
|
||||
//create base controller
|
||||
$this->buildBaseApiPublicController();//开放控制器
|
||||
$this->buildBaseApiAuthController();//权限控制器
|
||||
$this->errController();//错误控制器
|
||||
//基础 end
|
||||
|
||||
//接口类名
|
||||
$classname = ucfirst(Tools::convertUnderLine($tablename));
|
||||
//接口注释
|
||||
$comment = $this->table_obj->getTableComment($tablename);
|
||||
|
||||
//批量构建方法代码
|
||||
$build_functions_code = $this->syncCreateFunction($func_name_arr);
|
||||
|
||||
//PHP文件名,不含物理路径
|
||||
$file_name = $classname.$this->ext();
|
||||
|
||||
//PHP文件路径和文件名
|
||||
$php_file = $this->apidir.$file_name;
|
||||
|
||||
if(file_exists($php_file)){
|
||||
//追加代码
|
||||
//读取并删除最后的“}”
|
||||
$php_code_str = file_get_contents($php_file);
|
||||
$sub_php_code_str = mb_substr($php_code_str,0,mb_strlen($php_code_str)-2);
|
||||
//追加新的代码
|
||||
$sub_php_code_str .= $build_functions_code ."\n }";
|
||||
//清空代码
|
||||
file_put_contents($php_file,'');
|
||||
//追加
|
||||
$this->createFileExists($php_file,$sub_php_code_str);
|
||||
}else{
|
||||
//创建代码文件
|
||||
$use_tpl = $this->useTpl();
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
{$use_tpl}
|
||||
|
||||
/**
|
||||
* {$comment}
|
||||
* Class {$classname}
|
||||
* @package {$this->namespace}
|
||||
*/
|
||||
class {$classname} extends BaseApiPublicController
|
||||
{
|
||||
|
||||
|
||||
|
||||
{$build_functions_code}
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:公共方法模块
|
||||
*
|
||||
* author:wh
|
||||
* @param $comment
|
||||
* @return string
|
||||
*/
|
||||
private function commonFunctionCodeModule($comment){
|
||||
$php = <<<EOF
|
||||
try {
|
||||
Tools::log_to_write_txt(['title'=>'{$comment},__IN:','INPUT'=>input()]);
|
||||
//region 校验区 start
|
||||
|
||||
//endregion 校验区 end
|
||||
|
||||
|
||||
|
||||
|
||||
//region 业务逻辑区 start
|
||||
|
||||
//endregion 业务逻辑区 end
|
||||
|
||||
|
||||
|
||||
|
||||
//响应结果处理
|
||||
Tools::log_to_write_txt(['title'=>'{$comment},__OUT:','OUTPUT'=>[]]);
|
||||
return json(Tools::set_res(200,'ok'));
|
||||
}catch (\Exception \$e){
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'{$comment},API异常。'.\$e->getMessage(),
|
||||
'入参'=>input(),
|
||||
'error_info'=>\$e->getTraceAsString()
|
||||
]);
|
||||
return json(Tools::set_res(500,'系统繁忙'));
|
||||
}
|
||||
EOF;
|
||||
|
||||
return $php;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api基础开放控制器
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function buildBaseApiPublicController(){
|
||||
$file_name = 'BaseApiPublicController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api基础开放架构
|
||||
*
|
||||
* 所有开放接口继承此父类
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api基础权限控制器
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function buildBaseApiAuthController(){
|
||||
$file_name = 'BaseApiAuthController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api基础权限架构
|
||||
*
|
||||
* 所有权限接口继承此父类
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api底层基础控制器架构
|
||||
*
|
||||
* [按需创建][可单独调用]
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildBaseApiController(){
|
||||
$file_name = 'BaseApiController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api底层基础控制器架构
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:use模块
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
private function useTpl(){
|
||||
$php = <<<EOF
|
||||
use wanghua\general_utility_tools_php\\tool\Tools;
|
||||
EOF;
|
||||
return $php;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误控制器
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function errController(){
|
||||
$file_name = 'Err';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\\framework\\base\PublicController;
|
||||
use wanghua\general_utility_tools_php\\tool\Tools;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 错误(异常)中转架构
|
||||
*
|
||||
* Class Err
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class {$file_name} extends BaseApiPublicController
|
||||
{
|
||||
/**
|
||||
* desc:校验失败中转
|
||||
*
|
||||
* 场景:内网端口验证未通过时跳转;
|
||||
*
|
||||
* author:wh
|
||||
* @return \\think\\response\\Json
|
||||
*/
|
||||
function checkfailed(){
|
||||
|
||||
return json(Tools::set_res(500,'Permission denied',input()));
|
||||
}
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
}
|
||||
317
superadmin/vendor/wanghua/general-utility-tools-php/src/api/ApiDocument.php
vendored
Normal file
317
superadmin/vendor/wanghua/general-utility-tools-php/src/api/ApiDocument.php
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/15} {21:40}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* desc:接口文档构建器
|
||||
*
|
||||
* 使用步骤:
|
||||
* (new ApiDocument())->buildDoc();
|
||||
* Class ApiDocument
|
||||
*/
|
||||
class ApiDocument
|
||||
{
|
||||
public $app_name = 'api';
|
||||
private $api_cache_arr = [];//缓存所有接口
|
||||
public $api_domain = 'http://127.0.0.1:8080/';//接口域名/ip
|
||||
/**
|
||||
* @var string 接口控制器命名空间
|
||||
*/
|
||||
public $namespace = 'app\\api\\controller';
|
||||
/**
|
||||
* @var string 接口控制器基类,精确到类名,如:app\\common\\controller\\Api
|
||||
* 注意:如果同级目录存在多个基类,则设置直接基类,如果同级目录没有基类,则设置底层基类
|
||||
*/
|
||||
public $extends_base_class = '';
|
||||
//控制器目录物理路径
|
||||
public $controllerDirectory = '';
|
||||
/**
|
||||
* @var string 接口文档保存路径
|
||||
*/
|
||||
public $api_docs_save_dir = 'public/api_docs/';
|
||||
//设置过滤类
|
||||
private $filterClassArr = [];
|
||||
//设置过滤方法
|
||||
private $filterFunctionArr = [];
|
||||
|
||||
public function __construct($api_domain='',$controllerDirectory='')
|
||||
{
|
||||
//默认,如果是tp6,那application就要改为app了,自行传参吧
|
||||
$this->controllerDirectory = Tools::get_root_path()."application/{$this->app_name}/controller";
|
||||
if($api_domain){
|
||||
$this->api_domain = $api_domain;
|
||||
}
|
||||
if($controllerDirectory){
|
||||
$this->controllerDirectory = $controllerDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置过滤类(类名)
|
||||
* 过滤场景:
|
||||
* 1、基类
|
||||
* 2、测试类
|
||||
* 3、定时任务类
|
||||
* 4、其它非必要类
|
||||
* author:wh
|
||||
* @param array $filterClassArr
|
||||
*/
|
||||
function setFilterClass(array $filterClassArr=[]){
|
||||
$this->filterClassArr = $filterClassArr;
|
||||
}
|
||||
function setFilterFunction(array $filterArr=[]){
|
||||
$this->filterFunctionArr = $filterArr;
|
||||
}
|
||||
/**
|
||||
* desc:构建接口文档,支持同步到在线文档
|
||||
* author:wh
|
||||
*/
|
||||
function buildDoc(){
|
||||
if(empty($this->extends_base_class)){
|
||||
throw new Exception('请设置接口控制器基类,精确到类名,如:app\\common\\controller\\Api');
|
||||
}
|
||||
$out_path = Tools::get_root_path().$this->api_docs_save_dir;
|
||||
if(!file_exists($out_path)){
|
||||
mkdir($out_path,0777,true);
|
||||
}
|
||||
$outputFile = $out_path.'api_list.md';
|
||||
$controllerClasses = [];
|
||||
|
||||
// 搜索控制器目录下的所有PHP文件
|
||||
foreach (glob($this->controllerDirectory . '/*.php') as $filename) {
|
||||
// 获取文件中的类名
|
||||
$class = basename($filename, '.php');
|
||||
if(in_array($class,$this->filterClassArr)){
|
||||
continue;
|
||||
}
|
||||
// 构建完整的命名空间类名
|
||||
$fullClassName = $this->namespace . '\\' . $class;
|
||||
foreach (explode(',',$this->extends_base_class) as $base_class){
|
||||
// 检查类是否有效并且是think\Controller的子类
|
||||
if (class_exists($fullClassName) && is_subclass_of($fullClassName, $base_class)) {
|
||||
$controllerClasses[] = $fullClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Markdown文件
|
||||
$file = fopen($outputFile, 'w') or die('无法创建文件');
|
||||
|
||||
$head_text = <<<EOF
|
||||
# API 文档
|
||||
## 接口列表
|
||||
###### (ctrl+f 搜索)(如果更改了路由,请根据路由规则定位)
|
||||
##### 请求域名:{$this->api_domain}
|
||||
##### 请求方式:POST(默认)
|
||||
|
||||
EOF;
|
||||
// 写入Markdown文件头部
|
||||
fwrite($file, $head_text);
|
||||
|
||||
foreach ($controllerClasses as $controllerClass) {
|
||||
$reflector = new \ReflectionClass($controllerClass);
|
||||
// 遍历控制器中的公共方法
|
||||
$methods = $reflector->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method) {
|
||||
//过滤方法
|
||||
if(in_array($method->name, $this->filterFunctionArr)){
|
||||
continue;
|
||||
}
|
||||
$exp_class = explode('\\',$controllerClass);
|
||||
//过滤类
|
||||
if(in_array($exp_class[count($exp_class)-1],$this->filterClassArr)){
|
||||
continue;
|
||||
}
|
||||
$comments = $method->getDocComment();
|
||||
if ($comments) {
|
||||
$this->processMethodComment($comments, $controllerClass, $method->name, $outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($file);
|
||||
|
||||
//缓存所有接口
|
||||
cache('api_doc_cache_arr',$this->api_cache_arr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:解析方法注释并写入Markdown文件
|
||||
* author:wh
|
||||
* @param $comments
|
||||
* @param $className
|
||||
* @param $methodName
|
||||
* @param $savepath
|
||||
*/
|
||||
private function processMethodComment($comments, $className, $methodName, $savepath) {
|
||||
if($methodName == '__construct'){
|
||||
return '';
|
||||
}
|
||||
$api_url = "/{$this->app_name}/{$className}/{$methodName}";
|
||||
$js_api_func_name = "api_{$className}_{$methodName}";
|
||||
$str = <<<EOF
|
||||
|
||||
***
|
||||
```
|
||||
|
||||
EOF;
|
||||
|
||||
$comments_str = mb_substr($comments,0,-2);
|
||||
$class_arr = explode('\\',$className);
|
||||
$className = $class_arr[count($class_arr)-1];
|
||||
$className = $this->camelCaseToUnderscore($className);
|
||||
|
||||
|
||||
$api_name = "{$this->app_name}/{$className}/{$methodName}";
|
||||
$doc_txt = <<<EOF
|
||||
* $api_name
|
||||
*/
|
||||
```
|
||||
EOF;
|
||||
$doc_txt= $str.$comments_str.$doc_txt." \r\n";
|
||||
$this->api_cache_arr[$className][] = ['api_name'=>$api_name,'doc_txt'=>$doc_txt,'class_name'=>$className];
|
||||
file_put_contents($savepath,$doc_txt, FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:驼峰转下划线
|
||||
* author:wh
|
||||
* @param $string
|
||||
* @return string
|
||||
*/
|
||||
private function camelCaseToUnderscore($string) {
|
||||
$str = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $string));
|
||||
return strpos($str,'_')===0?substr($str,1):$str;
|
||||
}
|
||||
|
||||
function buildApiDocHtml(){
|
||||
//给定一组浅色背景色码
|
||||
$color_code_arr = [
|
||||
'#f0f8ff', '#f0ffff', '#f5f5dc', '#ffe4c4', '#f5f5f5', '#f5fffa', '#fff5ee', '#f8f8ff', '#fffaf0', '#fffff0', '#fafad2', '#f0fff0', '#fff0f5', '#ffe4e1', '#f0ffff', '#f0f8ff', '#f8f8ff', '#faebd7', '#fff0f5', '#ffe4e1', '#ffe4b5', '#ffdead', '#dcdcdc', '#dda0dd', '#fffaf0', '#eee8aa', '#fffafa', '#f0fff0', '#f0fff0', '#f0f8ff', '#f0ffff', '#f5f5dc', '#ffe4c4', '#f5f5f5', '#f5fffa', '#fff5ee', '#f8f8ff', '#fffaf0', '#f0fff0', '#fff0f5', '#ffe4e1', '#f0ffff', '#f0f8ff', '#f8f8ff', '#faebd7', '#fff0f5', '#ffe4e1', '#ffe4b5', '#ffdead', '#dcdcdc', '#dda0dd', '#fffaf0', '#eee8aa', '#fffafa', '#f0fff0', '#f0fff0', '#f0f8ff', '#f0ffff', '#f5f5dc', '#ffe4c4', '#f5f5f5', '#f5fffa', '#fff5ee', '#f8f8ff', '#fffaf0',
|
||||
];
|
||||
|
||||
$api_doc_cache_arr = cache('api_doc_cache_arr');
|
||||
|
||||
$htm_str = <<<EOF
|
||||
<style>
|
||||
.txt-lf{text-align: left}
|
||||
</style>
|
||||
<div style="width: 50%;margin: 0 auto;color: red;text-align: center;">
|
||||
<div class="txt-lf">文档说明:</div>
|
||||
<div class="txt-lf">1、如果没有明确说明,提交请求均使用post</div>
|
||||
<div class="txt-lf">2、此接口文档不包含websocket接口</div>
|
||||
<div class="txt-lf">3、接口参数之间使用“/”符号隔开</div>
|
||||
<div class="txt-lf">4、此文档接口测试功能只针对普通post、get接口,不能测试文件上传或文件流</div>
|
||||
<div class="txt-lf">5、功能模块按照颜色分组</div>
|
||||
<div class="txt-lf" style="color: black;">清理缓存:
|
||||
<a href='JavaScript:;' onclick="CacheObj.clearCache()">
|
||||
点击清理
|
||||
</a><span style="color: gray;font-size: 12px;">(由于接口数据可能会被缓存,发现数据没变化或需要时,可清理缓存)</span>
|
||||
</div>
|
||||
<div class="txt-lf">
|
||||
<a href="/api_docs/api_list.html" style="margin: 20px">api应用文档</a>
|
||||
<a href="/api_docs/{$this->app_name}_list.html" style="margin: 20px">{$this->app_name}应用文档</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
EOF;
|
||||
|
||||
$script_str = "";
|
||||
foreach ($api_doc_cache_arr as $class_name_key=>$func_arr){
|
||||
//随机取一个颜色
|
||||
$color_code = $color_code_arr[array_rand($color_code_arr,1)];
|
||||
//是否显示上边距
|
||||
$is_show_margin_top = 'margin-top: 50px;';
|
||||
foreach ($func_arr as $k => $item){
|
||||
$api_name = $item['api_name'];
|
||||
$doc_txt = $item['doc_txt'];
|
||||
|
||||
if($k > 0){
|
||||
|
||||
$is_show_margin_top = '';
|
||||
}
|
||||
|
||||
|
||||
$function_name = str_replace('/','_',$api_name);
|
||||
$htm_str .= <<<EOF
|
||||
<div id="{$function_name}" style="background-color: {$color_code};{$is_show_margin_top}">
|
||||
<div class="markdown_content">{$doc_txt}</div>
|
||||
<div>
|
||||
按需填写其它接口参数:
|
||||
<textarea name="" id="{$function_name}_textarea" cols="100" rows="3">/{$api_name}</textarea>
|
||||
<a href='JavaScript:;' onclick="DocObject.{$function_name}()">测试</a>
|
||||
</div>
|
||||
<div class="{$function_name}_response_result"></div>
|
||||
|
||||
</div>
|
||||
EOF;
|
||||
$script_str.=<<<EOF
|
||||
{$function_name}(){
|
||||
let url = $('#{$function_name}_textarea').val();
|
||||
$.post(url,{},function(res) {
|
||||
$('.{$function_name}_response_result').html(JSON.stringify(res, null, "\\t"));
|
||||
$('.{$function_name}_response_result').attr('style','color:green');
|
||||
},'json');
|
||||
},
|
||||
EOF;
|
||||
|
||||
}
|
||||
}
|
||||
$html = <<<EOF
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>接口文档</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
{$htm_str}
|
||||
</div>
|
||||
</body>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="/webautocodestatic/marked.min.js"></script>
|
||||
<script src="/webautocodestatic/plugs/layui-v2.9.2/layui.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
|
||||
//加载markdown
|
||||
DocObject.markdown_content();
|
||||
});
|
||||
|
||||
let CacheObj = {
|
||||
clearCache: function () {
|
||||
let url = '/index/test/clearCache';
|
||||
$.post(url,{},function(res) {
|
||||
layer.msg('清理成功')
|
||||
},'json');
|
||||
}
|
||||
};
|
||||
|
||||
let DocObject = {
|
||||
markdown_content(){
|
||||
$('.markdown_content').each(function(k,ele) {
|
||||
$(ele).html(marked.parse($(ele).html()));
|
||||
});
|
||||
},
|
||||
$script_str
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
||||
EOF;
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
230
superadmin/vendor/wanghua/general-utility-tools-php/src/api/BaseApi.php
vendored
Normal file
230
superadmin/vendor/wanghua/general-utility-tools-php/src/api/BaseApi.php
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {16:14}
|
||||
*/
|
||||
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\api\ApiException;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃
|
||||
* desc:api交互
|
||||
*
|
||||
* author:wh
|
||||
* Class BaseApi
|
||||
* @package app\apidata
|
||||
*/
|
||||
class BaseApi
|
||||
{
|
||||
protected $post_url = '';
|
||||
private $prefix = 'api_';
|
||||
protected $log_file_name = 'log';
|
||||
protected $__sit__ = '';
|
||||
function __construct(string $url)
|
||||
{
|
||||
$this->post_url = $url;
|
||||
if(empty($this->post_url)) {
|
||||
Tools::log_to_write_txt(['error'=>'API OPERATE: '.ApiException::EMPTY_URL_ERROR], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::EMPTY_URL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置api请求日志文件名称
|
||||
*
|
||||
* 日志保存在runtime中
|
||||
*
|
||||
* author:wh
|
||||
* @param string $log_file_name
|
||||
*/
|
||||
function setLogFileName(string $log_file_name=''){
|
||||
if($log_file_name)$this->log_file_name = $log_file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc 获取记录日志的文件名
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getLogFileName(){
|
||||
return $this->prefix.$this->log_file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置调用位置
|
||||
* author:wh
|
||||
* @param $__file__
|
||||
* @param $__line__
|
||||
*/
|
||||
function setFileDir($__file__, $__line__){
|
||||
$this->__sit__ = $__file__.' > '.$__line__;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误位置
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getErrorSit(){
|
||||
return $this->__sit__;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* @param array $params
|
||||
*/
|
||||
private function mergeAuthParams(array &$params){
|
||||
$params['nonce'] = Tools::rand_str(10);
|
||||
$params['timestamp'] = time();
|
||||
$token = config('service_framework_config.sign_token');
|
||||
$params['sign'] = Tools::signature($params, $token);
|
||||
}
|
||||
/**
|
||||
* desc:执行post请求, 带权限参数
|
||||
*
|
||||
* 同框架、内部系统推荐
|
||||
*
|
||||
* 返回结果由code 错误码和msg 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以表单格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function apiPost($param){
|
||||
$this->mergeAuthParams($param);
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, $param);
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行post请求
|
||||
*
|
||||
* 返回结果由code 错误码和msg 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以json格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function do($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, json_encode($param));
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR.$this->post_url);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行请求
|
||||
*
|
||||
* do 方法的改版,返回结果由state 错误码和err 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以json格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function apiDo($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, json_encode($param));
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
|
||||
if(is_null($data['state'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
$data['code'] = isset($data['state'])&&$data['state']==0?200:$data['state'];
|
||||
$data['msg'] = isset($data['err'])?$data['err']:'api接口错误';
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行请求
|
||||
*
|
||||
* 同框架、内部系统推荐
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以表单方式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function doPost($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, $param);
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
54
superadmin/vendor/wanghua/general-utility-tools-php/src/api/BaseLibApi.php
vendored
Normal file
54
superadmin/vendor/wanghua/general-utility-tools-php/src/api/BaseLibApi.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {15:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
class BaseLibApi
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:创建目录
|
||||
*
|
||||
* author:wh
|
||||
* @param $apidir
|
||||
*/
|
||||
function createDir($apidir){
|
||||
if(!is_dir($apidir)){
|
||||
mkdir($apidir,0777,true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文件存在不写入
|
||||
*
|
||||
* author:wh
|
||||
* @param $php_file
|
||||
* @param $php
|
||||
*/
|
||||
function createFile($php_file,$php){
|
||||
if(!file_exists($php_file)){
|
||||
file_put_contents($php_file,$php);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:追加文本
|
||||
*
|
||||
* author:wh
|
||||
* @param $php_file
|
||||
* @param $php
|
||||
*/
|
||||
function createFileExists($php_file,$php){
|
||||
file_put_contents($php_file,$php,FILE_APPEND);
|
||||
}
|
||||
|
||||
function ext(){
|
||||
return '.php';
|
||||
}
|
||||
}
|
||||
193
superadmin/vendor/wanghua/general-utility-tools-php/src/api/BaseUserLogic.php
vendored
Normal file
193
superadmin/vendor/wanghua/general-utility-tools-php/src/api/BaseUserLogic.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/2/26} {10:54}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class BaseUserLogic
|
||||
{
|
||||
public $user_table = 'fa_users';
|
||||
|
||||
/**
|
||||
* desc:【通用】用户登录逻辑
|
||||
*
|
||||
* 请求端加密,服务端校验
|
||||
*
|
||||
* 签名规则
|
||||
* 请求参数:
|
||||
username //用户名
|
||||
password //密码 md5(md5('a123456')) d477887b0636e5d87f79cc25c99d7dc9
|
||||
timestamp //请求时间戳 2020-01-01 12:34:07
|
||||
noncestr //随机字符串8位
|
||||
sign //签名串,参考全站签名规则
|
||||
|
||||
other_params //其它接口的其它参数
|
||||
* 全站sign规则:
|
||||
1. 对关联数组按照键升序排序
|
||||
2. 拼接成字符串 keyvalkey2val2key3val3
|
||||
3. 再2次md5生成32位小写串
|
||||
4. 与请求参数一起发送到服务器
|
||||
*
|
||||
* author:wh
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
function tologin(){
|
||||
if(!request()->isPost()){
|
||||
return Tools::set_fail('错误');
|
||||
}
|
||||
Tools::log_to_write_txt(['登录入参:'=>input()]);
|
||||
$input_data = input();
|
||||
if(empty($input_data)){
|
||||
return Tools::set_fail('请求参数错误');
|
||||
}
|
||||
if(empty($input_data['username'])){
|
||||
return Tools::set_fail('用户名或密码错误');
|
||||
}
|
||||
if(empty($input_data['password'])){
|
||||
return Tools::set_fail('用户名或密码错误.');
|
||||
}
|
||||
// start 这段代码可放在请求合法性里面校验 Tools::signature
|
||||
if(empty($input_data['timestamp'])){
|
||||
return Tools::set_fail('请求错误..');
|
||||
}
|
||||
if(empty($input_data['noncestr'])){
|
||||
return Tools::set_fail('请求错误...');
|
||||
}
|
||||
if(empty($input_data['sign'])){
|
||||
return Tools::set_fail('请求错误。');
|
||||
}
|
||||
|
||||
$sign = $input_data['sign'];//md5后的字符串
|
||||
unset($input_data['sign']);
|
||||
//验签
|
||||
$signstr = Tools::signature($input_data);
|
||||
//Tools::log_to_write_txt([
|
||||
// '签名日志:',
|
||||
// $signstr,
|
||||
// $sign,
|
||||
// 'input'=>input(),
|
||||
//]);
|
||||
if($signstr != $sign){
|
||||
return Tools::set_fail('非法请求');
|
||||
}
|
||||
|
||||
//请求时间超过有效期 N分钟内有效
|
||||
if(time()-5*60 > strtotime($input_data['timestamp'])){
|
||||
return Tools::set_fail('请求失效');
|
||||
}
|
||||
// end 这段代码可放在请求合法性里面校验 Tools::signature
|
||||
|
||||
$username = $input_data['username'];
|
||||
$user = Db::table($this->user_table)->where('username',$username)->find();
|
||||
if(empty($user)){
|
||||
return Tools::set_fail('账号密码错误!');
|
||||
}
|
||||
//校验密码
|
||||
if($user['password'] != $input_data['password']){
|
||||
return Tools::set_fail('账号密码错误!!');
|
||||
}
|
||||
|
||||
$expires = time()+12*60*60;
|
||||
|
||||
|
||||
|
||||
//返回票据
|
||||
$ticketstr = md5($user['username'].$user['expires']);
|
||||
//保存ticket
|
||||
$user[$ticketstr] = $expires;//N秒后过期
|
||||
//修改有效期
|
||||
Db::table($this->user_table)
|
||||
->data([
|
||||
'ticket'=>$ticketstr,
|
||||
'expires'=>7*86400+time(),//7天
|
||||
])
|
||||
->where('username',$username)
|
||||
->update();
|
||||
session('api_user',$user);//备用(跨环境情况下session不生效)
|
||||
|
||||
return Tools::set_ok('登录成功',['ticket'=>$ticketstr]);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证登录,根据提交的ticket来校验是否登录,适用于跨环境登录
|
||||
*
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
function isLogin(){
|
||||
|
||||
$ticket = input('ticket');
|
||||
if(empty($ticket)){
|
||||
Tools::log_to_write_txt(['title'=>'业务ticket字段不存在','input'=>input()]);
|
||||
return false;
|
||||
}
|
||||
$user = Db::table(TabConf::$fa_users)
|
||||
->where('ticket',$ticket)
|
||||
->find();
|
||||
if(empty($user)){
|
||||
Tools::log_to_write_txt(['title'=>'用户未登录']);
|
||||
return false;
|
||||
}
|
||||
//无效票据
|
||||
//if(empty($user[$ticket])){
|
||||
// Tools::log_to_write_txt(['title'=>'未获取到用户ticket',$ticket=>$user]);
|
||||
//
|
||||
// return false;
|
||||
//}
|
||||
//已过期
|
||||
if(time() > $user['expires']){
|
||||
Tools::log_to_write_txt(['title'=>'ticket已过期',$ticket=>$user]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* desc:用户注册
|
||||
*
|
||||
* 此模块通用性不高,按需使用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function reg($input_data){
|
||||
try {
|
||||
if(empty($input_data['username'])){
|
||||
return Tools::set_fail('用户名错误');
|
||||
}
|
||||
if(empty($input_data['password'])){
|
||||
return Tools::set_fail('密码错误.');
|
||||
}
|
||||
if(empty($input_data['password2'])){
|
||||
return Tools::set_fail('密码错误!');
|
||||
}
|
||||
if($input_data['password'] != $input_data['password2']){
|
||||
return Tools::set_fail('密码不一致!');
|
||||
}
|
||||
$insert_data = [
|
||||
'username'=>$input_data['username'],
|
||||
'password'=>$input_data['password'],
|
||||
];
|
||||
if(!empty($input_data['phone'])){
|
||||
$insert_data['phone'] = $input_data['phone'];
|
||||
}
|
||||
Db::table($this->user_table)
|
||||
->data($insert_data)
|
||||
->insert();
|
||||
return Tools::set_ok();
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
superadmin/vendor/wanghua/general-utility-tools-php/src/apk/Apk.php
vendored
Normal file
79
superadmin/vendor/wanghua/general-utility-tools-php/src/apk/Apk.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*
|
||||
* description: apk应用安装包信息读取
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {17:16}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\apk;
|
||||
|
||||
|
||||
class Apk
|
||||
{
|
||||
|
||||
/**
|
||||
* 前提:安装PHP ZIP扩展
|
||||
* 扩展下载:https://windows.php.net/downloads/pecl/releases/zip/
|
||||
* desc:读取APK
|
||||
* author:wh
|
||||
* @param string $path 文件地址
|
||||
* @param bool $isRemote 是否远程文件
|
||||
* @param string $proxy 代理
|
||||
* @return array
|
||||
*/
|
||||
function read(string $path, $filename, bool $isRemote=false, $proxy=''){
|
||||
/*解析安卓apk包中的压缩XML文件,还原和读取XML内容
|
||||
|
||||
依赖功能:需要PHP的ZIP包函数支持。*/
|
||||
|
||||
$appObj = new ApkParser();
|
||||
|
||||
$targetFile = $path;//a.apk; apk所在的路径地址
|
||||
// 如果是远程文件,先下载到本地
|
||||
if ($isRemote) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $path);
|
||||
if ($proxy != '') {
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxy);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 50);
|
||||
$fileContent = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// 写入临时文件
|
||||
$sys_tmp_path = tempnam(sys_get_temp_dir(), 'DL');
|
||||
$fp = @fopen($sys_tmp_path, 'w+');
|
||||
fwrite($fp, $fileContent);
|
||||
|
||||
$tmp_path = config('app.ROOT_PATH_PRO').'runtime/temp_file';
|
||||
if(!file_exists($tmp_path)){
|
||||
mkdir($tmp_path, 0777, true);
|
||||
}
|
||||
$targetFile = $tmp_path. '/' .time().$filename;
|
||||
$res = move_uploaded_file($sys_tmp_path, $targetFile);
|
||||
dump($res);die;
|
||||
}
|
||||
$result = [
|
||||
'app_name'=>'',// 应用名称
|
||||
'package'=>'',// 应用包名
|
||||
'version_name'=>'',// 版本名称
|
||||
'version_code'=>'',// 版本代码
|
||||
];
|
||||
|
||||
dump($targetFile);die;
|
||||
if(!is_file($targetFile)){
|
||||
return $result;
|
||||
}
|
||||
$appObj->open($targetFile);//$res
|
||||
|
||||
$result = [
|
||||
'app_name'=>$appObj->getAppName(),// 应用名称
|
||||
'package'=>$appObj->getPackage(),// 应用包名
|
||||
'version_name'=>$appObj->getVersionName(),// 版本名称
|
||||
'version_code'=>$appObj->getVersionCode(),// 版本代码
|
||||
];
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
421
superadmin/vendor/wanghua/general-utility-tools-php/src/apk/ApkParser.php
vendored
Normal file
421
superadmin/vendor/wanghua/general-utility-tools-php/src/apk/ApkParser.php
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {17:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\apk;
|
||||
|
||||
|
||||
use Exception;
|
||||
|
||||
class ApkParser{
|
||||
//----------------------
|
||||
// 公共函数,供外部调用
|
||||
//----------------------
|
||||
public function open($apk_file, $xml_file='AndroidManifest.xml'){
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($apk_file) === TRUE) {
|
||||
$xml = $zip->getFromName($xml_file);
|
||||
$zip->close();
|
||||
if ($xml){
|
||||
try {
|
||||
return $this->parseString($xml);
|
||||
}catch (Exception $e){
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function parseString($xml){
|
||||
$this->xml = $xml;
|
||||
$this->length = strlen($xml);
|
||||
|
||||
$this->root = $this->parseBlock(self::AXML_FILE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getXML($node=NULL, $lv=-1){
|
||||
if ($lv == -1) $node = $this->root;
|
||||
if (!$node) return '';
|
||||
|
||||
if ($node['type'] == self::END_TAG) $lv--;
|
||||
$xml = @($node['line'] == 0 || $node['line'] == $this->line) ? '' : "\n".str_repeat(' ', $lv);
|
||||
$xml .= $node['tag'];
|
||||
$this->line = @$node['line'];
|
||||
foreach ($node['child'] as $c){
|
||||
$xml .= $this->getXML($c, $lv+1);
|
||||
}
|
||||
return $xml;
|
||||
}
|
||||
|
||||
public function getPackage(){
|
||||
return $this->getAttribute('manifest', 'package');
|
||||
}
|
||||
|
||||
public function getVersionName(){
|
||||
return $this->getAttribute('manifest', 'android:versionName');
|
||||
}
|
||||
|
||||
public function getVersionCode(){
|
||||
return $this->getAttribute('manifest', 'android:versionCode');
|
||||
}
|
||||
|
||||
public function getAppName(){
|
||||
return $this->getAttribute('manifest/application', 'android:name');
|
||||
}
|
||||
|
||||
public function getMainActivity(){
|
||||
for ($id=0; true; $id++){
|
||||
$act = $this->getAttribute("manifest/application/activity[{$id}]/intent-filter/action", 'android:name');
|
||||
if (!$act) break;
|
||||
if ($act == 'android.intent.action.MAIN') return $this->getActivity($id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function getActivity($idx=0){
|
||||
$idx = intval($idx);
|
||||
return $this->getAttribute("manifest/application/activity[{$idx}]", 'android:name');
|
||||
}
|
||||
|
||||
public function getAttribute($path, $name){
|
||||
$r = $this->getElement($path);
|
||||
if (is_null($r)) return NULL;
|
||||
|
||||
if (isset($r['attrs'])){
|
||||
foreach ($r['attrs'] as $a){
|
||||
if ($a['ns_name'] == $name) return $this->getAttributeValue($a);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//----------------------
|
||||
// 类型常量定义
|
||||
//----------------------
|
||||
const AXML_FILE = 0x00080003;
|
||||
const STRING_BLOCK = 0x001C0001;
|
||||
const RESOURCEIDS = 0x00080180;
|
||||
const START_NAMESPACE = 0x00100100;
|
||||
const END_NAMESPACE = 0x00100101;
|
||||
const START_TAG = 0x00100102;
|
||||
const END_TAG = 0x00100103;
|
||||
const TEXT = 0x00100104;
|
||||
|
||||
const TYPE_NULL =0;
|
||||
const TYPE_REFERENCE =1;
|
||||
const TYPE_ATTRIBUTE =2;
|
||||
const TYPE_STRING =3;
|
||||
const TYPE_FLOAT =4;
|
||||
const TYPE_DIMENSION =5;
|
||||
const TYPE_FRACTION =6;
|
||||
const TYPE_INT_DEC =16;
|
||||
const TYPE_INT_HEX =17;
|
||||
const TYPE_INT_BOOLEAN =18;
|
||||
const TYPE_INT_COLOR_ARGB8 =28;
|
||||
const TYPE_INT_COLOR_RGB8 =29;
|
||||
const TYPE_INT_COLOR_ARGB4 =30;
|
||||
const TYPE_INT_COLOR_RGB4 =31;
|
||||
|
||||
const UNIT_MASK = 15;
|
||||
private static $RADIX_MULTS = array(0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010);
|
||||
private static $DIMENSION_UNITS = array("px","dip","sp","pt","in","mm","","");
|
||||
private static $FRACTION_UNITS = array("%","%p","","","","","","");
|
||||
|
||||
private $xml='';
|
||||
private $length = 0;
|
||||
private $stringCount = 0;
|
||||
private $styleCount = 0;
|
||||
private $stringTab = array();
|
||||
private $styleTab = array();
|
||||
private $resourceIDs = array();
|
||||
private $ns = array();
|
||||
private $cur_ns = NULL;
|
||||
private $root = NULL;
|
||||
private $line = 0;
|
||||
|
||||
//----------------------
|
||||
// 内部私有函数
|
||||
//----------------------
|
||||
private function getElement($path){
|
||||
if (!$this->root) return NULL;
|
||||
$ps = explode('/', $path);
|
||||
$r = $this->root;
|
||||
foreach ($ps as $v){
|
||||
if (preg_match('/([^\[]+)\[([0-9]+)\]$/', $v, $ms)){
|
||||
$v = $ms[1];
|
||||
$off = $ms[2];
|
||||
}else {
|
||||
$off = 0;
|
||||
}
|
||||
foreach ($r['child'] as $c){
|
||||
if ($c['type'] == self::START_TAG && $c['ns_name'] == $v){
|
||||
if ($off == 0){
|
||||
$r = $c; continue 2;
|
||||
}else {
|
||||
$off--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 没有找到节点
|
||||
return NULL;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
private function parseBlock($need = 0){
|
||||
$o = 0;
|
||||
$type = $this->get32($o);
|
||||
if ($need && $type != $need) throw new Exception('Block Type Error', 1);
|
||||
$size = $this->get32($o);
|
||||
if ($size < 8 || $size > $this->length) throw new Exception('Block Size Error', 2);
|
||||
$left = $this->length - $size;
|
||||
|
||||
$props = false;
|
||||
switch ($type){
|
||||
case self::AXML_FILE:
|
||||
$props = array(
|
||||
'line' => 0,
|
||||
'tag' => '<?xml version="1.0" encoding="utf-8"?>'
|
||||
);
|
||||
break;
|
||||
case self::STRING_BLOCK:
|
||||
$this->stringCount = $this->get32($o);
|
||||
$this->styleCount = $this->get32($o);
|
||||
$o += 4;
|
||||
$strOffset = $this->get32($o);
|
||||
$styOffset = $this->get32($o);
|
||||
$strListOffset = $this->get32array($o, $this->stringCount);
|
||||
$styListOffset = $this->get32array($o, $this->styleCount);
|
||||
$this->stringTab = $this->stringCount > 0 ? $this->getStringTab($strOffset, $strListOffset) : array();
|
||||
$this->styleTab = $this->styleCount > 0 ? $this->getStringTab($styOffset, $styListOffset) : array();
|
||||
$o = $size;
|
||||
break;
|
||||
case self::RESOURCEIDS:
|
||||
$count = $size / 4 - 2;
|
||||
$this->resourceIDs = $this->get32array($o, $count);
|
||||
break;
|
||||
case self::START_NAMESPACE:
|
||||
$o += 8;
|
||||
$prefix = $this->get32($o);
|
||||
$uri = $this->get32($o);
|
||||
|
||||
if (empty($this->cur_ns)){
|
||||
$this->cur_ns = array();
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
}
|
||||
$this->cur_ns[$uri] = $prefix;
|
||||
break;
|
||||
case self::END_NAMESPACE:
|
||||
$o += 8;
|
||||
$prefix = $this->get32($o);
|
||||
$uri = $this->get32($o);
|
||||
|
||||
if (empty($this->cur_ns)) break;
|
||||
unset($this->cur_ns[$uri]);
|
||||
break;
|
||||
case self::START_TAG:
|
||||
$line = $this->get32($o);
|
||||
|
||||
$o += 4;
|
||||
$attrs = array();
|
||||
$props = array(
|
||||
'line' => $line,
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o)),
|
||||
'flag' => $this->get32($o),
|
||||
'count' => $this->get16($o),
|
||||
'id' => $this->get16($o)-1,
|
||||
'class' => $this->get16($o)-1,
|
||||
'style' => $this->get16($o)-1,
|
||||
'attrs' => &$attrs
|
||||
);
|
||||
$props['ns_name'] = $props['ns'].$props['name'];
|
||||
for ($i=0; $i < $props['count']; $i++){
|
||||
$a = array(
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o)),
|
||||
'val_str' => $this->get32($o),
|
||||
'val_type' => $this->get32($o),
|
||||
'val_data' => $this->get32($o)
|
||||
);
|
||||
$a['ns_name'] = $a['ns'].$a['name'];
|
||||
$a['val_type'] >>= 24;
|
||||
$attrs[] = $a;
|
||||
}
|
||||
// 处理TAG字符串
|
||||
$tag = "<{$props['ns_name']}";
|
||||
foreach ($this->cur_ns as $uri => $prefix){
|
||||
$uri = $this->getString($uri);
|
||||
$prefix = $this->getString($prefix);
|
||||
$tag .= " xmlns:{$prefix}=\"{$uri}\"";
|
||||
}
|
||||
foreach ($props['attrs'] as $a){
|
||||
$tag .= " {$a['ns_name']}=\"".
|
||||
$this->getAttributeValue($a).
|
||||
'"';
|
||||
}
|
||||
$tag .= '>';
|
||||
$props['tag'] = $tag;
|
||||
|
||||
unset($this->cur_ns);
|
||||
$this->cur_ns = array();
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
$left = -1;
|
||||
break;
|
||||
case self::END_TAG:
|
||||
$line = $this->get32($o);
|
||||
$o += 4;
|
||||
$props = array(
|
||||
'line' => $line,
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o))
|
||||
);
|
||||
$props['ns_name'] = $props['ns'].$props['name'];
|
||||
$props['tag'] = "</{$props['ns_name']}>";
|
||||
if (count($this->ns) > 1){
|
||||
array_pop($this->ns);
|
||||
unset($this->cur_ns);
|
||||
$this->cur_ns = array_pop($this->ns);
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
}
|
||||
break;
|
||||
case self::TEXT:
|
||||
$o += 8;
|
||||
$props = array(
|
||||
'tag' => $this->getString($this->get32($o))
|
||||
);
|
||||
$o += 8;
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Block Type Error', 3);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->skip($o);
|
||||
$child = array();
|
||||
while ($this->length > $left){
|
||||
$c = $this->parseBlock();
|
||||
if ($props && $c) $child[] = $c;
|
||||
if ($left == -1 && $c['type'] == self::END_TAG){
|
||||
$left = $this->length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this->length != $left) throw new Exception('Block Overflow Error', 4);
|
||||
if ($props){
|
||||
$props['type'] = $type;
|
||||
$props['size'] = $size;
|
||||
$props['child'] = $child;
|
||||
return $props;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getAttributeValue($a){
|
||||
$type = &$a['val_type'];
|
||||
$data = &$a['val_data'];
|
||||
switch ($type){
|
||||
case self::TYPE_STRING:
|
||||
return $this->getString($a['val_str']);
|
||||
case self::TYPE_ATTRIBUTE:
|
||||
return sprintf('?%s%08X', self::_getPackage($data), $data);
|
||||
case self::TYPE_REFERENCE:
|
||||
return sprintf('@%s%08X', self::_getPackage($data), $data);
|
||||
case self::TYPE_INT_HEX:
|
||||
return sprintf('0x%08X', $data);
|
||||
case self::TYPE_INT_BOOLEAN:
|
||||
return ($data != 0 ? 'true' : 'false');
|
||||
case self::TYPE_INT_COLOR_ARGB8:
|
||||
case self::TYPE_INT_COLOR_RGB8:
|
||||
case self::TYPE_INT_COLOR_ARGB4:
|
||||
case self::TYPE_INT_COLOR_RGB4:
|
||||
return sprintf('#%08X', $data);
|
||||
case self::TYPE_DIMENSION:
|
||||
return $this->_complexToFloat($data).self::$DIMENSION_UNITS[$data & self::UNIT_MASK];
|
||||
case self::TYPE_FRACTION:
|
||||
return $this->_complexToFloat($data).self::$FRACTION_UNITS[$data & self::UNIT_MASK];
|
||||
case self::TYPE_FLOAT:
|
||||
return $this->_int2float($data);
|
||||
}
|
||||
if ($type >=self::TYPE_INT_DEC && $type < self::TYPE_INT_COLOR_ARGB8){
|
||||
return (string)$data;
|
||||
}
|
||||
return sprintf('<0x%X, type 0x%02X>', $data, $type);
|
||||
}
|
||||
|
||||
private function _complexToFloat($data){
|
||||
return (float)($data & 0xFFFFFF00) * self::$RADIX_MULTS[($data>>4) & 3];
|
||||
}
|
||||
private function _int2float($v) {
|
||||
$x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
|
||||
$exp = ($v >> 23 & 0xFF) - 127;
|
||||
return $x * pow(2, $exp - 23);
|
||||
}
|
||||
private static function _getPackage($data){
|
||||
return ($data >> 24 == 1) ? 'android:' : '';
|
||||
}
|
||||
|
||||
private function getStringTab($base, $list){
|
||||
$tab = array();
|
||||
foreach ($list as $off){
|
||||
$off += $base;
|
||||
$len = $this->get16($off);
|
||||
$mask = ($len >> 0x8) & 0xFF;
|
||||
$len = $len & 0xFF;
|
||||
if ($len == $mask){
|
||||
if ($off + $len > $this->length) throw new Exception('String Table Overflow', 11);
|
||||
$tab[] = substr($this->xml, $off, $len);
|
||||
}else {
|
||||
if ($off + $len * 2 > $this->length) throw new Exception('String Table Overflow', 11);
|
||||
$str = substr($this->xml, $off, $len * 2);
|
||||
$tab[] = mb_convert_encoding($str, 'UTF-8', 'UCS-2LE');
|
||||
}
|
||||
}
|
||||
return $tab;
|
||||
}
|
||||
private function getString($id){
|
||||
if ($id > -1 && $id < $this->stringCount){
|
||||
return $this->stringTab[$id];
|
||||
}else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
private function getNameSpace($uri){
|
||||
for ($i=count($this->ns); $i > 0; ){
|
||||
$ns = $this->ns[--$i];
|
||||
if (isset($ns[$uri])){
|
||||
$ns = $this->getString($ns[$uri]);
|
||||
if (!empty($ns)) $ns .= ':';
|
||||
return $ns;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
private function get32(&$off){
|
||||
$int = unpack('V', substr($this->xml, $off, 4));
|
||||
$off += 4;
|
||||
return array_shift($int);
|
||||
}
|
||||
private function get32array(&$off, $size){
|
||||
if ($size <= 0) return NULL;
|
||||
$arr = unpack('V*', substr($this->xml, $off, 4 * $size));
|
||||
if (count($arr) != $size) throw new Exception('Array Size Error', 10);
|
||||
$off += 4 * $size;
|
||||
return $arr;
|
||||
}
|
||||
private function get16(&$off){
|
||||
$int = unpack('v', substr($this->xml, $off, 2));
|
||||
$off += 2;
|
||||
return array_shift($int);
|
||||
}
|
||||
private function skip($size){
|
||||
$this->xml = substr($this->xml, $size);
|
||||
$this->length -= $size;
|
||||
}
|
||||
}
|
||||
103
superadmin/vendor/wanghua/general-utility-tools-php/src/coin/Coin.php
vendored
Normal file
103
superadmin/vendor/wanghua/general-utility-tools-php/src/coin/Coin.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/3/19} {13:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\coin;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
|
||||
class Coin
|
||||
{
|
||||
|
||||
public $apiKey = 'f94a2a9c-28be-47c3aaa-9c29-1e83b309d076';
|
||||
public $url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest';
|
||||
|
||||
|
||||
/**
|
||||
* desc:
|
||||
'limit'=>'1000',
|
||||
'sort'=>'market_cap',
|
||||
'sort_dir'=>'desc',
|
||||
* @param array $params
|
||||
* @return array|bool|int|string
|
||||
*/
|
||||
function getAll(array $params){
|
||||
$params_str = http_build_query($params);
|
||||
$url = $this->url.'?'.$params_str;
|
||||
|
||||
$header = [
|
||||
'X-CMC_PRO_API_KEY:'.$this->apiKey,
|
||||
'accept: application/json',
|
||||
];
|
||||
|
||||
return Curl::curl_get($url,10,$header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:
|
||||
*
|
||||
*https://coinmarketcap.com/api/documentation/v1/#section/Introduction
|
||||
* 'https://pro-api.coinmarketcap.com/v2/cryptocurrency/ohlcv/historical'
|
||||
* author:wh
|
||||
*/
|
||||
function k(){
|
||||
$url = $this->url;
|
||||
$time_start = input('time_start');
|
||||
$time_end = input('time_end');
|
||||
$type = input('type');
|
||||
|
||||
$header = [
|
||||
'X-CMC_PRO_API_KEY:'.$this->apiKey,
|
||||
];
|
||||
|
||||
$arr = explode('=',$type);
|
||||
$params = [
|
||||
$arr[0]=>$arr[1],//币种
|
||||
'time_start'=>$time_start,
|
||||
'time_end'=>$time_end,
|
||||
'count'=>7,
|
||||
];
|
||||
|
||||
$url = $url.'?'.http_build_query($params);
|
||||
|
||||
return Curl::curl_get($url,10,$header);
|
||||
}
|
||||
|
||||
private function curl_request($url, $method = 'GET',$data=null,$header=array(),$call_back=null)
|
||||
{
|
||||
set_time_limit(30);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
}
|
||||
if($method == 'POST'){
|
||||
if($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
if($call_back){
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $call_back);
|
||||
}
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return [
|
||||
'status' => 'error',
|
||||
'message' => 'curl 错误信息: ' . curl_error($ch)
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
390
superadmin/vendor/wanghua/general-utility-tools-php/src/db/DbCacheUtility.php
vendored
Normal file
390
superadmin/vendor/wanghua/general-utility-tools-php/src/db/DbCacheUtility.php
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/12/17} {14:30}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
use wanghua\db\general_utility_tools_php\SqlOperateLog;
|
||||
use think\Container;
|
||||
use think\Db;
|
||||
use think\Paginator;
|
||||
|
||||
/**
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
*
|
||||
* 查询缓存器、监控器
|
||||
* 【使用框架链式操作时,配合此类才能发挥完美效果】
|
||||
* 举例
|
||||
* function getMemberInIds(string $ids){
|
||||
$obj = Db::name($this->table)->whereIn("id",$ids)->where(["is_deleted"=>0]);
|
||||
return DbCacheUtility::getAll($obj);
|
||||
}
|
||||
* Class DbCacheUtility
|
||||
* @package libraries
|
||||
*/
|
||||
class DbCacheUtility
|
||||
{
|
||||
const NoCacheTime = 0;
|
||||
const LowCacheTime = 60 * 1;
|
||||
const NormalCacheTime = 60 * 10;
|
||||
const HighCacheTime = 60 * 60;
|
||||
const LongCacheTime = 60 * 60 * 24;
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object 查询对象
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getOne($object, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->fetchSql(true)->find();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'get_one:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->find();
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'get_one', $is_cache);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object 查询对象
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getAll($object, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->fetchSql(true)->select();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'get_all:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->select();
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'get_all', $is_cache);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object
|
||||
* @param int $page
|
||||
* @param int $listRows
|
||||
* @param bool $simple
|
||||
* @param array $config
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
static function paginates($object, $page=1, $listRows = null, $simple = false, $config = [], $cacheDuration = self::NoCacheTime, $is_log = true){
|
||||
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->limit(abs(1*$page-1) * $listRows, $listRows)->fetchSql(true)->select();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'paginates:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->paginate($listRows, $simple, $config);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'paginates', $is_cache);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryScalar($sql, $bind = [], $field, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_scalar:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_scalar', $is_cache);
|
||||
}
|
||||
|
||||
return $result ? $result[0][$field] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryOne($sql, $bind = [], $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_one:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_one', $is_cache);
|
||||
}
|
||||
|
||||
return $result ? $result[0] : [];
|
||||
}
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryAll($sql, $bind = [], $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
//echo $last_sql;die;
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_all:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_all', $is_cache);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return int
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function execute($sql, $bind = []){
|
||||
return Db::execute($sql, $bind);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
*/
|
||||
static function presetBind($sql, $bind = []){
|
||||
if($bind){
|
||||
foreach ($bind as $key=>$val){
|
||||
$sql = str_replace(':'.$key, $val, $sql);
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
static function paginate($sql, $bind, $total, $listRows = null, $simple = false, $config = [])
|
||||
{
|
||||
//if (is_int($simple)) {
|
||||
// $total = $simple;
|
||||
// $simple = false;
|
||||
//}
|
||||
|
||||
$paginate = Container::get('config')->pull('paginate');
|
||||
|
||||
if (is_array($listRows)) {
|
||||
$config = array_merge($paginate, $listRows);
|
||||
$listRows = $config['list_rows'];
|
||||
} else {
|
||||
$config = array_merge($paginate, $config);
|
||||
$listRows = $listRows ?: $config['list_rows'];
|
||||
}
|
||||
|
||||
/** @var Paginator $class */
|
||||
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\paginator\\driver\\' . ucwords($config['type']);
|
||||
$page = isset($config['page']) ? (int) $config['page'] : call_user_func([
|
||||
$class,
|
||||
'getCurrentPage',
|
||||
], $config['var_page']);
|
||||
|
||||
$page = $page < 1 ? 1 : $page;
|
||||
|
||||
$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);
|
||||
|
||||
//if (!isset($total) && !$simple) {
|
||||
//
|
||||
//
|
||||
// unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
||||
//
|
||||
// $bind = $this->bind;
|
||||
// $total = $this->count();
|
||||
// $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
|
||||
//} elseif ($simple) {
|
||||
// $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
|
||||
// $total = null;
|
||||
//} else {
|
||||
// $results = $this->page($page, $listRows)->select();
|
||||
//}
|
||||
|
||||
$results = DbCacheUtility::queryAll($sql, $bind);
|
||||
|
||||
return $class::make($results, $listRows, $page, $total, $simple, $config);
|
||||
}
|
||||
}
|
||||
109
superadmin/vendor/wanghua/general-utility-tools-php/src/db/RedisUtility.php
vendored
Normal file
109
superadmin/vendor/wanghua/general-utility-tools-php/src/db/RedisUtility.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/5/22} {16:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\cache\driver\Redis as RedisDriver;
|
||||
use think\Db;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* Redis操作工具
|
||||
*
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
*
|
||||
* Class RedisUtility
|
||||
* @package libraries
|
||||
*/
|
||||
class RedisUtility
|
||||
{
|
||||
protected static $redisHandle = null;
|
||||
|
||||
/**
|
||||
* desc:初始化Redis对象
|
||||
* author:wh
|
||||
* @return object|null
|
||||
*/
|
||||
static function redisObject(){
|
||||
if(empty(self::$redisHandle)){
|
||||
//初始化驱动拿到句柄
|
||||
self::$redisHandle = (new RedisDriver(config('cache.redis')))->handler();
|
||||
}
|
||||
return self::$redisHandle;
|
||||
}
|
||||
/**
|
||||
* desc:设置 0 永久有效
|
||||
* author:wh
|
||||
* @param $key_name 键名
|
||||
* @param $value 值 json数据
|
||||
* @return bool
|
||||
*/
|
||||
static function set($key_name, $value){
|
||||
return Cache::store('redis')->set($key_name, json_encode($value, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:重置
|
||||
* author:wh
|
||||
* @param $key_name
|
||||
* @return bool
|
||||
*/
|
||||
static function reset($key_name){
|
||||
return Cache::store('redis')->set($key_name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置过期时间
|
||||
* author:wh
|
||||
* @param $key_name 键名
|
||||
* @param $value 值 json数据
|
||||
* @param int $expire 过期时间 0 永久有效
|
||||
* @return bool
|
||||
*/
|
||||
static function setExpire($key_name, $value, $expire=0){
|
||||
return Cache::store('redis')->set($key_name, json_encode($value), $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:存储hash类型
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @param $field
|
||||
* @param $value
|
||||
*/
|
||||
static function hSet($key, $field, $value){
|
||||
return self::redisObject()->hSet($key, $field, json_encode($value, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除指定的键。
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
static function delete($key){
|
||||
return self::redisObject()->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:从存储在键上的哈希中移除一个值。
|
||||
* 如果哈希表不存在,或者键不存在,则返回 FALSE 。
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @param $hashKey1
|
||||
* @return mixed
|
||||
*/
|
||||
static function hDel($key, $hashKey1){
|
||||
return self::redisObject()->hDel($key, $hashKey1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
55
superadmin/vendor/wanghua/general-utility-tools-php/src/db/SqlOperateLog.php
vendored
Normal file
55
superadmin/vendor/wanghua/general-utility-tools-php/src/db/SqlOperateLog.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/10/31} {9:25}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\Db;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
* 日志操作类,配合DbCacheUtility.php使用。
|
||||
* 使用前先在系统config.php文件中添加配置:
|
||||
* 1、is_sql_slow_log:是否记录sql慢日志,true or false
|
||||
* 2、新建表(log_sql_operate)字段:action,is_cache,duration_time,type,is_cache,sql,md5_name
|
||||
* 3、如果什么错都没有报,但是程序就是没反应,则去runtime目录中找错误。
|
||||
*
|
||||
* Class SqlOperateLog
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class SqlOperateLog
|
||||
{
|
||||
|
||||
static function add($sql,$end_time,$begin_time,$md5_name,$type,$is_cache){
|
||||
$data = [
|
||||
'action'=>request()->baseUrl(),
|
||||
'duration_time'=>$end_time - $begin_time,
|
||||
'type'=>$type,
|
||||
'is_cache'=>$is_cache?1:0,
|
||||
'sql'=>$sql,
|
||||
'md5_name'=>$md5_name,
|
||||
];
|
||||
try{
|
||||
if(config('app.is_sql_slow_log') && ($end_time - $begin_time) >= config('app.is_sql_slow_log')){
|
||||
Db::table('log_sql_operate')->insert($data);
|
||||
}
|
||||
}catch (\Exception $e){
|
||||
//DATABASE BOOM
|
||||
//tp6
|
||||
//Log::error('========[数据库异常:DATABASE BOOM]========'.$e->getTraceAsString());
|
||||
//Log::close();
|
||||
//tp5.1
|
||||
Log::write('========[DATABASE ERROR:DATABASE BOOM]========【'.$e->getMessage().'】'.$e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
262
superadmin/vendor/wanghua/general-utility-tools-php/src/db/es/Elasticsearch.php
vendored
Normal file
262
superadmin/vendor/wanghua/general-utility-tools-php/src/db/es/Elasticsearch.php
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/26} {9:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\es;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Date;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 【es原生操作库】
|
||||
* 【仅支持框架ThinkPHP5+、 PHP7.2+】
|
||||
*
|
||||
* BaseElasticsearch.php类库的替代库
|
||||
*
|
||||
* 使用步骤:
|
||||
* 初始化(设置ip、索引前缀-普通索引请设置为空字符串)
|
||||
* 设置索引范围(例如查询本月,如果索引不是按日期规律设置,请使用普通索引设置方法setIndexNormal,并设置前缀为空字符串)
|
||||
* 设置查询方法(eg: _search)
|
||||
* 设置查询参数(查询条件)
|
||||
* 执行
|
||||
* 返回结果
|
||||
* Class ElasticsearchUtility
|
||||
* @package app\admin\logic
|
||||
*/
|
||||
class Elasticsearch
|
||||
{
|
||||
protected $es_log_file = 'es_log';
|
||||
//最终拼装的请求地址
|
||||
protected $post_url = ''; //eg: $url = 'http://49.4.3.4:9111/qa-item-2021.04/_search';
|
||||
//查询参数
|
||||
protected $query_param = [];
|
||||
//查询方法
|
||||
protected $query_method = '_search';
|
||||
//文档索引
|
||||
protected $index = '';
|
||||
//服务器ip
|
||||
protected $ip = '';
|
||||
//索引前缀(优先设置)
|
||||
protected $index_sign = '';//eg: qa-stat-
|
||||
//设置查询日期格式符号
|
||||
protected $doc_date_sign = '.';
|
||||
//设置是哪个方法调用本es库,用于日志记录
|
||||
protected $exe_func = '';
|
||||
|
||||
|
||||
/**
|
||||
* ElasticsearchUtility constructor.
|
||||
* @param string $ip_port 协议+服务器ip+端口号,必须
|
||||
* @param string $index_sign 当es索引为有规律的日期索引时,可使用前缀并配合日期索引设置方法,体验更佳
|
||||
*/
|
||||
public function __construct(string $ip_port, string $index_sign='')
|
||||
{
|
||||
$this->ip = false===strpos($ip_port,'http')?'http://'.$ip_port:$ip_port;
|
||||
$this->index_sign = $index_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置查询方法,默认_search
|
||||
* author:wh
|
||||
* @param $method_name
|
||||
*/
|
||||
function setQueryMethod($method_name){
|
||||
$this->query_method = $method_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:根据日期索引查询文档
|
||||
* 注:默认一个月
|
||||
*
|
||||
* eg:'qa-stat-2021.01';
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
* author:wh
|
||||
*/
|
||||
function setIndexDefault(){
|
||||
$this->setRequestIndex(date('Y'.$this->doc_date_sign.'m'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置要查询的日期文档索引
|
||||
*
|
||||
* 1、按年检索文档[建议5年左右]
|
||||
*
|
||||
* eg: qa-stat-2018.*,qa-stat-2019.*,qa-stat-2020.*,qa-stat-2021.*
|
||||
*
|
||||
* 注意:当索引过长,es会抛出索引太长异常
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间 eg:2010-01-01 08:05:55
|
||||
* @param string $end_time 结束时间 eg:2021-12-31 12:05:00
|
||||
* @return string
|
||||
*/
|
||||
function setIndexYearDate(string $start_time, string $end_time){
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'*', strtotime($start_time));
|
||||
|
||||
$sign = ',';//分隔符
|
||||
|
||||
$m = date('Y', strtotime($end_time)) - date('Y', strtotime($start_time));
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
|
||||
$index .= $sign.($this->index_sign.(date('Y', strtotime($start_time))+$i).$this->doc_date_sign.'*');
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日期索引
|
||||
*
|
||||
* 检索全部日期索引文档
|
||||
*
|
||||
* 例如es设置的索引为:
|
||||
* qa-stat-2021.01
|
||||
qa-stat-2021.02
|
||||
qa-stat-2021.03
|
||||
qa-stat-2021.04
|
||||
*
|
||||
* 实际查询自动设置为:qa-stat-*
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function setIndexAllDate(){
|
||||
|
||||
$this->setRequestIndex('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置普通索引
|
||||
*
|
||||
* 调用此方法,请在初始化时,设置索引前缀index_sign为""空字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
function setIndexNormal(string $index){
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置跨月份索引
|
||||
*
|
||||
* eg: qa-stat-2021.01,qa-stat-2021.02
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time eg:'2020-11'
|
||||
* @param string $end_time eg:'2021-01'
|
||||
* @return string eg: qa-stat-2020.11,qa-stat-2020.12,qa-stat-2021.01
|
||||
*/
|
||||
function setIndexDate(string $start_time, string $end_time){
|
||||
$date = new Date();
|
||||
|
||||
//计算月份
|
||||
$m = $date->dateCutMonth($start_time, $end_time);
|
||||
////解决跨年且不足1个月时,索引设置错误问题
|
||||
//if($m == 0 && (date('Y', strtotime($end_time)) > date('Y', strtotime($start_time)))){
|
||||
// $m = 1;
|
||||
//}
|
||||
//格式
|
||||
$date->date_format = 'Y-m';
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'m', strtotime($start_time));
|
||||
|
||||
$tmp_time = $start_time;
|
||||
$sign = ',';//分隔符
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
$tmp_time = $date->addTime(1, 'M', strtotime($tmp_time));
|
||||
$index .= $sign.$this->index_sign.(date('Y'.$this->doc_date_sign.'m', strtotime($tmp_time)));
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:设置查询参数
|
||||
* author:wh
|
||||
* @param string $query_param_json
|
||||
*/
|
||||
function setQueryParam(string $query_param_json){
|
||||
$this->query_param = $query_param_json;
|
||||
$this->post_url = $this->ip.'/'.$this->index.'/'.$this->query_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取查询参数,用于调试
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getQueryParam(){
|
||||
return [
|
||||
'ip'=>$this->ip,
|
||||
'index_sign'=>$this->index_sign,
|
||||
'index'=>$this->index,
|
||||
'query_method'=>$this->query_method,
|
||||
'post_url'=>$this->post_url,
|
||||
'query_param'=>$this->query_param,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:执行es查询
|
||||
* author:wh
|
||||
* @return array|bool|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function execute(){
|
||||
if(empty($this->ip)) throw new \Exception('请设置ip');
|
||||
//if(empty($this->index_sign)) throw new \Exception('请设置索引前缀');
|
||||
if(empty($this->index)) throw new \Exception('请设置索引');
|
||||
if(empty($this->query_method)) throw new \Exception('请设置查询方法');
|
||||
if(empty($this->query_param)) throw new \Exception('请设置查询参数');
|
||||
|
||||
|
||||
|
||||
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'request_url'=>$this->post_url,'IN'=>" | IN: ",'query_params'=>$this->query_param, 'input'=>input()], $this->es_log_file);
|
||||
$result = Tools::curl_post($this->post_url, $this->query_param);
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'OUT'=>" | OUT: ", 'result'=>$result], $this->es_log_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置是哪个方法调用本es库,用于日志记录
|
||||
* author:wh
|
||||
* @param string $function
|
||||
*/
|
||||
function setExecuteFunction(string $function){
|
||||
$this->exe_func = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置请求文档索引
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
protected function setRequestIndex(string $index){
|
||||
$this->index = $this->index_sign.$index;
|
||||
}
|
||||
|
||||
}
|
||||
1340
superadmin/vendor/wanghua/general-utility-tools-php/src/db/es/README.md
vendored
Normal file
1340
superadmin/vendor/wanghua/general-utility-tools-php/src/db/es/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
superadmin/vendor/wanghua/general-utility-tools-php/src/db/mysql/README.MD
vendored
Normal file
6
superadmin/vendor/wanghua/general-utility-tools-php/src/db/mysql/README.MD
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
## 仅适用于tp5+, php7+
|
||||
|
||||
|
||||
## 表管理
|
||||
|
||||
## 字段管理
|
||||
304
superadmin/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Field.php
vendored
Normal file
304
superadmin/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Field.php
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\mysql\lib;
|
||||
|
||||
|
||||
use think\Db;
|
||||
|
||||
class Field
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:创建字段,存在则修改字段
|
||||
* author:wh
|
||||
* @param array $table
|
||||
*/
|
||||
function createfield(array $table){
|
||||
$table_name = $table['tablename'];
|
||||
//新增字段
|
||||
$dec_num = '';
|
||||
|
||||
if(in_array(strtoupper($table['type']), ['TINYINT','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL'])){
|
||||
$table['default'] = '0';//整型默认值 浮点类型自动转为0.00
|
||||
if(in_array(strtoupper($table['type']), ['FLOAT','DOUBLE','DECIMAL'])){
|
||||
$dec_num = ','.$table['decimals_size'];//浮点类型小数位位数
|
||||
}
|
||||
}elseif ($table['type'] == 'enum'){
|
||||
//枚举值不转换
|
||||
}else{
|
||||
$table['default'] = '""';
|
||||
}
|
||||
|
||||
if(in_array(strtolower($table['type']), ['timestamp','datetime','date','time','text','mediumtext','longtext'])){
|
||||
$table['size'] = 0;//重写 默认0
|
||||
$table['default'] = 'null';//重写
|
||||
}
|
||||
//是否可以负数
|
||||
if(in_array(strtolower($table['type']), ['int','tinyint','bigint','smallint', 'double', 'float', 'decimal']) && !empty($post['is_unsigned'])){//不是
|
||||
$is_unsigned = 'unsigned';
|
||||
}else{//是 表单可选值
|
||||
$is_unsigned = '';
|
||||
}
|
||||
|
||||
if (in_array($table['fields_name'], ['create_time', 'update_time'])){
|
||||
if($table['fields_name'] == 'create_time'){
|
||||
$table['default'] = 'CURRENT_TIMESTAMP';
|
||||
}
|
||||
if($table['fields_name'] == 'update_time'){
|
||||
$table['default'] = 'NULL ON UPDATE CURRENT_TIMESTAMP';
|
||||
}
|
||||
}
|
||||
//验证字段是否存在
|
||||
$f = DB::table($table_name)->getTableFields();
|
||||
if(in_array($table['fields_name'], $f)){
|
||||
//枚举类型
|
||||
if ($table['type'] == 'enum'){
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}';";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}';";
|
||||
}
|
||||
}else{
|
||||
|
||||
if(in_array($table['type'], ['text','longtext'])){
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}elseif ($table['type'] == 'enum'){//枚举类型
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}' AFTER id;";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}
|
||||
}
|
||||
|
||||
DB::execute($sql2);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除字段
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $fieldname
|
||||
*/
|
||||
function dropFieldName($tablename, $fieldname){
|
||||
$sql = "ALTER TABLE {$tablename} DROP COLUMN {$fieldname};";
|
||||
DB::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename,$field, $comment){
|
||||
|
||||
$sql = "ALTER TABLE {$tablename} MODIFY COLUMN {$field} INT COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中所有字段的数据类型(含其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldsDataType(string $dbname,string $tablename){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'";
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型(含这个字段的其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataType(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型
|
||||
*
|
||||
* 不含这个字段的其它属性
|
||||
*
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataTypeVal(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0]['F_DATATYPE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的属性
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldAttrVal(string $dbname,string $tablename,string $fieldname,string $attr){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0][$attr];
|
||||
}
|
||||
}
|
||||
162
superadmin/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Table.php
vendored
Normal file
162
superadmin/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Table.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\mysql\lib;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Table
|
||||
{
|
||||
/**
|
||||
* desc:创建表,初始化默认字段
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
function createTable($data){
|
||||
$tablename = $data['tablename'];
|
||||
$title = $data['title'];
|
||||
//创建表
|
||||
$sql = "CREATE TABLE IF NOT EXISTS {$tablename}(
|
||||
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
update_time timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY key(id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='{$title}' ;";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename, $comment){
|
||||
$sql = "ALTER TABLE {$tablename} COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改表名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $new_table_name
|
||||
* @return bool
|
||||
*/
|
||||
function updateTableName($tablename, $new_table_name){
|
||||
$sql = "ALTER TABLE {$tablename} RENAME TO {$new_table_name}";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询当前数据库所有的表名
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTables(){
|
||||
return array_column(Db::query('SHOW TABLES;'), 'Tables_in_'.config('database.database'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表字所有段名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return array
|
||||
*/
|
||||
function getTableFields($tablename){
|
||||
$dbname = config('database.database');
|
||||
$sql = "SELECT COLUMN_NAME column_name,COLUMN_COMMENT column_comment,DATA_TYPE data_type
|
||||
FROM information_schema.columns WHERE TABLE_NAME='{$tablename}' AND table_schema='{$dbname}'";
|
||||
return array_column(Db::query($sql), 'column_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表的属性
|
||||
* Name:
|
||||
表名称
|
||||
Engine:
|
||||
表的存储引擎
|
||||
Version:
|
||||
版本
|
||||
Row_format:
|
||||
行格式。对于MyISAM引擎,这可能是Dynamic,Fixed或Compressed。动态行的行长度可变,例如Varchar或Blob类型字段。固定行是指行长度不变,例如Char和Integer类型字段
|
||||
Rows:
|
||||
表中的行数。对于MyISAM和其他存储引擎,这个值是精确的,对于innoDB存储引擎,这个值通常是估算的
|
||||
Avg_row_length:
|
||||
平均每行包括的字节数
|
||||
Data_length:
|
||||
整个表的数据量(以字节为单位)
|
||||
Max_data_length:
|
||||
表可以容纳的最大数据量,该值和存储引擎相关
|
||||
Index_length:
|
||||
索引占用磁盘的空间大小(以字节为单位)
|
||||
Data_free:
|
||||
对于MyISAM引擎,表示已经分配,但目前没有使用的空间。这部分空间包含之前被删除的行,以及后续可以被insert利用到的空间
|
||||
Auto_increment:
|
||||
下一个Auto_increment的值
|
||||
Create_time:
|
||||
表的创建时间
|
||||
Update_time:
|
||||
表的最近更新时间
|
||||
Check_time:
|
||||
使用 check table 或myisamchk工具最后一次检查表的时间
|
||||
Collation:
|
||||
表的默认字符集和字符排序规则
|
||||
Checksum:
|
||||
如果启用,保存的是整个表的实时校验和
|
||||
Create_options:
|
||||
创建表时指定的其他选项
|
||||
Comment:
|
||||
包含了其他额外信息,对于MyISAM引擎,保存的是表在创建时带的注释。如果表使用的是innodb引擎 ,保存的是InnoDB表空间的剩余空间。如果是一个视图,注释里面包含了VIEW字样。
|
||||
*
|
||||
* @param $tablename 表名(无表名则查询所有表)
|
||||
*
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTableInfo(string $tablename=''){
|
||||
if($tablename){
|
||||
$sql = "SHOW TABLE STATUS WHERE Name = 'fa_agent';";
|
||||
return Db::query($sql);
|
||||
}
|
||||
$sql = 'show table status;';
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:检查某个表是否存在
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @return bool
|
||||
*/
|
||||
function isExistTable(string $dbname,string $tablename){
|
||||
$sql = "SELECT TABLE_SCHEMA,TABLE_NAME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA ='$dbname'
|
||||
AND TABLE_NAME = '$tablename';";
|
||||
return empty(Db::query($sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表注释
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getTableComment($table){
|
||||
$prefix = config('database.prefix');
|
||||
$table = $prefix.$table;
|
||||
$sql = 'show table status;';
|
||||
$arr = Db::query($sql);
|
||||
$tmp = Tools::key_val_arr($arr,'Name','Comment');
|
||||
return empty($tmp[$table])?'':$tmp[$table];
|
||||
}
|
||||
}
|
||||
15
superadmin/vendor/wanghua/general-utility-tools-php/src/douyin/BaseDouYin.php
vendored
Normal file
15
superadmin/vendor/wanghua/general-utility-tools-php/src/douyin/BaseDouYin.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/4/5} {10:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\douyin;
|
||||
|
||||
|
||||
class BaseDouYin
|
||||
{
|
||||
|
||||
}
|
||||
193
superadmin/vendor/wanghua/general-utility-tools-php/src/douyin/DouYinMiniGame.php
vendored
Normal file
193
superadmin/vendor/wanghua/general-utility-tools-php/src/douyin/DouYinMiniGame.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/4/4} {12:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\douyin;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class DouYinMiniGame extends BaseDouYin
|
||||
{
|
||||
public $appid = 'tt3c974a2aa3a6ee7c02';
|
||||
public $secret = '5c2414e47a18b9655a164b14ef31ac7cb58179ca';
|
||||
|
||||
|
||||
/**
|
||||
* desc:每2小时更新一次
|
||||
*
|
||||
* https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/server/interface-request-credential/get-access-token
|
||||
*
|
||||
* {"err_no":0,"err_tips":"success","data":{"access_token":"0801121846384c316e52536e5a76396769565145696f597742673d3d","expires_in":7200,"expiresAt":1712208063,"expires_at":1712208063}}
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getAccessToken(){
|
||||
$url = "https://minigame.zijieapi.com/mgplatform/api/apps/v2/token";
|
||||
$method = 'POST';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
|
||||
$params = [
|
||||
|
||||
'appid'=>$this->appid,
|
||||
'secret'=>$this->secret,
|
||||
'grant_type'=>'client_credential',
|
||||
];
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
$res = Curl::curl_request($url,$method,json_encode($params),$header);
|
||||
|
||||
$json_arr = json_decode($res, true);
|
||||
if($json_arr['err_no']){
|
||||
return Tools::set_res($json_arr['err_no'],$json_arr['err_tips']);
|
||||
}
|
||||
//保存
|
||||
session('ses_dou_yin_access_token',$json_arr['data']);
|
||||
return Tools::set_ok('ok',$json_arr['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:实时获取token
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function realTimeGetAccessToken(){
|
||||
$json_arr = session('ses_dou_yin_access_token');
|
||||
if(empty($json_arr)){
|
||||
return $this->getAccessToken();
|
||||
}
|
||||
if(time() >= $json_arr['expiresAt']){
|
||||
//过期
|
||||
return $this->getAccessToken();
|
||||
}
|
||||
return Tools::set_ok('ok',$json_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前端tt.login触发调用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function jscode2session($code='',$anonymous_code=''){
|
||||
$url = 'https://minigame.zijieapi.com/mgplatform/api/apps/jscode2session';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
$method = 'GET';
|
||||
|
||||
if(empty($code) && empty($anonymous_code)){
|
||||
return Tools::set_fail('tt.login 接口返回的匿名登录凭证(code 和 anonymous_code 至少要有一个)');
|
||||
}
|
||||
$params = [
|
||||
'appid'=>$this->appid,
|
||||
'secret'=>$this->secret,
|
||||
];
|
||||
if($code){
|
||||
$params['code'] = $code;
|
||||
}
|
||||
if($anonymous_code){
|
||||
$params['anonymous_code'] = $anonymous_code;
|
||||
}
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
$url .= '?'.http_build_query($params);
|
||||
//dump($url);
|
||||
Tools::log_to_write_txt(['input'=>$url]);
|
||||
$res = Curl::curl_request($url,$method,[],$header);
|
||||
Tools::log_to_write_txt(['output'=>$res]);
|
||||
//dump($res);
|
||||
$json_arr = json_decode($res, true);
|
||||
//dump($json_arr);die;
|
||||
if($json_arr['error']){
|
||||
return Tools::set_res($json_arr['errcode'],$json_arr['errmsg']);
|
||||
}
|
||||
//保存
|
||||
session('ses_dou_yin_js_code_2_session',$json_arr);
|
||||
return Tools::set_ok('ok',$json_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建二维码
|
||||
* 接口说明
|
||||
* 获取小程序/小游戏的二维码。该二维码可通过任意 app 扫码打开,
|
||||
* 能跳转到开发者指定的对应字节系 app 内拉起小程序/小游戏,并传入开发者指定的参数。
|
||||
* 通过该接口生成的二维码,永久有效,暂无数量限制。
|
||||
*
|
||||
* ⚠ Tip:在使用该功能之前请记得先配置您的默认分享文案和图片,配置方式可参考论坛。
|
||||
* ⚠ Tip:小程序的 path 要 encode 一次,如 pages%3fparam%3dtrue,小游戏的 path 为 JSON 字符串,
|
||||
* 如{"param":true},否则会导致取不到。
|
||||
*
|
||||
* 参数:
|
||||
* code和anonymous_code二选一 必须
|
||||
* appname 可选,目标打开应用名称 默认douyin
|
||||
* background 可选,背景色,rgb格式,英文逗号隔开,默认透明色
|
||||
* path 可选,小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
|
||||
* width 宽度 可选,二维码宽度,单位 px,最小 280px,最大 1280px,默认为 430px
|
||||
* line_color 可选,二维码线条颜色,默认为黑色,rgb格式,英文逗号隔开,默认黑色
|
||||
* set_icon 可选,是否展示小程序/小游戏 icon,默认不展示,传yes展示,no不展示,默认no
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function createQRCode($path='',$appname='',$width='',$background='',$line_color='',$set_icon='no'){
|
||||
try {
|
||||
$url = 'https://minigame.zijieapi.com/mgplatform/api/apps/qrcode';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
$method = 'POST';
|
||||
|
||||
$json_arr = $this->realTimeGetAccessToken();
|
||||
if(empty($json_arr)){
|
||||
return Tools::set_fail('请重新授权');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'access_token'=>$json_arr['data']['access_token'],
|
||||
];
|
||||
if($appname){
|
||||
$params['appname'] = $appname;
|
||||
}
|
||||
if($width){
|
||||
$params['width'] = $width;
|
||||
}
|
||||
//if($path){
|
||||
//小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
|
||||
$params['path'] = $path;
|
||||
//}
|
||||
//英文逗号隔开,r,g,b格式
|
||||
if($background){
|
||||
$background_rgb = explode(',',$background);
|
||||
$params['r'] = $background_rgb[0];
|
||||
$params['g'] = $background_rgb[1];
|
||||
$params['b'] = $background_rgb[2];
|
||||
}
|
||||
if($line_color){
|
||||
$line_color_rgb = explode(',',$line_color);
|
||||
$params['r'] = $line_color_rgb[0];
|
||||
$params['g'] = $line_color_rgb[1];
|
||||
$params['b'] = $line_color_rgb[2];
|
||||
}
|
||||
$params['set_icon'] = $set_icon=='yes';
|
||||
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
|
||||
Tools::log_to_write_txt(['input'=>input(),'$params'=>$params]);
|
||||
$res = Curl::curl_request($url,$method,json_encode($params),$header);
|
||||
Tools::log_to_write_txt(['output'=>$res]);
|
||||
|
||||
//流
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
88
superadmin/vendor/wanghua/general-utility-tools-php/src/encrypt/TripleDES.php
vendored
Normal file
88
superadmin/vendor/wanghua/general-utility-tools-php/src/encrypt/TripleDES.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/10} {15:51}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\encrypt;
|
||||
|
||||
|
||||
/**
|
||||
* 3DES,三重数据加密算法
|
||||
*
|
||||
* Class TripleDES
|
||||
* @package wanghua\general_utility_tools_php\encrypt
|
||||
*/
|
||||
class TripleDES
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:加密
|
||||
*
|
||||
* author:wh
|
||||
* @param string $value
|
||||
* @param $key
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt(string $value, $key)
|
||||
{
|
||||
$value = self::PaddingPKCS7($value);
|
||||
//AES-128-ECB|不能用 AES-256-CBC|16 AES-128-CBC|16 BF-CBC|8 aes-128-gcm|需要加$tag DES-EDE3-CBC|8
|
||||
$cipher = "DES-EDE3";
|
||||
// if (in_array($cipher, openssl_get_cipher_methods())) {}
|
||||
$result = openssl_encrypt($value, $cipher, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, "");
|
||||
return base64_encode($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title 解密
|
||||
*
|
||||
* @param string $str 要传的参数
|
||||
* @param $key
|
||||
* @return bool|false|string
|
||||
*
|
||||
*/
|
||||
public function decrypt(string $str, $key)
|
||||
{
|
||||
$decrypted = openssl_decrypt(base64_decode($str), 'DES-EDE3', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, "");
|
||||
$ret = self::UnPaddingPKCS7($decrypted);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
private function PaddingPKCS7($data)
|
||||
{
|
||||
//$block_size = mcrypt_get_block_size('tripledes', 'cbc');//获取长度
|
||||
//$block_size = openssl_cipher_iv_length('tripledes', 'cbc');//获取长度
|
||||
$block_size = 8;
|
||||
$padding_char = $block_size - (strlen($data) % $block_size);
|
||||
$data .= str_repeat(chr($padding_char), $padding_char);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $text
|
||||
* @return false|string
|
||||
*/
|
||||
private function UnPaddingPKCS7($text)
|
||||
{
|
||||
$pad = ord($text{strlen($text) - 1});
|
||||
if ($pad > strlen($text)) {
|
||||
return false;
|
||||
}
|
||||
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) {
|
||||
return false;
|
||||
}
|
||||
return substr($text, 0, -1 * $pad);
|
||||
}
|
||||
}
|
||||
20
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/AuthError.php
vendored
Normal file
20
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/AuthError.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {19:05}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class AuthError
|
||||
{
|
||||
|
||||
const PERMISSION_DENIED = [60000, '权限拒绝'];
|
||||
|
||||
const ACCESS_REFUSE_ERROR = [60100, '访问被拒绝'];//请求不合法资源
|
||||
|
||||
const ACCESS_TIMES_ERROR = [60200, '访问次数限制'];
|
||||
}
|
||||
84
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/Code.php
vendored
Normal file
84
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/Code.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/11/12} {21:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
/**
|
||||
* 系统级错误, 业务错误代码放在业务层,不要放在此处
|
||||
* Class SystemError
|
||||
* @package errorcode
|
||||
*/
|
||||
class Code
|
||||
{
|
||||
//region 系统级别错误
|
||||
const SUCCESS = [200, 'SUCCESS'];
|
||||
|
||||
const REQUEST_ERROR = [10000, '请求错误'];//一般url资源错误;url错误、敏感参数错误等
|
||||
|
||||
const REQUEST_TYPE_ERROR = [10001, '请求类型错误'];//ajax get post
|
||||
|
||||
const FAILED = [10002, '操作失败'];
|
||||
|
||||
const SOURCE_NOT_FIND = [10003, '资源找不到'];
|
||||
|
||||
const SYSTEM_ERROR = [500, '系统错误'];
|
||||
|
||||
const PERMISSION_DENIED = [10005, '权限拒绝'];
|
||||
|
||||
const ACCESS_REFUSE_ERROR = [10006, '访问被拒绝'];//请求不合法资源
|
||||
|
||||
const ACCESS_TIMES_ERROR = [10007, '访问次数限制'];
|
||||
//endregion 系统级别错误
|
||||
|
||||
|
||||
|
||||
//region 短信错误
|
||||
|
||||
const MESSAGE_SEND_ERROR = [13500, '短信发送失败'];
|
||||
|
||||
const MESSAGE_SEND_ULTRALIMIT = [13600, '短信发送超限'];
|
||||
|
||||
const MESSAGE_VERIFY_FAILED = [13700, '短信验证失败'];
|
||||
|
||||
const MESSAGE_NUM_LITTLE = [13800, '短信余额不足'];
|
||||
|
||||
const MESSAGE_SEND_EXCEPTION = [13900, '短信发送异常'];
|
||||
//endregion
|
||||
|
||||
//region 文件上传
|
||||
const UPLOAD_FAILED = [14000, '上传失败'];
|
||||
|
||||
const UPLOAD_FILE_IS_EMPTY = [14000, '无文件上传'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_EMPTY = [14100, '文件内容为空'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_ERROR = [14200, '文件大小超过限制'];
|
||||
|
||||
const UPLOAD_FILE_MIME_ERROR = [14300, '文件类型错误'];
|
||||
|
||||
const UPLOAD_FILE_EXT_ERROR = [14500, '文件扩展名错误'];
|
||||
|
||||
const FILE_FROM_ERROR = [14520, '来源错误'];
|
||||
//endregion
|
||||
|
||||
|
||||
//region 数据库错误
|
||||
const DATA_IS_EMPTY = [50000, '未获取到相关数据'];
|
||||
|
||||
const UPDATE_ERROR = [50001, '修改异常'];
|
||||
|
||||
const INSERT_ERROR = [50002, '数据保存异常'];
|
||||
|
||||
const SELECT_ERROR = [50003, '查询异常'];
|
||||
|
||||
const DATA_REPEAT_ERROR = [50005, '数据重复'];
|
||||
|
||||
const DATA_INSERT_ERROR = [50006, '数据入库异常'];
|
||||
|
||||
//endregion
|
||||
}
|
||||
30
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/DbError.php
vendored
Normal file
30
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/DbError.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class DbError
|
||||
{
|
||||
|
||||
|
||||
//region 数据库错误
|
||||
const DATA_IS_EMPTY = [16000, '未获取到相关数据'];
|
||||
|
||||
const UPDATE_ERROR = [16100, '修改异常'];
|
||||
|
||||
const INSERT_ERROR = [16200, '数据保存异常'];
|
||||
|
||||
const SELECT_ERROR = [16300, '查询异常'];
|
||||
|
||||
const DATA_REPEAT_ERROR = [16400, '数据重复'];
|
||||
|
||||
const DATA_INSERT_ERROR = [16500, '数据入库异常'];
|
||||
|
||||
//endregion
|
||||
}
|
||||
19
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/EmailError.php
vendored
Normal file
19
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/EmailError.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:47}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class EmailError
|
||||
{
|
||||
//region 邮件错误
|
||||
const EMAIL_RECEIVER_IS_EMPTY = [23100, '未设置收信人'];
|
||||
|
||||
const EMAIL_SEND_FAILED = [23200, '邮件发送失败'];
|
||||
//endregion
|
||||
}
|
||||
29
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/FileUploadError.php
vendored
Normal file
29
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/FileUploadError.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class FileUploadError
|
||||
{
|
||||
//region 文件上传
|
||||
const UPLOAD_FAILED = [24000, '上传失败'];
|
||||
|
||||
const UPLOAD_FILE_IS_EMPTY = [24100, '无文件上传'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_EMPTY = [24200, '文件内容为空'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_ERROR = [24300, '文件大小超过限制'];
|
||||
|
||||
const UPLOAD_FILE_MIME_ERROR = [24400, '文件类型错误'];
|
||||
|
||||
const UPLOAD_FILE_EXT_ERROR = [24500, '文件扩展名错误'];
|
||||
|
||||
const FILE_SOURCE_ERROR = [24600, '文件来源错误'];
|
||||
//endregion
|
||||
}
|
||||
19
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/LoginError.php
vendored
Normal file
19
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/LoginError.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class LoginError
|
||||
{
|
||||
|
||||
const OFF_LINE_ERROR = [30100, '未登录'];
|
||||
|
||||
const LOGIN_SESSION_INVALID = [30200, '登录已过期,请重新登录'];
|
||||
|
||||
}
|
||||
27
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/RequestError.php
vendored
Normal file
27
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/RequestError.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/3} {14:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class RequestError
|
||||
{
|
||||
//region 请求错误
|
||||
const SUCCESS = [200, 'SUCCESS'];
|
||||
|
||||
const REQUEST_TYPE_ERROR = [50601, '请求类型错误'];//ajax get post
|
||||
|
||||
const SOURCE_NOT_FIND = [50400, '资源找不到'];
|
||||
|
||||
const SYSTEM_ERROR = [50500, '系统错误'];
|
||||
|
||||
const REQUEST_ERROR = [50600, '请求错误'];//一般url资源错误;url错误、敏感参数错误等
|
||||
|
||||
const FAILED = [50602, '请求失败'];
|
||||
//endregion 请求错误
|
||||
}
|
||||
26
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/SmsError.php
vendored
Normal file
26
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/SmsError.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class SmsError
|
||||
{
|
||||
//region 短信错误
|
||||
|
||||
const MESSAGE_SEND_ERROR = [43500, '短信发送失败'];
|
||||
|
||||
const MESSAGE_SEND_ULTRALIMIT = [43600, '短信发送超限'];
|
||||
|
||||
const MESSAGE_VERIFY_FAILED = [43700, '短信验证失败'];
|
||||
|
||||
const MESSAGE_NUM_LITTLE = [43800, '短信余额不足'];
|
||||
|
||||
const MESSAGE_SEND_EXCEPTION = [43900, '短信发送异常'];
|
||||
//endregion
|
||||
}
|
||||
15
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/SystemError.php
vendored
Normal file
15
superadmin/vendor/wanghua/general-utility-tools-php/src/errorcode/SystemError.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:50}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class SystemError
|
||||
{
|
||||
|
||||
}
|
||||
264
superadmin/vendor/wanghua/general-utility-tools-php/src/es/Elasticsearch.php
vendored
Normal file
264
superadmin/vendor/wanghua/general-utility-tools-php/src/es/Elasticsearch.php
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/26} {9:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\es;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Date;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,即将删除
|
||||
*
|
||||
* 【es原生操作库】
|
||||
* 【仅支持框架ThinkPHP5+、 PHP7.2+】
|
||||
*
|
||||
* BaseElasticsearch.php类库的替代库
|
||||
*
|
||||
* 使用步骤:
|
||||
* 初始化(设置ip、索引前缀-普通索引请设置为空字符串)
|
||||
* 设置索引范围(例如查询本月,如果索引不是按日期规律设置,请使用普通索引设置方法setIndexNormal,并设置前缀为空字符串)
|
||||
* 设置查询方法(eg: _search)
|
||||
* 设置查询参数(查询条件)
|
||||
* 执行
|
||||
* 返回结果
|
||||
* Class ElasticsearchUtility
|
||||
* @package app\admin\logic
|
||||
*/
|
||||
class Elasticsearch
|
||||
{
|
||||
protected $es_log_file = 'es_log';
|
||||
//最终拼装的请求地址
|
||||
protected $post_url = ''; //eg: $url = 'http://49.4.3.4:9111/qa-item-2021.04/_search';
|
||||
//查询参数
|
||||
protected $query_param = [];
|
||||
//查询方法
|
||||
protected $query_method = '_search';
|
||||
//文档索引
|
||||
protected $index = '';
|
||||
//服务器ip
|
||||
protected $ip = '';
|
||||
//索引前缀(优先设置)
|
||||
protected $index_sign = '';//eg: qa-stat-
|
||||
//设置查询日期格式符号
|
||||
protected $doc_date_sign = '.';
|
||||
//设置是哪个方法调用本es库,用于日志记录
|
||||
protected $exe_func = '';
|
||||
|
||||
|
||||
/**
|
||||
* ElasticsearchUtility constructor.
|
||||
* @param string $ip_port 协议+服务器ip+端口号,必须
|
||||
* @param string $index_sign 当es索引为有规律的日期索引时,可使用前缀并配合日期索引设置方法,体验更佳
|
||||
*/
|
||||
public function __construct(string $ip_port, string $index_sign='')
|
||||
{
|
||||
$this->ip = false===strpos($ip_port,'http')?'http://'.$ip_port:$ip_port;
|
||||
$this->index_sign = $index_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置查询方法,默认_search
|
||||
* author:wh
|
||||
* @param $method_name
|
||||
*/
|
||||
function setQueryMethod($method_name){
|
||||
$this->query_method = $method_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:根据日期索引查询文档
|
||||
* 注:默认一个月
|
||||
*
|
||||
* eg:'qa-stat-2021.01';
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
* author:wh
|
||||
*/
|
||||
function setIndexDefault(){
|
||||
$this->setRequestIndex(date('Y'.$this->doc_date_sign.'m'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置要查询的日期文档索引
|
||||
*
|
||||
* 1、按年检索文档[建议5年左右]
|
||||
*
|
||||
* eg: qa-stat-2018.*,qa-stat-2019.*,qa-stat-2020.*,qa-stat-2021.*
|
||||
*
|
||||
* 注意:当索引过长,es会抛出索引太长异常
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间 eg:2010-01-01 08:05:55
|
||||
* @param string $end_time 结束时间 eg:2021-12-31 12:05:00
|
||||
* @return string
|
||||
*/
|
||||
function setIndexYearDate(string $start_time, string $end_time){
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'*', strtotime($start_time));
|
||||
|
||||
$sign = ',';//分隔符
|
||||
|
||||
$m = date('Y', strtotime($end_time)) - date('Y', strtotime($start_time));
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
|
||||
$index .= $sign.($this->index_sign.(date('Y', strtotime($start_time))+$i).$this->doc_date_sign.'*');
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日期索引
|
||||
*
|
||||
* 检索全部日期索引文档
|
||||
*
|
||||
* 例如es设置的索引为:
|
||||
* qa-stat-2021.01
|
||||
qa-stat-2021.02
|
||||
qa-stat-2021.03
|
||||
qa-stat-2021.04
|
||||
*
|
||||
* 实际查询自动设置为:qa-stat-*
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function setIndexAllDate(){
|
||||
|
||||
$this->setRequestIndex('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置普通索引
|
||||
*
|
||||
* 调用此方法,请在初始化时,设置索引前缀index_sign为""空字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
function setIndexNormal(string $index){
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置跨月份索引
|
||||
*
|
||||
* eg: qa-stat-2021.01,qa-stat-2021.02
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time eg:'2020-11'
|
||||
* @param string $end_time eg:'2021-01'
|
||||
* @return string eg: qa-stat-2020.11,qa-stat-2020.12,qa-stat-2021.01
|
||||
*/
|
||||
function setIndexDate(string $start_time, string $end_time){
|
||||
$date = new Date();
|
||||
|
||||
//计算月份
|
||||
$m = $date->dateCutMonth($start_time, $end_time);
|
||||
////解决跨年且不足1个月时,索引设置错误问题
|
||||
//if($m == 0 && (date('Y', strtotime($end_time)) > date('Y', strtotime($start_time)))){
|
||||
// $m = 1;
|
||||
//}
|
||||
//格式
|
||||
$date->date_format = 'Y-m';
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'m', strtotime($start_time));
|
||||
|
||||
$tmp_time = $start_time;
|
||||
$sign = ',';//分隔符
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
$tmp_time = $date->addTime(1, 'M', strtotime($tmp_time));
|
||||
$index .= $sign.$this->index_sign.(date('Y'.$this->doc_date_sign.'m', strtotime($tmp_time)));
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:设置查询参数
|
||||
* author:wh
|
||||
* @param string $query_param_json
|
||||
*/
|
||||
function setQueryParam(string $query_param_json){
|
||||
$this->query_param = $query_param_json;
|
||||
$this->post_url = $this->ip.'/'.$this->index.'/'.$this->query_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取查询参数,用于调试
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getQueryParam(){
|
||||
return [
|
||||
'ip'=>$this->ip,
|
||||
'index_sign'=>$this->index_sign,
|
||||
'index'=>$this->index,
|
||||
'query_method'=>$this->query_method,
|
||||
'post_url'=>$this->post_url,
|
||||
'query_param'=>$this->query_param,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:执行es查询
|
||||
* author:wh
|
||||
* @return array|bool|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function execute(){
|
||||
if(empty($this->ip)) throw new \Exception('请设置ip');
|
||||
//if(empty($this->index_sign)) throw new \Exception('请设置索引前缀');
|
||||
if(empty($this->index)) throw new \Exception('请设置索引');
|
||||
if(empty($this->query_method)) throw new \Exception('请设置查询方法');
|
||||
if(empty($this->query_param)) throw new \Exception('请设置查询参数');
|
||||
|
||||
|
||||
|
||||
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'request_url'=>$this->post_url,'IN'=>" | IN: ",'query_params'=>$this->query_param, 'input'=>input()], $this->es_log_file);
|
||||
$result = Tools::curl_post($this->post_url, $this->query_param);
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'OUT'=>" | OUT: ", 'result'=>$result], $this->es_log_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置是哪个方法调用本es库,用于日志记录
|
||||
* author:wh
|
||||
* @param string $function
|
||||
*/
|
||||
function setExecuteFunction(string $function){
|
||||
$this->exe_func = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置请求文档索引
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
protected function setRequestIndex(string $index){
|
||||
$this->index = $this->index_sign.$index;
|
||||
}
|
||||
|
||||
}
|
||||
1340
superadmin/vendor/wanghua/general-utility-tools-php/src/es/README.md
vendored
Normal file
1340
superadmin/vendor/wanghua/general-utility-tools-php/src/es/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/BaseException.php
vendored
Normal file
16
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/BaseException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception;
|
||||
|
||||
use think\Exception;
|
||||
|
||||
class BaseException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
27
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/README.md
vendored
Normal file
27
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/README.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# 系统业务级异常类
|
||||
1. api异常
|
||||
2. 请求异常
|
||||
3. api异常
|
||||
4. 响应异常
|
||||
5. 待扩展......
|
||||
|
||||
|
||||
|
||||
##使用说明
|
||||
例1:
|
||||
|
||||
if(empty($params)){
|
||||
//参数错误,抛出空参数异常
|
||||
throw new RequestException(RequestException::EMPTY_PARAM_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
例2:
|
||||
|
||||
//假设返回结果格式为:['code'=>200, 'msg'=>'操作成功', 'data'=>[]]
|
||||
if(is_null($result['code'])){
|
||||
//无code字段,抛出响应格式错误
|
||||
throw new ResponseException(ResponseException::RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
60
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/SystemException.php
vendored
Normal file
60
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/SystemException.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/03/08} {14:17}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception;
|
||||
|
||||
|
||||
use think\exception\Handle;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\SundryConfig;
|
||||
use wanghua\general_utility_tools_php\tool\EmailTool;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class SystemException extends Handle
|
||||
{
|
||||
public function render(\Exception $e)
|
||||
{
|
||||
// 参数验证错误
|
||||
//if ($e instanceof ValidateException) {
|
||||
// return json($e->getError(), 422);
|
||||
//}
|
||||
|
||||
// 请求异常
|
||||
//if ($e instanceof HttpException && request()->isAjax()) {
|
||||
// return response($e->getMessage(), $e->getStatusCode());
|
||||
//}
|
||||
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'系统错误.'.$e->getMessage(),
|
||||
'input'=>input(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
]);
|
||||
|
||||
$title = '新的【系统异常】,请立即处理';
|
||||
//邮件通知管理员
|
||||
$mail_content = '<p>error:'.$e->getMessage().'</p>';
|
||||
$mail_content .= '<p>url:'.request()->url(true).'</p>';
|
||||
$mail_content .= '<p>ip:'.request()->ip().'</p>';
|
||||
$mail_content .= '<p>详情请登录宝塔查看日志</p>';
|
||||
|
||||
$emails = SundryConfig::val('admin_error_log_email');
|
||||
if(config('sys_env') == 'PROD'){//线上环境才发错误邮件
|
||||
EmailTool::email_to_person($title,$mail_content,$emails);
|
||||
}
|
||||
|
||||
if(request()->LogObj){
|
||||
request()->LogObj->flush();
|
||||
}
|
||||
if(request()->ServeLogObj){
|
||||
request()->ServeLogObj->flush();
|
||||
}
|
||||
|
||||
//可以在此交由系统处理
|
||||
return parent::render($e);
|
||||
}
|
||||
}
|
||||
21
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/api/ApiException.php
vendored
Normal file
21
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/api/ApiException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:04}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class ApiException extends BaseException
|
||||
{
|
||||
const API_RESPONSE_FORMAT_ERROR='The api response result is incorrectly formatted: code is not exist.';
|
||||
|
||||
|
||||
const EMPTY_PARAM_ERROR ='param is empty.';
|
||||
const EMPTY_URL_ERROR ='url of param is empty.';
|
||||
}
|
||||
18
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/request/RequestException.php
vendored
Normal file
18
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/request/RequestException.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:13}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\request;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class RequestException extends BaseException
|
||||
{
|
||||
const EMPTY_PARAM_ERROR ='param is empty.';
|
||||
const EMPTY_URL_ERROR ='url of param is empty.';
|
||||
}
|
||||
19
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/response/ResponseException.php
vendored
Normal file
19
superadmin/vendor/wanghua/general-utility-tools-php/src/exception/response/ResponseException.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\response;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class ResponseException extends BaseException
|
||||
{
|
||||
const RESPONSE_FORMAT_ERROR='The response result is incorrectly formatted.';
|
||||
|
||||
}
|
||||
53
superadmin/vendor/wanghua/general-utility-tools-php/src/fastadmin/FastadminTools.php
vendored
Normal file
53
superadmin/vendor/wanghua/general-utility-tools-php/src/fastadmin/FastadminTools.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/1/16} {17:15}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\fastadmin;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 为fastadmin框架定制的功能
|
||||
*
|
||||
* Class FastadminTools
|
||||
* @package wanghua\general_utility_tools_php\fastadmin
|
||||
*/
|
||||
class FastadminTools
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:线上需要自动隐藏的菜单
|
||||
*
|
||||
* 当你有这种需求:
|
||||
* 我的菜单只需要本地显示,线上或非本地环境不需要显示时,就可以使用此方法。
|
||||
* 为什么需要此方法?
|
||||
* 因为,我每次在本地增加功能并新增菜单之后,都需要把本地的菜单同步到线上,但是命令管理菜单,或者有些只需要开发者才能
|
||||
* 动的菜单,需要在线上隐藏。我又不想每次同步之后去改菜单表。
|
||||
* 手动去菜单表改也是可以,但是次数多了就很麻烦,有时候会忘记。
|
||||
*
|
||||
* 如:命令管理菜单、开发者相关配置
|
||||
*
|
||||
* author:wh
|
||||
* @param array $menu_arr 需要隐藏的菜单数组
|
||||
* @param string $sys_env
|
||||
* @return bool
|
||||
*/
|
||||
static function auto_hidden_menu_online(array $menu_arr, string $sys_env){
|
||||
|
||||
foreach ($menu_arr as $menu_name){
|
||||
if($sys_env == 'LOCAL'){
|
||||
//本地显示
|
||||
Db::table('fa_auth_rule')->where('name',$menu_name)->data(['status'=>'normal'])->update();
|
||||
}else{
|
||||
Db::table('fa_auth_rule')->where('name',$menu_name)->data(['status'=>'hidden'])->update();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
236
superadmin/vendor/wanghua/general-utility-tools-php/src/file/File.php
vendored
Normal file
236
superadmin/vendor/wanghua/general-utility-tools-php/src/file/File.php
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/2/4} {16:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\file;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 文件、文件夹操作类
|
||||
*
|
||||
* eg:读取文件夹、复制文件等
|
||||
*
|
||||
* Class FileOperate
|
||||
* @package wanghua\general_utility_tools_php\file
|
||||
*/
|
||||
class File
|
||||
{
|
||||
|
||||
public $file_ext = '*.*';//扩展名
|
||||
public $unzip_path = '';//解压路径
|
||||
|
||||
/**
|
||||
* desc:读取文件和文件夹
|
||||
*
|
||||
* author:wh
|
||||
* @param $folderPath 读取目标路径下的文件夹和文件
|
||||
*
|
||||
* @param $dirs 存储文件路径 eg:D:\wanghua\old_files
|
||||
*
|
||||
//array(3) {
|
||||
// [0] => array(1) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// }
|
||||
// [1] => array(1) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/222"
|
||||
// }
|
||||
//}
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param $file_name_arr 存储文件路径、文件名称
|
||||
*
|
||||
//array(64) {
|
||||
// [0] => array(3) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// ["path_file"] => string(33) "D:\wanghua\test_files/111/111.txt"
|
||||
// ["filename"] => string(7) "111.txt"
|
||||
// }
|
||||
// [1] => array(3) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// ["path_file"] => string(37) "D:\wanghua\test_files/111/1111111.txt"
|
||||
// ["filename"] => string(11) "1111111.txt"
|
||||
// }
|
||||
//}
|
||||
*/
|
||||
function read_folder($folderPath,&$dirs,&$file_name_arr) {
|
||||
// 获取指定目录下所有文件和文件夹
|
||||
$files = scandir($folderPath);
|
||||
foreach ($files as $file) {
|
||||
// 如果当前项为文件夹且不是"."或者".."
|
||||
if (is_dir("$folderPath/$file") && !in_array($file, array('.', '..'))) {
|
||||
$dirs[] = ['path'=>$folderPath.'/'.$file];//此时的$file是文件夹名称
|
||||
// 调用自身进行递归操作
|
||||
$this->read_folder("$folderPath/$file",$dirs,$file_name_arr);
|
||||
} elseif (!in_array($file, array('.', '..'))){ // 如果当前项为文件而非"."或者".."
|
||||
$file_name_arr[] = ['path'=>$folderPath,'path_file'=>"$folderPath/$file",'filename'=>$file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:复制文件
|
||||
*
|
||||
* author:wh
|
||||
* @param array $sourceFileArr 源文件路径数组 path,path_file,filename
|
||||
*
|
||||
* @param string $destination_path 目标存放路径 D:\wanghua\test_files\new_files
|
||||
*
|
||||
* @param array $cp_type_arr 允许复制的文件后缀 eg:['jpg','png,'spine']
|
||||
*
|
||||
* @param bool $is_cover 是否覆盖 默认false,不覆盖会以源文件名+微秒时间戳格式作为新的文件名
|
||||
*
|
||||
* @param bool $is_continue 相同文件是否跳过复制 默认 true
|
||||
*
|
||||
* 实战案例:
|
||||
*
|
||||
function testcopy(){
|
||||
$source_dir = 'D:\wanghua\test_files';//源文件路径
|
||||
$destination_path = 'D:\wanghua\test_files\new_files';//目标文件路径
|
||||
|
||||
$dirs = [];//存储文件路径
|
||||
$file_name_arr = [];//含文件路径、名称
|
||||
$file_obj = new File();
|
||||
$file_obj->read_folder($source_dir,$dirs,$file_name_arr);
|
||||
//dump($dirs);
|
||||
//dump($file_name_arr);die;
|
||||
$file_obj->copy($file_name_arr,$destination_path,['jpg','png,'spine']);
|
||||
}
|
||||
*
|
||||
*/
|
||||
function copy(array $sourceFileArr, string $destination_path, $cp_type_arr=['jpg','png'], $is_cover=false, $is_continue=false){
|
||||
//设置不超时
|
||||
set_time_limit(0);
|
||||
//源文件路径 => 目标文件路径
|
||||
foreach ($sourceFileArr as $key=>$file_arr){
|
||||
if(!file_exists($file_arr['path_file'])){
|
||||
continue;
|
||||
}
|
||||
//验证目标文件夹路径
|
||||
if(!file_exists($destination_path)){
|
||||
mkdir($destination_path,0777,true);
|
||||
}
|
||||
$name_arr = explode('.',$file_arr['filename']);
|
||||
//验证符合条件的文件类型
|
||||
if(!in_array($name_arr[1],$cp_type_arr)){
|
||||
continue;
|
||||
}
|
||||
if(file_exists($destination_path.'/'.$file_arr['filename'])){
|
||||
if($is_continue){
|
||||
continue;//相同文件跳过复制
|
||||
}
|
||||
//覆盖
|
||||
if($is_cover){
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
|
||||
}else{
|
||||
//不覆盖,名称区分
|
||||
$microsecond = Tools::getMicrosecond();
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$name_arr[0].'('.$microsecond.').'.$name_arr[1]);
|
||||
}
|
||||
}else{
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:递归删除目录
|
||||
*
|
||||
* $dir 物理路径
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function recursive_delete($dir) {
|
||||
if (!is_dir($dir)) {
|
||||
return unlink($dir);
|
||||
}
|
||||
|
||||
$handle = opendir($dir);
|
||||
while (($file = readdir($handle)) !== false) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
$path = $dir . DIRECTORY_SEPARATOR . $file;
|
||||
if (is_dir($path)) {
|
||||
$this->recursive_delete($path);
|
||||
} else {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
rmdir($dir);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:解压ZIP文件并存储在本地
|
||||
* author:wh
|
||||
* @param resource $file_stream 文件流
|
||||
* 例如:$response = $client->request('POST', $url, [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
]);
|
||||
// 处理响应
|
||||
//$file_stream = $response->getBody();
|
||||
* @param string $save_path 存储路径
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function unzip($file_stream,$save_path){
|
||||
$zpi_file_name = 'zip_tmp_file_'.Tools::rand_str(20).'.zip';
|
||||
//这个目录将会在结束时删除
|
||||
$zipTempPath = $save_path.'/tmp_zip_files/'; // 临时存放ZIP文件的路径
|
||||
//压缩文件保存目录
|
||||
if(!file_exists($zipTempPath)){
|
||||
mkdir($zipTempPath,0777,true);
|
||||
}
|
||||
$zpi_file = $zipTempPath.$zpi_file_name;
|
||||
// 保存ZIP文件到临时路径
|
||||
file_put_contents($zpi_file, $file_stream);
|
||||
|
||||
$this->unzip_path = $zipTempPath.'unzip_files/';
|
||||
//解压目录
|
||||
if(!file_exists( $this->unzip_path)){
|
||||
mkdir( $this->unzip_path,0777,true);
|
||||
}
|
||||
// 解压ZIP文件
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($zpi_file) === TRUE) {
|
||||
$zip->extractTo( $this->unzip_path);//移动到临时解压目录
|
||||
$zip->close();
|
||||
//遍历所有文件(file_ext后缀自行指定),遍历部分文件,如:*.json,*.zip,*.mp4,*.mp3等
|
||||
$wavFiles = $this->glob_by_ext( $this->unzip_path.$this->file_ext);
|
||||
|
||||
//$urls = [];
|
||||
//// 遍历解压后的文件,生成URL
|
||||
//foreach ($wavFiles as $wavFilePath) {
|
||||
// // 生成外部访问的URL
|
||||
// $downloadUrl = request()->domain() . explode('public',$wavFilePath)[1];
|
||||
// $urls[] = $downloadUrl;
|
||||
//}
|
||||
//// 返回所有WAV文件的URL
|
||||
//return ['wav_urls' => $urls];
|
||||
return $wavFiles;
|
||||
} else {
|
||||
throw new \Exception('Failed to open ZIP file.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取指定扩展类型的文件列表
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_ext 如: wav,pm4,mp3,json,zip
|
||||
* @return array|false
|
||||
*/
|
||||
function glob_by_ext($file_ext='*'){
|
||||
return glob( $this->unzip_path.'*.'.$file_ext);
|
||||
}
|
||||
}
|
||||
5
superadmin/vendor/wanghua/general-utility-tools-php/src/file/README.MD
vendored
Normal file
5
superadmin/vendor/wanghua/general-utility-tools-php/src/file/README.MD
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
## 文件处理
|
||||
|
||||
#### 文件夹读取,文件复制
|
||||
|
||||
#### 文件上传
|
||||
767
superadmin/vendor/wanghua/general-utility-tools-php/src/file/upload/FileUpload.php
vendored
Normal file
767
superadmin/vendor/wanghua/general-utility-tools-php/src/file/upload/FileUpload.php
vendored
Normal file
@@ -0,0 +1,767 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/4/3} {9:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\file\upload;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\oss\alicloud\Objects;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use wanghua\general_utility_tools_php\huawei\obs\InitObs;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\oss\huawei\obs\Config;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 上传组件
|
||||
* 支持单图,多图,单文件,多文件
|
||||
* Class FileUpload
|
||||
* @package libraries
|
||||
*/
|
||||
class FileUpload
|
||||
{
|
||||
//文件扩展
|
||||
protected $file_ext = 'ico,jpg,jpeg,png,gif,pdf,zip,rar,xls,xlsx,doc,docx';
|
||||
//图片扩展
|
||||
protected $img_ext = 'ico,jpg,jpeg,png,gif';
|
||||
|
||||
public $unique_key = '';//唯一key,临时文件会存储至该目录,推荐使用用户id
|
||||
|
||||
public $file_lists_urls = [];//要读取的文件地址列表
|
||||
/**
|
||||
* 文件存放目录
|
||||
*
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* @var string
|
||||
*/
|
||||
private $file_dir = '/uploads';
|
||||
|
||||
/**
|
||||
* desc:默认目录/uploads
|
||||
*
|
||||
* eg:/uploads/user/head_image 或 /files_manage/goods/images
|
||||
*
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
*
|
||||
* author:wh
|
||||
* @param $file_dir
|
||||
*/
|
||||
function setFileDir($file_dir){
|
||||
$this->file_dir = $file_dir;
|
||||
}
|
||||
/**
|
||||
* desc:单图
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认2M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function image($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件 例如上传了001.jpg
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '请上传文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$outer_req_url = $this->file_dir.'/image';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '上传文件不存在');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->img_ext;
|
||||
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}else{
|
||||
// 上传失败获取错误信息
|
||||
return Tools::set_res(1, $file->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:多图
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认2M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function images($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_res(1, '请上传文件');
|
||||
}
|
||||
$outer_req_url = $this->file_dir.'/image';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->img_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach($files as $file){
|
||||
if(!is_object($file)){
|
||||
return Tools::set_res(1, '请上传正确的文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result[] = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
}else{
|
||||
//忽略错误
|
||||
// 上传失败获取错误信息
|
||||
$error[] = $file->getError();
|
||||
}
|
||||
}
|
||||
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:单文件
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认10M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function file($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件 例如上传了001.jpg
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '请上传文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$outer_req_url = $this->file_dir.'/file';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '上传文件不存在');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}else{
|
||||
// 上传失败获取错误信息
|
||||
return Tools::set_res(1, $file->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:多文件
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function files($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_res(1, '请上传文件');
|
||||
}
|
||||
$outer_req_url = $this->file_dir.'/file';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach($files as $file){
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result[] = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
}else{
|
||||
//忽略错误
|
||||
// 上传失败获取错误信息
|
||||
$error[] = $file->getError();
|
||||
}
|
||||
}
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:单文件或多文件上传至阿里云OSS服务
|
||||
*
|
||||
* author:wh
|
||||
* @param array $config 配置
|
||||
* //阿里云oss配置
|
||||
'aliyun_oss_config' => [
|
||||
//项目应用名称
|
||||
'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀,代表这个bucket属于哪个项目
|
||||
'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
|
||||
'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
|
||||
'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
|
||||
'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
|
||||
//https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
|
||||
'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀,否则提示:Invalid signing region in Authorization header
|
||||
//西南1(成都)
|
||||
//oss-cn-chengdu
|
||||
//oss-cn-chengdu.aliyuncs.com
|
||||
//oss-cn-chengdu-internal.aliyuncs.com
|
||||
'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
|
||||
'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
|
||||
]
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识,默认存放在(项目名称/控制器/方法/(唯一标识,可为空)/年月日/*.jpg)
|
||||
* @param string $file_upload_name 文件上传控件的name值,必须带[],例如:file_upload[]
|
||||
* @param string $oss_type oss类型,可选值:ali_cloud 阿里云,hua_wei 华为云(待扩展)
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的文件扩展名
|
||||
* @return array
|
||||
*/
|
||||
function filesUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
|
||||
return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
if(($size > $ini_upload_max_filesize)){
|
||||
return Tools::set_res(1, '上传文件size受限,不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_res(1, '请上传文件');
|
||||
}
|
||||
//扩展
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
//初始化阿里云OSS客户端
|
||||
$oss_obj= new Objects($config);
|
||||
//默认存储地址
|
||||
$file_save_dir = $this->setFileSaveDir($unique_id);
|
||||
$urls = [];
|
||||
foreach($files as $file){
|
||||
if(!$file->isValid()){
|
||||
return Tools::set_res(1,'文件不合法');
|
||||
}
|
||||
$check_size = $file->checkSize($size*1024*1024);
|
||||
if(!$check_size){
|
||||
return Tools::set_res(1,'文件大小超限');
|
||||
}
|
||||
$check_res = $file->checkExt($ext);
|
||||
if(!$check_res){
|
||||
return Tools::set_res(1,'请上传合法文件');
|
||||
}
|
||||
$extension = explode('.',$file->getInfo('name'))[1];
|
||||
$new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
|
||||
//必须加后缀
|
||||
$filename = $file_save_dir.$new_filename;
|
||||
|
||||
// 从文件流上传
|
||||
$res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
|
||||
$urls[] = [
|
||||
'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
|
||||
'source_file_name'=>$file->getInfo('name'),//源文件名
|
||||
'size'=>$file->getInfo('size'),//大小(b)
|
||||
'extension'=>$extension,//扩展名
|
||||
'file_type'=>$file->getInfo('type'),//文件后缀
|
||||
'save_name'=>$filename,//保存文件名
|
||||
'new_filename'=>$new_filename,//新文件名
|
||||
'real_path'=>$res['info']['url'],//实际路径
|
||||
'outer_req_url'=>$res['info']['url'],//外部访问地址
|
||||
'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
|
||||
];
|
||||
}
|
||||
return Tools::set_ok('ok', $urls);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:单文件上传至阿里云OSS
|
||||
*
|
||||
* author:wh
|
||||
* @param array $config 配置
|
||||
* //阿里云oss配置
|
||||
'aliyun_oss_config' => [
|
||||
//项目应用名称
|
||||
'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀,代表这个bucket属于哪个项目
|
||||
'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
|
||||
'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
|
||||
'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
|
||||
'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
|
||||
//https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
|
||||
'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀,否则提示:Invalid signing region in Authorization header
|
||||
//西南1(成都)
|
||||
//oss-cn-chengdu
|
||||
//oss-cn-chengdu.aliyuncs.com
|
||||
//oss-cn-chengdu-internal.aliyuncs.com
|
||||
'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
|
||||
'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
|
||||
]
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识,默认存放在(项目名称/控制器/方法/(唯一标识,可为空)/年月日/*.jpg)
|
||||
* @param string $file_upload_name 文件上传控件的name值,例如:file_upload
|
||||
* @param string $oss_type oss类型,可选值:ali_cloud 阿里云,hua_wei 华为云(待扩展)
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的文件扩展名
|
||||
* @return array
|
||||
*/
|
||||
function fileUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
|
||||
return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
if(($size > $ini_upload_max_filesize)){
|
||||
return Tools::set_res(1, '上传文件size受限,不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '请上传文件');
|
||||
}
|
||||
//扩展
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
//初始化阿里云OSS客户端
|
||||
$oss_obj= new Objects($config);
|
||||
//默认存储地址
|
||||
$file_save_dir = $this->setFileSaveDir($unique_id);
|
||||
$urls = [];
|
||||
if(!$file->isValid()){
|
||||
return Tools::set_res(1,'文件不合法');
|
||||
}
|
||||
$check_size = $file->checkSize($size*1024*1024);
|
||||
if(!$check_size){
|
||||
return Tools::set_res(1,'文件大小超限');
|
||||
}
|
||||
$check_res = $file->checkExt($ext);
|
||||
if(!$check_res){
|
||||
return Tools::set_res(1,'请上传合法文件');
|
||||
}
|
||||
$extension = explode('.',$file->getInfo('name'))[1];
|
||||
$new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
|
||||
//必须加后缀
|
||||
$filename = $file_save_dir.$new_filename;
|
||||
|
||||
// 从文件流上传
|
||||
$res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
|
||||
$urls[] = [
|
||||
'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
|
||||
'source_file_name'=>$file->getInfo('name'),//源文件名
|
||||
'size'=>$file->getInfo('size'),//大小(b)
|
||||
'extension'=>$extension,//扩展名
|
||||
'file_type'=>$file->getInfo('type'),//文件后缀
|
||||
'save_name'=>$filename,//保存文件名
|
||||
'new_filename'=>$new_filename,//新文件名
|
||||
'real_path'=>$res['info']['url'],//实际路径
|
||||
'outer_req_url'=>$res['info']['url'],//外部访问地址
|
||||
'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
|
||||
];
|
||||
return Tools::set_ok('ok', $urls);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置文件保存目录
|
||||
* author:wh
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识
|
||||
* @return string
|
||||
*/
|
||||
function setFileSaveDir($unique_id=''){
|
||||
if($unique_id){
|
||||
$unique_id = $unique_id.'/';
|
||||
}
|
||||
//项目名称
|
||||
$project_name = Tools::get_project_name();
|
||||
//控制器方法路径
|
||||
$ctl = strtolower(request()->controller().'/'.request()->action());
|
||||
return $project_name.'/'.$ctl.'/'.$unique_id.date('Ymd').'/';//日期
|
||||
}
|
||||
/**
|
||||
* desc:检测size是否在ini配置范围
|
||||
*
|
||||
* author:wh
|
||||
* @param $size
|
||||
* @return bool
|
||||
*/
|
||||
private function uploadMaxFilesizeCheck($size){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
return $size<=$ini_upload_max_filesize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:上传base64格式图片【文件不用base64传输】
|
||||
* author:wh
|
||||
* @param string $file_upload_name
|
||||
* @param int $size
|
||||
* @param array $ext
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function uploadBase64Img($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
$source = input($file_upload_name, 'file_upload');
|
||||
$file_size = strlen($source);
|
||||
if($file_size > $size * 1024 * 1024){
|
||||
return Tools::set_res(1, '上传失败,大小限制');
|
||||
}
|
||||
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $result) < 1){
|
||||
return Tools::set_res(1, '上传文件不合法');
|
||||
}
|
||||
$type = $result[2];
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
if(!in_array($type, explode($ext))){
|
||||
return Tools::set_res(1, '上传失败,类型限制');
|
||||
}
|
||||
$result = base64_image_content($source);
|
||||
if(false === $result){
|
||||
return Tools::set_res(1, '上传失败');
|
||||
}
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:批量上传base64格式图片【文件不用base64传输】
|
||||
* author:wh
|
||||
* @param string $file_upload_name
|
||||
* @param int $size
|
||||
* @param array $ext
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function uploadBase64Imgs($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
$source_list = input($file_upload_name, 'file_upload');
|
||||
if(!is_array($source_list)){
|
||||
return Tools::set_res(1, '参数错误');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach ($source_list as $source){
|
||||
$file_size = strlen($source);
|
||||
if($file_size > $size * 1024 * 1024){
|
||||
$error[] = '上传失败,大小限制';
|
||||
continue;
|
||||
}
|
||||
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $temp) < 1){
|
||||
$error[] = '上传文件不合法';
|
||||
continue;
|
||||
}
|
||||
$type = $temp[2];
|
||||
if(!in_array($type, explode(',', $ext))){
|
||||
$error[] = '类型限制';
|
||||
continue;
|
||||
}
|
||||
$up_result = base64_image_content($source);
|
||||
if(false === $up_result){
|
||||
$error[] = '上传失败';
|
||||
continue;
|
||||
}
|
||||
$result[] = $up_result;
|
||||
}
|
||||
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:优化路径格式
|
||||
* author:wh
|
||||
*/
|
||||
private function dealPath(string $path){
|
||||
$str = str_replace('\\','/',$path);
|
||||
|
||||
return str_replace('//','/',$str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:curl上传文件,php上传文件到远程服务器地址
|
||||
*
|
||||
* [php curl模拟文件上传]
|
||||
*
|
||||
* 依赖库:"guzzlehttp/guzzle": "^7.8",
|
||||
*
|
||||
* author:wh
|
||||
* @param $url
|
||||
* @param $params
|
||||
* @param false[] $config
|
||||
*/
|
||||
function uploadCurlFiles($url,$params, $config=['verify' => false]){
|
||||
if(empty($this->unique_key)){
|
||||
throw new \Exception('UNIQUE_KEY 不能为空');
|
||||
}
|
||||
if(empty($this->file_lists_urls)){
|
||||
throw new \Exception('文件地址列表不能为空');
|
||||
}
|
||||
// 创建 Guzzle HTTP 客户端实例
|
||||
$client = new Client($config);
|
||||
|
||||
// 定义要上传的文件列表
|
||||
$files = [
|
||||
//[
|
||||
// 'name' => 'file1', // 服务器接收的文件字段名
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\dc1c441d81d48565ac6817b89d0f8bef.mp4', 'r'), // 文件路径
|
||||
// 'filename' => 'dc1c441d81d48565ac6817b89d0f8bef.mp4', // 文件名,可自定义
|
||||
//],
|
||||
//[
|
||||
// 'name' => 'files',
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\f80179b23b60619fba8033bfd64f8817.mp4', 'r'),
|
||||
// 'filename' => 'f80179b23b60619fba8033bfd64f8817.mp4',
|
||||
//],
|
||||
//['name'=>'prompt','contents'=>$prompt],
|
||||
//['name'=>'tts_url','contents'=>$tts_url]
|
||||
// 可以继续添加更多文件...
|
||||
];
|
||||
//print_r($params);
|
||||
foreach ($params as $key=>$val){
|
||||
$files[] = ['name'=>$key,'contents'=>$val];
|
||||
}
|
||||
$controller = strtolower(request()->controller());
|
||||
$action = strtolower(request()->action());
|
||||
$save_path = Tools::get_root_path() . "public/uploads/{$controller}/{$action}/".$this->unique_key;
|
||||
if(!file_exists($save_path)){
|
||||
mkdir($save_path,0777,true);
|
||||
}
|
||||
|
||||
//文件远程可访问地址列表
|
||||
foreach ($this->file_lists_urls as $name=>$video_url) {
|
||||
//处理可用地址(可能存储在本地或oss)
|
||||
$video_url = $this->get_usable_url($video_url);
|
||||
$files[] = [
|
||||
'name'=>"files",//服务器接收的文件字段名
|
||||
//读取地址文件流(本地地址或远程地址均可,本地真实物理地址也行)
|
||||
'contents'=>Utils::tryFopen($video_url, 'r'),
|
||||
'filename'=>$name,//可自定义 文件名
|
||||
];
|
||||
}
|
||||
|
||||
// 构建多部分表单数据
|
||||
$multipartStream = new MultipartStream($files);
|
||||
$boundary = $multipartStream->getBoundary();
|
||||
$headers = [
|
||||
'Content-Type' => "multipart/form-data; boundary={$boundary}",
|
||||
];
|
||||
|
||||
// 准备请求体
|
||||
$body = $multipartStream->getContents();
|
||||
|
||||
// 发起 POST 请求
|
||||
try {
|
||||
$postinfo = [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
];
|
||||
//上传
|
||||
$response = $client->request('POST', $url, $postinfo);
|
||||
// 处理响应
|
||||
//$responseBody = (string) $response->getBody();
|
||||
// 检查状态码
|
||||
//if ($response->getStatusCode() !== 200) {
|
||||
// return false;
|
||||
//}
|
||||
return $response;//返回上传结果
|
||||
} catch (\GuzzleHttp\Exception\RequestException $e) {
|
||||
// 错误处理
|
||||
//echo "Error: " . $e->getMessage();
|
||||
Tools::error_txt_log($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取视频可用地址(兼容远程地址或本地地址)
|
||||
* author:wh
|
||||
* @param $video_url
|
||||
* @return string|string[]
|
||||
*/
|
||||
private function get_usable_url($video_url){
|
||||
if(strpos($video_url,'http')!==false){
|
||||
return $video_url;//远程地址
|
||||
}
|
||||
return Tools::get_root_path().$video_url;//本地地址
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
1
superadmin/vendor/wanghua/general-utility-tools-php/src/file/upload/README.MD
vendored
Normal file
1
superadmin/vendor/wanghua/general-utility-tools-php/src/file/upload/README.MD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
## 文件上传类库
|
||||
219
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/BaseController.php
vendored
Normal file
219
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/BaseController.php
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/25} {15:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Cache;
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\api\ApiDocument;
|
||||
use wanghua\general_utility_tools_php\tool\MySqlTools;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 基础架构
|
||||
*
|
||||
* Class BaseController
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class BaseController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
//校验系统维护状态 start
|
||||
$chm = $this->checkMaintain();
|
||||
if ($chm['is_maintain']) {
|
||||
if ($chm['users_ids']) {
|
||||
//解析openid
|
||||
if (!in_array(api_user_info('id'), explode(',', $chm['users_ids']))) {
|
||||
//白名单之外维护中
|
||||
//Tools::log_to_write_txt([
|
||||
// '维护测试'=>$chm['users_ids'],
|
||||
// 'my'=>index_user_openid()
|
||||
//]);
|
||||
return $this->error($chm['msg']);
|
||||
}
|
||||
} else {
|
||||
//不存在,直接维护中
|
||||
return $this->error($chm['msg'] . '!');
|
||||
}
|
||||
}
|
||||
//校验系统维护状态 end
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:空控操作
|
||||
* author:wh
|
||||
*/
|
||||
function _empty($info='')
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* desc:检查路径维护状态
|
||||
*
|
||||
* “===”完全匹配,不能使用like
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
protected function checkMaintain(){
|
||||
$configs = Db::table(TabConf::$fa_sys_maintain_config)
|
||||
->where('status','1')
|
||||
->cache()
|
||||
->select();
|
||||
|
||||
//模块
|
||||
$strmodule = request()->module();
|
||||
foreach ($configs as $config){
|
||||
if($strmodule == $config['url']){
|
||||
//模块维护中
|
||||
return ['is_maintain'=>true,'msg'=>$config['msg'],'users_ids'=>$config['users_ids']];
|
||||
}
|
||||
}
|
||||
|
||||
//模块/控制器
|
||||
$strcontroller = strtolower(request()->module().'/'.request()->controller());
|
||||
foreach ($configs as $config){
|
||||
if($strcontroller == $config['url']){
|
||||
//模块维护中
|
||||
return ['is_maintain'=>true,'msg'=>$config['msg'],'users_ids'=>$config['users_ids']];
|
||||
}
|
||||
}
|
||||
|
||||
//模块/控制器/方法
|
||||
$straction = strtolower(request()->module().'/'.request()->controller().'/'.request()->action());
|
||||
foreach ($configs as $config){
|
||||
if($straction == $config['url']){
|
||||
//模块维护中
|
||||
return ['is_maintain'=>true,'msg'=>$config['msg'],'users_ids'=>$config['users_ids']];
|
||||
}
|
||||
}
|
||||
|
||||
//未维护
|
||||
return ['is_maintain'=>false,'msg'=>'服务运行中'];
|
||||
}
|
||||
/**
|
||||
* desc:清空系统缓存
|
||||
*
|
||||
/index/Test/clearCache
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function clearCache(){
|
||||
|
||||
Tools::clear_cache();
|
||||
}
|
||||
/**
|
||||
* eg:/index/test/buildTablesConf
|
||||
*
|
||||
* desc:构建统一的表名配置
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildTablesConf(){
|
||||
|
||||
(new MySqlTools())->buildTablesConf();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建&更新接口文档
|
||||
*
|
||||
* 默认存放在/public/api_docs/api_list.md
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildApiDoc()
|
||||
{
|
||||
$obj = new ApiDocument();
|
||||
//根据自己的实际情况设置直接继承类(仅供参考)
|
||||
$obj->extends_base_class = 'app\\api\\controller\\BaseHttpApi,wanghua\\general_utility_tools_php\\framework\\base\\BaseWechatAuthController';
|
||||
//设置过滤的类(仅供参考)
|
||||
$obj->setFilterClass([
|
||||
'BaseCommonController',
|
||||
'BaseHttpApi',
|
||||
'BaseWssApi',
|
||||
'Wsspush',
|
||||
'BaseController',
|
||||
'BaseAuthController',
|
||||
//'BaseWechatAuthController',
|
||||
'BasePublicController'
|
||||
]);
|
||||
$obj->setFilterFunction([
|
||||
'buildApiDoc',
|
||||
'buildTablesConf',
|
||||
'checkfailed',
|
||||
'clearCache',
|
||||
'defaultAuth',
|
||||
'operateLog',
|
||||
'checkMaintain',
|
||||
'_empty'
|
||||
]);
|
||||
//构建接口文档
|
||||
$obj->buildDoc();
|
||||
//生成html
|
||||
$html = $obj->buildApiDocHtml();
|
||||
$path = Tools::get_root_path().'/public/api_docs/';
|
||||
if(!file_exists($path)){
|
||||
mkdir($path,0777,true);
|
||||
}
|
||||
file_put_contents($path.'api_list.html',$html);
|
||||
echo "<a href='/api_docs/api_list.html' target='_blank'>api_list.html</a>";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:用户操作日志
|
||||
* author:wh
|
||||
*/
|
||||
protected function operateLog($msg,$users_id=0,$username='',$name=''){
|
||||
$tbname = 'fa_users_operate_log';
|
||||
$sql = "
|
||||
CREATE TABLE IF NOT EXISTS `{$tbname}` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`users_id` int(10) unsigned DEFAULT '0' COMMENT '用户ID',
|
||||
`username` varchar(15) DEFAULT '' COMMENT '用户名',
|
||||
`name` varchar(20) DEFAULT '' COMMENT '名称',
|
||||
`url` varchar(60) DEFAULT '' COMMENT 'URL',
|
||||
`msg` varchar(90) DEFAULT '' COMMENT '做了什么',
|
||||
`ip` varchar(30) DEFAULT '' COMMENT '登录ip',
|
||||
`input` text COMMENT '提交参数',
|
||||
`create_time` timestamp NULL DEFAULT NULL COMMENT '登陆时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户操作日志';";
|
||||
|
||||
if(cache('cache_db_tables_now_project')){
|
||||
$table_arr = cache('cache_db_tables_now_project');
|
||||
}else{
|
||||
$table_arr = Tools::get_tables();
|
||||
}
|
||||
//表是否存在
|
||||
if(!in_array($tbname,$table_arr)){
|
||||
cache('cache_db_tables_now_project',$table_arr);
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'users_id'=>$users_id,
|
||||
'username'=>$username,
|
||||
'name'=>$name,
|
||||
'url'=>request()->url(),
|
||||
'msg'=>$msg,
|
||||
'ip'=>request()->ip(),
|
||||
'input'=>json_encode(input(),JSON_UNESCAPED_UNICODE),
|
||||
];
|
||||
Db::table($tbname)->data($data)->insert();
|
||||
|
||||
}
|
||||
}
|
||||
1
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/README.MD
vendored
Normal file
1
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/README.MD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
### this classes only to thinkphp5+
|
||||
80
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/base/BaseAuthController.php
vendored
Normal file
80
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/base/BaseAuthController.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/27} {10:35}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework\base;
|
||||
|
||||
use wanghua\general_utility_tools_php\framework\BaseController;
|
||||
use think\Exception;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 基础权限架构
|
||||
* Class BaseAuthController
|
||||
* @package library\framework\base
|
||||
*/
|
||||
class BaseAuthController extends BaseController
|
||||
{
|
||||
|
||||
public $debug = false;
|
||||
//权限错误重定向URL
|
||||
protected $auth_err_redirect_url = '/index/err/fail';
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
||||
$err_redirect_url = config('service_framework_config.auth_err_redirect_url');
|
||||
if($err_redirect_url){
|
||||
$this->auth_err_redirect_url = $err_redirect_url;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:默认鉴权
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
function defaultAuth(){
|
||||
$params = input();
|
||||
if(empty($params['nonce'])){
|
||||
Tools::log_to_write_txt(['服务被拒绝,鉴权参数缺失:nonce。params'=>input()]);
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied']);
|
||||
}
|
||||
if(empty($params['timestamp'])){
|
||||
Tools::log_to_write_txt(['服务被拒绝,鉴权参数缺失:timestamp。params'=>input()]);
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied.']);
|
||||
}
|
||||
if(empty($params['sign'])){
|
||||
Tools::log_to_write_txt(['服务被拒绝,鉴权参数缺失:sign。params'=>input()]);
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied。']);
|
||||
}
|
||||
$sign = $params['sign'];
|
||||
unset($params['sign']);
|
||||
if(Tools::signature($params) != $sign){
|
||||
|
||||
Tools::log_to_write_txt(['签名失败,服务被拒绝.'=>input()]);
|
||||
|
||||
//跳转至错误中转控制器
|
||||
return $this->response($this->auth_err_redirect_url,['title'=>'服务被拒绝. permission denied!']);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected function response($url,$params){
|
||||
|
||||
if(Request::instance()->isAjax() || Request::instance()->isPost()){
|
||||
return json(Tools::set_res(500,$params['title'],['url'=>$url]));
|
||||
}
|
||||
//跳转至错误中转控制器
|
||||
return $this->redirect(url($url,$params));
|
||||
}
|
||||
}
|
||||
29
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/base/BasePublicController.php
vendored
Normal file
29
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/base/BasePublicController.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/25} {15:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework\base;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\framework\BaseController;
|
||||
use think\Request;
|
||||
|
||||
/**
|
||||
* common controller have no permission
|
||||
*
|
||||
* 外部公用架构
|
||||
*
|
||||
* 无权限校验的公用架构
|
||||
*
|
||||
* Class PublicController
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class BasePublicController extends BaseController
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
194
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/base/BaseWechatAuthController.php
vendored
Normal file
194
superadmin/vendor/wanghua/general-utility-tools-php/src/framework/base/BaseWechatAuthController.php
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/23} {0:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\framework\base;
|
||||
|
||||
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\framework\BaseController;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 微信专用权限架构
|
||||
*
|
||||
* Class BaseWechatAuthController
|
||||
* @package wanghua\general_utility_tools_php\framework\base
|
||||
*/
|
||||
class BaseWechatAuthController extends BaseController
|
||||
{
|
||||
protected $wechat_user_table_name = 'fa_users';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
||||
//首页提示语
|
||||
$this->assign('index_msg', cache('index_msg_alert_cache_time'));
|
||||
|
||||
//线上环境加载微信授权
|
||||
if (config('sys_env') == 'PROD') {
|
||||
$wx_user_info = session('wx_user_info');
|
||||
if (empty($wx_user_info['openid'])) {
|
||||
//重定向之前,保存当前url, 在获取授权信息之后,回跳到授权之前的网页地址
|
||||
session('redirect_before_url_session', request()->url(true));
|
||||
$ver = Tools::get_thinkphp_version();
|
||||
if($ver == '5.0'){
|
||||
$url = url('index/Wexinauth/usrAuth','',false,true);
|
||||
}else{
|
||||
$url = request()->domain().url('index/Wexinauth/usrAuth');
|
||||
}
|
||||
//没有则重定向去授权
|
||||
return $this->redirect($url);
|
||||
}
|
||||
|
||||
$this->saveWechatUser($wx_user_info);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:周期更新当前用户信息
|
||||
* author:wh
|
||||
* @param $wx_user_info
|
||||
*/
|
||||
private function saveWechatUser($wx_user_info)
|
||||
{
|
||||
try {
|
||||
$wechat_user = $this->getWxUserByOpenid($wx_user_info['openid']);
|
||||
if (empty($wechat_user)) {
|
||||
return $this->insertInfo($wx_user_info);
|
||||
}
|
||||
//扩展,按周期更新,而不是不更新
|
||||
if (empty($wechat_user['update_time']) || time() - strtotime($wechat_user['update_time']) > 5 * 3600) {
|
||||
|
||||
return $this->updateUser($wx_user_info);
|
||||
}
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Tools::log_to_write_txt([
|
||||
'error' => '存储异常.' . $e->getMessage(),
|
||||
'wx_user_info' => $wx_user_info,
|
||||
'error_info' => $e->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:新增微信用户信息
|
||||
* author:wh
|
||||
* @param $wx_user_info \app\index\model\微信用户
|
||||
*
|
||||
* {
|
||||
* "openid":"or9D2vs863Ky5Py2ovkAiu9XFLO4",
|
||||
* "nickname":"起源果蔬副食大华",
|
||||
* "sex":0,
|
||||
* "language":"",
|
||||
* "city":"",
|
||||
* "province":"",
|
||||
* "country":"",
|
||||
* "headimgurl":"https://thirdwx.qlogo.cn/mmopen/vi_32/joiaA475nx3fJiaqx0ibdnWo4A7Q3uCgu2hsribI0ATLItORjuUgCSP8mCaBkqL61ibGojib4pQYX1djUhZpF5zoqpSg/132",
|
||||
* "privilege":[]
|
||||
* }
|
||||
*/
|
||||
private function insertInfo(array $wx_user_info)
|
||||
{
|
||||
|
||||
if (isset($wx_user_info['privilege'])) {
|
||||
$wx_user_info['privilege'] = json_encode($wx_user_info['privilege']);
|
||||
}
|
||||
$data = [
|
||||
'nickname' => $wx_user_info['nickname'],
|
||||
'country' => $wx_user_info['country'],
|
||||
'province' => $wx_user_info['province'],
|
||||
'city' => $wx_user_info['city'],
|
||||
'headimage' => $wx_user_info['headimgurl'],
|
||||
'language' => $wx_user_info['language'],
|
||||
'openid' => $wx_user_info['openid'],
|
||||
'unionid' => isset($wx_user_info['unionid']) ? $wx_user_info['unionid'] : '',
|
||||
'privilege' => $wx_user_info['privilege'],
|
||||
'sex' => $wx_user_info['sex'],
|
||||
//'arm_group' => '',
|
||||
//'score' => 0,//积分
|
||||
//'group_buy_earnings' => 0,//拼团收益
|
||||
//'water_drop_balance' => 0,//水滴
|
||||
];
|
||||
Db::table($this->wechat_user_table_name)
|
||||
->data($data)
|
||||
->insert();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:更新当前用户信息
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function updateUser($wx_user_info)
|
||||
{
|
||||
$data = [
|
||||
'nickname' => $wx_user_info['nickname'],
|
||||
'headimage' => $wx_user_info['headimgurl'],
|
||||
'unionid' => isset($wx_user_info['unionid']) ? $wx_user_info['unionid'] : '',
|
||||
];
|
||||
Db::table($this->wechat_user_table_name)
|
||||
->data($data)
|
||||
->where('openid', index_user_openid())
|
||||
->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:根据unionid获取用户信息
|
||||
* author:wh
|
||||
* @param string $unionid
|
||||
*/
|
||||
private function getWxUserByUnionid(string $unionid)
|
||||
{
|
||||
return Db::table($this->wechat_user_table_name)
|
||||
->field('id')
|
||||
->where('unionid', $unionid)
|
||||
->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取微信用户信息
|
||||
* author:wh
|
||||
* @param string $openid
|
||||
*/
|
||||
private function getWxUserByOpenid(string $openid)
|
||||
{
|
||||
return Db::table($this->wechat_user_table_name)
|
||||
//->field('id')
|
||||
->where('openid', $openid)
|
||||
->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:根据openid获取昵称
|
||||
* author:wh
|
||||
* @param string $openid
|
||||
*/
|
||||
private function getNicknameByOpenid(string $openid)
|
||||
{
|
||||
return Db::table($this->wechat_user_table_name)
|
||||
->where('openid', $openid)
|
||||
->value('nickname');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
213
superadmin/vendor/wanghua/general-utility-tools-php/src/ftp/Ftp.php
vendored
Normal file
213
superadmin/vendor/wanghua/general-utility-tools-php/src/ftp/Ftp.php
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/3/22} {9:42}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\ftp;
|
||||
|
||||
|
||||
/**
|
||||
* 利用ftp操作服务器文件(增删改查下载)
|
||||
* Class Ftp
|
||||
* @package wanghua\general_utility_tools_php\ftp
|
||||
*/
|
||||
class Ftp
|
||||
{
|
||||
public $off; // 返回操作状态(成功/失败)
|
||||
public $conn_id; // FTP连接
|
||||
|
||||
/**
|
||||
* FTP连接
|
||||
* $host -- FTP主机
|
||||
* $port -- 端口
|
||||
* $user -- 用户名
|
||||
* $password -- 密码
|
||||
*/
|
||||
function __construct(string $host,string $port='21',string $user,string $password)
|
||||
{
|
||||
set_time_limit(10);//防止连接超时
|
||||
|
||||
$this->conn_id = ftp_connect($host, $port);
|
||||
if(!$this->conn_id) throw new \Exception("FTP服务器连接失败");
|
||||
$login_res = ftp_login($this->conn_id, $user, $password);
|
||||
if(!$login_res) throw new \Exception("FTP服务器登陆失败");
|
||||
ftp_pasv($this->conn_id, false); // true打开被动模拟,默认关闭,如果总是失败,可试试true
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:打开被动模拟,登录后使用
|
||||
* author:wh
|
||||
*/
|
||||
function set_ftp_pasv(){
|
||||
ftp_pasv($this->conn_id, true); // true打开被动模拟
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* param $path 本地文件路径[包含文件名]
|
||||
* param $newPath 目标目录[包含文件名][默认存放在ftp用户被授权的根路径]
|
||||
* param bool $type 若目标目录不存在则新建
|
||||
*/
|
||||
function up_file($path, $newPath, $type = true)
|
||||
{
|
||||
if ($type) $this->dir_mkdirs($newPath);
|
||||
$this->off = ftp_put($this->conn_id, $newPath, $path, FTP_BINARY);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件上传失败,请检查权限及路径是否正确!'];
|
||||
return ['code'=>200, 'msg'=>'文件移动成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件
|
||||
* 特别注意:
|
||||
* $path 如果是当前目录,则必须以 “/”开始
|
||||
* 正确:/test2.zip
|
||||
* 错误:test2.zip
|
||||
* param $path 原路径(含文件名)
|
||||
* param $newPath 新路径(含文件名)
|
||||
* param bool $type 若目标目录不存在则新建
|
||||
*/
|
||||
function move_file($path, $newPath, $ftpbasedir, $type = true)
|
||||
{
|
||||
if ($type) $this->ftp_mksubdirs($ftpbasedir,$newPath);
|
||||
$this->off = ftp_rename($this->conn_id, $path, $newPath);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件移动失败,请检查权限及原路径是否正确!'];
|
||||
return ['code'=>200, 'msg'=>'文件移动成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件改名
|
||||
* param $path 原路径
|
||||
* param $newPath 新路径
|
||||
*/
|
||||
function rename_file($path, $newPath)
|
||||
{
|
||||
$this->off = ftp_rename($this->conn_id, $path, $newPath);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件改名失败,请检查权限及原路径是否正确!'];
|
||||
return ['code'=>200, 'msg'=>'文件改名成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制文件
|
||||
* 说明:由于FTP无复制命令,本方法变通操作为:下载后再上传到新的路径
|
||||
* param $path 原路径
|
||||
* param $newPath 新路径
|
||||
* param bool $type 若目标目录不存在则新建
|
||||
*/
|
||||
function copy_file($path, $newPath, $type = true)
|
||||
{
|
||||
$downPath = "c:/tmp.dat";
|
||||
$this->off = ftp_get($this->conn_id, $downPath, $path, FTP_BINARY);// 下载
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件复制失败,请检查权限及原路径是否正确!'];
|
||||
|
||||
$this->up_file($downPath, $newPath, $type);
|
||||
return ['code'=>200, 'msg'=>'文件复制成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* param $path 路径
|
||||
*/
|
||||
function del_file($path)
|
||||
{
|
||||
$this->off = ftp_delete($this->conn_id, $path);
|
||||
if (!$this->off)
|
||||
return ['code'=>500, 'msg'=>'文件删除失败,请检查权限及路径是否正确!'];
|
||||
|
||||
return ['code'=>200, 'msg'=>'文件删除成功'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除给定目录
|
||||
* 注:
|
||||
* 删除多个目录需重复调用
|
||||
* author:wh
|
||||
* param $dir
|
||||
* return bool
|
||||
*/
|
||||
function del_dir($dir){
|
||||
|
||||
|
||||
$children = ftp_nlist ($this->conn_id, $dir);
|
||||
if(!$children) {
|
||||
ftp_rmdir($this->conn_id, $dir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new \Exception('请确保目录中无内容');
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:生成目录
|
||||
* author:wh
|
||||
* param $ftpcon
|
||||
* param $ftpbasedir
|
||||
* param $ftpath
|
||||
*/
|
||||
function ftp_mksubdirs($ftpbasedir,$ftpath){
|
||||
ftp_chdir($this->conn_id, $ftpbasedir); // /var/www/uploads
|
||||
$parts = explode('/',$ftpath); // 2013/06/11/username
|
||||
|
||||
if(strpos($parts[count($parts)-1], '.')){
|
||||
unset($parts[count($parts)-1]);
|
||||
}
|
||||
|
||||
foreach($parts as $part){
|
||||
if(!ftp_chdir($this->conn_id, $part)){
|
||||
ftp_mkdir($this->conn_id, $part);
|
||||
ftp_chdir($this->conn_id, $part);
|
||||
//ftp_chmod($this->conn_id, 0777, $part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:使用ftp连接方式下载文件
|
||||
* author:wh
|
||||
* param string $local_file 文件本地的路径(如果文件已经存在,则会被覆盖)。
|
||||
* param string $remote_file 文件的远程路径。[默认查找ftp用户被授权的根路径]
|
||||
* return array
|
||||
*/
|
||||
function download(string $local_file, string $remote_file){
|
||||
// 进行ftp下载[默认保存在本地根目录]
|
||||
if (!ftp_get($this->conn_id, $local_file, $remote_file, FTP_BINARY)) {
|
||||
return ['code'=>500, 'msg'=>'ftp download fail'];
|
||||
}
|
||||
return ['code'=>200, 'msg'=>'ftp download success'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:判断ftp文件大小, 如果>-1, 说明文件存在;否则不存在.
|
||||
* author:wh
|
||||
* param $remote_file
|
||||
* return int
|
||||
*/
|
||||
function ftp_size($remote_file){
|
||||
return ftp_size($this->conn_id, $remote_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:返回当前目录
|
||||
* author:wh
|
||||
* return false|string
|
||||
*/
|
||||
function ftp_pwd(){
|
||||
return ftp_pwd($this->conn_id);
|
||||
}
|
||||
/**
|
||||
* 关闭FTP连接
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
ftp_close($this->conn_id);
|
||||
}
|
||||
}
|
||||
21
superadmin/vendor/wanghua/general-utility-tools-php/src/ftp/README.md
vendored
Normal file
21
superadmin/vendor/wanghua/general-utility-tools-php/src/ftp/README.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# PHP ftp类库
|
||||
#### 实现用ftp方式上传、复制、移动、重命名、删除、下载文件
|
||||
|
||||
##### 案例代码:
|
||||
```
|
||||
$ftp = new Ftp();//初始化
|
||||
//$ftp->up_file('D:\whua\test.zip','test.zip'); // 上传文件
|
||||
//$ftp->rename_file('test.zip','test-rename.zip'); // 移动文件
|
||||
//$ftp->move_file('/test2.zip','/testdir2/test2.zip', '/www/wwwroot/testftp/'); // 移动文件2
|
||||
//$ftp->copy_file('test.zip','test-copy.zip'); // 复制文件
|
||||
//$ftp->del_file('/www/aaa.txt'); // 删除具体文件
|
||||
$ftp->del_dir('/www'); // 删除目录(错误示范),必须精确到具体文件夹删除
|
||||
$ftp->del_dir('/ftp/test/copy-test/a-dir'); // 删除目录(正确示范),必须精确到具体文件夹删除,批量删除请多次调用
|
||||
|
||||
//下载文件
|
||||
//$ftp->download('D:\whua\projects\zc_game_admin3.0\data\local.zip', 'test.zip');
|
||||
//$ftp->close(); // 关闭FTP连接
|
||||
|
||||
//dump($ftp->ftp_pwd());die;
|
||||
//dump($ftp->ftp_size('test2.zip'));die;
|
||||
```
|
||||
188
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/AliCloudChatGPT.php
vendored
Normal file
188
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/AliCloudChatGPT.php
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
|
||||
/**
|
||||
* 阿里云百炼多模态chat
|
||||
*
|
||||
* 单模态请使用ChatGPT.php
|
||||
*
|
||||
* Class AliCloudMultiChatGPT
|
||||
* @package wanghua\general_utility_tools_php\gpt\chat
|
||||
*/
|
||||
class AliCloudChatGPT extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
private $messages = [];
|
||||
public $post_msg_body;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//调用父级
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:定制个性
|
||||
* author:wh
|
||||
* @param array $customize
|
||||
*/
|
||||
function setCustomize($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:定制个性(多模态)
|
||||
* author:wh
|
||||
* @param array $customize
|
||||
*/
|
||||
function setCustomizeMulti($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBefore($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAfter($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey) || empty($this->model)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
function chat($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
$answer .= $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
return $answer;
|
||||
}
|
||||
|
||||
function returnAnswer($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
$answer .= $data;
|
||||
return strlen($data);
|
||||
});
|
||||
return $answer;
|
||||
}
|
||||
|
||||
private function curlPostChat($question = '', $config = [], $callback)
|
||||
{
|
||||
$url = $this->url;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ["model" => $model, 'stream' => true, 'chatId'=>$this->chatId];
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$this->post_msg_body = $post_msg_body;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* desc:多模态场景chat(如多图多轮对话)
|
||||
* author:wh
|
||||
* @param $images
|
||||
* @param $text
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
function generateMultimodalContent($images, $text)
|
||||
{
|
||||
$url = $this->url;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$messages = [
|
||||
[
|
||||
'role' => 'user',
|
||||
'content' => array_map(function ($image) {
|
||||
return ['image' => $image];
|
||||
}, $images),
|
||||
],
|
||||
];
|
||||
|
||||
if (!empty($text)) {
|
||||
$messages[0]['content'][] = ['text' => $text];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'model' => $model,
|
||||
'input' => [
|
||||
'messages' => $messages,
|
||||
],
|
||||
];
|
||||
|
||||
$options = [
|
||||
'http' => [
|
||||
'header' => "Authorization: Bearer $apiKey\r\n" .
|
||||
"Content-Type: application/json\r\n",
|
||||
'method' => 'POST',
|
||||
'content' => json_encode($data),
|
||||
],
|
||||
];
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$result = file_get_contents($url, false, $context);
|
||||
|
||||
if ($result === FALSE) {
|
||||
throw new \Exception('Failed to fetch data from API');
|
||||
}
|
||||
|
||||
return json_decode($result, true);
|
||||
}
|
||||
}
|
||||
42
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/BaseChat.php
vendored
Normal file
42
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/BaseChat.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/3/26} {16:06}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class BaseChat
|
||||
{
|
||||
public $chatId = '';
|
||||
public function __construct()
|
||||
{
|
||||
$this->chatId = Tools::getMillisecond();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:将字符串里含有json_encode后的一维数组提取出来
|
||||
* @param $str
|
||||
* @return string
|
||||
*/
|
||||
function dealstr($str){
|
||||
$rep_str = str_replace("\n",'',$str);
|
||||
$rep_str = str_replace("\r",'',$rep_str);
|
||||
$rep_str = str_replace(" ",'',$rep_str);
|
||||
|
||||
$start_sit = strpos($rep_str,"[{");
|
||||
$end_sit = strpos($rep_str,"}]");
|
||||
|
||||
$last_json_str = substr($rep_str,$start_sit,$end_sit-$start_sit);
|
||||
|
||||
$last_json_str.="}]";
|
||||
|
||||
return $last_json_str;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
215
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/ChatGPT.php
vendored
Normal file
215
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/ChatGPT.php
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
|
||||
class ChatGPT extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
private $messages = [];
|
||||
public $post_msg_body;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//调用父级
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:定制个性
|
||||
* author:wh
|
||||
* @param array $customize
|
||||
*/
|
||||
function setCustomize($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBefore($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAfter($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey) || empty($this->model)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:对话,仅流式输出时调用该方法
|
||||
* author:wh
|
||||
* @param string $question
|
||||
* @param array $config
|
||||
* @param $answer_json_arr
|
||||
* @return string
|
||||
*/
|
||||
function chat($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
$answer .= $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
return $answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,因其不兼容故废弃
|
||||
* desc:非流式请求对话,一次返回结果
|
||||
* author:wh
|
||||
* @param string $question
|
||||
* @param array $config
|
||||
* @param $answer_json_arr
|
||||
* @return string
|
||||
*/
|
||||
function returnAnswer($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
$answer .= $data;
|
||||
return strlen($data);
|
||||
});
|
||||
return $answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 废弃
|
||||
* desc:一般未使用
|
||||
* author:wh
|
||||
* @param string $question
|
||||
* @param array $config
|
||||
* @param $callback
|
||||
*/
|
||||
private function curlPostChat($question = '', $config = [], $callback)
|
||||
{
|
||||
$url = $this->url;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ["model" => $model, 'stream' => true, 'chatId'=>$this->chatId];
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$this->post_msg_body = $post_msg_body;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc: 获取对话结果,非流式输出时调用该方法
|
||||
* author:wh
|
||||
* @param string $question
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
function getchatgptresponse($question = '', $config = [])
|
||||
{
|
||||
$url = $this->url;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$headers = ["Authorization: Bearer $apiKey", "Content-Type: application/json"];
|
||||
$post_msg_body = ["model" => $model, 'stream' => false];
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$this->post_msg_body = $post_msg_body;
|
||||
$post_msg_body = json_encode($post_msg_body);
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_msg_body);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
// 忽略 SSL 证书验证
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$response = curl_exec($ch);
|
||||
if (curl_error($ch)) {
|
||||
return ['code' => curl_errno($ch), 'msg' => curl_error($ch)];
|
||||
} else {
|
||||
curl_close($ch);
|
||||
return ['code' => 200, 'msg' => 'cURL ok', 'data' => $response];
|
||||
}
|
||||
}
|
||||
|
||||
private function parseData($data)
|
||||
{
|
||||
if (@json_decode($data)->choices[0]->message->content) {
|
||||
return json_decode($data)->choices[0]->message->content;
|
||||
}
|
||||
$data = str_replace('data: {', '{', $data);
|
||||
$data = rtrim($data, "\n\n");
|
||||
if (strpos($data, 'data: [DONE]') !== false) {
|
||||
return 'data: [DONE]';
|
||||
} else {
|
||||
if (false !== strpos($data, "\n\n")) {
|
||||
$exp_arr = explode("\n\n", $data);
|
||||
$str = '';
|
||||
try {
|
||||
for ($i = 0; $i < count($exp_arr) - 1; $i++) {
|
||||
$jsondecode_arr = json_decode($exp_arr[$i], true);
|
||||
$str .= $jsondecode_arr['choices'][0]['delta']['content'];
|
||||
}
|
||||
return $str;
|
||||
} catch (\Exception $e) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
if ($data['choices'][0]['finish_reason'] == 'stop') {
|
||||
return 'data: [DONE]';
|
||||
} elseif ($data['choices'][0]['finish_reason'] == 'length') {
|
||||
return 'data: [CONTINUE]';
|
||||
}
|
||||
return $data['choices'][0]['delta']['content'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class F37A49CDED4199801B05D5FFFAF78E010 extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
public $chatId = '';
|
||||
public $detail = false;
|
||||
private $messages = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
function s8EB5A47634F626B142D2A93E9BAF009F($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function s3ASCD163240094B8C736D3A1A5CSD($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function s326723D163240094B8C736D3A1A5CAD3($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function c2111E682402A3955B616FA5795DEDE4F()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
function cAA8AF3EBE14831A7CD1B6D1383A03755($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->c8ECA4C82960B4611B076D51EF8ADF979($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
}
|
||||
|
||||
private function c8ECA4C82960B4611B076D51EF8ADF979($question = '', $config = [], $callback)
|
||||
{
|
||||
$this->c2111E682402A3955B616FA5795DEDE4F();
|
||||
$url = $this->url;;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$chatId = $this->chatId;
|
||||
$detail = $this->detail;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ['detail' => $detail, 'stream' => true,];
|
||||
if ($detail) {
|
||||
$post_msg_body['detail'] = $detail;
|
||||
}
|
||||
if ($chatId) {
|
||||
$post_msg_body['chatId'] = $chatId;
|
||||
}
|
||||
if ($model) {
|
||||
$post_msg_body['model'] = $model;
|
||||
}
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
private function pCD736318A127E12426EED8700FF2BF28($data)
|
||||
{
|
||||
if (@json_decode($data)->choices[0]->message->content) {
|
||||
return json_decode($data)->choices[0]->message->content;
|
||||
}
|
||||
$data = str_replace('data: {', '{', $data);
|
||||
$data = rtrim($data, "\n\n");
|
||||
if (strpos($data, 'data: [DONE]') !== false) {
|
||||
return 'data: [DONE]';
|
||||
} else {
|
||||
if (false !== strpos($data, "\n\n")) {
|
||||
$exp_arr = explode("\n\n", $data);
|
||||
$str = '';
|
||||
try {
|
||||
for ($i = 0; $i < count($exp_arr) - 1; $i++) {
|
||||
$jsondecode_arr = json_decode($exp_arr[$i], true);
|
||||
$str .= $jsondecode_arr['choices'][0]['delta']['content'];
|
||||
}
|
||||
return $str;
|
||||
} catch (\Exception $e) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
if ($data['choices'][0]['finish_reason'] == 'stop') {
|
||||
return 'data: [DONE]';
|
||||
} elseif ($data['choices'][0]['finish_reason'] == 'length') {
|
||||
return 'data: [CONTINUE]';
|
||||
}
|
||||
return $data['choices'][0]['delta']['content'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
148
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/FastGPT.php
vendored
Normal file
148
superadmin/vendor/wanghua/general-utility-tools-php/src/gpt/chat/FastGPT.php
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php namespace wanghua\general_utility_tools_php\gpt\chat;
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class FastGPT extends BaseChat
|
||||
{
|
||||
public $url = '';
|
||||
public $apiKey = '';
|
||||
public $model = '';
|
||||
public $chatId = '';
|
||||
public $detail = false;
|
||||
private $messages = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//调用父级
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:定制个性
|
||||
* author:wh
|
||||
* @param array $customize
|
||||
*/
|
||||
function setCustomize($customize = [])
|
||||
{
|
||||
if ($customize) {
|
||||
foreach ($customize as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBefore($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setAfter($describe = [])
|
||||
{
|
||||
if ($describe) {
|
||||
foreach ($describe as $item) {
|
||||
$this->messages[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->apiKey)) {
|
||||
throw new Exception('PARAMS ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
function chat($question = '', $config = [], &$answer_json_arr)
|
||||
{
|
||||
$answer = '';
|
||||
$this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
|
||||
$answer_json_arr[] = $data;
|
||||
echo $data;
|
||||
ob_flush();
|
||||
flush();
|
||||
return strlen($data);
|
||||
});
|
||||
}
|
||||
|
||||
private function curlPostChat($question = '', $config = [], $callback)
|
||||
{
|
||||
$this->check();
|
||||
$url = $this->url;;
|
||||
$apiKey = $this->apiKey;
|
||||
$model = $this->model;
|
||||
$chatId = $this->chatId;
|
||||
$detail = $this->detail;
|
||||
$headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
|
||||
$post_msg_body = ['detail' => $detail, 'stream' => true, 'chatId'=>$this->chatId];
|
||||
if ($detail) {
|
||||
$post_msg_body['detail'] = $detail;
|
||||
}
|
||||
if ($chatId) {
|
||||
$post_msg_body['chatId'] = $chatId;
|
||||
}
|
||||
if ($model) {
|
||||
$post_msg_body['model'] = $model;
|
||||
}
|
||||
if ($config) {
|
||||
foreach ($config as $key => $val) {
|
||||
$post_msg_body[$key] = $val;
|
||||
}
|
||||
}
|
||||
if ($question) {
|
||||
$this->messages[] = ["role" => "user", "content" => $question];
|
||||
}
|
||||
$post_msg_body['messages'] = $this->messages;
|
||||
$postData = json_encode($post_msg_body);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
|
||||
curl_exec($ch);
|
||||
}
|
||||
|
||||
private function parseData($data)
|
||||
{
|
||||
if (@json_decode($data)->choices[0]->message->content) {
|
||||
return json_decode($data)->choices[0]->message->content;
|
||||
}
|
||||
$data = str_replace('data: {', '{', $data);
|
||||
$data = rtrim($data, "\n\n");
|
||||
if (strpos($data, 'data: [DONE]') !== false) {
|
||||
return 'data: [DONE]';
|
||||
} else {
|
||||
if (false !== strpos($data, "\n\n")) {
|
||||
$exp_arr = explode("\n\n", $data);
|
||||
$str = '';
|
||||
try {
|
||||
for ($i = 0; $i < count($exp_arr) - 1; $i++) {
|
||||
$jsondecode_arr = json_decode($exp_arr[$i], true);
|
||||
$str .= $jsondecode_arr['choices'][0]['delta']['content'];
|
||||
}
|
||||
return $str;
|
||||
} catch (\Exception $e) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
$data = @json_decode($data, true);
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
if ($data['choices'][0]['finish_reason'] == 'stop') {
|
||||
return 'data: [DONE]';
|
||||
} elseif ($data['choices'][0]['finish_reason'] == 'length') {
|
||||
return 'data: [CONTINUE]';
|
||||
}
|
||||
return $data['choices'][0]['delta']['content'] ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
224
superadmin/vendor/wanghua/general-utility-tools-php/src/html/Html.php
vendored
Normal file
224
superadmin/vendor/wanghua/general-utility-tools-php/src/html/Html.php
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/19} {11:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\html;
|
||||
|
||||
|
||||
/**
|
||||
* PHP操作html元素【不包含修改】
|
||||
* Class Html
|
||||
* @package wanghua\general_utility_tools_php\html
|
||||
*/
|
||||
class Html
|
||||
{
|
||||
/**
|
||||
* desc:提取a标签
|
||||
* 返回标签和标签包含的内容
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @return null
|
||||
*/
|
||||
function getAElement(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<a .*?>.*?<\/a>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:提取div标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getDiv(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<div .*?>.*?<\/div>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取img标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getImg(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<img .*?>.*?<\/img>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取span标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getSpan(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<span .*?>.*?<\/span>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取ul标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getUl(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<ul .*?>.*?<\/ul>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取li标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getLi(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<li .*?>.*?<\/li>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取table标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getTable(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<table .*?>.*?<\/table>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取table tr标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getTableTr(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<tr .*?>.*?<\/tr>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
/**
|
||||
* desc:提取table td标签
|
||||
* author:wh
|
||||
* @param string $html
|
||||
* @return null
|
||||
*/
|
||||
function getTableTd(string $html){
|
||||
$a_array = null;
|
||||
$reg="/<td .*?>.*?<\/td>/";
|
||||
preg_match_all($reg,$html,$a_array);
|
||||
return $a_array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:提取a标签属性
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @return array
|
||||
*/
|
||||
function getAAttribute($html){
|
||||
$aarray = null;
|
||||
$reg1="/<a .*?>.*?<\/a>/";
|
||||
preg_match_all($reg1,$html,$aarray);
|
||||
|
||||
$hrefarray=null;//这个存放的是匹配出来的href的链接地址
|
||||
$acontent=null;//存放匹配出来的a标签的内容
|
||||
$reg2="/href=\"([^\"]+)/";
|
||||
$a_arr = [];
|
||||
for($i=0;$i<count($aarray[0]);$i++){
|
||||
preg_match_all($reg2,$aarray[0][$i],$hrefarray);
|
||||
//这里输出的就是遍历出来的所有a标签的链接
|
||||
$a_arr['url'] = $hrefarray[1][0];
|
||||
|
||||
//拿出《a》标签的内容
|
||||
$reg3="/>(.*)<\/a>/";
|
||||
preg_match_all($reg3,$aarray[0][$i],$acontent);
|
||||
//这里输出的就是a标签的文字了
|
||||
$a_arr['text'] = $acontent[1][0];
|
||||
}
|
||||
return $a_arr;
|
||||
}
|
||||
/**
|
||||
* desc:提取img标签src(提取图片链接)
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @return array
|
||||
*/
|
||||
function getImgAttribute($html){
|
||||
$aarray = null;
|
||||
$reg1="/<img .*?>.*?<\/img>/";
|
||||
preg_match_all($reg1,$html,$aarray);
|
||||
|
||||
$hrefarray=null;//这个存放的是匹配出来的href的链接地址
|
||||
$acontent=null;//存放匹配出来的a标签的内容
|
||||
$reg2="/src=\"([^\"]+)/";
|
||||
$a_arr = [];
|
||||
for($i=0;$i<count($aarray[0]);$i++){
|
||||
preg_match_all($reg2,$aarray[0][$i],$hrefarray);
|
||||
//这里输出的就是遍历出来的所有a标签的链接
|
||||
$a_arr['url'] = $hrefarray[1][0];
|
||||
|
||||
//拿出《a》标签的内容
|
||||
$reg3="/>(.*)<\/img>/";
|
||||
preg_match_all($reg3,$aarray[0][$i],$acontent);
|
||||
//这里输出的就是a标签的文字了
|
||||
$a_arr['text'] = $acontent[1][0];
|
||||
}
|
||||
return $a_arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除字符串
|
||||
* author:wh
|
||||
*/
|
||||
function clearHtml($html, $str){
|
||||
return str_replace($str,'',$html);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:正则提取html元素的内容
|
||||
*
|
||||
* 用法eg:
|
||||
* $temp = '
|
||||
<div class="num">1</div>
|
||||
<div class="num">2</div>
|
||||
<div class="num">3</div>
|
||||
<div class="num">4</div>
|
||||
<div class="num1">3</div>
|
||||
<div class="num2">4</div>
|
||||
<div class="num">5</div>';
|
||||
$result = $this->get_tag_data($html,"div","class","num");
|
||||
*
|
||||
* author:wh
|
||||
* @param $html
|
||||
* @param $tag
|
||||
* @param $class
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
function getTagData($html,$tag,$class,$value){
|
||||
//$value 为空,则获取class=$class的所有内容
|
||||
$regex = $value ? "/<$tag.*?$class=\"$value\".*?>(.*?)<\/$tag>/is" : "/<$tag.*?$class=\".*?$value.*?\".*?>(.*?)<\/$tag>/is";
|
||||
preg_match_all($regex,$html,$matches,PREG_PATTERN_ORDER);
|
||||
//返回数组 ,指定标签内容
|
||||
return $matches[1];
|
||||
}
|
||||
}
|
||||
126
superadmin/vendor/wanghua/general-utility-tools-php/src/html/Htmlcontent.php
vendored
Normal file
126
superadmin/vendor/wanghua/general-utility-tools-php/src/html/Htmlcontent.php
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/11/8} {15:05}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\html;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Htmlcontent
|
||||
{
|
||||
|
||||
/**
|
||||
* [curlHtml 获取页面信息]
|
||||
* 使用curl获取html页面内容
|
||||
* @param [type] $url [网址]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
|
||||
function curlHtml($url)
|
||||
{
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, array(
|
||||
CURLOPT_URL => "{$url}",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_MAXREDIRS => 10,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST => "GET",
|
||||
CURLOPT_HTTPHEADER => array(
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
|
||||
"Accept-Encoding: gzip, deflate, br",
|
||||
"Accept-Language: zh-CN,zh;q=0.9",
|
||||
"Cache-Control: no-cache",
|
||||
"Connection: keep-alive",
|
||||
"Pragma: no-cache",
|
||||
"Upgrade-Insecure-Requests: 1",
|
||||
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
|
||||
"cache-control: no-cache"
|
||||
),
|
||||
));
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$response = curl_exec($curl);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
if ($err) return false;
|
||||
else return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* [get_tag_data 使用正则获取html内容中指定的内容]
|
||||
* @param [type] $html [爬取的页面内容]
|
||||
* @param [type] $tag [要查找的标签]
|
||||
* @param [type] $attr [要查找的属性名]
|
||||
* @param [type] $value [属性名对应的值]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
function get_tag_data($html, $tag, $attr, $value)
|
||||
{
|
||||
|
||||
// var_dump($tag, $attr, $value);
|
||||
$regex = "/<$tag.*?$attr=\".*?$value.*?\".*?>(.*?)<\/$tag>/is";
|
||||
// var_dump($regex);
|
||||
preg_match_all($regex, $html, $matches, PREG_PATTERN_ORDER);
|
||||
//var_dump($matches);die;
|
||||
$data = isset($matches[1]) ? $matches[1] : '';
|
||||
// var_dump($data);die;
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* [get_html_data 使用xpath对获取到的html内容进行处理]
|
||||
* @param [type] $html [爬取的页面内容]
|
||||
* @param [type] $path [Xpath语句]
|
||||
* @param integer $tag [类型 0内容 1标签内容 自定义标签]
|
||||
* @param boolean $type [单个 还是多个(默认单个时输出单个)]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
|
||||
function get_html_data($html, $path, $tag = 1, $type = true)
|
||||
{
|
||||
$dom = new \DOMDocument();
|
||||
@$dom->loadHTML("<?xml encoding='UTF-8'>" . $html); // 从一个字符串加载HTML并设置UTF8编码
|
||||
$dom->normalize(); // 使该HTML规范化
|
||||
$xpath = new \DOMXPath($dom); //用DOMXpath加载DOM,用于查询
|
||||
$contents = $xpath->query($path); // 获取所有内容
|
||||
$data = [];
|
||||
foreach ($contents as $value) {
|
||||
if ($tag == 1) {
|
||||
$data[] = $value->nodeValue; // 获取不带标签内容
|
||||
} elseif ($tag == 2) {
|
||||
$data[] = $dom->saveHtml($value); // 获取带标签内容
|
||||
} else {
|
||||
$data[] = $value->attributes->getNamedItem($tag)->nodeValue; // 获取attr内容
|
||||
}
|
||||
}
|
||||
if (count($data) == 1) {
|
||||
$data = $data[0];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
//调用
|
||||
public function get_content($url,$tag,$attr='',$value='')
|
||||
{
|
||||
//$url = input('url') ?? '';
|
||||
//$tag = g('tag') ?? '';
|
||||
//$attr = g('attr') ?? '';
|
||||
//$value = g('value') ?? '';
|
||||
if (empty($url) || empty($tag)) {
|
||||
return Tools::set_res(4, '缺少关键参数!');
|
||||
}
|
||||
|
||||
$html = $this->curlHtml($url);
|
||||
//使用正则获取
|
||||
$data = $this->get_tag_data($html, $tag, $attr, $value);
|
||||
//Xpath方法,暂未搞明白
|
||||
// $data = $this->get_html_data($html, $path, $tag = 1, $type = true);
|
||||
return Tools::set_res(1, 'ok!', $data);
|
||||
}
|
||||
}
|
||||
611
superadmin/vendor/wanghua/general-utility-tools-php/src/http/Curl.php
vendored
Normal file
611
superadmin/vendor/wanghua/general-utility-tools-php/src/http/Curl.php
vendored
Normal file
@@ -0,0 +1,611 @@
|
||||
<?php
|
||||
/*
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/03/30} {09:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\http;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* desc:cUrl网络库【推荐】
|
||||
*
|
||||
* author:wh
|
||||
* Class Curl
|
||||
* @package wanghua\general_utility_tools_php\http
|
||||
*/
|
||||
class Curl
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:[推荐] curl请求
|
||||
*
|
||||
* 如果是文件流,则需要用getContents()方法获取
|
||||
* eg: $res->getBody()->getContents();
|
||||
*
|
||||
* author:wh
|
||||
* @param $url
|
||||
* @param string $method
|
||||
* @param false[] $config
|
||||
* @param array $headers
|
||||
* @return mixed
|
||||
*/
|
||||
static function request($url,$method='POST',$config=['verify' => false],$headers=[]){
|
||||
$client = new Client($config);
|
||||
//$headers = [
|
||||
// //'User-Agent' => 'Apifox/1.0.0 (https://apifox.com)',
|
||||
// //'Accept' => '*/*',
|
||||
// //'Host' => 'vits_simple.excn.top',
|
||||
// //'Connection' => 'keep-alive'
|
||||
//];
|
||||
$request = new Request($method, $url, $headers);
|
||||
$res = $client->sendAsync($request)->wait();
|
||||
//$res->getBody()->getContents();//如果是文件流,则需要用getContents()方法获取
|
||||
return $res->getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:php curl远程上传文件,提交到远程服务器,适用于上传多个文件(文件类型不限)
|
||||
*
|
||||
* 应用场景:
|
||||
* 前端->后端A->后端B
|
||||
* 说明:前端发起文件上传,后端A接收到文件后,将文件使用guzzlehttp/guzzle上传到后端B,后端B将文件处理
|
||||
*
|
||||
* 当前版本依赖:"guzzlehttp/guzzle": "^7.8"
|
||||
*
|
||||
* author:wh
|
||||
* @param $url 远程地址
|
||||
* @param $params 提交参数
|
||||
* @param array $config 配置项
|
||||
*/
|
||||
function curlRemoteUploadFiles($url,$params, $config=['verify' => false]){
|
||||
// 创建 Guzzle HTTP 客户端实例
|
||||
$client = new Client($config);
|
||||
|
||||
// 定义要上传的文件列表
|
||||
$files = [
|
||||
//[
|
||||
// 'name' => 'file1', // 服务器接收的文件字段名
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\dc1c441d81d48565ac6817b89d0f8bef.mp4', 'r'), // 文件路径
|
||||
// 'filename' => 'dc1c441d81d48565ac6817b89d0f8bef.mp4', // 文件名,可自定义
|
||||
//],
|
||||
//[
|
||||
// 'name' => 'files',
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\f80179b23b60619fba8033bfd64f8817.mp4', 'r'),
|
||||
// 'filename' => 'f80179b23b60619fba8033bfd64f8817.mp4',
|
||||
//],
|
||||
//['name'=>'prompt','contents'=>$prompt],
|
||||
//['name'=>'tts_url','contents'=>$tts_url]
|
||||
// 可以继续添加更多文件...
|
||||
];
|
||||
foreach ($params as $key=>$val){
|
||||
$files[] = ['name'=>$key,'contents'=>$val];
|
||||
}
|
||||
$controller = \request()->controller();
|
||||
$action = \request()->action();
|
||||
$save_path = Tools::get_root_path() . "public/uploads/{$controller}/{$action}/";
|
||||
$files_obj = \request()->file('files');
|
||||
foreach ($files_obj as $k=>$file) {
|
||||
if ($file->check()) {
|
||||
$save_res = $file->move($save_path);
|
||||
$fileinfo = $file->getInfo();
|
||||
// 使用CURLFile包装文件路径以供上传
|
||||
$filename = $save_path.date('Ymd').'/'.$save_res->getFilename();
|
||||
$files[] = [
|
||||
'name'=>"files",//服务器接收的文件字段名
|
||||
'contents'=>Utils::tryFopen($filename, 'r'),
|
||||
'filename'=>$fileinfo['name'],//可自定义
|
||||
];
|
||||
}
|
||||
//else {
|
||||
// return json(['code' => -1, 'msg' => '文件上传失败: ' . $file->getError()]);
|
||||
//}
|
||||
}
|
||||
|
||||
// 构建多部分表单数据
|
||||
$multipartStream = new MultipartStream($files);
|
||||
$boundary = $multipartStream->getBoundary();
|
||||
$headers = [
|
||||
'Content-Type' => "multipart/form-data; boundary={$boundary}",
|
||||
];
|
||||
|
||||
// 准备请求体
|
||||
$body = $multipartStream->getContents();
|
||||
|
||||
// 发起 POST 请求
|
||||
try {
|
||||
$response = $client->request('POST', $url, [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
]);
|
||||
|
||||
// 处理响应
|
||||
$responseBody = (string) $response->getBody();
|
||||
//echo "Server response: " . $responseBody;
|
||||
return Tools::set_ok('ok',$responseBody);
|
||||
} catch (\GuzzleHttp\Exception\RequestException $e) {
|
||||
// 错误处理
|
||||
//echo "Error: " . $e->getMessage();
|
||||
return Tools::set_fail("Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url
|
||||
* @param int $timeout
|
||||
* @return bool|int|string
|
||||
*/
|
||||
static function curl_get(string $url, int $timeout = 10, $header=[])
|
||||
{
|
||||
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
$curl = curl_init();
|
||||
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
//curl_setopt($curl, CURLOPT_SSLVERSION, 3);
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
// 超时设置,以秒为单位
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//print "Error: ".curl_errno($curl).'-' . curl_error($curl);
|
||||
//返回错误码
|
||||
return ['code' => curl_errno($curl), 'msg' => curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code' => 200, 'msg' => 'cURL ok', 'data' => $data];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* POST 表单
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param $postdata 传输的数据,数组格式 (跟$header的参数相关)
|
||||
* @return bool|int|string
|
||||
*/
|
||||
static function curl_post(string $url, $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code'=>200, 'msg'=>'cURL ok', 'data'=>$data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发即忘的异步HTTP请求(无需等待响应)
|
||||
*
|
||||
* 环境:[linux]
|
||||
*
|
||||
* @param string $url 目标URL
|
||||
* @param array $data POST数据(可选)
|
||||
*/
|
||||
static function asyncPostWithPopen(string $url, array $data = [])
|
||||
{
|
||||
$escapedUrl = escapeshellarg($url);
|
||||
$postData = !empty($data) ? ' -d ' . escapeshellarg(http_build_query($data)) : '';
|
||||
|
||||
// 构建命令(nohup 确保脱离终端)
|
||||
$cmd = sprintf(
|
||||
'nohup curl -s -X POST %s %s > /dev/null 2>&1 </dev/null &',
|
||||
$escapedUrl,
|
||||
$postData
|
||||
);
|
||||
|
||||
$descriptors = [
|
||||
0 => ['file', '/dev/null', 'r'],
|
||||
1 => ['file', '/dev/null', 'w'],
|
||||
2 => ['file', '/dev/null', 'w'],
|
||||
];
|
||||
|
||||
$proc = proc_open($cmd, $descriptors, $pipes, null, null, ['bypass_shell' => false]);
|
||||
|
||||
if (!is_resource($proc)) {
|
||||
Tools::log_to_write_txt('异步请求启动失败: ' . $cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 非阻塞关闭
|
||||
proc_get_status($proc);
|
||||
proc_close($proc);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST 查询参数
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,http_build_query查询参数格式
|
||||
* @return bool|int|string
|
||||
*/
|
||||
static function curl_post_build_query(string $url, $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postdata));
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code'=>200, 'msg'=>'ok', 'data'=>$data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST json
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,json格式
|
||||
* @return 返回数组格式
|
||||
*/
|
||||
static function curl_post_json(string $url, $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postdata,JSON_UNESCAPED_UNICODE));
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code'=>200, 'msg'=>'cURL ok', 'data'=>$data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST json ,成功直接返回请求结果,错误返回数组
|
||||
*
|
||||
* 注:此方法不是表单提交
|
||||
*
|
||||
* author:wh
|
||||
* @param string $url 是请求的链接
|
||||
* @param array $postdata 传输的数据,最终会转换为json格式请求
|
||||
* @return 直接返回请求数据,适合请求第三方返回BUFFER数据流的接口
|
||||
*/
|
||||
static function curl_post_json_return_buffer(string $url, array $postdata, $header=[]) {
|
||||
$timeout = 4;
|
||||
$connect_timeout = 1;
|
||||
$set_time_limit = 5;
|
||||
if($timeout + $connect_timeout < $set_time_limit) throw new \Exception('脚本超时值必须大于等于连接超时与请求处理超时之和');
|
||||
set_time_limit($set_time_limit);
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
//发起连接前等待的时间,如果设置为0,则无限等待。
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connect_timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postdata,JSON_UNESCAPED_UNICODE));
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code'=>curl_errno($curl), 'msg'=>curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* POST [流]
|
||||
*
|
||||
* [请求Java接口]
|
||||
*
|
||||
* 思考:1、Java端如果用文件流的方式去获取数据,调用此方法
|
||||
*
|
||||
* @param $url
|
||||
* @param $postdata
|
||||
* @param int $timeout
|
||||
* @return array
|
||||
* @link
|
||||
* @example
|
||||
* @see
|
||||
*/
|
||||
static function java_curl_post_file_request($url, $postdata, $timeout = 10, $header=[])
|
||||
{
|
||||
|
||||
$header = $header?:array(
|
||||
'Accept: application/json',
|
||||
);
|
||||
|
||||
//初始化
|
||||
$curl = curl_init();
|
||||
//设置抓取的url
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
//设置头文件的信息作为数据流输出
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
//设置获取的信息以文件流的形式返回,而不是直接输出。
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
// 超时设置
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
||||
|
||||
// 超时设置,以毫秒为单位
|
||||
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
|
||||
|
||||
// 设置请求头
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
|
||||
//设置post方式提交
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
|
||||
//执行命令
|
||||
$data = curl_exec($curl);
|
||||
|
||||
// 显示错误信息
|
||||
if (curl_error($curl)) {
|
||||
//返回错误码
|
||||
return ['code' => curl_errno($curl), 'msg' => curl_error($curl)];
|
||||
} else {
|
||||
//关闭句柄
|
||||
curl_close($curl);
|
||||
// 返回的内容
|
||||
return ['code' => 200, 'msg' => 'ok', 'data' => $data];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* 统一请求 GET/POST请求
|
||||
*
|
||||
* 注:此设置允许header重定向,适合部分请求头中携带参数的接口,如请求头携带token
|
||||
*
|
||||
* @param String $url 接口地址
|
||||
*/
|
||||
static function curl_request($url, $method = 'GET',$data=null,$header=array(),$call_back=null)
|
||||
{
|
||||
set_time_limit(30);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
}
|
||||
if($method == 'POST'){
|
||||
if($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
if($call_back){
|
||||
//使用此特性前除非你清楚理解回调函数,否则不推荐
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $call_back);
|
||||
}
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return [
|
||||
'status' => 'error',
|
||||
'message' => 'curl 错误信息: ' . curl_error($ch)
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 弃用
|
||||
* desc:php curl模拟文件上传
|
||||
* post
|
||||
* author:wh
|
||||
* @param $url 提交地址
|
||||
* @param $params 表单参数
|
||||
* @param $files 上传文件
|
||||
* @param $header 请求头
|
||||
* @return array
|
||||
*/
|
||||
static function curlFileUpload($url,$params,$files,$header)
|
||||
{
|
||||
// 初始化cURL会话
|
||||
$ch = curl_init();
|
||||
$header = $header ?: array(
|
||||
'Accept: application/json',
|
||||
'Content-Type: multipart/form-data'
|
||||
);
|
||||
// 合并文件和其他字段数据
|
||||
$data = array_merge($params, $files);
|
||||
|
||||
// 设置cURL选项
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
// 设置请求头
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
|
||||
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
|
||||
// 执行cURL请求
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return ['code' => curl_errno($ch), 'msg' => curl_error($ch)];
|
||||
}
|
||||
//关闭句柄
|
||||
curl_close($ch);
|
||||
// 返回的内容
|
||||
return ['code' => 200, 'msg' => 'cURL ok', 'data' => $result];
|
||||
}
|
||||
|
||||
}
|
||||
76
superadmin/vendor/wanghua/general-utility-tools-php/src/image/Image.php
vendored
Normal file
76
superadmin/vendor/wanghua/general-utility-tools-php/src/image/Image.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/1/17} {13:07}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\image;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Image
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:将二进制字符串转为PNG图片
|
||||
*
|
||||
* 应用场景:当你的图片来源是buffer二进制时
|
||||
*
|
||||
* 实战场景:微信小程序获取小程序码,调用获取微信小程序码接口时,微信接口返回的是图片Buffer二进制,
|
||||
* 这时候需要前端转换为图片,有时候与你和做的前端技术需要你转换为图片,再把图片路径传给他直接使用
|
||||
*
|
||||
* author:wh
|
||||
* @param $binary 图片的Buffer二进制数据
|
||||
* @param $img_save_path 系统保存路径(传public网站根目录下面的路径)
|
||||
* @param $filename 要保存的文件名称,必须带后缀名
|
||||
*/
|
||||
static function binaryToImage($binary,$img_save_path,$filename){
|
||||
// 获取二进制数据(这里假设从文件或其他地方获得)
|
||||
//$binaryData = file_get_contents($binary); // 替换成真正的路径
|
||||
|
||||
// 创建图像资源
|
||||
$imageResource = imagecreatefromstring($binary);
|
||||
|
||||
$img_save_path = Tools::get_root_path().'public/'.$img_save_path;
|
||||
if(!file_exists($img_save_path)){
|
||||
mkdir($img_save_path,0777,true);
|
||||
}
|
||||
// 保存图像到指定位置
|
||||
imagepng($imageResource, $img_save_path.$filename); // 替换成想要保存的路径及名称
|
||||
|
||||
// 释放内存并关闭图像资源
|
||||
imagedestroy($imageResource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:从富文本(任意文本)中提取图片链接
|
||||
*
|
||||
* 使用场景
|
||||
* 在需要的任意场景调用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
static function extractImageUrls(string $html){
|
||||
// $html = <<<HTML
|
||||
//<p>这是一张图片:<a href="http://example.com/images/photo1.jpg" target="_blank">点击查看</a></p>
|
||||
//<p>还有一张:<img src="http://example.com/images/photo2.jpg" alt="Another Photo"></p>
|
||||
//<p>图片链接也可以是:<img src="https://example.com/images/photo3.png"></p>
|
||||
//HTML;
|
||||
// 使用正则表达式匹配图片链接
|
||||
$pattern = '/(https?:\/\/[^\s]+\.(?:jpg|jpeg|png|gif))/i';
|
||||
$images = [];
|
||||
if (preg_match_all($pattern, $html, $matches)) {
|
||||
//echo "找到的图片链接如下:\n";
|
||||
foreach ($matches[0] as $match) {
|
||||
$images[] = $match;
|
||||
}
|
||||
} else {
|
||||
return $images;
|
||||
}
|
||||
return $images;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user