更新组件
This commit is contained in:
parent
78a9655d10
commit
d82f29fbe5
@ -341,11 +341,11 @@ class Addons extends AdminController
|
||||
{
|
||||
$name = input('name');
|
||||
$config = get_addons_config($name);
|
||||
// halt($config);
|
||||
|
||||
if(empty($config)) return json(['code'=>-1,'msg'=>'无配置项!无需操作']);
|
||||
if(Request::isAjax()){
|
||||
$params = Request::param('params/a',[],'trim');
|
||||
// halt($params);
|
||||
|
||||
if ($params) {
|
||||
foreach ($config as $k => &$v) {
|
||||
if (isset($params[$k])) {
|
||||
@ -359,6 +359,9 @@ class Addons extends AdminController
|
||||
$value = $params[$k];
|
||||
$v['content'] = $value;
|
||||
$v['value'] = $value;
|
||||
} elseif ($v['type'] == 'select'){
|
||||
$value = [(int)$params[$k]];
|
||||
$v['value'] = $value;
|
||||
} else {
|
||||
$value = $params[$k];
|
||||
}
|
||||
@ -371,7 +374,7 @@ class Addons extends AdminController
|
||||
}
|
||||
return json(['code'=>0,'msg'=>'配置成功!']);
|
||||
}
|
||||
//halt($config);
|
||||
|
||||
//模板引擎初始化
|
||||
$view = ['formData'=>$config,'title'=>'title'];
|
||||
View::assign($view);
|
||||
|
@ -4,5 +4,5 @@ return [
|
||||
// 检测安装
|
||||
\app\middleware\Install::class,
|
||||
// 权限检测
|
||||
app\middleware\Auth::class,
|
||||
app\middleware\AdminAuth::class,
|
||||
];
|
@ -4,6 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<title>{block name="title"}TaoLerCMS后台管理系统{/block}</title>
|
||||
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
|
||||
{block name="link"}{/block}
|
||||
</head>
|
||||
<body>
|
||||
{block name="body"}内容{/block}
|
||||
|
66
app/common/lib/JwtAuth.php
Normal file
66
app/common/lib/JwtAuth.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\common\lib;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
class JwtAuth
|
||||
{
|
||||
// 访问密钥
|
||||
const KEY = 'adsfhgkjl1324675809';
|
||||
// 签发者
|
||||
const ISS = 'www.aieok.com';
|
||||
// 接收者
|
||||
const AUD = 'www.aieok.com';
|
||||
// 加密算法
|
||||
const ALG = 'HS256';
|
||||
|
||||
/** 对数据进行编码
|
||||
* @param array $data
|
||||
*/
|
||||
|
||||
public static function encode(array $data)
|
||||
{
|
||||
$time = time();
|
||||
$payload = [
|
||||
"iss" => self::ISS,
|
||||
"aud" => self::AUD,
|
||||
"iat" => $time,
|
||||
"nbf" => $time,
|
||||
'exp' => $time + 86400 * 30,
|
||||
'data' => $data,
|
||||
];
|
||||
$token = JWT::encode($payload, self::KEY, self::ALG);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 对 token 进行编码验证
|
||||
* @param string $token
|
||||
* @param integer $user_id
|
||||
*/
|
||||
public static function decode(string $token)
|
||||
{
|
||||
try {
|
||||
// 对 token 进行编码
|
||||
$decoded = JWT::decode($token, new Key(self::KEY, self::ALG));
|
||||
// 检测 token 附加数据中是否存在用户id
|
||||
if (!empty($decoded->data->uid)) {
|
||||
$data = $decoded->data;
|
||||
} else {
|
||||
throw new \Exception('token 中没有用户信息');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception($e->getMessage(), 201);
|
||||
}
|
||||
return $data; // 用户信息
|
||||
}
|
||||
|
||||
public static function getHeaderToken(array $header)
|
||||
{
|
||||
return str_replace('Bearer ', '', $header['authorization']);
|
||||
}
|
||||
}
|
@ -155,6 +155,7 @@ class Uploads
|
||||
->check(['file'=>$file]);
|
||||
|
||||
} catch (ValidateException $e) {
|
||||
halt($e->getMessage());
|
||||
return json(['status'=>-1,'msg'=>$e->getMessage()]);
|
||||
}
|
||||
|
||||
@ -200,4 +201,75 @@ class Uploads
|
||||
return json(['status'=>0,'msg'=>'上传成功','url'=> $name_path, 'location'=>$name_path]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param string $fileName 文件名
|
||||
* @param string $dirName 目录名
|
||||
* @param int $fileSize 文件大小
|
||||
* @param string $fileType 文件类型
|
||||
* @param string $rule 文件命名规则 默认md5,uniqid,date,sha1,_self为上传文件名称作为文件名,或者自定义如a.jpg文件名
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function put_api(string $fileName, string $dirName, int $fileSize, string $fileType, int $uid, string $rule = '' )
|
||||
{
|
||||
if(stripos($fileName,'http') !== false) {
|
||||
$file = $fileName;
|
||||
} else {
|
||||
$file = request()->file($fileName);
|
||||
}
|
||||
|
||||
$fileExt = $this->getFileInfo($fileType,'ext');
|
||||
$fileMime = $this->getFileInfo($fileType,'mime');
|
||||
|
||||
try {
|
||||
validate([$fileName=>['fileSize'=>$fileSize * 1024,'fileExt'=>$fileExt,'fileMime'=>$fileMime]])
|
||||
->check(['file'=>$file]);
|
||||
|
||||
} catch (ValidateException $e) {
|
||||
halt($e->getMessage());
|
||||
return json(['status'=>-1,'msg'=>$e->getMessage()]);
|
||||
}
|
||||
|
||||
// 解析存储位置 SYS_开头为系统位置
|
||||
$isSys = stripos($dirName, 'SYS_');
|
||||
if($isSys) {
|
||||
$disk = 'sys';
|
||||
$dirName = substr($dirName,4);
|
||||
$uploadDir = Config::get('filesystem.disks.sys.url');
|
||||
$path = DIRECTORY_SEPARATOR . $disk . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . date('Ymd');
|
||||
} else {
|
||||
$disk = 'public';
|
||||
$dirName = $uid . DIRECTORY_SEPARATOR . $dirName;
|
||||
$uploadDir = Config::get('filesystem.disks.public.url');
|
||||
$path = DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . date('Ymd');
|
||||
}
|
||||
|
||||
$realPath = app()->getRootPath() . 'public' . $path;
|
||||
|
||||
$rules = ['md5','date','sha1','uniqid'];
|
||||
|
||||
try{
|
||||
// 解析是否自定义文件名
|
||||
if(in_array($rule, $rules)) {
|
||||
// rule命名
|
||||
$info = $file->move($realPath, $file->hashName($rule));
|
||||
} elseif(!empty($rule)) {
|
||||
// 自定义文件名
|
||||
if(stripos($rule, '_self')) {
|
||||
$info = $file->move($realPath, $file->getOriginalName());
|
||||
}
|
||||
$info = $file->move($realPath, $rule);
|
||||
} else {
|
||||
// 默认
|
||||
$info = $file->move($realPath, $file->hashName());
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return json(['code' => -1, 'msg' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
$name_path = str_replace('\\',"/", $path . '/' . $info->getBasename());
|
||||
|
||||
return json(['code' => 1,'msg'=>'上传成功', 'data' => ['url'=> $name_path]]);
|
||||
}
|
||||
|
||||
}
|
@ -42,7 +42,7 @@ class Login extends BaseController
|
||||
// 检验登录是否开放
|
||||
if(config('taoler.config.is_login') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,网站维护中,暂时不能登录哦!']);
|
||||
//登陆前数据校验
|
||||
$data = Request::param();
|
||||
$data = Request::only(['name','email','phone','password','captcha']);
|
||||
if(Config::get('taoler.config.login_captcha') == 1)
|
||||
{
|
||||
//先校验验证码
|
||||
|
117
app/middleware/AdminAuth.php
Normal file
117
app/middleware/AdminAuth.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/*
|
||||
* @Author: TaoLer <alipey_tao@qq.com>
|
||||
* @Date: 2021-12-06 16:04:50
|
||||
* @LastEditTime: 2022-04-22 06:24:03
|
||||
* @LastEditors: TaoLer
|
||||
* @Description: 搜索引擎SEO优化设置
|
||||
* @FilePath: \TaoLer\app\middleware\Auth.php
|
||||
* Copyright (c) 2020~2022 http://www.aieok.com All rights reserved.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use taoser\think\Auth as UserAuth;
|
||||
use think\facade\Session;
|
||||
use think\facade\Cookie;
|
||||
use think\facade\Db;
|
||||
use think\facade\Config;
|
||||
use think\facade\Request;
|
||||
|
||||
class AdminAuth
|
||||
{
|
||||
/**
|
||||
* 处理请求
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Closure $next
|
||||
* @return Response
|
||||
*/
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
// var_dump(Request::url(),Request::pathinfo(),$request->baseUrl(),$request->controller());
|
||||
//访问路径
|
||||
// $path = app('http')->getName().'/'.stristr($request->pathinfo(),".html",true);
|
||||
$path = stristr($request->pathinfo(),".html",true) ?: Request::pathinfo();
|
||||
// var_dump($path);
|
||||
//登陆前获取加密的Cookie
|
||||
$cooAuth = Cookie::get('adminAuth');
|
||||
|
||||
if(!empty($cooAuth)){
|
||||
$resArr = explode(':',$cooAuth);
|
||||
$userId = end($resArr);
|
||||
//检验用户
|
||||
$user = Db::name('admin')->where('id',$userId)->find();
|
||||
if(!empty($user)){
|
||||
//验证cookie
|
||||
$salt = Config::get('taoler.salt');
|
||||
$auth = md5($user['username'].$salt).":".$userId;
|
||||
if($auth == $cooAuth){
|
||||
Session::set('admin_name',$user['username']);
|
||||
Session::set('admin_id',$userId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// //没有登录及当前非登录页重定向登录页
|
||||
// if(!Session::has('admin_id') && $path !== 'admin/login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
|
||||
// {
|
||||
// return redirect((string) url('login/index'));
|
||||
// }
|
||||
// //登陆后无法访问登录页
|
||||
// if(Session::has('admin_id') && $path == 'admin/login/index'){
|
||||
// return redirect((string) url('index/index'));
|
||||
// }
|
||||
// // 排除公共权限
|
||||
// $not_check = ['admin/','index/index', 'admin/menu/getMenuNavbar','admin/login/index','admin/index/index','admin/index/home','admin/Admin/info','admin/Admin/repass','admin/Admin/logout','admin/Index/news','admin/Index/cunsult','admin/Index/replys','admin/Index/reply','admin/captcha','addons/socail/','admin/addons/social/oauth/login','admin/addons/bacimg/index/getImages'];
|
||||
|
||||
|
||||
//没有登录及当前非登录页重定向登录页
|
||||
if(!Session::has('admin_id') && $path !== 'login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
|
||||
{
|
||||
return redirect((string) url('login/index'));
|
||||
}
|
||||
//登陆后无法访问登录页
|
||||
if(Session::has('admin_id') && $path == 'login/index' || $path == ''){
|
||||
return redirect((string) url('index/index'));
|
||||
}
|
||||
|
||||
// 排除公共权限
|
||||
$not_check = [
|
||||
'captcha',
|
||||
'login/index',
|
||||
'admin/index',
|
||||
'system.menu/getnav',
|
||||
'index/index',
|
||||
'index/console1',
|
||||
'index/console2',
|
||||
'index/news',
|
||||
'menu/getMenuNavbar',
|
||||
'index/home',
|
||||
'Admin/info',
|
||||
'system.admin/repass',
|
||||
'system.admin/logout',
|
||||
'Index/cunsult',
|
||||
'Index/replys',
|
||||
'Index/reply',
|
||||
'admin/captcha',
|
||||
'addons/socail/',
|
||||
'addons/social/oauth/login',
|
||||
'addons/bacimg/index/getImages'
|
||||
];
|
||||
|
||||
if (!in_array($path, $not_check)) {
|
||||
$auth = new UserAuth();
|
||||
$admin_id = Session::get('admin_id'); //登录用户的id
|
||||
|
||||
if (!$auth->check($path, $admin_id) && $admin_id != 1) {
|
||||
//return view('public/auth');
|
||||
//return response("<script>alert('没有操作权限')</script>");
|
||||
return json(['code'=>-1,'msg'=>'无权限']);
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@ -1,117 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
* @Author: TaoLer <alipey_tao@qq.com>
|
||||
* @Date: 2021-12-06 16:04:50
|
||||
* @LastEditTime: 2022-04-22 06:24:03
|
||||
* @LastEditors: TaoLer
|
||||
* @Description: 搜索引擎SEO优化设置
|
||||
* @FilePath: \TaoLer\app\middleware\Auth.php
|
||||
* Copyright (c) 2020~2022 http://www.aieok.com All rights reserved.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use taoser\think\Auth as UserAuth;
|
||||
use think\facade\Session;
|
||||
use think\facade\Cookie;
|
||||
use think\facade\Db;
|
||||
use think\facade\Config;
|
||||
use think\facade\Request;
|
||||
use app\common\lib\JwtAuth;
|
||||
|
||||
class Auth
|
||||
{
|
||||
/**
|
||||
* 处理请求
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Closure $next
|
||||
* @return Response
|
||||
*/
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
// var_dump(Request::url(),Request::pathinfo(),$request->baseUrl(),$request->controller());
|
||||
//访问路径
|
||||
// $path = app('http')->getName().'/'.stristr($request->pathinfo(),".html",true);
|
||||
$path = stristr($request->pathinfo(),".html",true) ?: Request::pathinfo();
|
||||
// var_dump($path);
|
||||
//登陆前获取加密的Cookie
|
||||
$cooAuth = Cookie::get('adminAuth');
|
||||
$header = $request->header();
|
||||
|
||||
if(!empty($cooAuth)){
|
||||
$resArr = explode(':',$cooAuth);
|
||||
$userId = end($resArr);
|
||||
//检验用户
|
||||
$user = Db::name('admin')->where('id',$userId)->find();
|
||||
if(!empty($user)){
|
||||
//验证cookie
|
||||
$salt = Config::get('taoler.salt');
|
||||
$auth = md5($user['username'].$salt).":".$userId;
|
||||
if($auth == $cooAuth){
|
||||
Session::set('admin_name',$user['username']);
|
||||
Session::set('admin_id',$userId);
|
||||
}
|
||||
if(isset($header['authorization'])) {
|
||||
$token = trim(ltrim($request->header('authorization'), 'Bearer'));
|
||||
|
||||
try{
|
||||
$data = JwtAuth::decode($token);
|
||||
|
||||
$request->uid = $data->uid;
|
||||
|
||||
} catch(\Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => 'no auth']);
|
||||
}
|
||||
|
||||
// //没有登录及当前非登录页重定向登录页
|
||||
// if(!Session::has('admin_id') && $path !== 'admin/login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
|
||||
// {
|
||||
// return redirect((string) url('login/index'));
|
||||
// }
|
||||
// //登陆后无法访问登录页
|
||||
// if(Session::has('admin_id') && $path == 'admin/login/index'){
|
||||
// return redirect((string) url('index/index'));
|
||||
// }
|
||||
// // 排除公共权限
|
||||
// $not_check = ['admin/','index/index', 'admin/menu/getMenuNavbar','admin/login/index','admin/index/index','admin/index/home','admin/Admin/info','admin/Admin/repass','admin/Admin/logout','admin/Index/news','admin/Index/cunsult','admin/Index/replys','admin/Index/reply','admin/captcha','addons/socail/','admin/addons/social/oauth/login','admin/addons/bacimg/index/getImages'];
|
||||
|
||||
|
||||
//没有登录及当前非登录页重定向登录页
|
||||
if(!Session::has('admin_id') && $path !== 'login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
|
||||
{
|
||||
return redirect((string) url('login/index'));
|
||||
}
|
||||
//登陆后无法访问登录页
|
||||
if(Session::has('admin_id') && $path == 'login/index' || $path == ''){
|
||||
return redirect((string) url('index/index'));
|
||||
}
|
||||
|
||||
// 排除公共权限
|
||||
$not_check = [
|
||||
'captcha',
|
||||
'login/index',
|
||||
'admin/index',
|
||||
'system.menu/getnav',
|
||||
'index/index',
|
||||
'index/console1',
|
||||
'index/console2',
|
||||
'index/news',
|
||||
'menu/getMenuNavbar',
|
||||
'index/home',
|
||||
'Admin/info',
|
||||
'system.admin/repass',
|
||||
'system.admin/logout',
|
||||
'Index/cunsult',
|
||||
'Index/replys',
|
||||
'Index/reply',
|
||||
'admin/captcha',
|
||||
'addons/socail/',
|
||||
'addons/social/oauth/login',
|
||||
'addons/bacimg/index/getImages'
|
||||
];
|
||||
|
||||
if (!in_array($path, $not_check)) {
|
||||
$auth = new UserAuth();
|
||||
$admin_id = Session::get('admin_id'); //登录用户的id
|
||||
|
||||
if (!$auth->check($path, $admin_id) && $admin_id != 1) {
|
||||
//return view('public/auth');
|
||||
//return response("<script>alert('没有操作权限')</script>");
|
||||
return json(['code'=>-1,'msg'=>'无权限']);
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
//登陆前获取加密的Cookie
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
33
app/middleware/Auths.php
Normal file
33
app/middleware/Auths.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use app\common\lib\JwtAuth;
|
||||
|
||||
class Auths
|
||||
{
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
$header = $request->header();
|
||||
|
||||
if(isset($header['authorization'])) {
|
||||
$token = trim(ltrim($request->header('authorization'), 'Bearer'));
|
||||
|
||||
try{
|
||||
$data = JwtAuth::decode($token);
|
||||
|
||||
$request->uid = $data->uid;
|
||||
|
||||
} catch(\Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => 'no auth']);
|
||||
}
|
||||
//登陆前获取加密的Cookie
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@ -24,8 +24,6 @@
|
||||
"topthink/think-view": "^1.0",
|
||||
"topthink/think-captcha": "^3.0",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"lotofbadcode/phpspirit_databackup": "^1.1",
|
||||
"wamkj/thinkphp6.0-databackup": "^1.0",
|
||||
"taoser/think-addons": "^1.0",
|
||||
"liliuwei/thinkphp-social": "^1.3",
|
||||
"taoser/think-setarr": "^0.0.3",
|
||||
@ -38,7 +36,9 @@
|
||||
"workerman/phpsocket.io": "^1.1",
|
||||
"jaeger/querylist": "^4.2",
|
||||
"symfony/var-exporter": "^5.4",
|
||||
"yzh52521/easyhttp": "^1.0"
|
||||
"yzh52521/easyhttp": "^1.0",
|
||||
"firebase/php-jwt": "^6.8",
|
||||
"overtrue/easy-sms": "^2.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^4.2",
|
||||
|
301
composer.lock
generated
301
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "20dad4ba0451f20b1191711c63ad21c7",
|
||||
"content-hash": "6be3b456c215d7ae6d3ba8a28f6697b4",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@ -257,16 +257,16 @@
|
||||
},
|
||||
{
|
||||
"name": "dasprid/enum",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DASPRiD/Enum.git",
|
||||
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
|
||||
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
|
||||
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016",
|
||||
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -301,9 +301,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/DASPRiD/Enum/issues",
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.5"
|
||||
},
|
||||
"time": "2023-03-01T18:44:03+00:00"
|
||||
"time": "2023-08-25T16:18:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "endroid/qr-code",
|
||||
@ -377,6 +377,69 @@
|
||||
],
|
||||
"time": "2022-10-26T08:48:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"version": "v6.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/firebase/php-jwt.git",
|
||||
"reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26",
|
||||
"reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4||^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/guzzle": "^6.5||^7.4",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psr/cache": "^1.0||^2.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-sodium": "Support EdDSA (Ed25519) signatures",
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Neuman Vong",
|
||||
"email": "neuman+pear@twilio.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Anant Narayanan",
|
||||
"email": "anant@php.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
|
||||
"homepage": "https://github.com/firebase/php-jwt",
|
||||
"keywords": [
|
||||
"jwt",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
||||
"source": "https://github.com/firebase/php-jwt/tree/v6.8.1"
|
||||
},
|
||||
"time": "2023-07-14T18:33:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.0.0",
|
||||
@ -950,26 +1013,26 @@
|
||||
},
|
||||
{
|
||||
"name": "league/mime-type-detection",
|
||||
"version": "1.11.0",
|
||||
"version": "1.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/mime-type-detection.git",
|
||||
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
|
||||
"reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
|
||||
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
|
||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96",
|
||||
"reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"phpstan/phpstan": "^0.12.68",
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3"
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -990,7 +1053,7 @@
|
||||
"description": "Mime-type detection for Flysystem",
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
|
||||
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
|
||||
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1002,7 +1065,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-04-17T13:12:02+00:00"
|
||||
"time": "2023-08-05T12:09:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "liliuwei/thinkphp-social",
|
||||
@ -1080,61 +1143,83 @@
|
||||
"time": "2021-01-13T05:11:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lotofbadcode/phpspirit_databackup",
|
||||
"version": "v1.2",
|
||||
"name": "overtrue/easy-sms",
|
||||
"version": "2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lotofbadcode/phpspirit_databackup.git",
|
||||
"reference": "77c2421f8461392c044cf8c29918f495c22a5612"
|
||||
"url": "https://github.com/overtrue/easy-sms.git",
|
||||
"reference": "81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lotofbadcode/phpspirit_databackup/zipball/77c2421f8461392c044cf8c29918f495c22a5612",
|
||||
"reference": "77c2421f8461392c044cf8c29918f495c22a5612",
|
||||
"url": "https://api.github.com/repos/overtrue/easy-sms/zipball/81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046",
|
||||
"reference": "81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/guzzle": "^6.2 || ^7.0",
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"brainmaestro/composer-git-hooks": "^2.8",
|
||||
"jetbrains/phpstorm-attributes": "^1.0",
|
||||
"mockery/mockery": "~1.3.3 || ^1.4.2",
|
||||
"phpunit/phpunit": "^5.7 || ^7.5 || ^8.5.19 || ^9.5.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-commit": [
|
||||
"composer check-style",
|
||||
"composer psalm",
|
||||
"composer test"
|
||||
],
|
||||
"pre-push": [
|
||||
"composer check-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpspirit\\databackup\\": "src/"
|
||||
"Overtrue\\EasySms\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "代码庸医",
|
||||
"email": "3359964266@qq.com"
|
||||
"name": "overtrue",
|
||||
"email": "i@overtrue.me"
|
||||
}
|
||||
],
|
||||
"description": "一个PHP数据库备份恢复的插件",
|
||||
"keywords": [
|
||||
"library",
|
||||
"php"
|
||||
],
|
||||
"description": "The easiest way to send short message.",
|
||||
"support": {
|
||||
"issues": "https://github.com/lotofbadcode/phpspirit_databackup/issues",
|
||||
"source": "https://github.com/lotofbadcode/phpspirit_databackup/tree/v1.2"
|
||||
"issues": "https://github.com/overtrue/easy-sms/issues",
|
||||
"source": "https://github.com/overtrue/easy-sms/tree/2.5.0"
|
||||
},
|
||||
"time": "2023-05-12T12:02:05+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/overtrue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-07T07:51:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-di/invoker",
|
||||
"version": "2.3.3",
|
||||
"version": "2.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-DI/Invoker.git",
|
||||
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786"
|
||||
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/cd6d9f267d1a3474bdddf1be1da079f01b942786",
|
||||
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786",
|
||||
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86",
|
||||
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1168,7 +1253,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-DI/Invoker/issues",
|
||||
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.3"
|
||||
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1176,7 +1261,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-12-13T09:22:56+00:00"
|
||||
"time": "2023-09-08T09:24:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-di/php-di",
|
||||
@ -1298,16 +1383,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v6.8.0",
|
||||
"version": "v6.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||
"reference": "df16b615e371d81fb79e506277faea67a1be18f1"
|
||||
"reference": "e88da8d679acc3824ff231fdc553565b802ac016"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1",
|
||||
"reference": "df16b615e371d81fb79e506277faea67a1be18f1",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e88da8d679acc3824ff231fdc553565b802ac016",
|
||||
"reference": "e88da8d679acc3824ff231fdc553565b802ac016",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1317,13 +1402,13 @@
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
||||
"phpcompatibility/php-compatibility": "^9.3.5",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"squizlabs/php_codesniffer": "^3.7.1",
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
"yoast/phpunit-polyfills": "^1.0.4"
|
||||
},
|
||||
"suggest": {
|
||||
@ -1366,7 +1451,7 @@
|
||||
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0"
|
||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1374,7 +1459,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-03-06T14:43:22+00:00"
|
||||
"time": "2023-08-29T08:26:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
@ -1775,16 +1860,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.27.0",
|
||||
"version": "v1.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1799,7 +1884,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1838,7 +1923,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1854,20 +1939,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
"time": "2023-07-28T09:04:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.27.0",
|
||||
"version": "v1.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
|
||||
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
|
||||
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
|
||||
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1876,7 +1961,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1914,7 +1999,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1930,20 +2015,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.27.0",
|
||||
"version": "v1.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
|
||||
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
|
||||
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1952,7 +2037,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1997,7 +2082,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2013,7 +2098,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
@ -2592,24 +2677,27 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-migration",
|
||||
"version": "v3.0.6",
|
||||
"version": "v3.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-migration.git",
|
||||
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030"
|
||||
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-migration/zipball/82c4226cb14f973b9377c7fc6e89c525cbb8b030",
|
||||
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030",
|
||||
"url": "https://api.github.com/repos/top-think/think-migration/zipball/22c44058e1454f3af1d346e7f6524fbe654de7fb",
|
||||
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"topthink/framework": "^6.0 || ^8.0",
|
||||
"topthink/think-helper": "^3.0.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "^1.8"
|
||||
"composer/composer": "^2.5.8",
|
||||
"fzaninotto/faker": "^1.8",
|
||||
"robmorgan/phinx": "^0.13.4"
|
||||
},
|
||||
"suggest": {
|
||||
"fzaninotto/faker": "Required to use the factory builder (^1.8)."
|
||||
@ -2624,7 +2712,7 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Phinx\\": "phinx/src/Phinx",
|
||||
"Phinx\\": "phinx",
|
||||
"think\\migration\\": "src"
|
||||
}
|
||||
},
|
||||
@ -2640,9 +2728,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-migration/issues",
|
||||
"source": "https://github.com/top-think/think-migration/tree/v3.0.6"
|
||||
"source": "https://github.com/top-think/think-migration/tree/v3.1.1"
|
||||
},
|
||||
"time": "2023-07-01T11:01:52+00:00"
|
||||
"time": "2023-09-14T05:51:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-multi-app",
|
||||
@ -2829,51 +2917,6 @@
|
||||
},
|
||||
"time": "2019-11-06T11:40:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wamkj/thinkphp6.0-databackup",
|
||||
"version": "v1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wamkj/thinkphp6.0-databackup.git",
|
||||
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wamkj/thinkphp6.0-databackup/zipball/28a0e406d827132942723a3c9f69bb20c98e652f",
|
||||
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"topthink/framework": "^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"wamkj\\thinkphp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "wamkj",
|
||||
"email": "1149183529@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "thinkphp6.0的数据库自动备份扩展",
|
||||
"keywords": [
|
||||
"think-databackup",
|
||||
"thinkphp"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/wamkj/thinkphp6.0-databackup/issues",
|
||||
"source": "https://github.com/wamkj/thinkphp6.0-databackup/tree/v1.0"
|
||||
},
|
||||
"time": "2020-02-15T13:04:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "workerman/channel",
|
||||
"version": "v1.2.0",
|
||||
@ -3159,21 +3202,21 @@
|
||||
},
|
||||
{
|
||||
"name": "yzh52521/easyhttp",
|
||||
"version": "v1.0.7",
|
||||
"version": "v1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yzh52521/easyhttp.git",
|
||||
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e"
|
||||
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/52cb9aba60a725bef77acd9c4c48ecc78931af9e",
|
||||
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e",
|
||||
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/78ec5cea1884d6da0709cac95a1e4d23fe9bfc65",
|
||||
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.0|^7.0",
|
||||
"php": "^7.2.5|^8.0",
|
||||
"php": ">=7.2.5",
|
||||
"psr/log": "^1.0|^2.0|^3.0"
|
||||
},
|
||||
"type": "library",
|
||||
@ -3205,9 +3248,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/yzh52521/easyhttp/issues",
|
||||
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.7"
|
||||
"source": "https://github.com/yzh52521/easyhttp/tree/v1.1.0"
|
||||
},
|
||||
"time": "2023-02-16T03:04:02+00:00"
|
||||
"time": "2023-08-31T06:20:52+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
@ -16,7 +16,7 @@ return [
|
||||
// 应用名,此项不可更改
|
||||
'appname' => 'TaoLer',
|
||||
// 版本配置
|
||||
'version' => '2.3.9',
|
||||
'version' => '2.3.12',
|
||||
// 加盐
|
||||
'salt' => 'taoler',
|
||||
// 数据库备份目录
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
105
public/static/component/pear/module/imagecut.js
Normal file
105
public/static/component/pear/module/imagecut.js
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
images压缩扩展模块
|
||||
changlin_zhao@qq.com
|
||||
2023.5.23
|
||||
**/
|
||||
layui.define(['upload','layer'],function(exports){
|
||||
|
||||
var layer = layui.layer;
|
||||
|
||||
var Compressor = {
|
||||
upload: function (obj) {
|
||||
// opthions = {
|
||||
// width: option[0],
|
||||
// height: option[1],
|
||||
// quality: option[2]
|
||||
// }
|
||||
obj.preview(function(index, file, result){
|
||||
canvasDataURL(result, {quality: 0.7}, function(base64Codes){
|
||||
obj.upload(index, convertBase64UrlTo(base64Codes, file.name));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 已知 base64
|
||||
// canvasDataURL(base64, {quality: 0.7}, function(base64Codes){
|
||||
// // base64Codes 为压缩后的
|
||||
// // 其中 convertBase64UrlTo(base64Codes, file.name) 可返回 File 对象和 Blob
|
||||
// obj.upload(index, convertBase64UrlTo(base64Codes, file.name));
|
||||
// });
|
||||
|
||||
// 未知 base64
|
||||
// imageCompress(file, {quality: 0.7}, function(base64Codes){
|
||||
// // base64Codes 为压缩后的
|
||||
// obj.upload(index, convertBase64UrlTo(base64Codes, file.name));
|
||||
// });
|
||||
|
||||
/**
|
||||
* 读取文件
|
||||
* @param {file or Blob} file 上传文件
|
||||
* @param {object} config 压缩配置 可配置压缩长宽、质量等
|
||||
* @param {function} callback
|
||||
*/
|
||||
function imageCompress(file, config, callback){
|
||||
var ready = new FileReader();
|
||||
ready.readAsDataURL(file);
|
||||
|
||||
ready.onload=function(){
|
||||
canvasDataURL(this.result, config, callback)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} path
|
||||
* @param {object} config -- {width: '', height: '', quality: 0.7}
|
||||
* @param {function} callback
|
||||
*/
|
||||
function canvasDataURL(path, config, callback){
|
||||
var img = new Image();
|
||||
img.src = path;
|
||||
|
||||
img.onload = function(){
|
||||
var that = this, quality = 0.6;
|
||||
var w = that.width, h = that.height, scale = w / h;
|
||||
w = config.width || w;
|
||||
h = config.height || (w / scale);
|
||||
|
||||
//生成canvas
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
var anw = document.createAttribute("width");
|
||||
anw.nodeValue = w;
|
||||
var anh = document.createAttribute("height");
|
||||
anh.nodeValue = h;
|
||||
canvas.setAttributeNode(anw);
|
||||
canvas.setAttributeNode(anh);
|
||||
ctx.drawImage(that, 0, 0, w, h);
|
||||
|
||||
if(config.quality && config.quality <= 1 && config.quality > 0){
|
||||
quality = config.quality;
|
||||
}
|
||||
callback(canvas.toDataURL('image/jpeg', quality));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将图片 base64 转为 File 对象或者 Blob
|
||||
* @param {*} urlData 图片 base64
|
||||
* @param {*} filename 图片名 没有图片名将转为 Blob
|
||||
*/
|
||||
function convertBase64UrlTo(urlData, filename = null){
|
||||
var base64Arr = urlData.split(','), mime = base64Arr[0].match(/:(.*?);/)[1],
|
||||
bstr = atob(base64Arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
||||
while(n--){
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
|
||||
return filename ? new File([u8arr], filename, {type:mime}) : new Blob([u8arr], {type:mime});
|
||||
}
|
||||
|
||||
//输出 imagecut接口
|
||||
exports('imagecut', Compressor);
|
||||
|
||||
});
|
@ -61,7 +61,7 @@ layui.define(['upload','layer'],function(exports){
|
||||
img.src = path;
|
||||
|
||||
img.onload = function(){
|
||||
var that = this, quality = 0.7;
|
||||
var that = this, quality = 0.6;
|
||||
var w = that.width, h = that.height, scale = w / h;
|
||||
w = config.width || w;
|
||||
h = config.height || (w / scale);
|
||||
|
2
vendor/composer/autoload_files.php
vendored
2
vendor/composer/autoload_files.php
vendored
@ -9,9 +9,9 @@ return array(
|
||||
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
|
||||
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
||||
|
8
vendor/composer/autoload_psr4.php
vendored
8
vendor/composer/autoload_psr4.php
vendored
@ -7,17 +7,15 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'yzh52521\\EasyHttp\\' => array($vendorDir . '/yzh52521/easyhttp/src'),
|
||||
'wamkj\\thinkphp\\' => array($vendorDir . '/wamkj/thinkphp6.0-databackup/src'),
|
||||
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
|
||||
'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
|
||||
'think\\migration\\' => array($vendorDir . '/topthink/think-migration/src'),
|
||||
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
|
||||
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
|
||||
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
|
||||
'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/framework/src/think'),
|
||||
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'),
|
||||
'taoser\\think\\' => array($vendorDir . '/taoser/think-auth/src'),
|
||||
'taoser\\' => array($vendorDir . '/taoser/think-addons/src', $vendorDir . '/taoser/think-setarr/src'),
|
||||
'phpspirit\\databackup\\' => array($vendorDir . '/lotofbadcode/phpspirit_databackup/src'),
|
||||
'liliuwei\\social\\' => array($vendorDir . '/liliuwei/thinkphp-social/src'),
|
||||
'app\\' => array($baseDir . '/app'),
|
||||
'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'),
|
||||
@ -38,9 +36,10 @@ return array(
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||
'PhpDocReader\\' => array($vendorDir . '/php-di/phpdoc-reader/src/PhpDocReader'),
|
||||
'Phinx\\' => array($vendorDir . '/topthink/think-migration/phinx/src/Phinx'),
|
||||
'Phinx\\' => array($vendorDir . '/topthink/think-migration/phinx'),
|
||||
'PHPSocketIO\\' => array($vendorDir . '/workerman/phpsocket.io/src'),
|
||||
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||
'Overtrue\\EasySms\\' => array($vendorDir . '/overtrue/easy-sms/src'),
|
||||
'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
|
||||
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
|
||||
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
|
||||
@ -49,6 +48,7 @@ return array(
|
||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
||||
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
|
||||
'Endroid\\QrCode\\' => array($vendorDir . '/endroid/qr-code/src'),
|
||||
'DI\\' => array($vendorDir . '/php-di/php-di/src'),
|
||||
'DASPRiD\\Enum\\' => array($vendorDir . '/dasprid/enum/src'),
|
||||
|
44
vendor/composer/autoload_static.php
vendored
44
vendor/composer/autoload_static.php
vendored
@ -10,9 +10,9 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
|
||||
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
|
||||
@ -32,10 +32,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
array (
|
||||
'yzh52521\\EasyHttp\\' => 18,
|
||||
),
|
||||
'w' =>
|
||||
array (
|
||||
'wamkj\\thinkphp\\' => 15,
|
||||
),
|
||||
't' =>
|
||||
array (
|
||||
'think\\view\\driver\\' => 18,
|
||||
@ -48,10 +44,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
'taoser\\think\\' => 13,
|
||||
'taoser\\' => 7,
|
||||
),
|
||||
'p' =>
|
||||
array (
|
||||
'phpspirit\\databackup\\' => 21,
|
||||
),
|
||||
'l' =>
|
||||
array (
|
||||
'liliuwei\\social\\' => 16,
|
||||
@ -99,6 +91,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
'PHPSocketIO\\' => 12,
|
||||
'PHPMailer\\PHPMailer\\' => 20,
|
||||
),
|
||||
'O' =>
|
||||
array (
|
||||
'Overtrue\\EasySms\\' => 17,
|
||||
),
|
||||
'L' =>
|
||||
array (
|
||||
'League\\MimeTypeDetection\\' => 25,
|
||||
@ -119,6 +115,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
'GuzzleHttp\\Promise\\' => 19,
|
||||
'GuzzleHttp\\' => 11,
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'Firebase\\JWT\\' => 13,
|
||||
),
|
||||
'E' =>
|
||||
array (
|
||||
'Endroid\\QrCode\\' => 15,
|
||||
@ -146,10 +146,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/yzh52521/easyhttp/src',
|
||||
),
|
||||
'wamkj\\thinkphp\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/wamkj/thinkphp6.0-databackup/src',
|
||||
),
|
||||
'think\\view\\driver\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-view/src',
|
||||
@ -176,10 +172,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
),
|
||||
'think\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
||||
1 => __DIR__ . '/..' . '/topthink/think-orm/src',
|
||||
2 => __DIR__ . '/..' . '/topthink/think-template/src',
|
||||
3 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
||||
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
||||
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
||||
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
|
||||
3 => __DIR__ . '/..' . '/topthink/think-template/src',
|
||||
),
|
||||
'taoser\\think\\' =>
|
||||
array (
|
||||
@ -190,10 +186,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
0 => __DIR__ . '/..' . '/taoser/think-addons/src',
|
||||
1 => __DIR__ . '/..' . '/taoser/think-setarr/src',
|
||||
),
|
||||
'phpspirit\\databackup\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/lotofbadcode/phpspirit_databackup/src',
|
||||
),
|
||||
'liliuwei\\social\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/liliuwei/thinkphp-social/src',
|
||||
@ -276,7 +268,7 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
),
|
||||
'Phinx\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-migration/phinx/src/Phinx',
|
||||
0 => __DIR__ . '/..' . '/topthink/think-migration/phinx',
|
||||
),
|
||||
'PHPSocketIO\\' =>
|
||||
array (
|
||||
@ -286,6 +278,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
|
||||
),
|
||||
'Overtrue\\EasySms\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/overtrue/easy-sms/src',
|
||||
),
|
||||
'League\\MimeTypeDetection\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/mime-type-detection/src',
|
||||
@ -318,6 +314,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
||||
),
|
||||
'Firebase\\JWT\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
|
||||
),
|
||||
'Endroid\\QrCode\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/endroid/qr-code/src',
|
||||
|
381
vendor/composer/installed.json
vendored
381
vendor/composer/installed.json
vendored
@ -269,24 +269,18 @@
|
||||
},
|
||||
{
|
||||
"name": "dasprid/enum",
|
||||
"version": "1.0.4",
|
||||
"version_normalized": "1.0.4.0",
|
||||
"version": "1.0.5",
|
||||
"version_normalized": "1.0.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DASPRiD/Enum.git",
|
||||
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
|
||||
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
|
||||
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016",
|
||||
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1 <9.0"
|
||||
@ -295,7 +289,7 @@
|
||||
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||
"squizlabs/php_codesniffer": "*"
|
||||
},
|
||||
"time": "2023-03-01T18:44:03+00:00",
|
||||
"time": "2023-08-25T16:18:39+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -322,7 +316,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/DASPRiD/Enum/issues",
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.5"
|
||||
},
|
||||
"install-path": "../dasprid/enum"
|
||||
},
|
||||
@ -401,6 +395,72 @@
|
||||
],
|
||||
"install-path": "../endroid/qr-code"
|
||||
},
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"version": "v6.8.1",
|
||||
"version_normalized": "6.8.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/firebase/php-jwt.git",
|
||||
"reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26",
|
||||
"reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4||^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/guzzle": "^6.5||^7.4",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psr/cache": "^1.0||^2.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-sodium": "Support EdDSA (Ed25519) signatures",
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
|
||||
},
|
||||
"time": "2023-07-14T18:33:00+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Neuman Vong",
|
||||
"email": "neuman+pear@twilio.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Anant Narayanan",
|
||||
"email": "anant@php.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
|
||||
"homepage": "https://github.com/firebase/php-jwt",
|
||||
"keywords": [
|
||||
"jwt",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
||||
"source": "https://github.com/firebase/php-jwt/tree/v6.8.1"
|
||||
},
|
||||
"install-path": "../firebase/php-jwt"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.0.0",
|
||||
@ -1016,29 +1076,29 @@
|
||||
},
|
||||
{
|
||||
"name": "league/mime-type-detection",
|
||||
"version": "1.11.0",
|
||||
"version_normalized": "1.11.0.0",
|
||||
"version": "1.13.0",
|
||||
"version_normalized": "1.13.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/mime-type-detection.git",
|
||||
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
|
||||
"reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
|
||||
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
|
||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96",
|
||||
"reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"phpstan/phpstan": "^0.12.68",
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3"
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
|
||||
},
|
||||
"time": "2022-04-17T13:12:02+00:00",
|
||||
"time": "2023-08-05T12:09:49+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -1059,7 +1119,7 @@
|
||||
"description": "Mime-type detection for Flysystem",
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
|
||||
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
|
||||
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1158,71 +1218,87 @@
|
||||
"install-path": "../liliuwei/thinkphp-social"
|
||||
},
|
||||
{
|
||||
"name": "lotofbadcode/phpspirit_databackup",
|
||||
"version": "v1.2",
|
||||
"version_normalized": "1.2.0.0",
|
||||
"name": "overtrue/easy-sms",
|
||||
"version": "2.5.0",
|
||||
"version_normalized": "2.5.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lotofbadcode/phpspirit_databackup.git",
|
||||
"reference": "77c2421f8461392c044cf8c29918f495c22a5612"
|
||||
"url": "https://github.com/overtrue/easy-sms.git",
|
||||
"reference": "81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lotofbadcode/phpspirit_databackup/zipball/77c2421f8461392c044cf8c29918f495c22a5612",
|
||||
"reference": "77c2421f8461392c044cf8c29918f495c22a5612",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
"url": "https://api.github.com/repos/overtrue/easy-sms/zipball/81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046",
|
||||
"reference": "81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/guzzle": "^6.2 || ^7.0",
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"time": "2023-05-12T12:02:05+00:00",
|
||||
"require-dev": {
|
||||
"brainmaestro/composer-git-hooks": "^2.8",
|
||||
"jetbrains/phpstorm-attributes": "^1.0",
|
||||
"mockery/mockery": "~1.3.3 || ^1.4.2",
|
||||
"phpunit/phpunit": "^5.7 || ^7.5 || ^8.5.19 || ^9.5.8"
|
||||
},
|
||||
"time": "2023-08-07T07:51:17+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-commit": [
|
||||
"composer check-style",
|
||||
"composer psalm",
|
||||
"composer test"
|
||||
],
|
||||
"pre-push": [
|
||||
"composer check-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"phpspirit\\databackup\\": "src/"
|
||||
"Overtrue\\EasySms\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "代码庸医",
|
||||
"email": "3359964266@qq.com"
|
||||
"name": "overtrue",
|
||||
"email": "i@overtrue.me"
|
||||
}
|
||||
],
|
||||
"description": "一个PHP数据库备份恢复的插件",
|
||||
"keywords": [
|
||||
"library",
|
||||
"php"
|
||||
],
|
||||
"description": "The easiest way to send short message.",
|
||||
"support": {
|
||||
"issues": "https://github.com/lotofbadcode/phpspirit_databackup/issues",
|
||||
"source": "https://github.com/lotofbadcode/phpspirit_databackup/tree/v1.2"
|
||||
"issues": "https://github.com/overtrue/easy-sms/issues",
|
||||
"source": "https://github.com/overtrue/easy-sms/tree/2.5.0"
|
||||
},
|
||||
"install-path": "../lotofbadcode/phpspirit_databackup"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/overtrue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../overtrue/easy-sms"
|
||||
},
|
||||
{
|
||||
"name": "php-di/invoker",
|
||||
"version": "2.3.3",
|
||||
"version_normalized": "2.3.3.0",
|
||||
"version": "2.3.4",
|
||||
"version_normalized": "2.3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-DI/Invoker.git",
|
||||
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786"
|
||||
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/cd6d9f267d1a3474bdddf1be1da079f01b942786",
|
||||
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786",
|
||||
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86",
|
||||
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1234,7 +1310,7 @@
|
||||
"mnapoli/hard-mode": "~0.3.0",
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"time": "2021-12-13T09:22:56+00:00",
|
||||
"time": "2023-09-08T09:24:21+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -1258,7 +1334,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-DI/Invoker/issues",
|
||||
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.3"
|
||||
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1394,17 +1470,17 @@
|
||||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v6.8.0",
|
||||
"version_normalized": "6.8.0.0",
|
||||
"version": "v6.8.1",
|
||||
"version_normalized": "6.8.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||
"reference": "df16b615e371d81fb79e506277faea67a1be18f1"
|
||||
"reference": "e88da8d679acc3824ff231fdc553565b802ac016"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1",
|
||||
"reference": "df16b615e371d81fb79e506277faea67a1be18f1",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e88da8d679acc3824ff231fdc553565b802ac016",
|
||||
"reference": "e88da8d679acc3824ff231fdc553565b802ac016",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1414,13 +1490,13 @@
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
||||
"phpcompatibility/php-compatibility": "^9.3.5",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"squizlabs/php_codesniffer": "^3.7.1",
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
"yoast/phpunit-polyfills": "^1.0.4"
|
||||
},
|
||||
"suggest": {
|
||||
@ -1433,7 +1509,7 @@
|
||||
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
|
||||
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
|
||||
},
|
||||
"time": "2023-03-06T14:43:22+00:00",
|
||||
"time": "2023-08-29T08:26:30+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -1465,7 +1541,7 @@
|
||||
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
|
||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0"
|
||||
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1922,24 +1998,18 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.27.0",
|
||||
"version_normalized": "1.27.0.0",
|
||||
"version": "v1.28.0",
|
||||
"version_normalized": "1.28.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
@ -1950,11 +2020,11 @@
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"time": "2022-11-03T14:55:06+00:00",
|
||||
"time": "2023-07-28T09:04:16+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1994,7 +2064,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2014,33 +2084,27 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.27.0",
|
||||
"version_normalized": "1.27.0.0",
|
||||
"version": "v1.28.0",
|
||||
"version_normalized": "1.28.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
|
||||
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
|
||||
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
|
||||
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"time": "2022-11-03T14:55:06+00:00",
|
||||
"time": "2023-01-26T09:26:14+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -2079,7 +2143,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2099,33 +2163,27 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.27.0",
|
||||
"version_normalized": "1.27.0.0",
|
||||
"version": "v1.28.0",
|
||||
"version_normalized": "1.28.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
|
||||
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
|
||||
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"time": "2022-11-03T14:55:06+00:00",
|
||||
"time": "2023-01-26T09:26:14+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -2171,7 +2229,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2832,30 +2890,33 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-migration",
|
||||
"version": "v3.0.6",
|
||||
"version_normalized": "3.0.6.0",
|
||||
"version": "v3.1.1",
|
||||
"version_normalized": "3.1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-migration.git",
|
||||
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030"
|
||||
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-migration/zipball/82c4226cb14f973b9377c7fc6e89c525cbb8b030",
|
||||
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030",
|
||||
"url": "https://api.github.com/repos/top-think/think-migration/zipball/22c44058e1454f3af1d346e7f6524fbe654de7fb",
|
||||
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"topthink/framework": "^6.0 || ^8.0",
|
||||
"topthink/think-helper": "^3.0.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "^1.8"
|
||||
"composer/composer": "^2.5.8",
|
||||
"fzaninotto/faker": "^1.8",
|
||||
"robmorgan/phinx": "^0.13.4"
|
||||
},
|
||||
"suggest": {
|
||||
"fzaninotto/faker": "Required to use the factory builder (^1.8)."
|
||||
},
|
||||
"time": "2023-07-01T11:01:52+00:00",
|
||||
"time": "2023-09-14T05:51:31+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"think": {
|
||||
@ -2867,7 +2928,7 @@
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Phinx\\": "phinx/src/Phinx",
|
||||
"Phinx\\": "phinx",
|
||||
"think\\migration\\": "src"
|
||||
}
|
||||
},
|
||||
@ -2883,7 +2944,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-migration/issues",
|
||||
"source": "https://github.com/top-think/think-migration/tree/v3.0.6"
|
||||
"source": "https://github.com/top-think/think-migration/tree/v3.1.1"
|
||||
},
|
||||
"install-path": "../topthink/think-migration"
|
||||
},
|
||||
@ -3164,60 +3225,6 @@
|
||||
"description": "thinkphp template driver",
|
||||
"install-path": "../topthink/think-view"
|
||||
},
|
||||
{
|
||||
"name": "wamkj/thinkphp6.0-databackup",
|
||||
"version": "v1.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wamkj/thinkphp6.0-databackup.git",
|
||||
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wamkj/thinkphp6.0-databackup/zipball/28a0e406d827132942723a3c9f69bb20c98e652f",
|
||||
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"topthink/framework": "^6.0"
|
||||
},
|
||||
"time": "2020-02-15T13:04:16+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"wamkj\\thinkphp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "wamkj",
|
||||
"email": "1149183529@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "thinkphp6.0的数据库自动备份扩展",
|
||||
"keywords": [
|
||||
"think-databackup",
|
||||
"thinkphp"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/wamkj/thinkphp6.0-databackup/issues",
|
||||
"source": "https://github.com/wamkj/thinkphp6.0-databackup/tree/v1.0"
|
||||
},
|
||||
"install-path": "../wamkj/thinkphp6.0-databackup"
|
||||
},
|
||||
{
|
||||
"name": "workerman/channel",
|
||||
"version": "v1.2.0",
|
||||
@ -3524,31 +3531,25 @@
|
||||
},
|
||||
{
|
||||
"name": "yzh52521/easyhttp",
|
||||
"version": "v1.0.7",
|
||||
"version_normalized": "1.0.7.0",
|
||||
"version": "v1.1.0",
|
||||
"version_normalized": "1.1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yzh52521/easyhttp.git",
|
||||
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e"
|
||||
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/52cb9aba60a725bef77acd9c4c48ecc78931af9e",
|
||||
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/78ec5cea1884d6da0709cac95a1e4d23fe9bfc65",
|
||||
"reference": "78ec5cea1884d6da0709cac95a1e4d23fe9bfc65",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.0|^7.0",
|
||||
"php": "^7.2.5|^8.0",
|
||||
"php": ">=7.2.5",
|
||||
"psr/log": "^1.0|^2.0|^3.0"
|
||||
},
|
||||
"time": "2023-02-16T03:04:02+00:00",
|
||||
"time": "2023-08-31T06:20:52+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -3579,7 +3580,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/yzh52521/easyhttp/issues",
|
||||
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.7"
|
||||
"source": "https://github.com/yzh52521/easyhttp/tree/v1.1.0"
|
||||
},
|
||||
"install-path": "../yzh52521/easyhttp"
|
||||
}
|
||||
|
86
vendor/composer/installed.php
vendored
86
vendor/composer/installed.php
vendored
@ -3,7 +3,7 @@
|
||||
'name' => 'taoser/taoler',
|
||||
'pretty_version' => '2.3.10.x-dev',
|
||||
'version' => '2.3.10.9999999-dev',
|
||||
'reference' => '0c2f0154a81dd0a6268da627982d1bf41c0ef231',
|
||||
'reference' => 'c237566bcd13c4e1ed7fff650c97d64a9fa2c9d8',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -47,9 +47,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dasprid/enum' => array(
|
||||
'pretty_version' => '1.0.4',
|
||||
'version' => '1.0.4.0',
|
||||
'reference' => '8e6b6ea76eabbf19ea2bf5b67b98e1860474012f',
|
||||
'pretty_version' => '1.0.5',
|
||||
'version' => '1.0.5.0',
|
||||
'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dasprid/enum',
|
||||
'aliases' => array(),
|
||||
@ -64,6 +64,15 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'firebase/php-jwt' => array(
|
||||
'pretty_version' => 'v6.8.1',
|
||||
'version' => '6.8.1.0',
|
||||
'reference' => '5dbc8959427416b8ee09a100d7a8588c00fb2e26',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../firebase/php-jwt',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/guzzle' => array(
|
||||
'pretty_version' => '7.0.0',
|
||||
'version' => '7.0.0.0',
|
||||
@ -137,9 +146,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/mime-type-detection' => array(
|
||||
'pretty_version' => '1.11.0',
|
||||
'version' => '1.11.0.0',
|
||||
'reference' => 'ff6248ea87a9f116e78edd6002e39e5128a0d4dd',
|
||||
'pretty_version' => '1.13.0',
|
||||
'version' => '1.13.0.0',
|
||||
'reference' => 'a6dfb1194a2946fcdc1f38219445234f65b35c96',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/mime-type-detection',
|
||||
'aliases' => array(),
|
||||
@ -154,19 +163,19 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'lotofbadcode/phpspirit_databackup' => array(
|
||||
'pretty_version' => 'v1.2',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => '77c2421f8461392c044cf8c29918f495c22a5612',
|
||||
'overtrue/easy-sms' => array(
|
||||
'pretty_version' => '2.5.0',
|
||||
'version' => '2.5.0.0',
|
||||
'reference' => '81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../lotofbadcode/phpspirit_databackup',
|
||||
'install_path' => __DIR__ . '/../overtrue/easy-sms',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'php-di/invoker' => array(
|
||||
'pretty_version' => '2.3.3',
|
||||
'version' => '2.3.3.0',
|
||||
'reference' => 'cd6d9f267d1a3474bdddf1be1da079f01b942786',
|
||||
'pretty_version' => '2.3.4',
|
||||
'version' => '2.3.4.0',
|
||||
'reference' => '33234b32dafa8eb69202f950a1fc92055ed76a86',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-di/invoker',
|
||||
'aliases' => array(),
|
||||
@ -191,9 +200,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpmailer/phpmailer' => array(
|
||||
'pretty_version' => 'v6.8.0',
|
||||
'version' => '6.8.0.0',
|
||||
'reference' => 'df16b615e371d81fb79e506277faea67a1be18f1',
|
||||
'pretty_version' => 'v6.8.1',
|
||||
'version' => '6.8.1.0',
|
||||
'reference' => 'e88da8d679acc3824ff231fdc553565b802ac016',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
|
||||
'aliases' => array(),
|
||||
@ -302,27 +311,27 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.27.0',
|
||||
'version' => '1.27.0.0',
|
||||
'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534',
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '42292d99c55abe617799667f454222c54c60e229',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'pretty_version' => 'v1.27.0',
|
||||
'version' => '1.27.0.0',
|
||||
'reference' => '869329b1e9894268a8a61dabb69153029b7a8c97',
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '70f4aebd92afca2f865444d30a4d2151c13c3179',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.27.0',
|
||||
'version' => '1.27.0.0',
|
||||
'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936',
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
@ -349,7 +358,7 @@
|
||||
'taoser/taoler' => array(
|
||||
'pretty_version' => '2.3.10.x-dev',
|
||||
'version' => '2.3.10.9999999-dev',
|
||||
'reference' => '0c2f0154a81dd0a6268da627982d1bf41c0ef231',
|
||||
'reference' => 'c237566bcd13c4e1ed7fff650c97d64a9fa2c9d8',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -428,9 +437,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-migration' => array(
|
||||
'pretty_version' => 'v3.0.6',
|
||||
'version' => '3.0.6.0',
|
||||
'reference' => '82c4226cb14f973b9377c7fc6e89c525cbb8b030',
|
||||
'pretty_version' => 'v3.1.1',
|
||||
'version' => '3.1.1.0',
|
||||
'reference' => '22c44058e1454f3af1d346e7f6524fbe654de7fb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-migration',
|
||||
'aliases' => array(),
|
||||
@ -481,15 +490,6 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'wamkj/thinkphp6.0-databackup' => array(
|
||||
'pretty_version' => 'v1.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => '28a0e406d827132942723a3c9f69bb20c98e652f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../wamkj/thinkphp6.0-databackup',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'workerman/channel' => array(
|
||||
'pretty_version' => 'v1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
@ -536,9 +536,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yzh52521/easyhttp' => array(
|
||||
'pretty_version' => 'v1.0.7',
|
||||
'version' => '1.0.7.0',
|
||||
'reference' => '52cb9aba60a725bef77acd9c4c48ecc78931af9e',
|
||||
'pretty_version' => 'v1.1.0',
|
||||
'version' => '1.1.0.0',
|
||||
'reference' => '78ec5cea1884d6da0709cac95a1e4d23fe9bfc65',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../yzh52521/easyhttp',
|
||||
'aliases' => array(),
|
||||
|
156
vendor/firebase/php-jwt/CHANGELOG.md
vendored
Normal file
156
vendor/firebase/php-jwt/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
# Changelog
|
||||
|
||||
## [6.8.1](https://github.com/firebase/php-jwt/compare/v6.8.0...v6.8.1) (2023-07-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* accept float claims but round down to ignore them ([#492](https://github.com/firebase/php-jwt/issues/492)) ([3936842](https://github.com/firebase/php-jwt/commit/39368423beeaacb3002afa7dcb75baebf204fe7e))
|
||||
* different BeforeValidException messages for nbf and iat ([#526](https://github.com/firebase/php-jwt/issues/526)) ([0a53cf2](https://github.com/firebase/php-jwt/commit/0a53cf2986e45c2bcbf1a269f313ebf56a154ee4))
|
||||
|
||||
## [6.8.0](https://github.com/firebase/php-jwt/compare/v6.7.0...v6.8.0) (2023-06-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support for P-384 curve ([#515](https://github.com/firebase/php-jwt/issues/515)) ([5de4323](https://github.com/firebase/php-jwt/commit/5de4323f4baf4d70bca8663bd87682a69c656c3d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* handle invalid http responses ([#508](https://github.com/firebase/php-jwt/issues/508)) ([91c39c7](https://github.com/firebase/php-jwt/commit/91c39c72b22fc3e1191e574089552c1f2041c718))
|
||||
|
||||
## [6.7.0](https://github.com/firebase/php-jwt/compare/v6.6.0...v6.7.0) (2023-06-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add ed25519 support to JWK (public keys) ([#452](https://github.com/firebase/php-jwt/issues/452)) ([e53979a](https://github.com/firebase/php-jwt/commit/e53979abae927de916a75b9d239cfda8ce32be2a))
|
||||
|
||||
## [6.6.0](https://github.com/firebase/php-jwt/compare/v6.5.0...v6.6.0) (2023-06-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* allow get headers when decoding token ([#442](https://github.com/firebase/php-jwt/issues/442)) ([fb85f47](https://github.com/firebase/php-jwt/commit/fb85f47cfaeffdd94faf8defdf07164abcdad6c3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* only check iat if nbf is not used ([#493](https://github.com/firebase/php-jwt/issues/493)) ([398ccd2](https://github.com/firebase/php-jwt/commit/398ccd25ea12fa84b9e4f1085d5ff448c21ec797))
|
||||
|
||||
## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a))
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495))
|
||||
|
||||
## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95))
|
||||
* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c))
|
||||
|
||||
## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd))
|
||||
|
||||
## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22))
|
||||
* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2))
|
||||
|
||||
## 6.3.0 / 2022-07-15
|
||||
|
||||
- Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
|
||||
- Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))
|
||||
|
||||
## 6.2.0 / 2022-05-14
|
||||
|
||||
- Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
|
||||
- Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)).
|
||||
|
||||
## 6.1.0 / 2022-03-23
|
||||
|
||||
- Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
|
||||
- Add parameter typing and return types where possible
|
||||
|
||||
## 6.0.0 / 2022-01-24
|
||||
|
||||
- **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
|
||||
- New Key object to prevent key/algorithm type confusion (#365)
|
||||
- Add JWK support (#273)
|
||||
- Add ES256 support (#256)
|
||||
- Add ES384 support (#324)
|
||||
- Add Ed25519 support (#343)
|
||||
|
||||
## 5.0.0 / 2017-06-26
|
||||
- Support RS384 and RS512.
|
||||
See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
|
||||
- Add an example for RS256 openssl.
|
||||
See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
|
||||
- Detect invalid Base64 encoding in signature.
|
||||
See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
|
||||
- Update `JWT::verify` to handle OpenSSL errors.
|
||||
See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
|
||||
- Add `array` type hinting to `decode` method
|
||||
See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
|
||||
- Add all JSON error types.
|
||||
See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
|
||||
- Bugfix 'kid' not in given key list.
|
||||
See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
|
||||
- Miscellaneous cleanup, documentation and test fixes.
|
||||
See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
|
||||
[#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
|
||||
[#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
|
||||
[@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
|
||||
|
||||
## 4.0.0 / 2016-07-17
|
||||
- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
|
||||
- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
|
||||
- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
|
||||
- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
|
||||
|
||||
## 3.0.0 / 2015-07-22
|
||||
- Minimum PHP version updated from `5.2.0` to `5.3.0`.
|
||||
- Add `\Firebase\JWT` namespace. See
|
||||
[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
|
||||
[@Dashron](https://github.com/Dashron)!
|
||||
- Require a non-empty key to decode and verify a JWT. See
|
||||
[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
|
||||
[@sjones608](https://github.com/sjones608)!
|
||||
- Cleaner documentation blocks in the code. See
|
||||
[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
|
||||
[@johanderuijter](https://github.com/johanderuijter)!
|
||||
|
||||
## 2.2.0 / 2015-06-22
|
||||
- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
|
||||
[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
|
||||
[@mcocaro](https://github.com/mcocaro)!
|
||||
|
||||
## 2.1.0 / 2015-05-20
|
||||
- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
|
||||
between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
|
||||
- Add support for passing an object implementing the `ArrayAccess` interface for
|
||||
`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
|
||||
|
||||
## 2.0.0 / 2015-04-01
|
||||
- **Note**: It is strongly recommended that you update to > v2.0.0 to address
|
||||
known security vulnerabilities in prior versions when both symmetric and
|
||||
asymmetric keys are used together.
|
||||
- Update signature for `JWT::decode(...)` to require an array of supported
|
||||
algorithms to use when verifying token signatures.
|
337
vendor/firebase/php-jwt/README.md
vendored
337
vendor/firebase/php-jwt/README.md
vendored
@ -1,4 +1,4 @@
|
||||
[](https://travis-ci.org/firebase/php-jwt)
|
||||

|
||||
[](https://packagist.org/packages/firebase/php-jwt)
|
||||
[](https://packagist.org/packages/firebase/php-jwt)
|
||||
[](https://packagist.org/packages/firebase/php-jwt)
|
||||
@ -29,13 +29,13 @@ Example
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
$key = "example_key";
|
||||
$payload = array(
|
||||
"iss" => "http://example.org",
|
||||
"aud" => "http://example.com",
|
||||
"iat" => 1356999524,
|
||||
"nbf" => 1357000000
|
||||
);
|
||||
$key = 'example_key';
|
||||
$payload = [
|
||||
'iss' => 'http://example.org',
|
||||
'aud' => 'http://example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
/**
|
||||
* IMPORTANT:
|
||||
@ -45,9 +45,12 @@ $payload = array(
|
||||
*/
|
||||
$jwt = JWT::encode($payload, $key, 'HS256');
|
||||
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
|
||||
|
||||
print_r($decoded);
|
||||
|
||||
// Pass a stdClass in as the third parameter to get the decoded header values
|
||||
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass());
|
||||
print_r($headers);
|
||||
|
||||
/*
|
||||
NOTE: This will now be an object instead of an associative array. To get
|
||||
an associative array, you will need to cast it as such:
|
||||
@ -65,6 +68,40 @@ $decoded_array = (array) $decoded;
|
||||
JWT::$leeway = 60; // $leeway in seconds
|
||||
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
|
||||
```
|
||||
Example encode/decode headers
|
||||
-------
|
||||
Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
|
||||
this library. This is because without verifying the JWT, the header values could have been tampered with.
|
||||
Any value pulled from an unverified header should be treated as if it could be any string sent in from an
|
||||
attacker. If this is something you still want to do in your application for whatever reason, it's possible to
|
||||
decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
|
||||
header part:
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
|
||||
$key = 'example_key';
|
||||
$payload = [
|
||||
'iss' => 'http://example.org',
|
||||
'aud' => 'http://example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
$headers = [
|
||||
'x-forwarded-for' => 'www.google.com'
|
||||
];
|
||||
|
||||
// Encode headers in the JWT string
|
||||
$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
|
||||
|
||||
// Decode headers from the JWT string WITHOUT validation
|
||||
// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
|
||||
// These headers could be any value sent by an attacker.
|
||||
list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
|
||||
$decoded = json_decode(base64_decode($headersB64), true);
|
||||
|
||||
print_r($decoded);
|
||||
```
|
||||
Example with RS256 (openssl)
|
||||
----------------------------
|
||||
```php
|
||||
@ -73,37 +110,52 @@ use Firebase\JWT\Key;
|
||||
|
||||
$privateKey = <<<EOD
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn
|
||||
vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9
|
||||
5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB
|
||||
AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz
|
||||
bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J
|
||||
Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1
|
||||
cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5
|
||||
5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck
|
||||
ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe
|
||||
k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb
|
||||
qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k
|
||||
eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm
|
||||
B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM=
|
||||
MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
|
||||
M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
|
||||
JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
|
||||
78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
|
||||
HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
|
||||
WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
|
||||
6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
|
||||
VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
|
||||
oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
|
||||
c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
|
||||
h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
|
||||
bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
|
||||
39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
|
||||
3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
|
||||
vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
|
||||
6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
|
||||
OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
|
||||
nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
|
||||
xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
|
||||
8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
|
||||
hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
|
||||
YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
|
||||
DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
|
||||
RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
|
||||
2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
|
||||
-----END RSA PRIVATE KEY-----
|
||||
EOD;
|
||||
|
||||
$publicKey = <<<EOD
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H
|
||||
4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t
|
||||
0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4
|
||||
ehde/zUxo6UvS7UrBQIDAQAB
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
|
||||
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
|
||||
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
|
||||
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
|
||||
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
|
||||
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
|
||||
wQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
EOD;
|
||||
|
||||
$payload = array(
|
||||
"iss" => "example.org",
|
||||
"aud" => "example.com",
|
||||
"iat" => 1356999524,
|
||||
"nbf" => 1357000000
|
||||
);
|
||||
$payload = [
|
||||
'iss' => 'example.org',
|
||||
'aud' => 'example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
$jwt = JWT::encode($payload, $privateKey, 'RS256');
|
||||
echo "Encode:\n" . print_r($jwt, true) . "\n";
|
||||
@ -139,12 +191,12 @@ $privateKey = openssl_pkey_get_private(
|
||||
$passphrase
|
||||
);
|
||||
|
||||
$payload = array(
|
||||
"iss" => "example.org",
|
||||
"aud" => "example.com",
|
||||
"iat" => 1356999524,
|
||||
"nbf" => 1357000000
|
||||
);
|
||||
$payload = [
|
||||
'iss' => 'example.org',
|
||||
'aud' => 'example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
$jwt = JWT::encode($payload, $privateKey, 'RS256');
|
||||
echo "Encode:\n" . print_r($jwt, true) . "\n";
|
||||
@ -173,12 +225,12 @@ $privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
|
||||
|
||||
$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
|
||||
|
||||
$payload = array(
|
||||
"iss" => "example.org",
|
||||
"aud" => "example.com",
|
||||
"iat" => 1356999524,
|
||||
"nbf" => 1357000000
|
||||
);
|
||||
$payload = [
|
||||
'iss' => 'example.org',
|
||||
'aud' => 'example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
|
||||
echo "Encode:\n" . print_r($jwt, true) . "\n";
|
||||
@ -187,6 +239,44 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
|
||||
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
|
||||
````
|
||||
|
||||
Example with multiple keys
|
||||
--------------------------
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
// Example RSA keys from previous example
|
||||
// $privateKey1 = '...';
|
||||
// $publicKey1 = '...';
|
||||
|
||||
// Example EdDSA keys from previous example
|
||||
// $privateKey2 = '...';
|
||||
// $publicKey2 = '...';
|
||||
|
||||
$payload = [
|
||||
'iss' => 'example.org',
|
||||
'aud' => 'example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
|
||||
$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
|
||||
echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
|
||||
echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
|
||||
|
||||
$keys = [
|
||||
'kid1' => new Key($publicKey1, 'RS256'),
|
||||
'kid2' => new Key($publicKey2, 'EdDSA'),
|
||||
];
|
||||
|
||||
$decoded1 = JWT::decode($jwt1, $keys);
|
||||
$decoded2 = JWT::decode($jwt2, $keys);
|
||||
|
||||
echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
|
||||
echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
|
||||
```
|
||||
|
||||
Using JWKs
|
||||
----------
|
||||
|
||||
@ -198,72 +288,117 @@ use Firebase\JWT\JWT;
|
||||
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
|
||||
$jwks = ['keys' => []];
|
||||
|
||||
// JWK::parseKeySet($jwks) returns an associative array of **kid** to private
|
||||
// key. Pass this as the second parameter to JWT::decode.
|
||||
// NOTE: The deprecated $supportedAlgorithm must be supplied when parsing from JWK.
|
||||
JWT::decode($payload, JWK::parseKeySet($jwks), $supportedAlgorithm);
|
||||
// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
|
||||
// objects. Pass this as the second parameter to JWT::decode.
|
||||
JWT::decode($payload, JWK::parseKeySet($jwks));
|
||||
```
|
||||
|
||||
Changelog
|
||||
---------
|
||||
Using Cached Key Sets
|
||||
---------------------
|
||||
|
||||
#### 5.0.0 / 2017-06-26
|
||||
- Support RS384 and RS512.
|
||||
See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
|
||||
- Add an example for RS256 openssl.
|
||||
See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
|
||||
- Detect invalid Base64 encoding in signature.
|
||||
See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
|
||||
- Update `JWT::verify` to handle OpenSSL errors.
|
||||
See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
|
||||
- Add `array` type hinting to `decode` method
|
||||
See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
|
||||
- Add all JSON error types.
|
||||
See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
|
||||
- Bugfix 'kid' not in given key list.
|
||||
See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
|
||||
- Miscellaneous cleanup, documentation and test fixes.
|
||||
See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
|
||||
[#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
|
||||
[#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
|
||||
[@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
|
||||
The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
|
||||
This has the following advantages:
|
||||
|
||||
#### 4.0.0 / 2016-07-17
|
||||
- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
|
||||
- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
|
||||
- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
|
||||
- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
|
||||
1. The results are cached for performance.
|
||||
2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
|
||||
3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
|
||||
|
||||
#### 3.0.0 / 2015-07-22
|
||||
- Minimum PHP version updated from `5.2.0` to `5.3.0`.
|
||||
- Add `\Firebase\JWT` namespace. See
|
||||
[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
|
||||
[@Dashron](https://github.com/Dashron)!
|
||||
- Require a non-empty key to decode and verify a JWT. See
|
||||
[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
|
||||
[@sjones608](https://github.com/sjones608)!
|
||||
- Cleaner documentation blocks in the code. See
|
||||
[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
|
||||
[@johanderuijter](https://github.com/johanderuijter)!
|
||||
```php
|
||||
use Firebase\JWT\CachedKeySet;
|
||||
use Firebase\JWT\JWT;
|
||||
|
||||
#### 2.2.0 / 2015-06-22
|
||||
- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
|
||||
[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
|
||||
[@mcocaro](https://github.com/mcocaro)!
|
||||
// The URI for the JWKS you wish to cache the results from
|
||||
$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
|
||||
|
||||
#### 2.1.0 / 2015-05-20
|
||||
- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
|
||||
between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
|
||||
- Add support for passing an object implementing the `ArrayAccess` interface for
|
||||
`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
|
||||
// Create an HTTP client (can be any PSR-7 compatible HTTP client)
|
||||
$httpClient = new GuzzleHttp\Client();
|
||||
|
||||
#### 2.0.0 / 2015-04-01
|
||||
- **Note**: It is strongly recommended that you update to > v2.0.0 to address
|
||||
known security vulnerabilities in prior versions when both symmetric and
|
||||
asymmetric keys are used together.
|
||||
- Update signature for `JWT::decode(...)` to require an array of supported
|
||||
algorithms to use when verifying token signatures.
|
||||
// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
|
||||
$httpFactory = new GuzzleHttp\Psr\HttpFactory();
|
||||
|
||||
// Create a cache item pool (can be any PSR-6 compatible cache item pool)
|
||||
$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
|
||||
|
||||
$keySet = new CachedKeySet(
|
||||
$jwksUri,
|
||||
$httpClient,
|
||||
$httpFactory,
|
||||
$cacheItemPool,
|
||||
null, // $expiresAfter int seconds to set the JWKS to expire
|
||||
true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
|
||||
);
|
||||
|
||||
$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
|
||||
$decoded = JWT::decode($jwt, $keySet);
|
||||
```
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
#### Exception Handling
|
||||
|
||||
When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
|
||||
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\SignatureInvalidException;
|
||||
use Firebase\JWT\BeforeValidException;
|
||||
use Firebase\JWT\ExpiredException;
|
||||
use DomainException;
|
||||
use InvalidArgumentException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
try {
|
||||
$decoded = JWT::decode($payload, $keys);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
// provided key/key-array is empty or malformed.
|
||||
} catch (DomainException $e) {
|
||||
// provided algorithm is unsupported OR
|
||||
// provided key is invalid OR
|
||||
// unknown error thrown in openSSL or libsodium OR
|
||||
// libsodium is required but not available.
|
||||
} catch (SignatureInvalidException $e) {
|
||||
// provided JWT signature verification failed.
|
||||
} catch (BeforeValidException $e) {
|
||||
// provided JWT is trying to be used before "nbf" claim OR
|
||||
// provided JWT is trying to be used before "iat" claim.
|
||||
} catch (ExpiredException $e) {
|
||||
// provided JWT is trying to be used after "exp" claim.
|
||||
} catch (UnexpectedValueException $e) {
|
||||
// provided JWT is malformed OR
|
||||
// provided JWT is missing an algorithm / using an unsupported algorithm OR
|
||||
// provided JWT algorithm does not match provided key OR
|
||||
// provided key ID in key/key-array is empty or invalid.
|
||||
}
|
||||
```
|
||||
|
||||
All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
|
||||
like this:
|
||||
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
use UnexpectedValueException;
|
||||
try {
|
||||
$decoded = JWT::decode($payload, $keys);
|
||||
} catch (LogicException $e) {
|
||||
// errors having to do with environmental setup or malformed JWT Keys
|
||||
} catch (UnexpectedValueException $e) {
|
||||
// errors having to do with JWT signature and claims
|
||||
}
|
||||
```
|
||||
|
||||
#### Casting to array
|
||||
|
||||
The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
|
||||
instead, you can do the following:
|
||||
|
||||
```php
|
||||
// return type is stdClass
|
||||
$decoded = JWT::decode($payload, $keys);
|
||||
|
||||
// cast to array
|
||||
$decoded = json_decode(json_encode($decoded), true);
|
||||
```
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
12
vendor/firebase/php-jwt/composer.json
vendored
12
vendor/firebase/php-jwt/composer.json
vendored
@ -20,10 +20,11 @@
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
"php": "^7.4||^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
|
||||
"ext-sodium": "Support EdDSA (Ed25519) signatures"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@ -31,6 +32,11 @@
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=4.8 <=9"
|
||||
"guzzlehttp/guzzle": "^6.5||^7.4",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psr/cache": "^1.0||^2.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0"
|
||||
}
|
||||
}
|
||||
|
268
vendor/firebase/php-jwt/src/CachedKeySet.php
vendored
Normal file
268
vendor/firebase/php-jwt/src/CachedKeySet.php
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
use ArrayAccess;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use OutOfBoundsException;
|
||||
use Psr\Cache\CacheItemInterface;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
use RuntimeException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @implements ArrayAccess<string, Key>
|
||||
*/
|
||||
class CachedKeySet implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $jwksUri;
|
||||
/**
|
||||
* @var ClientInterface
|
||||
*/
|
||||
private $httpClient;
|
||||
/**
|
||||
* @var RequestFactoryInterface
|
||||
*/
|
||||
private $httpFactory;
|
||||
/**
|
||||
* @var CacheItemPoolInterface
|
||||
*/
|
||||
private $cache;
|
||||
/**
|
||||
* @var ?int
|
||||
*/
|
||||
private $expiresAfter;
|
||||
/**
|
||||
* @var ?CacheItemInterface
|
||||
*/
|
||||
private $cacheItem;
|
||||
/**
|
||||
* @var array<string, array<mixed>>
|
||||
*/
|
||||
private $keySet;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $cacheKey;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $cacheKeyPrefix = 'jwks';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxKeyLength = 64;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $rateLimit;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rateLimitCacheKey;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxCallsPerMinute = 10;
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $defaultAlg;
|
||||
|
||||
public function __construct(
|
||||
string $jwksUri,
|
||||
ClientInterface $httpClient,
|
||||
RequestFactoryInterface $httpFactory,
|
||||
CacheItemPoolInterface $cache,
|
||||
int $expiresAfter = null,
|
||||
bool $rateLimit = false,
|
||||
string $defaultAlg = null
|
||||
) {
|
||||
$this->jwksUri = $jwksUri;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->httpFactory = $httpFactory;
|
||||
$this->cache = $cache;
|
||||
$this->expiresAfter = $expiresAfter;
|
||||
$this->rateLimit = $rateLimit;
|
||||
$this->defaultAlg = $defaultAlg;
|
||||
$this->setCacheKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $keyId
|
||||
* @return Key
|
||||
*/
|
||||
public function offsetGet($keyId): Key
|
||||
{
|
||||
if (!$this->keyIdExists($keyId)) {
|
||||
throw new OutOfBoundsException('Key ID not found');
|
||||
}
|
||||
return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $keyId
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($keyId): bool
|
||||
{
|
||||
return $this->keyIdExists($keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
* @param Key $value
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
throw new LogicException('Method not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
throw new LogicException('Method not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
private function formatJwksForCache(string $jwks): array
|
||||
{
|
||||
$jwks = json_decode($jwks, true);
|
||||
|
||||
if (!isset($jwks['keys'])) {
|
||||
throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
|
||||
}
|
||||
|
||||
if (empty($jwks['keys'])) {
|
||||
throw new InvalidArgumentException('JWK Set did not contain any keys');
|
||||
}
|
||||
|
||||
$keys = [];
|
||||
foreach ($jwks['keys'] as $k => $v) {
|
||||
$kid = isset($v['kid']) ? $v['kid'] : $k;
|
||||
$keys[(string) $kid] = $v;
|
||||
}
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
private function keyIdExists(string $keyId): bool
|
||||
{
|
||||
if (null === $this->keySet) {
|
||||
$item = $this->getCacheItem();
|
||||
// Try to load keys from cache
|
||||
if ($item->isHit()) {
|
||||
// item found! retrieve it
|
||||
$this->keySet = $item->get();
|
||||
// If the cached item is a string, the JWKS response was cached (previous behavior).
|
||||
// Parse this into expected format array<kid, jwk> instead.
|
||||
if (\is_string($this->keySet)) {
|
||||
$this->keySet = $this->formatJwksForCache($this->keySet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($this->keySet[$keyId])) {
|
||||
if ($this->rateLimitExceeded()) {
|
||||
return false;
|
||||
}
|
||||
$request = $this->httpFactory->createRequest('GET', $this->jwksUri);
|
||||
$jwksResponse = $this->httpClient->sendRequest($request);
|
||||
if ($jwksResponse->getStatusCode() !== 200) {
|
||||
throw new UnexpectedValueException(
|
||||
sprintf('HTTP Error: %d %s for URI "%s"',
|
||||
$jwksResponse->getStatusCode(),
|
||||
$jwksResponse->getReasonPhrase(),
|
||||
$this->jwksUri,
|
||||
),
|
||||
$jwksResponse->getStatusCode()
|
||||
);
|
||||
}
|
||||
$this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
|
||||
|
||||
if (!isset($this->keySet[$keyId])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$item = $this->getCacheItem();
|
||||
$item->set($this->keySet);
|
||||
if ($this->expiresAfter) {
|
||||
$item->expiresAfter($this->expiresAfter);
|
||||
}
|
||||
$this->cache->save($item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function rateLimitExceeded(): bool
|
||||
{
|
||||
if (!$this->rateLimit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
|
||||
if (!$cacheItem->isHit()) {
|
||||
$cacheItem->expiresAfter(1); // # of calls are cached each minute
|
||||
}
|
||||
|
||||
$callsPerMinute = (int) $cacheItem->get();
|
||||
if (++$callsPerMinute > $this->maxCallsPerMinute) {
|
||||
return true;
|
||||
}
|
||||
$cacheItem->set($callsPerMinute);
|
||||
$this->cache->save($cacheItem);
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getCacheItem(): CacheItemInterface
|
||||
{
|
||||
if (\is_null($this->cacheItem)) {
|
||||
$this->cacheItem = $this->cache->getItem($this->cacheKey);
|
||||
}
|
||||
|
||||
return $this->cacheItem;
|
||||
}
|
||||
|
||||
private function setCacheKeys(): void
|
||||
{
|
||||
if (empty($this->jwksUri)) {
|
||||
throw new RuntimeException('JWKS URI is empty');
|
||||
}
|
||||
|
||||
// ensure we do not have illegal characters
|
||||
$key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri);
|
||||
|
||||
// add prefix
|
||||
$key = $this->cacheKeyPrefix . $key;
|
||||
|
||||
// Hash keys if they exceed $maxKeyLength of 64
|
||||
if (\strlen($key) > $this->maxKeyLength) {
|
||||
$key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
|
||||
}
|
||||
|
||||
$this->cacheKey = $key;
|
||||
|
||||
if ($this->rateLimit) {
|
||||
// add prefix
|
||||
$rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
|
||||
|
||||
// Hash keys if they exceed $maxKeyLength of 64
|
||||
if (\strlen($rateLimitKey) > $this->maxKeyLength) {
|
||||
$rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
|
||||
}
|
||||
|
||||
$this->rateLimitCacheKey = $rateLimitKey;
|
||||
}
|
||||
}
|
||||
}
|
229
vendor/firebase/php-jwt/src/JWK.php
vendored
229
vendor/firebase/php-jwt/src/JWK.php
vendored
@ -20,12 +20,31 @@ use UnexpectedValueException;
|
||||
*/
|
||||
class JWK
|
||||
{
|
||||
private const OID = '1.2.840.10045.2.1';
|
||||
private const ASN1_OBJECT_IDENTIFIER = 0x06;
|
||||
private const ASN1_SEQUENCE = 0x10; // also defined in JWT
|
||||
private const ASN1_BIT_STRING = 0x03;
|
||||
private const EC_CURVES = [
|
||||
'P-256' => '1.2.840.10045.3.1.7', // Len: 64
|
||||
'secp256k1' => '1.3.132.0.10', // Len: 64
|
||||
'P-384' => '1.3.132.0.34', // Len: 96
|
||||
// 'P-521' => '1.3.132.0.35', // Len: 132 (not supported)
|
||||
];
|
||||
|
||||
// For keys with "kty" equal to "OKP" (Octet Key Pair), the "crv" parameter must contain the key subtype.
|
||||
// This library supports the following subtypes:
|
||||
private const OKP_SUBTYPES = [
|
||||
'Ed25519' => true, // RFC 8037
|
||||
];
|
||||
|
||||
/**
|
||||
* Parse a set of JWK keys
|
||||
*
|
||||
* @param array $jwks The JSON Web Key Set as an associative array
|
||||
* @param array<mixed> $jwks The JSON Web Key Set as an associative array
|
||||
* @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
|
||||
* JSON Web Key Set
|
||||
*
|
||||
* @return array An associative array that represents the set of keys
|
||||
* @return array<string, Key> An associative array of key IDs (kid) to Key objects
|
||||
*
|
||||
* @throws InvalidArgumentException Provided JWK Set is empty
|
||||
* @throws UnexpectedValueException Provided JWK Set was invalid
|
||||
@ -33,21 +52,22 @@ class JWK
|
||||
*
|
||||
* @uses parseKey
|
||||
*/
|
||||
public static function parseKeySet(array $jwks)
|
||||
public static function parseKeySet(array $jwks, string $defaultAlg = null): array
|
||||
{
|
||||
$keys = array();
|
||||
$keys = [];
|
||||
|
||||
if (!isset($jwks['keys'])) {
|
||||
throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
|
||||
}
|
||||
|
||||
if (empty($jwks['keys'])) {
|
||||
throw new InvalidArgumentException('JWK Set did not contain any keys');
|
||||
}
|
||||
|
||||
foreach ($jwks['keys'] as $k => $v) {
|
||||
$kid = isset($v['kid']) ? $v['kid'] : $k;
|
||||
if ($key = self::parseKey($v)) {
|
||||
$keys[$kid] = $key;
|
||||
if ($key = self::parseKey($v, $defaultAlg)) {
|
||||
$keys[(string) $kid] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,9 +81,11 @@ class JWK
|
||||
/**
|
||||
* Parse a JWK key
|
||||
*
|
||||
* @param array $jwk An individual JWK
|
||||
* @param array<mixed> $jwk An individual JWK
|
||||
* @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
|
||||
* JSON Web Key Set
|
||||
*
|
||||
* @return resource|array An associative array that represents the key
|
||||
* @return Key The key object for the JWK
|
||||
*
|
||||
* @throws InvalidArgumentException Provided JWK is empty
|
||||
* @throws UnexpectedValueException Provided JWK was invalid
|
||||
@ -71,15 +93,27 @@ class JWK
|
||||
*
|
||||
* @uses createPemFromModulusAndExponent
|
||||
*/
|
||||
public static function parseKey(array $jwk)
|
||||
public static function parseKey(array $jwk, string $defaultAlg = null): ?Key
|
||||
{
|
||||
if (empty($jwk)) {
|
||||
throw new InvalidArgumentException('JWK must not be empty');
|
||||
}
|
||||
|
||||
if (!isset($jwk['kty'])) {
|
||||
throw new UnexpectedValueException('JWK must contain a "kty" parameter');
|
||||
}
|
||||
|
||||
if (!isset($jwk['alg'])) {
|
||||
if (\is_null($defaultAlg)) {
|
||||
// The "alg" parameter is optional in a KTY, but an algorithm is required
|
||||
// for parsing in this library. Use the $defaultAlg parameter when parsing the
|
||||
// key set in order to prevent this error.
|
||||
// @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
|
||||
throw new UnexpectedValueException('JWK must contain an "alg" parameter');
|
||||
}
|
||||
$jwk['alg'] = $defaultAlg;
|
||||
}
|
||||
|
||||
switch ($jwk['kty']) {
|
||||
case 'RSA':
|
||||
if (!empty($jwk['d'])) {
|
||||
@ -96,11 +130,92 @@ class JWK
|
||||
'OpenSSL error: ' . \openssl_error_string()
|
||||
);
|
||||
}
|
||||
return $publicKey;
|
||||
return new Key($publicKey, $jwk['alg']);
|
||||
case 'EC':
|
||||
if (isset($jwk['d'])) {
|
||||
// The key is actually a private key
|
||||
throw new UnexpectedValueException('Key data must be for a public key');
|
||||
}
|
||||
|
||||
if (empty($jwk['crv'])) {
|
||||
throw new UnexpectedValueException('crv not set');
|
||||
}
|
||||
|
||||
if (!isset(self::EC_CURVES[$jwk['crv']])) {
|
||||
throw new DomainException('Unrecognised or unsupported EC curve');
|
||||
}
|
||||
|
||||
if (empty($jwk['x']) || empty($jwk['y'])) {
|
||||
throw new UnexpectedValueException('x and y not set');
|
||||
}
|
||||
|
||||
$publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
|
||||
return new Key($publicKey, $jwk['alg']);
|
||||
case 'OKP':
|
||||
if (isset($jwk['d'])) {
|
||||
// The key is actually a private key
|
||||
throw new UnexpectedValueException('Key data must be for a public key');
|
||||
}
|
||||
|
||||
if (!isset($jwk['crv'])) {
|
||||
throw new UnexpectedValueException('crv not set');
|
||||
}
|
||||
|
||||
if (empty(self::OKP_SUBTYPES[$jwk['crv']])) {
|
||||
throw new DomainException('Unrecognised or unsupported OKP key subtype');
|
||||
}
|
||||
|
||||
if (empty($jwk['x'])) {
|
||||
throw new UnexpectedValueException('x not set');
|
||||
}
|
||||
|
||||
// This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
|
||||
$publicKey = JWT::convertBase64urlToBase64($jwk['x']);
|
||||
return new Key($publicKey, $jwk['alg']);
|
||||
default:
|
||||
// Currently only RSA is supported
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the EC JWK values to pem format.
|
||||
*
|
||||
* @param string $crv The EC curve (only P-256 & P-384 is supported)
|
||||
* @param string $x The EC x-coordinate
|
||||
* @param string $y The EC y-coordinate
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
|
||||
{
|
||||
$pem =
|
||||
self::encodeDER(
|
||||
self::ASN1_SEQUENCE,
|
||||
self::encodeDER(
|
||||
self::ASN1_SEQUENCE,
|
||||
self::encodeDER(
|
||||
self::ASN1_OBJECT_IDENTIFIER,
|
||||
self::encodeOID(self::OID)
|
||||
)
|
||||
. self::encodeDER(
|
||||
self::ASN1_OBJECT_IDENTIFIER,
|
||||
self::encodeOID(self::EC_CURVES[$crv])
|
||||
)
|
||||
) .
|
||||
self::encodeDER(
|
||||
self::ASN1_BIT_STRING,
|
||||
\chr(0x00) . \chr(0x04)
|
||||
. JWT::urlsafeB64Decode($x)
|
||||
. JWT::urlsafeB64Decode($y)
|
||||
)
|
||||
);
|
||||
|
||||
return sprintf(
|
||||
"-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
|
||||
wordwrap(base64_encode($pem), 64, "\n", true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,22 +228,22 @@ class JWK
|
||||
*
|
||||
* @uses encodeLength
|
||||
*/
|
||||
private static function createPemFromModulusAndExponent($n, $e)
|
||||
{
|
||||
$modulus = JWT::urlsafeB64Decode($n);
|
||||
$publicExponent = JWT::urlsafeB64Decode($e);
|
||||
private static function createPemFromModulusAndExponent(
|
||||
string $n,
|
||||
string $e
|
||||
): string {
|
||||
$mod = JWT::urlsafeB64Decode($n);
|
||||
$exp = JWT::urlsafeB64Decode($e);
|
||||
|
||||
$components = array(
|
||||
'modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus),
|
||||
'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent)
|
||||
);
|
||||
$modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod);
|
||||
$publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);
|
||||
|
||||
$rsaPublicKey = \pack(
|
||||
'Ca*a*a*',
|
||||
48,
|
||||
self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])),
|
||||
$components['modulus'],
|
||||
$components['publicExponent']
|
||||
self::encodeLength(\strlen($modulus) + \strlen($publicExponent)),
|
||||
$modulus,
|
||||
$publicExponent
|
||||
);
|
||||
|
||||
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
|
||||
@ -143,11 +258,9 @@ class JWK
|
||||
$rsaOID . $rsaPublicKey
|
||||
);
|
||||
|
||||
$rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
return "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
\chunk_split(\base64_encode($rsaPublicKey), 64) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
|
||||
return $rsaPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,7 +272,7 @@ class JWK
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
private static function encodeLength($length)
|
||||
private static function encodeLength(int $length): string
|
||||
{
|
||||
if ($length <= 0x7F) {
|
||||
return \chr($length);
|
||||
@ -169,4 +282,68 @@ class JWK
|
||||
|
||||
return \pack('Ca*', 0x80 | \strlen($temp), $temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a value into a DER object.
|
||||
* Also defined in Firebase\JWT\JWT
|
||||
*
|
||||
* @param int $type DER tag
|
||||
* @param string $value the value to encode
|
||||
* @return string the encoded object
|
||||
*/
|
||||
private static function encodeDER(int $type, string $value): string
|
||||
{
|
||||
$tag_header = 0;
|
||||
if ($type === self::ASN1_SEQUENCE) {
|
||||
$tag_header |= 0x20;
|
||||
}
|
||||
|
||||
// Type
|
||||
$der = \chr($tag_header | $type);
|
||||
|
||||
// Length
|
||||
$der .= \chr(\strlen($value));
|
||||
|
||||
return $der . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a string into a DER-encoded OID.
|
||||
*
|
||||
* @param string $oid the OID string
|
||||
* @return string the binary DER-encoded OID
|
||||
*/
|
||||
private static function encodeOID(string $oid): string
|
||||
{
|
||||
$octets = explode('.', $oid);
|
||||
|
||||
// Get the first octet
|
||||
$first = (int) array_shift($octets);
|
||||
$second = (int) array_shift($octets);
|
||||
$oid = \chr($first * 40 + $second);
|
||||
|
||||
// Iterate over subsequent octets
|
||||
foreach ($octets as $octet) {
|
||||
if ($octet == 0) {
|
||||
$oid .= \chr(0x00);
|
||||
continue;
|
||||
}
|
||||
$bin = '';
|
||||
|
||||
while ($octet) {
|
||||
$bin .= \chr(0x80 | ($octet & 0x7f));
|
||||
$octet >>= 7;
|
||||
}
|
||||
$bin[0] = $bin[0] & \chr(0x7f);
|
||||
|
||||
// Convert to big endian if necessary
|
||||
if (pack('V', 65534) == pack('L', 65534)) {
|
||||
$oid .= strrev($bin);
|
||||
} else {
|
||||
$oid .= $bin;
|
||||
}
|
||||
}
|
||||
|
||||
return $oid;
|
||||
}
|
||||
}
|
||||
|
419
vendor/firebase/php-jwt/src/JWT.php
vendored
419
vendor/firebase/php-jwt/src/JWT.php
vendored
@ -3,12 +3,14 @@
|
||||
namespace Firebase\JWT;
|
||||
|
||||
use ArrayAccess;
|
||||
use DateTime;
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use OpenSSLAsymmetricKey;
|
||||
use OpenSSLCertificate;
|
||||
use stdClass;
|
||||
use UnexpectedValueException;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* JSON Web Token implementation, based on this spec:
|
||||
@ -25,52 +27,63 @@ use DateTime;
|
||||
*/
|
||||
class JWT
|
||||
{
|
||||
const ASN1_INTEGER = 0x02;
|
||||
const ASN1_SEQUENCE = 0x10;
|
||||
const ASN1_BIT_STRING = 0x03;
|
||||
private const ASN1_INTEGER = 0x02;
|
||||
private const ASN1_SEQUENCE = 0x10;
|
||||
private const ASN1_BIT_STRING = 0x03;
|
||||
|
||||
/**
|
||||
* When checking nbf, iat or expiration times,
|
||||
* we want to provide some extra leeway time to
|
||||
* account for clock skew.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public static $leeway = 0;
|
||||
|
||||
/**
|
||||
* Allow the current timestamp to be specified.
|
||||
* Useful for fixing a value within unit testing.
|
||||
*
|
||||
* Will default to PHP time() value if null.
|
||||
*
|
||||
* @var ?int
|
||||
*/
|
||||
public static $timestamp = null;
|
||||
|
||||
public static $supported_algs = array(
|
||||
'ES384' => array('openssl', 'SHA384'),
|
||||
'ES256' => array('openssl', 'SHA256'),
|
||||
'HS256' => array('hash_hmac', 'SHA256'),
|
||||
'HS384' => array('hash_hmac', 'SHA384'),
|
||||
'HS512' => array('hash_hmac', 'SHA512'),
|
||||
'RS256' => array('openssl', 'SHA256'),
|
||||
'RS384' => array('openssl', 'SHA384'),
|
||||
'RS512' => array('openssl', 'SHA512'),
|
||||
'EdDSA' => array('sodium_crypto', 'EdDSA'),
|
||||
);
|
||||
/**
|
||||
* @var array<string, string[]>
|
||||
*/
|
||||
public static $supported_algs = [
|
||||
'ES384' => ['openssl', 'SHA384'],
|
||||
'ES256' => ['openssl', 'SHA256'],
|
||||
'ES256K' => ['openssl', 'SHA256'],
|
||||
'HS256' => ['hash_hmac', 'SHA256'],
|
||||
'HS384' => ['hash_hmac', 'SHA384'],
|
||||
'HS512' => ['hash_hmac', 'SHA512'],
|
||||
'RS256' => ['openssl', 'SHA256'],
|
||||
'RS384' => ['openssl', 'SHA384'],
|
||||
'RS512' => ['openssl', 'SHA512'],
|
||||
'EdDSA' => ['sodium_crypto', 'EdDSA'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Decodes a JWT string into a PHP object.
|
||||
*
|
||||
* @param string $jwt The JWT
|
||||
* @param Key|array<Key>|mixed $keyOrKeyArray The Key or array of Key objects.
|
||||
* If the algorithm used is asymmetric, this is the public key
|
||||
* Each Key object contains an algorithm and matching key.
|
||||
* Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
|
||||
* 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||
* @param array $allowed_algs [DEPRECATED] List of supported verification algorithms. Only
|
||||
* should be used for backwards compatibility.
|
||||
* @param string $jwt The JWT
|
||||
* @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray The Key or associative array of key IDs
|
||||
* (kid) to Key objects.
|
||||
* If the algorithm used is asymmetric, this is
|
||||
* the public key.
|
||||
* Each Key object contains an algorithm and
|
||||
* matching key.
|
||||
* Supported algorithms are 'ES384','ES256',
|
||||
* 'HS256', 'HS384', 'HS512', 'RS256', 'RS384'
|
||||
* and 'RS512'.
|
||||
* @param stdClass $headers Optional. Populates stdClass with headers.
|
||||
*
|
||||
* @return object The JWT's payload as a PHP object
|
||||
* @return stdClass The JWT's payload as a PHP object
|
||||
*
|
||||
* @throws InvalidArgumentException Provided JWT was empty
|
||||
* @throws InvalidArgumentException Provided key/key-array was empty or malformed
|
||||
* @throws DomainException Provided JWT is malformed
|
||||
* @throws UnexpectedValueException Provided JWT was invalid
|
||||
* @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
|
||||
* @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
|
||||
@ -80,27 +93,41 @@ class JWT
|
||||
* @uses jsonDecode
|
||||
* @uses urlsafeB64Decode
|
||||
*/
|
||||
public static function decode($jwt, $keyOrKeyArray, array $allowed_algs = array())
|
||||
{
|
||||
public static function decode(
|
||||
string $jwt,
|
||||
$keyOrKeyArray,
|
||||
stdClass &$headers = null
|
||||
): stdClass {
|
||||
// Validate JWT
|
||||
$timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
|
||||
|
||||
if (empty($keyOrKeyArray)) {
|
||||
throw new InvalidArgumentException('Key may not be empty');
|
||||
}
|
||||
$tks = \explode('.', $jwt);
|
||||
if (\count($tks) != 3) {
|
||||
if (\count($tks) !== 3) {
|
||||
throw new UnexpectedValueException('Wrong number of segments');
|
||||
}
|
||||
list($headb64, $bodyb64, $cryptob64) = $tks;
|
||||
if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64)))) {
|
||||
$headerRaw = static::urlsafeB64Decode($headb64);
|
||||
if (null === ($header = static::jsonDecode($headerRaw))) {
|
||||
throw new UnexpectedValueException('Invalid header encoding');
|
||||
}
|
||||
if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64))) {
|
||||
if ($headers !== null) {
|
||||
$headers = $header;
|
||||
}
|
||||
$payloadRaw = static::urlsafeB64Decode($bodyb64);
|
||||
if (null === ($payload = static::jsonDecode($payloadRaw))) {
|
||||
throw new UnexpectedValueException('Invalid claims encoding');
|
||||
}
|
||||
if (false === ($sig = static::urlsafeB64Decode($cryptob64))) {
|
||||
throw new UnexpectedValueException('Invalid signature encoding');
|
||||
if (\is_array($payload)) {
|
||||
// prevent PHP Fatal Error in edge-cases when payload is empty array
|
||||
$payload = (object) $payload;
|
||||
}
|
||||
if (!$payload instanceof stdClass) {
|
||||
throw new UnexpectedValueException('Payload must be a JSON object');
|
||||
}
|
||||
$sig = static::urlsafeB64Decode($cryptob64);
|
||||
if (empty($header->alg)) {
|
||||
throw new UnexpectedValueException('Empty algorithm');
|
||||
}
|
||||
@ -108,48 +135,35 @@ class JWT
|
||||
throw new UnexpectedValueException('Algorithm not supported');
|
||||
}
|
||||
|
||||
list($keyMaterial, $algorithm) = self::getKeyMaterialAndAlgorithm(
|
||||
$keyOrKeyArray,
|
||||
empty($header->kid) ? null : $header->kid
|
||||
);
|
||||
$key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null);
|
||||
|
||||
if (empty($algorithm)) {
|
||||
// Use deprecated "allowed_algs" to determine if the algorithm is supported.
|
||||
// This opens up the possibility of an attack in some implementations.
|
||||
// @see https://github.com/firebase/php-jwt/issues/351
|
||||
if (!\in_array($header->alg, $allowed_algs)) {
|
||||
throw new UnexpectedValueException('Algorithm not allowed');
|
||||
}
|
||||
} else {
|
||||
// Check the algorithm
|
||||
if (!self::constantTimeEquals($algorithm, $header->alg)) {
|
||||
// See issue #351
|
||||
throw new UnexpectedValueException('Incorrect key for this algorithm');
|
||||
}
|
||||
// Check the algorithm
|
||||
if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) {
|
||||
// See issue #351
|
||||
throw new UnexpectedValueException('Incorrect key for this algorithm');
|
||||
}
|
||||
if ($header->alg === 'ES256' || $header->alg === 'ES384') {
|
||||
// OpenSSL expects an ASN.1 DER sequence for ES256/ES384 signatures
|
||||
if (\in_array($header->alg, ['ES256', 'ES256K', 'ES384'], true)) {
|
||||
// OpenSSL expects an ASN.1 DER sequence for ES256/ES256K/ES384 signatures
|
||||
$sig = self::signatureToDER($sig);
|
||||
}
|
||||
|
||||
if (!static::verify("$headb64.$bodyb64", $sig, $keyMaterial, $header->alg)) {
|
||||
if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) {
|
||||
throw new SignatureInvalidException('Signature verification failed');
|
||||
}
|
||||
|
||||
// Check the nbf if it is defined. This is the time that the
|
||||
// token can actually be used. If it's not yet that time, abort.
|
||||
if (isset($payload->nbf) && $payload->nbf > ($timestamp + static::$leeway)) {
|
||||
if (isset($payload->nbf) && floor($payload->nbf) > ($timestamp + static::$leeway)) {
|
||||
throw new BeforeValidException(
|
||||
'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->nbf)
|
||||
'Cannot handle token with nbf prior to ' . \date(DateTime::ISO8601, (int) $payload->nbf)
|
||||
);
|
||||
}
|
||||
|
||||
// Check that this token has been created before 'now'. This prevents
|
||||
// using tokens that have been created for later use (and haven't
|
||||
// correctly used the nbf claim).
|
||||
if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) {
|
||||
if (!isset($payload->nbf) && isset($payload->iat) && floor($payload->iat) > ($timestamp + static::$leeway)) {
|
||||
throw new BeforeValidException(
|
||||
'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat)
|
||||
'Cannot handle token with iat prior to ' . \date(DateTime::ISO8601, (int) $payload->iat)
|
||||
);
|
||||
}
|
||||
|
||||
@ -162,34 +176,37 @@ class JWT
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts and signs a PHP object or array into a JWT string.
|
||||
* Converts and signs a PHP array into a JWT string.
|
||||
*
|
||||
* @param object|array $payload PHP object or array
|
||||
* @param string|resource $key The secret key.
|
||||
* If the algorithm used is asymmetric, this is the private key
|
||||
* @param string $alg The signing algorithm.
|
||||
* Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
|
||||
* 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||
* @param mixed $keyId
|
||||
* @param array $head An array with header elements to attach
|
||||
* @param array<mixed> $payload PHP array
|
||||
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
|
||||
* @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
|
||||
* 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||
* @param string $keyId
|
||||
* @param array<string, string> $head An array with header elements to attach
|
||||
*
|
||||
* @return string A signed JWT
|
||||
*
|
||||
* @uses jsonEncode
|
||||
* @uses urlsafeB64Encode
|
||||
*/
|
||||
public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)
|
||||
{
|
||||
$header = array('typ' => 'JWT', 'alg' => $alg);
|
||||
public static function encode(
|
||||
array $payload,
|
||||
$key,
|
||||
string $alg,
|
||||
string $keyId = null,
|
||||
array $head = null
|
||||
): string {
|
||||
$header = ['typ' => 'JWT', 'alg' => $alg];
|
||||
if ($keyId !== null) {
|
||||
$header['kid'] = $keyId;
|
||||
}
|
||||
if (isset($head) && \is_array($head)) {
|
||||
$header = \array_merge($head, $header);
|
||||
}
|
||||
$segments = array();
|
||||
$segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
|
||||
$segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
|
||||
$segments = [];
|
||||
$segments[] = static::urlsafeB64Encode((string) static::jsonEncode($header));
|
||||
$segments[] = static::urlsafeB64Encode((string) static::jsonEncode($payload));
|
||||
$signing_input = \implode('.', $segments);
|
||||
|
||||
$signature = static::sign($signing_input, $key, $alg);
|
||||
@ -201,67 +218,84 @@ class JWT
|
||||
/**
|
||||
* Sign a string with a given key and algorithm.
|
||||
*
|
||||
* @param string $msg The message to sign
|
||||
* @param string|resource $key The secret key
|
||||
* @param string $alg The signing algorithm.
|
||||
* Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
|
||||
* 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||
* @param string $msg The message to sign
|
||||
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
|
||||
* @param string $alg Supported algorithms are 'EdDSA', 'ES384', 'ES256', 'ES256K', 'HS256',
|
||||
* 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
|
||||
*
|
||||
* @return string An encrypted message
|
||||
*
|
||||
* @throws DomainException Unsupported algorithm or bad key was specified
|
||||
*/
|
||||
public static function sign($msg, $key, $alg = 'HS256')
|
||||
{
|
||||
public static function sign(
|
||||
string $msg,
|
||||
$key,
|
||||
string $alg
|
||||
): string {
|
||||
if (empty(static::$supported_algs[$alg])) {
|
||||
throw new DomainException('Algorithm not supported');
|
||||
}
|
||||
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||
switch ($function) {
|
||||
case 'hash_hmac':
|
||||
if (!\is_string($key)) {
|
||||
throw new InvalidArgumentException('key must be a string when using hmac');
|
||||
}
|
||||
return \hash_hmac($algorithm, $msg, $key, true);
|
||||
case 'openssl':
|
||||
$signature = '';
|
||||
$success = \openssl_sign($msg, $signature, $key, $algorithm);
|
||||
$success = \openssl_sign($msg, $signature, $key, $algorithm); // @phpstan-ignore-line
|
||||
if (!$success) {
|
||||
throw new DomainException("OpenSSL unable to sign data");
|
||||
throw new DomainException('OpenSSL unable to sign data');
|
||||
}
|
||||
if ($alg === 'ES256') {
|
||||
if ($alg === 'ES256' || $alg === 'ES256K') {
|
||||
$signature = self::signatureFromDER($signature, 256);
|
||||
} elseif ($alg === 'ES384') {
|
||||
$signature = self::signatureFromDER($signature, 384);
|
||||
}
|
||||
return $signature;
|
||||
case 'sodium_crypto':
|
||||
if (!function_exists('sodium_crypto_sign_detached')) {
|
||||
if (!\function_exists('sodium_crypto_sign_detached')) {
|
||||
throw new DomainException('libsodium is not available');
|
||||
}
|
||||
if (!\is_string($key)) {
|
||||
throw new InvalidArgumentException('key must be a string when using EdDSA');
|
||||
}
|
||||
try {
|
||||
// The last non-empty line is used as the key.
|
||||
$lines = array_filter(explode("\n", $key));
|
||||
$key = base64_decode(end($lines));
|
||||
$key = base64_decode((string) end($lines));
|
||||
if (\strlen($key) === 0) {
|
||||
throw new DomainException('Key cannot be empty string');
|
||||
}
|
||||
return sodium_crypto_sign_detached($msg, $key);
|
||||
} catch (Exception $e) {
|
||||
throw new DomainException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new DomainException('Algorithm not supported');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a signature with the message, key and method. Not all methods
|
||||
* are symmetric, so we must have a separate verify and sign method.
|
||||
*
|
||||
* @param string $msg The original message (header and body)
|
||||
* @param string $signature The original signature
|
||||
* @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key
|
||||
* @param string $alg The algorithm
|
||||
* @param string $msg The original message (header and body)
|
||||
* @param string $signature The original signature
|
||||
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For Ed*, ES*, HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey
|
||||
* @param string $alg The algorithm
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure
|
||||
*/
|
||||
private static function verify($msg, $signature, $key, $alg)
|
||||
{
|
||||
private static function verify(
|
||||
string $msg,
|
||||
string $signature,
|
||||
$keyMaterial,
|
||||
string $alg
|
||||
): bool {
|
||||
if (empty(static::$supported_algs[$alg])) {
|
||||
throw new DomainException('Algorithm not supported');
|
||||
}
|
||||
@ -269,10 +303,11 @@ class JWT
|
||||
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||
switch ($function) {
|
||||
case 'openssl':
|
||||
$success = \openssl_verify($msg, $signature, $key, $algorithm);
|
||||
$success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line
|
||||
if ($success === 1) {
|
||||
return true;
|
||||
} elseif ($success === 0) {
|
||||
}
|
||||
if ($success === 0) {
|
||||
return false;
|
||||
}
|
||||
// returns 1 on success, 0 on failure, -1 on error.
|
||||
@ -280,21 +315,33 @@ class JWT
|
||||
'OpenSSL error: ' . \openssl_error_string()
|
||||
);
|
||||
case 'sodium_crypto':
|
||||
if (!function_exists('sodium_crypto_sign_verify_detached')) {
|
||||
throw new DomainException('libsodium is not available');
|
||||
}
|
||||
try {
|
||||
// The last non-empty line is used as the key.
|
||||
$lines = array_filter(explode("\n", $key));
|
||||
$key = base64_decode(end($lines));
|
||||
return sodium_crypto_sign_verify_detached($signature, $msg, $key);
|
||||
} catch (Exception $e) {
|
||||
throw new DomainException($e->getMessage(), 0, $e);
|
||||
}
|
||||
if (!\function_exists('sodium_crypto_sign_verify_detached')) {
|
||||
throw new DomainException('libsodium is not available');
|
||||
}
|
||||
if (!\is_string($keyMaterial)) {
|
||||
throw new InvalidArgumentException('key must be a string when using EdDSA');
|
||||
}
|
||||
try {
|
||||
// The last non-empty line is used as the key.
|
||||
$lines = array_filter(explode("\n", $keyMaterial));
|
||||
$key = base64_decode((string) end($lines));
|
||||
if (\strlen($key) === 0) {
|
||||
throw new DomainException('Key cannot be empty string');
|
||||
}
|
||||
if (\strlen($signature) === 0) {
|
||||
throw new DomainException('Signature cannot be empty string');
|
||||
}
|
||||
return sodium_crypto_sign_verify_detached($signature, $msg, $key);
|
||||
} catch (Exception $e) {
|
||||
throw new DomainException($e->getMessage(), 0, $e);
|
||||
}
|
||||
case 'hash_hmac':
|
||||
default:
|
||||
$hash = \hash_hmac($algorithm, $msg, $key, true);
|
||||
return self::constantTimeEquals($signature, $hash);
|
||||
if (!\is_string($keyMaterial)) {
|
||||
throw new InvalidArgumentException('key must be a string when using hmac');
|
||||
}
|
||||
$hash = \hash_hmac($algorithm, $msg, $keyMaterial, true);
|
||||
return self::constantTimeEquals($hash, $signature);
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,30 +350,16 @@ class JWT
|
||||
*
|
||||
* @param string $input JSON string
|
||||
*
|
||||
* @return object Object representation of JSON string
|
||||
* @return mixed The decoded JSON string
|
||||
*
|
||||
* @throws DomainException Provided string was invalid JSON
|
||||
*/
|
||||
public static function jsonDecode($input)
|
||||
public static function jsonDecode(string $input)
|
||||
{
|
||||
if (\version_compare(PHP_VERSION, '5.4.0', '>=') && !(\defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
|
||||
/** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
|
||||
* to specify that large ints (like Steam Transaction IDs) should be treated as
|
||||
* strings, rather than the PHP default behaviour of converting them to floats.
|
||||
*/
|
||||
$obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
|
||||
} else {
|
||||
/** Not all servers will support that, however, so for older versions we must
|
||||
* manually detect large ints in the JSON string and quote them (thus converting
|
||||
*them to strings) before decoding, hence the preg_replace() call.
|
||||
*/
|
||||
$max_int_length = \strlen((string) PHP_INT_MAX) - 1;
|
||||
$json_without_bigints = \preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
|
||||
$obj = \json_decode($json_without_bigints);
|
||||
}
|
||||
$obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
|
||||
|
||||
if ($errno = \json_last_error()) {
|
||||
static::handleJsonError($errno);
|
||||
self::handleJsonError($errno);
|
||||
} elseif ($obj === null && $input !== 'null') {
|
||||
throw new DomainException('Null result with non-null input');
|
||||
}
|
||||
@ -334,22 +367,30 @@ class JWT
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a PHP object into a JSON string.
|
||||
* Encode a PHP array into a JSON string.
|
||||
*
|
||||
* @param object|array $input A PHP object or array
|
||||
* @param array<mixed> $input A PHP array
|
||||
*
|
||||
* @return string JSON representation of the PHP object or array
|
||||
* @return string JSON representation of the PHP array
|
||||
*
|
||||
* @throws DomainException Provided object could not be encoded to valid JSON
|
||||
*/
|
||||
public static function jsonEncode($input)
|
||||
public static function jsonEncode(array $input): string
|
||||
{
|
||||
$json = \json_encode($input);
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
$json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
|
||||
} else {
|
||||
// PHP 5.3 only
|
||||
$json = \json_encode($input);
|
||||
}
|
||||
if ($errno = \json_last_error()) {
|
||||
static::handleJsonError($errno);
|
||||
} elseif ($json === 'null' && $input !== null) {
|
||||
self::handleJsonError($errno);
|
||||
} elseif ($json === 'null') {
|
||||
throw new DomainException('Null result with non-null input');
|
||||
}
|
||||
if ($json === false) {
|
||||
throw new DomainException('Provided object could not be encoded to valid JSON');
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
@ -359,15 +400,32 @@ class JWT
|
||||
* @param string $input A Base64 encoded string
|
||||
*
|
||||
* @return string A decoded string
|
||||
*
|
||||
* @throws InvalidArgumentException invalid base64 characters
|
||||
*/
|
||||
public static function urlsafeB64Decode($input)
|
||||
public static function urlsafeB64Decode(string $input): string
|
||||
{
|
||||
return \base64_decode(self::convertBase64UrlToBase64($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in the base64url (URL-safe Base64) encoding to standard base64.
|
||||
*
|
||||
* @param string $input A Base64 encoded string with URL-safe characters (-_ and no padding)
|
||||
*
|
||||
* @return string A Base64 encoded string with standard characters (+/) and padding (=), when
|
||||
* needed.
|
||||
*
|
||||
* @see https://www.rfc-editor.org/rfc/rfc4648
|
||||
*/
|
||||
public static function convertBase64UrlToBase64(string $input): string
|
||||
{
|
||||
$remainder = \strlen($input) % 4;
|
||||
if ($remainder) {
|
||||
$padlen = 4 - $remainder;
|
||||
$input .= \str_repeat('=', $padlen);
|
||||
}
|
||||
return \base64_decode(\strtr($input, '-_', '+/'));
|
||||
return \strtr($input, '-_', '+/');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -377,7 +435,7 @@ class JWT
|
||||
*
|
||||
* @return string The base64 encode of what you passed in
|
||||
*/
|
||||
public static function urlsafeB64Encode($input)
|
||||
public static function urlsafeB64Encode(string $input): string
|
||||
{
|
||||
return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
|
||||
}
|
||||
@ -386,67 +444,54 @@ class JWT
|
||||
/**
|
||||
* Determine if an algorithm has been provided for each Key
|
||||
*
|
||||
* @param Key|array<Key>|mixed $keyOrKeyArray
|
||||
* @param string|null $kid
|
||||
* @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray
|
||||
* @param string|null $kid
|
||||
*
|
||||
* @throws UnexpectedValueException
|
||||
*
|
||||
* @return array containing the keyMaterial and algorithm
|
||||
* @return Key
|
||||
*/
|
||||
private static function getKeyMaterialAndAlgorithm($keyOrKeyArray, $kid = null)
|
||||
{
|
||||
if (
|
||||
is_string($keyOrKeyArray)
|
||||
|| is_resource($keyOrKeyArray)
|
||||
|| $keyOrKeyArray instanceof OpenSSLAsymmetricKey
|
||||
) {
|
||||
return array($keyOrKeyArray, null);
|
||||
}
|
||||
|
||||
private static function getKey(
|
||||
$keyOrKeyArray,
|
||||
?string $kid
|
||||
): Key {
|
||||
if ($keyOrKeyArray instanceof Key) {
|
||||
return array($keyOrKeyArray->getKeyMaterial(), $keyOrKeyArray->getAlgorithm());
|
||||
return $keyOrKeyArray;
|
||||
}
|
||||
|
||||
if (is_array($keyOrKeyArray) || $keyOrKeyArray instanceof ArrayAccess) {
|
||||
if (!isset($kid)) {
|
||||
throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
|
||||
}
|
||||
if (!isset($keyOrKeyArray[$kid])) {
|
||||
throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
|
||||
}
|
||||
|
||||
$key = $keyOrKeyArray[$kid];
|
||||
|
||||
if ($key instanceof Key) {
|
||||
return array($key->getKeyMaterial(), $key->getAlgorithm());
|
||||
}
|
||||
|
||||
return array($key, null);
|
||||
if (empty($kid) && $kid !== '0') {
|
||||
throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
|
||||
}
|
||||
|
||||
throw new UnexpectedValueException(
|
||||
'$keyOrKeyArray must be a string|resource key, an array of string|resource keys, '
|
||||
. 'an instance of Firebase\JWT\Key key or an array of Firebase\JWT\Key keys'
|
||||
);
|
||||
if ($keyOrKeyArray instanceof CachedKeySet) {
|
||||
// Skip "isset" check, as this will automatically refresh if not set
|
||||
return $keyOrKeyArray[$kid];
|
||||
}
|
||||
|
||||
if (!isset($keyOrKeyArray[$kid])) {
|
||||
throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
|
||||
}
|
||||
|
||||
return $keyOrKeyArray[$kid];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $left
|
||||
* @param string $right
|
||||
* @param string $left The string of known length to compare against
|
||||
* @param string $right The user-supplied string
|
||||
* @return bool
|
||||
*/
|
||||
public static function constantTimeEquals($left, $right)
|
||||
public static function constantTimeEquals(string $left, string $right): bool
|
||||
{
|
||||
if (\function_exists('hash_equals')) {
|
||||
return \hash_equals($left, $right);
|
||||
}
|
||||
$len = \min(static::safeStrlen($left), static::safeStrlen($right));
|
||||
$len = \min(self::safeStrlen($left), self::safeStrlen($right));
|
||||
|
||||
$status = 0;
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$status |= (\ord($left[$i]) ^ \ord($right[$i]));
|
||||
}
|
||||
$status |= (static::safeStrlen($left) ^ static::safeStrlen($right));
|
||||
$status |= (self::safeStrlen($left) ^ self::safeStrlen($right));
|
||||
|
||||
return ($status === 0);
|
||||
}
|
||||
@ -456,17 +501,19 @@ class JWT
|
||||
*
|
||||
* @param int $errno An error number from json_last_error()
|
||||
*
|
||||
* @throws DomainException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function handleJsonError($errno)
|
||||
private static function handleJsonError(int $errno): void
|
||||
{
|
||||
$messages = array(
|
||||
$messages = [
|
||||
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
||||
JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
|
||||
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
|
||||
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
|
||||
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3
|
||||
);
|
||||
];
|
||||
throw new DomainException(
|
||||
isset($messages[$errno])
|
||||
? $messages[$errno]
|
||||
@ -481,7 +528,7 @@ class JWT
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function safeStrlen($str)
|
||||
private static function safeStrlen(string $str): int
|
||||
{
|
||||
if (\function_exists('mb_strlen')) {
|
||||
return \mb_strlen($str, '8bit');
|
||||
@ -495,10 +542,11 @@ class JWT
|
||||
* @param string $sig The ECDSA signature to convert
|
||||
* @return string The encoded DER object
|
||||
*/
|
||||
private static function signatureToDER($sig)
|
||||
private static function signatureToDER(string $sig): string
|
||||
{
|
||||
// Separate the signature into r-value and s-value
|
||||
list($r, $s) = \str_split($sig, (int) (\strlen($sig) / 2));
|
||||
$length = max(1, (int) (\strlen($sig) / 2));
|
||||
list($r, $s) = \str_split($sig, $length);
|
||||
|
||||
// Trim leading zeros
|
||||
$r = \ltrim($r, "\x00");
|
||||
@ -525,9 +573,10 @@ class JWT
|
||||
*
|
||||
* @param int $type DER tag
|
||||
* @param string $value the value to encode
|
||||
*
|
||||
* @return string the encoded object
|
||||
*/
|
||||
private static function encodeDER($type, $value)
|
||||
private static function encodeDER(int $type, string $value): string
|
||||
{
|
||||
$tag_header = 0;
|
||||
if ($type === self::ASN1_SEQUENCE) {
|
||||
@ -548,9 +597,10 @@ class JWT
|
||||
*
|
||||
* @param string $der binary signature in DER format
|
||||
* @param int $keySize the number of bits in the key
|
||||
*
|
||||
* @return string the signature
|
||||
*/
|
||||
private static function signatureFromDER($der, $keySize)
|
||||
private static function signatureFromDER(string $der, int $keySize): string
|
||||
{
|
||||
// OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
|
||||
list($offset, $_) = self::readDER($der);
|
||||
@ -575,9 +625,10 @@ class JWT
|
||||
* @param string $der the binary data in DER format
|
||||
* @param int $offset the offset of the data stream containing the object
|
||||
* to decode
|
||||
* @return array [$offset, $data] the new offset and the decoded object
|
||||
*
|
||||
* @return array{int, string|null} the new offset and the decoded object
|
||||
*/
|
||||
private static function readDER($der, $offset = 0)
|
||||
private static function readDER(string $der, int $offset = 0): array
|
||||
{
|
||||
$pos = $offset;
|
||||
$size = \strlen($der);
|
||||
@ -595,7 +646,7 @@ class JWT
|
||||
}
|
||||
|
||||
// Value
|
||||
if ($type == self::ASN1_BIT_STRING) {
|
||||
if ($type === self::ASN1_BIT_STRING) {
|
||||
$pos++; // Skip the first contents octet (padding indicator)
|
||||
$data = \substr($der, $pos, $len - 1);
|
||||
$pos += $len - 1;
|
||||
@ -606,6 +657,6 @@ class JWT
|
||||
$data = null;
|
||||
}
|
||||
|
||||
return array($pos, $data);
|
||||
return [$pos, $data];
|
||||
}
|
||||
}
|
||||
|
35
vendor/firebase/php-jwt/src/Key.php
vendored
35
vendor/firebase/php-jwt/src/Key.php
vendored
@ -4,37 +4,42 @@ namespace Firebase\JWT;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenSSLAsymmetricKey;
|
||||
use OpenSSLCertificate;
|
||||
use TypeError;
|
||||
|
||||
class Key
|
||||
{
|
||||
/** @var string $algorithm */
|
||||
/** @var string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate */
|
||||
private $keyMaterial;
|
||||
/** @var string */
|
||||
private $algorithm;
|
||||
|
||||
/** @var string|resource|OpenSSLAsymmetricKey $keyMaterial */
|
||||
private $keyMaterial;
|
||||
|
||||
/**
|
||||
* @param string|resource|OpenSSLAsymmetricKey $keyMaterial
|
||||
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial
|
||||
* @param string $algorithm
|
||||
*/
|
||||
public function __construct($keyMaterial, $algorithm)
|
||||
{
|
||||
public function __construct(
|
||||
$keyMaterial,
|
||||
string $algorithm
|
||||
) {
|
||||
if (
|
||||
!is_string($keyMaterial)
|
||||
&& !is_resource($keyMaterial)
|
||||
!\is_string($keyMaterial)
|
||||
&& !$keyMaterial instanceof OpenSSLAsymmetricKey
|
||||
&& !$keyMaterial instanceof OpenSSLCertificate
|
||||
&& !\is_resource($keyMaterial)
|
||||
) {
|
||||
throw new InvalidArgumentException('Type error: $keyMaterial must be a string, resource, or OpenSSLAsymmetricKey');
|
||||
throw new TypeError('Key material must be a string, resource, or OpenSSLAsymmetricKey');
|
||||
}
|
||||
|
||||
if (empty($keyMaterial)) {
|
||||
throw new InvalidArgumentException('Type error: $keyMaterial must not be empty');
|
||||
throw new InvalidArgumentException('Key material must not be empty');
|
||||
}
|
||||
|
||||
if (!is_string($algorithm)|| empty($keyMaterial)) {
|
||||
throw new InvalidArgumentException('Type error: $algorithm must be a string');
|
||||
if (empty($algorithm)) {
|
||||
throw new InvalidArgumentException('Algorithm must not be empty');
|
||||
}
|
||||
|
||||
// TODO: Remove in PHP 8.0 in favor of class constructor property promotion
|
||||
$this->keyMaterial = $keyMaterial;
|
||||
$this->algorithm = $algorithm;
|
||||
}
|
||||
@ -44,13 +49,13 @@ class Key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAlgorithm()
|
||||
public function getAlgorithm(): string
|
||||
{
|
||||
return $this->algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|resource|OpenSSLAsymmetricKey
|
||||
* @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate
|
||||
*/
|
||||
public function getKeyMaterial()
|
||||
{
|
||||
|
18
vendor/league/mime-type-detection/CHANGELOG.md
vendored
18
vendor/league/mime-type-detection/CHANGELOG.md
vendored
@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## 1.13.0 - 2022-08-05
|
||||
|
||||
### Added
|
||||
|
||||
- A reverse lookup mechanism to fetch one or all extensions for a given mimetype
|
||||
|
||||
## 1.12.0 - 2022-08-03
|
||||
|
||||
### Updated
|
||||
|
||||
- Updated lookup
|
||||
|
||||
## 1.11.0 - 2022-04-17
|
||||
|
||||
### Updated
|
||||
|
||||
- Updated lookup
|
||||
|
||||
## 1.10.0 - 2022-04-11
|
||||
|
||||
### Fixed
|
||||
|
2
vendor/league/mime-type-detection/LICENSE
vendored
2
vendor/league/mime-type-detection/LICENSE
vendored
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013-2022 Frank de Jonge
|
||||
Copyright (c) 2013-2023 Frank de Jonge
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -13,11 +13,11 @@
|
||||
"phpstan": "vendor/bin/phpstan analyse -l 6 src"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"ext-fileinfo": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3",
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0",
|
||||
"phpstan/phpstan": "^0.12.68",
|
||||
"friendsofphp/php-cs-fixer": "^3.2"
|
||||
},
|
||||
@ -28,7 +28,7 @@
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.2.0"
|
||||
"php": "7.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
vendor/league/mime-type-detection/src/ExtensionLookup.php
vendored
Normal file
14
vendor/league/mime-type-detection/src/ExtensionLookup.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\MimeTypeDetection;
|
||||
|
||||
interface ExtensionLookup
|
||||
{
|
||||
public function lookupExtension(string $mimetype): ?string;
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function lookupAllExtensions(string $mimetype): array;
|
||||
}
|
@ -6,7 +6,7 @@ namespace League\MimeTypeDetection;
|
||||
|
||||
use const PATHINFO_EXTENSION;
|
||||
|
||||
class ExtensionMimeTypeDetector implements MimeTypeDetector
|
||||
class ExtensionMimeTypeDetector implements MimeTypeDetector, ExtensionLookup
|
||||
{
|
||||
/**
|
||||
* @var ExtensionToMimeTypeMap
|
||||
@ -39,4 +39,18 @@ class ExtensionMimeTypeDetector implements MimeTypeDetector
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function lookupExtension(string $mimetype): ?string
|
||||
{
|
||||
return $this->extensions instanceof ExtensionLookup
|
||||
? $this->extensions->lookupExtension($mimetype)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function lookupAllExtensions(string $mimetype): array
|
||||
{
|
||||
return $this->extensions instanceof ExtensionLookup
|
||||
? $this->extensions->lookupAllExtensions($mimetype)
|
||||
: [];
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use const FILEINFO_MIME_TYPE;
|
||||
use const PATHINFO_EXTENSION;
|
||||
use finfo;
|
||||
|
||||
class FinfoMimeTypeDetector implements MimeTypeDetector
|
||||
class FinfoMimeTypeDetector implements MimeTypeDetector, ExtensionLookup
|
||||
{
|
||||
private const INCONCLUSIVE_MIME_TYPES = [
|
||||
'application/x-empty',
|
||||
@ -89,4 +89,18 @@ class FinfoMimeTypeDetector implements MimeTypeDetector
|
||||
|
||||
return (string) substr($contents, 0, $this->bufferSampleSize);
|
||||
}
|
||||
|
||||
public function lookupExtension(string $mimetype): ?string
|
||||
{
|
||||
return $this->extensionMap instanceof ExtensionLookup
|
||||
? $this->extensionMap->lookupExtension($mimetype)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function lookupAllExtensions(string $mimetype): array
|
||||
{
|
||||
return $this->extensionMap instanceof ExtensionLookup
|
||||
? $this->extensionMap->lookupAllExtensions($mimetype)
|
||||
: [];
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
20
vendor/overtrue/easy-sms/.editorconfig
vendored
Normal file
20
vendor/overtrue/easy-sms/.editorconfig
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{vue,js,scss}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
3
vendor/overtrue/easy-sms/.github/FUNDING.yml
vendored
Normal file
3
vendor/overtrue/easy-sms/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [overtrue]
|
24
vendor/overtrue/easy-sms/.github/workflows/tests.yml
vendored
Normal file
24
vendor/overtrue/easy-sms/.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
phpunit:
|
||||
strategy:
|
||||
matrix:
|
||||
php_version: [5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup PHP environment
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php_version }}
|
||||
coverage: xdebug
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: PHPUnit check
|
||||
run: ./vendor/bin/phpunit --coverage-text
|
49
vendor/overtrue/easy-sms/.php-cs-fixer.dist.php
vendored
Normal file
49
vendor/overtrue/easy-sms/.php-cs-fixer.dist.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRules([
|
||||
'@PSR12' => true,
|
||||
'binary_operator_spaces' => true,
|
||||
'blank_line_after_opening_tag' => true,
|
||||
'compact_nullable_typehint' => true,
|
||||
'declare_equal_normalize' => true,
|
||||
'lowercase_cast' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'new_with_braces' => true,
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'no_leading_import_slash' => true,
|
||||
'no_whitespace_in_blank_line' => true,
|
||||
'no_unused_imports' => true,
|
||||
'ordered_class_elements' => [
|
||||
'order' => [
|
||||
'use_trait',
|
||||
],
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'imports_order' => [
|
||||
'class',
|
||||
'function',
|
||||
'const',
|
||||
],
|
||||
'sort_algorithm' => 'none',
|
||||
],
|
||||
'return_type_declaration' => true,
|
||||
'short_scalar_cast' => true,
|
||||
'single_blank_line_before_namespace' => true,
|
||||
'single_trait_insert_per_statement' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'unary_operator_spaces' => true,
|
||||
'visibility_required' => [
|
||||
'elements' => [
|
||||
// 'const',
|
||||
'method',
|
||||
'property',
|
||||
],
|
||||
],
|
||||
])
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
->exclude('vendor')
|
||||
->in([__DIR__.'/src/', __DIR__.'/tests/'])
|
||||
)
|
||||
;
|
21
vendor/overtrue/easy-sms/LICENSE
vendored
Normal file
21
vendor/overtrue/easy-sms/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 overtrue
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
1007
vendor/overtrue/easy-sms/README.md
vendored
Normal file
1007
vendor/overtrue/easy-sms/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
62
vendor/overtrue/easy-sms/composer.json
vendored
Normal file
62
vendor/overtrue/easy-sms/composer.json
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "overtrue/easy-sms",
|
||||
"description": "The easiest way to send short message.",
|
||||
"type": "library",
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.2 || ^7.0",
|
||||
"php": ">=5.6",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7 || ^7.5 || ^8.5.19 || ^9.5.8",
|
||||
"mockery/mockery": "~1.3.3 || ^1.4.2",
|
||||
"brainmaestro/composer-git-hooks": "^2.8",
|
||||
"jetbrains/phpstorm-attributes": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\EasySms\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Overtrue\\EasySms\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [{
|
||||
"name": "overtrue",
|
||||
"email": "i@overtrue.me"
|
||||
}],
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-commit": [
|
||||
"composer check-style",
|
||||
"composer psalm",
|
||||
"composer test"
|
||||
],
|
||||
"pre-push": [
|
||||
"composer check-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-update-cmd": [
|
||||
"cghooks remove",
|
||||
"cghooks add --ignore-lock",
|
||||
"cghooks update"
|
||||
],
|
||||
"post-merge": "composer install",
|
||||
"post-install-cmd": [
|
||||
"cghooks remove",
|
||||
"cghooks add --ignore-lock",
|
||||
"cghooks update"
|
||||
],
|
||||
"phpstan": "phpstan analyse",
|
||||
"check-style": "php-cs-fixer fix --using-cache=no --diff --config=.php-cs-fixer.dist.php --dry-run --allow-risky=yes --ansi",
|
||||
"fix-style": "php-cs-fixer fix --using-cache=no --config=.php-cs-fixer.dist.php --allow-risky=yes --ansi",
|
||||
"test": "phpunit --colors",
|
||||
"psalm": "psalm --show-info=true --no-cache",
|
||||
"psalm-fix": "psalm --no-cache --alter --issues=MissingReturnType,MissingParamType"
|
||||
}
|
||||
}
|
15
vendor/overtrue/easy-sms/psalm.xml
vendored
Normal file
15
vendor/overtrue/easy-sms/psalm.xml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="6"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
38
vendor/overtrue/easy-sms/src/Contracts/GatewayInterface.php
vendored
Normal file
38
vendor/overtrue/easy-sms/src/Contracts/GatewayInterface.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class GatewayInterface.
|
||||
*/
|
||||
interface GatewayInterface
|
||||
{
|
||||
/**
|
||||
* Get gateway name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Send a short message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config);
|
||||
}
|
63
vendor/overtrue/easy-sms/src/Contracts/MessageInterface.php
vendored
Normal file
63
vendor/overtrue/easy-sms/src/Contracts/MessageInterface.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
/**
|
||||
* Interface MessageInterface.
|
||||
*/
|
||||
interface MessageInterface
|
||||
{
|
||||
const TEXT_MESSAGE = 'text';
|
||||
|
||||
const VOICE_MESSAGE = 'voice';
|
||||
|
||||
/**
|
||||
* Return the message type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMessageType();
|
||||
|
||||
/**
|
||||
* Return message content.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(GatewayInterface $gateway = null);
|
||||
|
||||
/**
|
||||
* Return the template id of message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate(GatewayInterface $gateway = null);
|
||||
|
||||
/**
|
||||
* Return the template data of message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData(GatewayInterface $gateway = null);
|
||||
|
||||
/**
|
||||
* Return message supported gateways.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGateways();
|
||||
}
|
53
vendor/overtrue/easy-sms/src/Contracts/PhoneNumberInterface.php
vendored
Normal file
53
vendor/overtrue/easy-sms/src/Contracts/PhoneNumberInterface.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
/**
|
||||
* Interface PhoneNumberInterface.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
interface PhoneNumberInterface extends \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* 86.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getIDDCode();
|
||||
|
||||
/**
|
||||
* 18888888888.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNumber();
|
||||
|
||||
/**
|
||||
* +8618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUniversalNumber();
|
||||
|
||||
/**
|
||||
* 008618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getZeroPrefixedNumber();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
27
vendor/overtrue/easy-sms/src/Contracts/StrategyInterface.php
vendored
Normal file
27
vendor/overtrue/easy-sms/src/Contracts/StrategyInterface.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Contracts;
|
||||
|
||||
/**
|
||||
* Interface StrategyInterface.
|
||||
*/
|
||||
interface StrategyInterface
|
||||
{
|
||||
/**
|
||||
* Apply the strategy and return result.
|
||||
*
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply(array $gateways);
|
||||
}
|
326
vendor/overtrue/easy-sms/src/EasySms.php
vendored
Normal file
326
vendor/overtrue/easy-sms/src/EasySms.php
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
use Closure;
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Contracts\StrategyInterface;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Gateways\Gateway;
|
||||
use Overtrue\EasySms\Strategies\OrderStrategy;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class EasySms.
|
||||
*/
|
||||
class EasySms
|
||||
{
|
||||
/**
|
||||
* @var \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultGateway;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $customCreators = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $gateways = [];
|
||||
|
||||
/**
|
||||
* @var \Overtrue\EasySms\Messenger
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $strategies = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = new Config($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* @param string|array $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface|array $message
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
* @throws \Overtrue\EasySms\Exceptions\NoGatewayAvailableException
|
||||
*/
|
||||
public function send($to, $message, array $gateways = [])
|
||||
{
|
||||
$to = $this->formatPhoneNumber($to);
|
||||
$message = $this->formatMessage($message);
|
||||
$gateways = empty($gateways) ? $message->getGateways() : $gateways;
|
||||
|
||||
if (empty($gateways)) {
|
||||
$gateways = $this->config->get('default.gateways', []);
|
||||
}
|
||||
|
||||
return $this->getMessenger()->send($to, $message, $this->formatGateways($gateways));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a gateway.
|
||||
*
|
||||
* @param string|null $name
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\GatewayInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public function gateway($name)
|
||||
{
|
||||
if (!isset($this->gateways[$name])) {
|
||||
$this->gateways[$name] = $this->createGateway($name);
|
||||
}
|
||||
|
||||
return $this->gateways[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a strategy instance.
|
||||
*
|
||||
* @param string|null $strategy
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\StrategyInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public function strategy($strategy = null)
|
||||
{
|
||||
if (\is_null($strategy)) {
|
||||
$strategy = $this->config->get('default.strategy', OrderStrategy::class);
|
||||
}
|
||||
|
||||
if (!\class_exists($strategy)) {
|
||||
$strategy = __NAMESPACE__.'\Strategies\\'.\ucfirst($strategy);
|
||||
}
|
||||
|
||||
if (!\class_exists($strategy)) {
|
||||
throw new InvalidArgumentException("Unsupported strategy \"{$strategy}\"");
|
||||
}
|
||||
|
||||
if (empty($this->strategies[$strategy]) || !($this->strategies[$strategy] instanceof StrategyInterface)) {
|
||||
$this->strategies[$strategy] = new $strategy($this);
|
||||
}
|
||||
|
||||
return $this->strategies[$strategy];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom driver creator Closure.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Closure $callback
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function extend($name, Closure $callback)
|
||||
{
|
||||
$this->customCreators[$name] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Overtrue\EasySms\Messenger
|
||||
*/
|
||||
public function getMessenger()
|
||||
{
|
||||
return $this->messenger ?: $this->messenger = new Messenger($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new driver instance.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return GatewayInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
protected function createGateway($name)
|
||||
{
|
||||
$config = $this->config->get("gateways.{$name}", []);
|
||||
|
||||
if (!isset($config['timeout'])) {
|
||||
$config['timeout'] = $this->config->get('timeout', Gateway::DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
$config['options'] = $this->config->get('options', []);
|
||||
|
||||
if (isset($this->customCreators[$name])) {
|
||||
$gateway = $this->callCustomCreator($name, $config);
|
||||
} else {
|
||||
$className = $this->formatGatewayClassName($name);
|
||||
$gateway = $this->makeGateway($className, $config);
|
||||
}
|
||||
|
||||
if (!($gateway instanceof GatewayInterface)) {
|
||||
throw new InvalidArgumentException(\sprintf('Gateway "%s" must implement interface %s.', $name, GatewayInterface::class));
|
||||
}
|
||||
|
||||
return $gateway;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make gateway instance.
|
||||
*
|
||||
* @param string $gateway
|
||||
* @param array $config
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\GatewayInterface
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
protected function makeGateway($gateway, $config)
|
||||
{
|
||||
if (!\class_exists($gateway) || !\in_array(GatewayInterface::class, \class_implements($gateway))) {
|
||||
throw new InvalidArgumentException(\sprintf('Class "%s" is a invalid easy-sms gateway.', $gateway));
|
||||
}
|
||||
|
||||
return new $gateway($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format gateway name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatGatewayClassName($name)
|
||||
{
|
||||
if (\class_exists($name) && \in_array(GatewayInterface::class, \class_implements($name))) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$name = \ucfirst(\str_replace(['-', '_', ''], '', $name));
|
||||
|
||||
return __NAMESPACE__."\\Gateways\\{$name}Gateway";
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a custom gateway creator.
|
||||
*
|
||||
* @param string $gateway
|
||||
* @param array $config
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function callCustomCreator($gateway, $config)
|
||||
{
|
||||
return \call_user_func($this->customCreators[$gateway], $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|\Overtrue\EasySms\Contracts\PhoneNumberInterface $number
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\PhoneNumberInterface|string
|
||||
*/
|
||||
protected function formatPhoneNumber($number)
|
||||
{
|
||||
if ($number instanceof PhoneNumberInterface) {
|
||||
return $number;
|
||||
}
|
||||
|
||||
return new PhoneNumber(\trim($number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string|\Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
*
|
||||
* @return \Overtrue\EasySms\Contracts\MessageInterface
|
||||
*/
|
||||
protected function formatMessage($message)
|
||||
{
|
||||
if (!($message instanceof MessageInterface)) {
|
||||
if (!\is_array($message)) {
|
||||
$message = [
|
||||
'content' => $message,
|
||||
'template' => $message,
|
||||
];
|
||||
}
|
||||
|
||||
$message = new Message($message);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
protected function formatGateways(array $gateways)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($gateways as $gateway => $setting) {
|
||||
if (\is_int($gateway) && \is_string($setting)) {
|
||||
$gateway = $setting;
|
||||
$setting = [];
|
||||
}
|
||||
|
||||
$formatted[$gateway] = $setting;
|
||||
$globalSettings = $this->config->get("gateways.{$gateway}", []);
|
||||
|
||||
if (\is_string($gateway) && !empty($globalSettings) && \is_array($setting)) {
|
||||
$formatted[$gateway] = new Config(\array_merge($globalSettings, $setting));
|
||||
}
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($this->strategy()->apply($formatted) as $name) {
|
||||
$result[$name] = $formatted[$name];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
21
vendor/overtrue/easy-sms/src/Exceptions/Exception.php
vendored
Normal file
21
vendor/overtrue/easy-sms/src/Exceptions/Exception.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
/**
|
||||
* Class Exception.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
37
vendor/overtrue/easy-sms/src/Exceptions/GatewayErrorException.php
vendored
Normal file
37
vendor/overtrue/easy-sms/src/Exceptions/GatewayErrorException.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
/**
|
||||
* Class GatewayErrorException.
|
||||
*/
|
||||
class GatewayErrorException extends Exception
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $raw = [];
|
||||
|
||||
/**
|
||||
* GatewayErrorException constructor.
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param array $raw
|
||||
*/
|
||||
public function __construct($message, $code, array $raw = [])
|
||||
{
|
||||
parent::__construct($message, intval($code));
|
||||
|
||||
$this->raw = $raw;
|
||||
}
|
||||
}
|
19
vendor/overtrue/easy-sms/src/Exceptions/InvalidArgumentException.php
vendored
Normal file
19
vendor/overtrue/easy-sms/src/Exceptions/InvalidArgumentException.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
/**
|
||||
* Class InvalidArgumentException.
|
||||
*/
|
||||
class InvalidArgumentException extends Exception
|
||||
{
|
||||
}
|
81
vendor/overtrue/easy-sms/src/Exceptions/NoGatewayAvailableException.php
vendored
Normal file
81
vendor/overtrue/easy-sms/src/Exceptions/NoGatewayAvailableException.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class NoGatewayAvailableException.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class NoGatewayAvailableException extends Exception
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $results = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $exceptions = [];
|
||||
|
||||
/**
|
||||
* NoGatewayAvailableException constructor.
|
||||
*
|
||||
* @param array $results
|
||||
* @param int $code
|
||||
* @param \Throwable|null $previous
|
||||
*/
|
||||
public function __construct(array $results = [], $code = 0, Throwable $previous = null)
|
||||
{
|
||||
$this->results = $results;
|
||||
$this->exceptions = \array_column($results, 'exception', 'gateway');
|
||||
|
||||
parent::__construct('All the gateways have failed. You can get error details by `$exception->getExceptions()`', $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $gateway
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getException($gateway)
|
||||
{
|
||||
return isset($this->exceptions[$gateway]) ? $this->exceptions[$gateway] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getExceptions()
|
||||
{
|
||||
return $this->exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastException()
|
||||
{
|
||||
return end($this->exceptions);
|
||||
}
|
||||
}
|
107
vendor/overtrue/easy-sms/src/Gateways/AliyunGateway.php
vendored
Normal file
107
vendor/overtrue/easy-sms/src/Gateways/AliyunGateway.php
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class AliyunGateway.
|
||||
*
|
||||
* @author carson <docxcn@gmail.com>
|
||||
*
|
||||
* @see https://help.aliyun.com/document_detail/55451.html
|
||||
*/
|
||||
class AliyunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://dysmsapi.aliyuncs.com';
|
||||
|
||||
const ENDPOINT_METHOD = 'SendSms';
|
||||
|
||||
const ENDPOINT_VERSION = '2017-05-25';
|
||||
|
||||
const ENDPOINT_FORMAT = 'JSON';
|
||||
|
||||
const ENDPOINT_REGION_ID = 'cn-hangzhou';
|
||||
|
||||
const ENDPOINT_SIGNATURE_METHOD = 'HMAC-SHA1';
|
||||
|
||||
const ENDPOINT_SIGNATURE_VERSION = '1.0';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
$signName = !empty($data['sign_name']) ? $data['sign_name'] : $config->get('sign_name');
|
||||
|
||||
unset($data['sign_name']);
|
||||
|
||||
$params = [
|
||||
'RegionId' => self::ENDPOINT_REGION_ID,
|
||||
'AccessKeyId' => $config->get('access_key_id'),
|
||||
'Format' => self::ENDPOINT_FORMAT,
|
||||
'SignatureMethod' => self::ENDPOINT_SIGNATURE_METHOD,
|
||||
'SignatureVersion' => self::ENDPOINT_SIGNATURE_VERSION,
|
||||
'SignatureNonce' => uniqid(),
|
||||
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
|
||||
'Action' => self::ENDPOINT_METHOD,
|
||||
'Version' => self::ENDPOINT_VERSION,
|
||||
'PhoneNumbers' => !\is_null($to->getIDDCode()) ? strval($to->getZeroPrefixedNumber()) : $to->getNumber(),
|
||||
'SignName' => $signName,
|
||||
'TemplateCode' => $message->getTemplate($this),
|
||||
'TemplateParam' => json_encode($data, JSON_FORCE_OBJECT),
|
||||
];
|
||||
|
||||
$params['Signature'] = $this->generateSign($params);
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if (!empty($result['Code']) && 'OK' != $result['Code']) {
|
||||
throw new GatewayErrorException($result['Message'], $result['Code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see https://help.aliyun.com/document_detail/101343.html
|
||||
*/
|
||||
protected function generateSign($params)
|
||||
{
|
||||
ksort($params);
|
||||
$accessKeySecret = $this->config->get('access_key_secret');
|
||||
$stringToSign = 'GET&%2F&'.urlencode(http_build_query($params, '', '&', PHP_QUERY_RFC3986));
|
||||
$stringToSign = str_replace('%7E', '~', $stringToSign);
|
||||
|
||||
return base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret.'&', true));
|
||||
}
|
||||
}
|
97
vendor/overtrue/easy-sms/src/Gateways/AliyunIntlGateway.php
vendored
Normal file
97
vendor/overtrue/easy-sms/src/Gateways/AliyunIntlGateway.php
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class AliyunIntlGateway
|
||||
*
|
||||
* @package \Overtrue\EasySms\Gateways
|
||||
*
|
||||
* @see https://www.alibabacloud.com/help/zh/doc-detail/162279.htm
|
||||
*/
|
||||
class AliyunIntlGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://dysmsapi.ap-southeast-1.aliyuncs.com';
|
||||
|
||||
const ENDPOINT_ACTION = 'SendMessageWithTemplate';
|
||||
|
||||
const ENDPOINT_VERSION = '2018-05-01';
|
||||
|
||||
const ENDPOINT_FORMAT = 'JSON';
|
||||
|
||||
const ENDPOINT_REGION_ID = 'ap-southeast-1';
|
||||
|
||||
const ENDPOINT_SIGNATURE_METHOD = 'HMAC-SHA1';
|
||||
|
||||
const ENDPOINT_SIGNATURE_VERSION = '1.0';
|
||||
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
$signName = !empty($data['sign_name']) ? $data['sign_name'] : $config->get('sign_name');
|
||||
|
||||
unset($data['sign_name']);
|
||||
|
||||
$params = [
|
||||
'RegionId' => self::ENDPOINT_REGION_ID,
|
||||
'AccessKeyId' => $config->get('access_key_id'),
|
||||
'Format' => self::ENDPOINT_FORMAT,
|
||||
'SignatureMethod' => self::ENDPOINT_SIGNATURE_METHOD,
|
||||
'SignatureVersion' => self::ENDPOINT_SIGNATURE_VERSION,
|
||||
'SignatureNonce' => uniqid('', true),
|
||||
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
|
||||
'Version' => self::ENDPOINT_VERSION,
|
||||
'To' => !\is_null($to->getIDDCode()) ? (int) $to->getZeroPrefixedNumber() : $to->getNumber(),
|
||||
'Action' => self::ENDPOINT_ACTION,
|
||||
'From' => $signName,
|
||||
'TemplateCode' => $message->getTemplate($this),
|
||||
'TemplateParam' => json_encode($data, JSON_FORCE_OBJECT),
|
||||
];
|
||||
|
||||
$params['Signature'] = $this->generateSign($params);
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ('OK' !== $result['ResponseCode']) {
|
||||
throw new GatewayErrorException($result['ResponseDescription'], $result['ResponseCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sign
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign(array $params)
|
||||
{
|
||||
ksort($params);
|
||||
$accessKeySecret = $this->config->get('access_key_secret');
|
||||
$stringToSign = 'GET&%2F&'.urlencode(http_build_query($params, '', '&', PHP_QUERY_RFC3986));
|
||||
|
||||
return base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret.'&', true));
|
||||
}
|
||||
}
|
107
vendor/overtrue/easy-sms/src/Gateways/AliyunrestGateway.php
vendored
Normal file
107
vendor/overtrue/easy-sms/src/Gateways/AliyunrestGateway.php
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class AliyunrestGateway.
|
||||
*/
|
||||
class AliyunrestGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://gw.api.taobao.com/router/rest';
|
||||
|
||||
const ENDPOINT_VERSION = '2.0';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const ENDPOINT_METHOD = 'alibaba.aliqin.fc.sms.num.send';
|
||||
|
||||
const ENDPOINT_SIGNATURE_METHOD = 'md5';
|
||||
|
||||
const ENDPOINT_PARTNER_ID = 'EasySms';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array|void
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$urlParams = [
|
||||
'app_key' => $config->get('app_key'),
|
||||
'v' => self::ENDPOINT_VERSION,
|
||||
'format' => self::ENDPOINT_FORMAT,
|
||||
'sign_method' => self::ENDPOINT_SIGNATURE_METHOD,
|
||||
'method' => self::ENDPOINT_METHOD,
|
||||
'timestamp' => date('Y-m-d H:i:s'),
|
||||
'partner_id' => self::ENDPOINT_PARTNER_ID,
|
||||
];
|
||||
|
||||
$params = [
|
||||
'extend' => '',
|
||||
'sms_type' => 'normal',
|
||||
'sms_free_sign_name' => $config->get('sign_name'),
|
||||
'sms_param' => json_encode($message->getData($this)),
|
||||
'rec_num' => !\is_null($to->getIDDCode()) ? strval($to->getZeroPrefixedNumber()) : $to->getNumber(),
|
||||
'sms_template_code' => $message->getTemplate($this),
|
||||
];
|
||||
$urlParams['sign'] = $this->generateSign(array_merge($params, $urlParams));
|
||||
|
||||
$result = $this->post($this->getEndpointUrl($urlParams), $params);
|
||||
|
||||
if (isset($result['error_response']) && 0 != $result['error_response']['code']) {
|
||||
throw new GatewayErrorException($result['error_response']['msg'], $result['error_response']['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEndpointUrl($params)
|
||||
{
|
||||
return self::ENDPOINT_URL.'?'.http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params)
|
||||
{
|
||||
ksort($params);
|
||||
|
||||
$stringToBeSigned = $this->config->get('app_secret_key');
|
||||
foreach ($params as $k => $v) {
|
||||
if (!is_array($v) && '@' != substr($v, 0, 1)) {
|
||||
$stringToBeSigned .= "$k$v";
|
||||
}
|
||||
}
|
||||
unset($k, $v);
|
||||
$stringToBeSigned .= $this->config->get('app_secret_key');
|
||||
|
||||
return strtoupper(md5($stringToBeSigned));
|
||||
}
|
||||
}
|
60
vendor/overtrue/easy-sms/src/Gateways/AvatardataGateway.php
vendored
Normal file
60
vendor/overtrue/easy-sms/src/Gateways/AvatardataGateway.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class AvatardataGateway.
|
||||
*
|
||||
* @see http://www.avatardata.cn/Docs/Api/fd475e40-7809-4be7-936c-5926dd41b0fe
|
||||
*/
|
||||
class AvatardataGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://v1.avatardata.cn/Sms/Send';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'templateId' => $message->getTemplate($this),
|
||||
'param' => implode(',', $message->getData($this)),
|
||||
'dtype' => self::ENDPOINT_FORMAT,
|
||||
'key' => $config->get('app_key'),
|
||||
];
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ($result['error_code']) {
|
||||
throw new GatewayErrorException($result['reason'], $result['error_code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
174
vendor/overtrue/easy-sms/src/Gateways/BaiduGateway.php
vendored
Normal file
174
vendor/overtrue/easy-sms/src/Gateways/BaiduGateway.php
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class BaiduGateway.
|
||||
*
|
||||
* @see https://cloud.baidu.com/doc/SMS/index.html
|
||||
*/
|
||||
class BaiduGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_HOST = 'smsv3.bj.baidubce.com';
|
||||
|
||||
const ENDPOINT_URI = '/api/v3/sendSms';
|
||||
|
||||
const BCE_AUTH_VERSION = 'bce-auth-v1';
|
||||
|
||||
const DEFAULT_EXPIRATION_IN_SECONDS = 1800; //签名有效期默认1800秒
|
||||
|
||||
const SUCCESS_CODE = 1000;
|
||||
|
||||
/**
|
||||
* Send message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'signatureId' => $config->get('invoke_id'),
|
||||
'mobile' => $to->getNumber(),
|
||||
'template' => $message->getTemplate($this),
|
||||
'contentVar' => $message->getData($this),
|
||||
];
|
||||
if (!empty($params['contentVar']['custom'])) {
|
||||
//用户自定义参数,格式为字符串,状态回调时会回传该值
|
||||
$params['custom'] = $params['contentVar']['custom'];
|
||||
unset($params['contentVar']['custom']);
|
||||
}
|
||||
if (!empty($params['contentVar']['userExtId'])) {
|
||||
//通道自定义扩展码,上行回调时会回传该值,其格式为纯数字串。默认为不开通,请求时无需设置该参数。如需开通请联系客服申请
|
||||
$params['userExtId'] = $params['contentVar']['userExtId'];
|
||||
unset($params['contentVar']['userExtId']);
|
||||
}
|
||||
|
||||
$datetime = gmdate('Y-m-d\TH:i:s\Z');
|
||||
|
||||
$headers = [
|
||||
'host' => self::ENDPOINT_HOST,
|
||||
'content-type' => 'application/json',
|
||||
'x-bce-date' => $datetime,
|
||||
];
|
||||
//获得需要签名的数据
|
||||
$signHeaders = $this->getHeadersToSign($headers, ['host', 'x-bce-date']);
|
||||
|
||||
$headers['Authorization'] = $this->generateSign($signHeaders, $datetime, $config);
|
||||
|
||||
$result = $this->request('post', self::buildEndpoint($config), ['headers' => $headers, 'json' => $params]);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['code']) {
|
||||
throw new GatewayErrorException($result['message'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint(Config $config)
|
||||
{
|
||||
return 'http://'.$config->get('domain', self::ENDPOINT_HOST).self::ENDPOINT_URI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Authorization header.
|
||||
*
|
||||
* @param array $signHeaders
|
||||
* @param int $datetime
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign(array $signHeaders, $datetime, Config $config)
|
||||
{
|
||||
// 生成 authString
|
||||
$authString = self::BCE_AUTH_VERSION.'/'.$config->get('ak').'/'
|
||||
.$datetime.'/'.self::DEFAULT_EXPIRATION_IN_SECONDS;
|
||||
|
||||
// 使用 sk 和 authString 生成 signKey
|
||||
$signingKey = hash_hmac('sha256', $authString, $config->get('sk'));
|
||||
// 生成标准化 URI
|
||||
// 根据 RFC 3986,除了:1.大小写英文字符 2.阿拉伯数字 3.点'.'、波浪线'~'、减号'-'以及下划线'_' 以外都要编码
|
||||
$canonicalURI = str_replace('%2F', '/', rawurlencode(self::ENDPOINT_URI));
|
||||
|
||||
// 生成标准化 QueryString
|
||||
$canonicalQueryString = ''; // 此 api 不需要此项。返回空字符串
|
||||
|
||||
// 整理 headersToSign,以 ';' 号连接
|
||||
$signedHeaders = empty($signHeaders) ? '' : strtolower(trim(implode(';', array_keys($signHeaders))));
|
||||
|
||||
// 生成标准化 header
|
||||
$canonicalHeader = $this->getCanonicalHeaders($signHeaders);
|
||||
|
||||
// 组成标准请求串
|
||||
$canonicalRequest = "POST\n{$canonicalURI}\n{$canonicalQueryString}\n{$canonicalHeader}";
|
||||
|
||||
// 使用 signKey 和标准请求串完成签名
|
||||
$signature = hash_hmac('sha256', $canonicalRequest, $signingKey);
|
||||
|
||||
// 组成最终签名串
|
||||
return "{$authString}/{$signedHeaders}/{$signature}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成标准化 http 请求头串.
|
||||
*
|
||||
* @param array $headers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCanonicalHeaders(array $headers)
|
||||
{
|
||||
$headerStrings = [];
|
||||
foreach ($headers as $name => $value) {
|
||||
//trim后再encode,之后使用':'号连接起来
|
||||
$headerStrings[] = rawurlencode(strtolower(trim($name))).':'.rawurlencode(trim($value));
|
||||
}
|
||||
|
||||
sort($headerStrings);
|
||||
|
||||
return implode("\n", $headerStrings);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 指定的 keys 过滤应该参与签名的 header.
|
||||
*
|
||||
* @param array $headers
|
||||
* @param array $keys
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHeadersToSign(array $headers, array $keys)
|
||||
{
|
||||
return array_intersect_key($headers, array_flip($keys));
|
||||
}
|
||||
}
|
156
vendor/overtrue/easy-sms/src/Gateways/ChuanglanGateway.php
vendored
Normal file
156
vendor/overtrue/easy-sms/src/Gateways/ChuanglanGateway.php
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class ChuanglanGateway.
|
||||
*
|
||||
* @see https://zz.253.com/v5.html#/api_doc
|
||||
*/
|
||||
class ChuanglanGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
/**
|
||||
* URL模板
|
||||
*/
|
||||
const ENDPOINT_URL_TEMPLATE = 'https://%s.253.com/msg/send/json';
|
||||
|
||||
/**
|
||||
* 国际短信
|
||||
*/
|
||||
const INT_URL = 'http://intapi.253.com/send/json';
|
||||
|
||||
/**
|
||||
* 验证码渠道code.
|
||||
*/
|
||||
const CHANNEL_VALIDATE_CODE = 'smsbj1';
|
||||
|
||||
/**
|
||||
* 会员营销渠道code.
|
||||
*/
|
||||
const CHANNEL_PROMOTION_CODE = 'smssh1';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$IDDCode = !empty($to->getIDDCode()) ? $to->getIDDCode() : 86;
|
||||
|
||||
$params = [
|
||||
'account' => $config->get('account'),
|
||||
'password' => $config->get('password'),
|
||||
'phone' => $to->getNumber(),
|
||||
'msg' => $this->wrapChannelContent($message->getContent($this), $config, $IDDCode),
|
||||
];
|
||||
|
||||
if (86 != $IDDCode) {
|
||||
$params['mobile'] = $to->getIDDCode().$to->getNumber();
|
||||
$params['account'] = $config->get('intel_account') ?: $config->get('account');
|
||||
$params['password'] = $config->get('intel_password') ?: $config->get('password');
|
||||
}
|
||||
|
||||
$result = $this->postJson($this->buildEndpoint($config, $IDDCode), $params);
|
||||
|
||||
if (!isset($result['code']) || '0' != $result['code']) {
|
||||
throw new GatewayErrorException(json_encode($result, JSON_UNESCAPED_UNICODE), isset($result['code']) ? $result['code'] : 0, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
* @param int $IDDCode
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function buildEndpoint(Config $config, $IDDCode = 86)
|
||||
{
|
||||
$channel = $this->getChannel($config, $IDDCode);
|
||||
|
||||
if (self::INT_URL === $channel) {
|
||||
return $channel;
|
||||
}
|
||||
|
||||
return sprintf(self::ENDPOINT_URL_TEMPLATE, $channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
* @param int $IDDCode
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function getChannel(Config $config, $IDDCode)
|
||||
{
|
||||
if (86 != $IDDCode) {
|
||||
return self::INT_URL;
|
||||
}
|
||||
$channel = $config->get('channel', self::CHANNEL_VALIDATE_CODE);
|
||||
|
||||
if (!in_array($channel, [self::CHANNEL_VALIDATE_CODE, self::CHANNEL_PROMOTION_CODE])) {
|
||||
throw new InvalidArgumentException('Invalid channel for ChuanglanGateway.');
|
||||
}
|
||||
|
||||
return $channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param Config $config
|
||||
* @param int $IDDCode
|
||||
*
|
||||
* @return string|string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function wrapChannelContent($content, Config $config, $IDDCode)
|
||||
{
|
||||
$channel = $this->getChannel($config, $IDDCode);
|
||||
|
||||
if (self::CHANNEL_PROMOTION_CODE == $channel) {
|
||||
$sign = (string) $config->get('sign', '');
|
||||
if (empty($sign)) {
|
||||
throw new InvalidArgumentException('Invalid sign for ChuanglanGateway when using promotion channel');
|
||||
}
|
||||
|
||||
$unsubscribe = (string) $config->get('unsubscribe', '');
|
||||
if (empty($unsubscribe)) {
|
||||
throw new InvalidArgumentException('Invalid unsubscribe for ChuanglanGateway when using promotion channel');
|
||||
}
|
||||
|
||||
$content = $sign.$content.$unsubscribe;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
147
vendor/overtrue/easy-sms/src/Gateways/Chuanglanv1Gateway.php
vendored
Normal file
147
vendor/overtrue/easy-sms/src/Gateways/Chuanglanv1Gateway.php
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class ChuanglanGateway.
|
||||
*
|
||||
* @see https://www.chuanglan.com/document/6110e57909fd9600010209de/62b3dc1d272e290001af3e75
|
||||
*/
|
||||
class Chuanglanv1Gateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
/**
|
||||
* 国际短信
|
||||
*/
|
||||
const INT_URL = 'http://intapi.253.com/send/json';
|
||||
|
||||
/**
|
||||
* URL模板
|
||||
*/
|
||||
const ENDPOINT_URL_TEMPLATE = 'https://smssh1.253.com/msg/%s/json';
|
||||
|
||||
/**
|
||||
* 支持单发、群发短信
|
||||
*/
|
||||
const CHANNEL_NORMAL_CODE = 'v1/send';
|
||||
|
||||
/**
|
||||
* 单号码对应单内容批量下发
|
||||
*/
|
||||
const CHANNEL_VARIABLE_CODE = 'variable';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$IDDCode = !empty($to->getIDDCode()) ? $to->getIDDCode() : 86;
|
||||
|
||||
$params = [
|
||||
'account' => $config->get('account'),
|
||||
'password' => $config->get('password'),
|
||||
'report' => $config->get('needstatus') ?? false
|
||||
];
|
||||
|
||||
if (86 != $IDDCode) {
|
||||
$params['mobile'] = $to->getIDDCode() . $to->getNumber();
|
||||
$params['account'] = $config->get('intel_account') ?: $config->get('account');
|
||||
$params['password'] = $config->get('intel_password') ?: $config->get('password');
|
||||
}
|
||||
|
||||
if (self::CHANNEL_VARIABLE_CODE == $this->getChannel($config, $IDDCode)) {
|
||||
$params['params'] = $message->getData($this);
|
||||
$params['msg'] = $this->wrapChannelContent($message->getTemplate($this), $config, $IDDCode);
|
||||
} else {
|
||||
$params['phone'] = $to->getNumber();
|
||||
$params['msg'] = $this->wrapChannelContent($message->getContent($this), $config, $IDDCode);
|
||||
}
|
||||
|
||||
$result = $this->postJson($this->buildEndpoint($config, $IDDCode), $params);
|
||||
|
||||
if (!isset($result['code']) || '0' != $result['code']) {
|
||||
throw new GatewayErrorException(json_encode($result, JSON_UNESCAPED_UNICODE), isset($result['code']) ? $result['code'] : 0, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
* @param int $IDDCode
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function buildEndpoint(Config $config, $IDDCode = 86)
|
||||
{
|
||||
$channel = $this->getChannel($config, $IDDCode);
|
||||
|
||||
if (self::INT_URL === $channel) {
|
||||
return $channel;
|
||||
}
|
||||
|
||||
return sprintf(self::ENDPOINT_URL_TEMPLATE, $channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
* @param int $IDDCode
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function getChannel(Config $config, $IDDCode)
|
||||
{
|
||||
if (86 != $IDDCode) {
|
||||
return self::INT_URL;
|
||||
}
|
||||
$channel = $config->get('channel', self::CHANNEL_NORMAL_CODE);
|
||||
|
||||
if (!in_array($channel, [self::CHANNEL_NORMAL_CODE, self::CHANNEL_VARIABLE_CODE])) {
|
||||
throw new InvalidArgumentException('Invalid channel for ChuanglanGateway.');
|
||||
}
|
||||
|
||||
return $channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param Config $config
|
||||
* @param int $IDDCode
|
||||
*
|
||||
* @return string|string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function wrapChannelContent($content, Config $config, $IDDCode)
|
||||
{
|
||||
return $content;
|
||||
}
|
||||
}
|
50
vendor/overtrue/easy-sms/src/Gateways/ErrorlogGateway.php
vendored
Normal file
50
vendor/overtrue/easy-sms/src/Gateways/ErrorlogGateway.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class ErrorlogGateway.
|
||||
*/
|
||||
class ErrorlogGateway extends Gateway
|
||||
{
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
if (is_array($to)) {
|
||||
$to = implode(',', $to);
|
||||
}
|
||||
|
||||
$message = sprintf(
|
||||
"[%s] to: %s | message: \"%s\" | template: \"%s\" | data: %s\n",
|
||||
date('Y-m-d H:i:s'),
|
||||
$to,
|
||||
$message->getContent($this),
|
||||
$message->getTemplate($this),
|
||||
json_encode($message->getData($this))
|
||||
);
|
||||
|
||||
$file = $this->config->get('file', ini_get('error_log'));
|
||||
$status = error_log($message, 3, $file);
|
||||
|
||||
return compact('status', 'file');
|
||||
}
|
||||
}
|
120
vendor/overtrue/easy-sms/src/Gateways/Gateway.php
vendored
Normal file
120
vendor/overtrue/easy-sms/src/Gateways/Gateway.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
|
||||
/**
|
||||
* Class Gateway.
|
||||
*/
|
||||
abstract class Gateway implements GatewayInterface
|
||||
{
|
||||
const DEFAULT_TIMEOUT = 5.0;
|
||||
|
||||
/**
|
||||
* @var \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $timeout;
|
||||
|
||||
/**
|
||||
* Gateway constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = new Config($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return timeout.
|
||||
*
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->timeout ?: $this->config->get('timeout', self::DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timeout.
|
||||
*
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->timeout = floatval($timeout);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Overtrue\EasySms\Support\Config
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setConfig(Config $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $options
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGuzzleOptions($options)
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getGuzzleOptions()
|
||||
{
|
||||
return $this->options ?: $this->config->get('options', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return \strtolower(str_replace([__NAMESPACE__.'\\', 'Gateway'], '', \get_class($this)));
|
||||
}
|
||||
}
|
148
vendor/overtrue/easy-sms/src/Gateways/HuaweiGateway.php
vendored
Normal file
148
vendor/overtrue/easy-sms/src/Gateways/HuaweiGateway.php
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
class HuaweiGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_HOST = 'https://api.rtc.huaweicloud.com:10443';
|
||||
|
||||
const ENDPOINT_URI = '/sms/batchSendSms/v1';
|
||||
|
||||
const SUCCESS_CODE = '000000';
|
||||
|
||||
/**
|
||||
* 发送信息.
|
||||
*
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$appKey = $config->get('app_key');
|
||||
$appSecret = $config->get('app_secret');
|
||||
$channels = $config->get('from');
|
||||
$statusCallback = $config->get('callback', '');
|
||||
|
||||
$endpoint = $this->getEndpoint($config);
|
||||
$headers = $this->getHeaders($appKey, $appSecret);
|
||||
|
||||
$templateId = $message->getTemplate($this);
|
||||
$messageData = $message->getData($this);
|
||||
|
||||
// 短信签名通道号码
|
||||
$from = 'default';
|
||||
if (isset($messageData['from'])) {
|
||||
$from = $messageData['from'];
|
||||
unset($messageData['from']);
|
||||
}
|
||||
$channel = isset($channels[$from]) ? $channels[$from] : '';
|
||||
|
||||
if (empty($channel)) {
|
||||
throw new InvalidArgumentException("From Channel [{$from}] Not Exist");
|
||||
}
|
||||
|
||||
$params = [
|
||||
'from' => $channel,
|
||||
'to' => $to->getUniversalNumber(),
|
||||
'templateId' => $templateId,
|
||||
'templateParas' => json_encode($messageData),
|
||||
'statusCallback' => $statusCallback,
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'form_params' => $params,
|
||||
//为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题
|
||||
'verify' => false,
|
||||
]);
|
||||
} catch (RequestException $e) {
|
||||
$result = $this->unwrapResponse($e->getResponse());
|
||||
}
|
||||
|
||||
if (self::SUCCESS_CODE != $result['code']) {
|
||||
throw new GatewayErrorException($result['description'], ltrim($result['code'], 'E'), $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 Endpoint.
|
||||
*
|
||||
* @param Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEndpoint(Config $config)
|
||||
{
|
||||
$endpoint = rtrim($config->get('endpoint', self::ENDPOINT_HOST), '/');
|
||||
|
||||
return $endpoint.self::ENDPOINT_URI;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求 Headers 参数.
|
||||
*
|
||||
* @param string $appKey
|
||||
* @param string $appSecret
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHeaders($appKey, $appSecret)
|
||||
{
|
||||
return [
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
'Authorization' => 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
|
||||
'X-WSSE' => $this->buildWsseHeader($appKey, $appSecret),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造X-WSSE参数值
|
||||
*
|
||||
* @param string $appKey
|
||||
* @param string $appSecret
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildWsseHeader($appKey, $appSecret)
|
||||
{
|
||||
$now = date('Y-m-d\TH:i:s\Z');
|
||||
$nonce = uniqid();
|
||||
$passwordDigest = base64_encode(hash('sha256', ($nonce.$now.$appSecret)));
|
||||
|
||||
return sprintf(
|
||||
'UsernameToken Username="%s",PasswordDigest="%s",Nonce="%s",Created="%s"',
|
||||
$appKey,
|
||||
$passwordDigest,
|
||||
$nonce,
|
||||
$now
|
||||
);
|
||||
}
|
||||
}
|
73
vendor/overtrue/easy-sms/src/Gateways/HuaxinGateway.php
vendored
Normal file
73
vendor/overtrue/easy-sms/src/Gateways/HuaxinGateway.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class HuaxinGateway.
|
||||
*
|
||||
* @see http://www.ipyy.com/help/
|
||||
*/
|
||||
class HuaxinGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://%s/smsJson.aspx';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint($config->get('ip'));
|
||||
|
||||
$result = $this->post($endpoint, [
|
||||
'userid' => $config->get('user_id'),
|
||||
'account' => $config->get('account'),
|
||||
'password' => $config->get('password'),
|
||||
'mobile' => $to->getNumber(),
|
||||
'content' => $message->getContent($this),
|
||||
'sendTime' => '',
|
||||
'action' => 'send',
|
||||
'extno' => $config->get('ext_no'),
|
||||
]);
|
||||
|
||||
if ('Success' !== $result['returnstatus']) {
|
||||
throw new GatewayErrorException($result['message'], 400, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $ip
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($ip)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $ip);
|
||||
}
|
||||
}
|
77
vendor/overtrue/easy-sms/src/Gateways/HuyiGateway.php
vendored
Normal file
77
vendor/overtrue/easy-sms/src/Gateways/HuyiGateway.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class HuyiGateway.
|
||||
*
|
||||
* @see http://www.ihuyi.com/api/sms.html
|
||||
*/
|
||||
class HuyiGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://106.ihuyi.com/webservice/sms.php?method=Submit';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const SUCCESS_CODE = 2;
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'account' => $config->get('api_id'),
|
||||
'mobile' => $to->getIDDCode() ? \sprintf('%s %s', $to->getIDDCode(), $to->getNumber()) : $to->getNumber(),
|
||||
'content' => $message->getContent($this),
|
||||
'time' => time(),
|
||||
'format' => self::ENDPOINT_FORMAT,
|
||||
'sign' => $config->get('signature'),
|
||||
];
|
||||
|
||||
$params['password'] = $this->generateSign($params);
|
||||
|
||||
$result = $this->post(self::ENDPOINT_URL, $params);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params)
|
||||
{
|
||||
return md5($params['account'].$this->config->get('api_key').$params['mobile'].$params['content'].$params['time']);
|
||||
}
|
||||
}
|
76
vendor/overtrue/easy-sms/src/Gateways/JuheGateway.php
vendored
Normal file
76
vendor/overtrue/easy-sms/src/Gateways/JuheGateway.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class JuheGateway.
|
||||
*
|
||||
* @see https://www.juhe.cn/docs/api/id/54
|
||||
*/
|
||||
class JuheGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://v.juhe.cn/sms/send';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'tpl_id' => $message->getTemplate($this),
|
||||
'tpl_value' => $this->formatTemplateVars($message->getData($this)),
|
||||
'dtype' => self::ENDPOINT_FORMAT,
|
||||
'key' => $config->get('app_key'),
|
||||
];
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ($result['error_code']) {
|
||||
throw new GatewayErrorException($result['reason'], $result['error_code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTemplateVars(array $vars)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($vars as $key => $value) {
|
||||
$formatted[sprintf('#%s#', trim($key, '#'))] = $value;
|
||||
}
|
||||
|
||||
return urldecode(http_build_query($formatted));
|
||||
}
|
||||
}
|
61
vendor/overtrue/easy-sms/src/Gateways/KingttoGateway.php
vendored
Normal file
61
vendor/overtrue/easy-sms/src/Gateways/KingttoGateway.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class KingttoGateWay.
|
||||
*
|
||||
* @see http://www.kingtto.cn/
|
||||
*/
|
||||
class KingttoGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://101.201.41.194:9999/sms.aspx';
|
||||
|
||||
const ENDPOINT_METHOD = 'send';
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface|array|string
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'action' => self::ENDPOINT_METHOD,
|
||||
'userid' => $config->get('userid'),
|
||||
'account' => $config->get('account'),
|
||||
'password' => $config->get('password'),
|
||||
'mobile' => $to->getNumber(),
|
||||
'content' => $message->getContent(),
|
||||
];
|
||||
|
||||
$result = $this->post(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ('Success' != $result['returnstatus']) {
|
||||
throw new GatewayErrorException($result['message'], $result['remainpoint'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
74
vendor/overtrue/easy-sms/src/Gateways/LuosimaoGateway.php
vendored
Normal file
74
vendor/overtrue/easy-sms/src/Gateways/LuosimaoGateway.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class LuosimaoGateway.
|
||||
*
|
||||
* @see https://luosimao.com/docs/api/
|
||||
*/
|
||||
class LuosimaoGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s.luosimao.com/%s/%s.%s';
|
||||
|
||||
const ENDPOINT_VERSION = 'v1';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint('sms-api', 'send');
|
||||
|
||||
$result = $this->post($endpoint, [
|
||||
'mobile' => $to->getNumber(),
|
||||
'message' => $message->getContent($this),
|
||||
], [
|
||||
'Authorization' => 'Basic '.base64_encode('api:key-'.$config->get('api_key')),
|
||||
]);
|
||||
|
||||
if ($result['error']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['error'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $type, self::ENDPOINT_VERSION, $function, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
72
vendor/overtrue/easy-sms/src/Gateways/MaapGateway.php
vendored
Normal file
72
vendor/overtrue/easy-sms/src/Gateways/MaapGateway.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class MaapGateway.
|
||||
*
|
||||
* @see https://maap.wo.cn/
|
||||
*/
|
||||
class MaapGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://rcsapi.wo.cn:8000/umcinterface/sendtempletmsg';
|
||||
|
||||
/**
|
||||
* Send message.
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'cpcode' => $config->get('cpcode'),
|
||||
'msg' => implode(',', $message->getData($this)),
|
||||
'mobiles' => $to->getNumber(),
|
||||
'excode' => $config->get('excode', ''),
|
||||
'templetid' => $message->getTemplate($this),
|
||||
];
|
||||
$params['sign'] = $this->generateSign($params, $config->get('key'));
|
||||
|
||||
$result = $this->postJson(self::ENDPOINT_URL, $params);
|
||||
|
||||
if (0 != $result['resultcode']) {
|
||||
throw new GatewayErrorException($result['resultmsg'], $result['resultcode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
* @param string $key 签名Key
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params, $key)
|
||||
{
|
||||
return md5($params['cpcode'] . $params['msg'] . $params['mobiles'] . $params['excode'] . $params['templetid'] . $key);
|
||||
}
|
||||
}
|
99
vendor/overtrue/easy-sms/src/Gateways/ModuyunGateway.php
vendored
Normal file
99
vendor/overtrue/easy-sms/src/Gateways/ModuyunGateway.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class ModuyunGateway.
|
||||
*
|
||||
* @see https://www.moduyun.com/doc/index.html#10002
|
||||
*/
|
||||
class ModuyunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://live.moduyun.com/sms/v2/sendsinglesms';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$urlParams = [
|
||||
'accesskey' => $config->get('accesskey'),
|
||||
'random' => rand(100000, 999999),
|
||||
];
|
||||
|
||||
$params = [
|
||||
'tel' => [
|
||||
'mobile' => $to->getNumber(),
|
||||
'nationcode' => $to->getIDDCode() ?: '86',
|
||||
],
|
||||
'signId' => $config->get('signId', ''),
|
||||
'templateId' => $message->getTemplate($this),
|
||||
'time' => time(),
|
||||
'type' => $config->get('type', 0),
|
||||
'params' => array_values($message->getData($this)),
|
||||
'ext' => '',
|
||||
'extend' => '',
|
||||
];
|
||||
$params['sig'] = $this->generateSign($params, $urlParams['random']);
|
||||
|
||||
$result = $this->postJson($this->getEndpointUrl($urlParams), $params);
|
||||
$result = is_string($result) ? json_decode($result, true) : $result;
|
||||
if (0 != $result['result']) {
|
||||
throw new GatewayErrorException($result['errmsg'], $result['result'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEndpointUrl($params)
|
||||
{
|
||||
return self::ENDPOINT_URL . '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
* @param string $random
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params, $random)
|
||||
{
|
||||
return hash('sha256', sprintf(
|
||||
'secretkey=%s&random=%d&time=%d&mobile=%s',
|
||||
$this->config->get('secretkey'),
|
||||
$random,
|
||||
$params['time'],
|
||||
$params['tel']['mobile']
|
||||
));
|
||||
}
|
||||
}
|
34
vendor/overtrue/easy-sms/src/Gateways/NowcnGateway.php
vendored
Normal file
34
vendor/overtrue/easy-sms/src/Gateways/NowcnGateway.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
class NowcnGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://ad1200.now.net.cn:2003/sms/sendSMS';
|
||||
|
||||
const SUCCESS_CODE = 0;
|
||||
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params=[
|
||||
'mobile' => $to->getNumber(),
|
||||
'content' => $message->getContent($this),
|
||||
'userId' => $config->get('key'),
|
||||
'password' => $config->get('secret'),
|
||||
'apiType' => $config->get('api_type'),
|
||||
];
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
if (self::SUCCESS_CODE != $result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
137
vendor/overtrue/easy-sms/src/Gateways/QcloudGateway.php
vendored
Normal file
137
vendor/overtrue/easy-sms/src/Gateways/QcloudGateway.php
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class QcloudGateway.
|
||||
*
|
||||
* @see https://cloud.tencent.com/document/api/382/55981
|
||||
*/
|
||||
class QcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://sms.tencentcloudapi.com';
|
||||
|
||||
const ENDPOINT_HOST = 'sms.tencentcloudapi.com';
|
||||
|
||||
const ENDPOINT_SERVICE = 'sms';
|
||||
|
||||
const ENDPOINT_METHOD = 'SendSms';
|
||||
|
||||
const ENDPOINT_VERSION = '2021-01-11';
|
||||
|
||||
const ENDPOINT_REGION = 'ap-guangzhou';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
$signName = !empty($data['sign_name']) ? $data['sign_name'] : $config->get('sign_name', '');
|
||||
|
||||
unset($data['sign_name']);
|
||||
|
||||
$phone = !\is_null($to->getIDDCode()) ? strval($to->getUniversalNumber()) : $to->getNumber();
|
||||
$params = [
|
||||
'PhoneNumberSet' => [
|
||||
$phone
|
||||
],
|
||||
'SmsSdkAppId' => $this->config->get('sdk_app_id'),
|
||||
'SignName' => $signName,
|
||||
'TemplateId' => (string) $message->getTemplate($this),
|
||||
'TemplateParamSet' => array_map('strval', array_values($data)),
|
||||
];
|
||||
|
||||
$time = time();
|
||||
|
||||
$result = $this->request('post', self::ENDPOINT_URL, [
|
||||
'headers' => [
|
||||
'Authorization' => $this->generateSign($params, $time),
|
||||
'Host' => self::ENDPOINT_HOST,
|
||||
'Content-Type' => 'application/json; charset=utf-8',
|
||||
'X-TC-Action' => self::ENDPOINT_METHOD,
|
||||
'X-TC-Region' => $this->config->get('region', self::ENDPOINT_REGION),
|
||||
'X-TC-Timestamp' => $time,
|
||||
'X-TC-Version' => self::ENDPOINT_VERSION,
|
||||
],
|
||||
'json' => $params,
|
||||
]);
|
||||
|
||||
if (!empty($result['Response']['Error']['Code'])) {
|
||||
throw new GatewayErrorException($result['Response']['Error']['Message'], 400, $result);
|
||||
}
|
||||
|
||||
if (!empty($result['Response']['SendStatusSet'])) {
|
||||
foreach ($result['Response']['SendStatusSet'] as $group) {
|
||||
if ($group['Code'] != 'Ok') {
|
||||
throw new GatewayErrorException($group['Message'], 400, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params, $timestamp)
|
||||
{
|
||||
$date = gmdate("Y-m-d", $timestamp);
|
||||
$secretKey = $this->config->get('secret_key');
|
||||
$secretId = $this->config->get('secret_id');
|
||||
|
||||
$canonicalRequest = 'POST'."\n".
|
||||
'/'."\n".
|
||||
'' ."\n".
|
||||
'content-type:application/json; charset=utf-8'."\n".
|
||||
'host:' . self::ENDPOINT_HOST."\n"."\n".
|
||||
'content-type;host'."\n".
|
||||
hash("SHA256", json_encode($params));
|
||||
|
||||
$stringToSign =
|
||||
'TC3-HMAC-SHA256'."\n".
|
||||
$timestamp."\n".
|
||||
$date . '/'. self::ENDPOINT_SERVICE .'/tc3_request'."\n".
|
||||
hash("SHA256", $canonicalRequest);
|
||||
|
||||
$secretDate = hash_hmac("SHA256", $date, "TC3".$secretKey, true);
|
||||
$secretService = hash_hmac("SHA256", self::ENDPOINT_SERVICE, $secretDate, true);
|
||||
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
|
||||
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
|
||||
|
||||
return 'TC3-HMAC-SHA256'
|
||||
." Credential=". $secretId ."/". $date . '/'. self::ENDPOINT_SERVICE .'/tc3_request'
|
||||
.", SignedHeaders=content-type;host, Signature=".$signature;
|
||||
}
|
||||
}
|
148
vendor/overtrue/easy-sms/src/Gateways/QiniuGateway.php
vendored
Normal file
148
vendor/overtrue/easy-sms/src/Gateways/QiniuGateway.php
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class QiniuGateway.
|
||||
*
|
||||
* @see https://developer.qiniu.com/sms/api/5897/sms-api-send-message
|
||||
*/
|
||||
class QiniuGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s.qiniuapi.com/%s/%s';
|
||||
|
||||
const ENDPOINT_VERSION = 'v1';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint('sms', 'message/single');
|
||||
|
||||
$data = $message->getData($this);
|
||||
|
||||
$params = [
|
||||
'template_id' => $message->getTemplate($this),
|
||||
'mobile' => $to->getNumber(),
|
||||
];
|
||||
|
||||
if (!empty($data)) {
|
||||
$params['parameters'] = $data;
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Content-Type' => 'application/json',
|
||||
];
|
||||
|
||||
$headers['Authorization'] = $this->generateSign($endpoint, 'POST', json_encode($params), $headers['Content-Type'], $config);
|
||||
|
||||
$result = $this->postJson($endpoint, $params, $headers);
|
||||
|
||||
if (isset($result['error'])) {
|
||||
throw new GatewayErrorException($result['message'], $result['error'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $type, self::ENDPOINT_VERSION, $function);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $method
|
||||
* @param string $body
|
||||
* @param string $contentType
|
||||
* @param Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($url, $method, $body, $contentType, Config $config)
|
||||
{
|
||||
$urlItems = parse_url($url);
|
||||
$host = $urlItems['host'];
|
||||
if (isset($urlItems['port'])) {
|
||||
$port = $urlItems['port'];
|
||||
} else {
|
||||
$port = '';
|
||||
}
|
||||
$path = $urlItems['path'];
|
||||
if (isset($urlItems['query'])) {
|
||||
$query = $urlItems['query'];
|
||||
} else {
|
||||
$query = '';
|
||||
}
|
||||
//write request uri
|
||||
$toSignStr = $method.' '.$path;
|
||||
if (!empty($query)) {
|
||||
$toSignStr .= '?'.$query;
|
||||
}
|
||||
//write host and port
|
||||
$toSignStr .= "\nHost: ".$host;
|
||||
if (!empty($port)) {
|
||||
$toSignStr .= ':'.$port;
|
||||
}
|
||||
//write content type
|
||||
if (!empty($contentType)) {
|
||||
$toSignStr .= "\nContent-Type: ".$contentType;
|
||||
}
|
||||
$toSignStr .= "\n\n";
|
||||
//write body
|
||||
if (!empty($body)) {
|
||||
$toSignStr .= $body;
|
||||
}
|
||||
|
||||
$hmac = hash_hmac('sha1', $toSignStr, $config->get('secret_key'), true);
|
||||
|
||||
return 'Qiniu '.$config->get('access_key').':'.$this->base64UrlSafeEncode($hmac);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function base64UrlSafeEncode($data)
|
||||
{
|
||||
$find = array('+', '/');
|
||||
$replace = array('-', '_');
|
||||
|
||||
return str_replace($find, $replace, base64_encode($data));
|
||||
}
|
||||
}
|
134
vendor/overtrue/easy-sms/src/Gateways/RongcloudGateway.php
vendored
Normal file
134
vendor/overtrue/easy-sms/src/Gateways/RongcloudGateway.php
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class RongcloudGateway.
|
||||
*
|
||||
* @author Darren Gao <realgaodacheng@gmail.com>
|
||||
*
|
||||
* @see http://www.rongcloud.cn/docs/sms_service.html#send_sms_code
|
||||
*/
|
||||
class RongcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://api.sms.ronghub.com/%s.%s';
|
||||
|
||||
const ENDPOINT_ACTION = 'sendCode';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const ENDPOINT_REGION = '86'; // 中国区,目前只支持此国别
|
||||
|
||||
const SUCCESS_CODE = 200;
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData();
|
||||
$action = array_key_exists('action', $data) ? $data['action'] : self::ENDPOINT_ACTION;
|
||||
$endpoint = $this->buildEndpoint($action);
|
||||
|
||||
$headers = [
|
||||
'Nonce' => uniqid(),
|
||||
'App-Key' => $config->get('app_key'),
|
||||
'Timestamp' => time(),
|
||||
];
|
||||
$headers['Signature'] = $this->generateSign($headers, $config);
|
||||
|
||||
switch ($action) {
|
||||
case 'sendCode':
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'region' => self::ENDPOINT_REGION,
|
||||
'templateId' => $message->getTemplate($this),
|
||||
];
|
||||
|
||||
break;
|
||||
case 'verifyCode':
|
||||
if (!array_key_exists('code', $data)
|
||||
or !array_key_exists('sessionId', $data)) {
|
||||
throw new GatewayErrorException('"code" or "sessionId" is not set', 0);
|
||||
}
|
||||
$params = [
|
||||
'code' => $data['code'],
|
||||
'sessionId' => $data['sessionId'],
|
||||
];
|
||||
|
||||
break;
|
||||
case 'sendNotify':
|
||||
$params = [
|
||||
'mobile' => $to->getNumber(),
|
||||
'region' => self::ENDPOINT_REGION,
|
||||
'templateId' => $message->getTemplate($this),
|
||||
];
|
||||
$params = array_merge($params, $data);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new GatewayErrorException(sprintf('action: %s not supported', $action));
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->post($endpoint, $params, $headers);
|
||||
|
||||
if (self::SUCCESS_CODE !== $result['code']) {
|
||||
throw new GatewayErrorException($result['errorMessage'], $result['code'], $result);
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
throw new GatewayErrorException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSign($params, Config $config)
|
||||
{
|
||||
return sha1(sprintf('%s%s%s', $config->get('app_secret'), $params['Nonce'], $params['Timestamp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $action
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($action)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $action, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
69
vendor/overtrue/easy-sms/src/Gateways/RongheyunGateway.php
vendored
Normal file
69
vendor/overtrue/easy-sms/src/Gateways/RongheyunGateway.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class RongheyunGateway.
|
||||
*
|
||||
* @see https://doc.zthysms.com/web/#/1?page_id=13
|
||||
*/
|
||||
class RongheyunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://api.mix2.zthysms.com/v2/sendSmsTp';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$tKey = time();
|
||||
$password = md5(md5($config->get('password')) . $tKey);
|
||||
$params = [
|
||||
'username' => $config->get('username', ''),
|
||||
'password' => $password,
|
||||
'tKey' => $tKey,
|
||||
'signature' => $config->get('signature', ''),
|
||||
'tpId' => $message->getTemplate($this),
|
||||
'ext' => '',
|
||||
'extend' => '',
|
||||
'records' => [
|
||||
'mobile' => $to->getNumber(),
|
||||
'tpContent' => $message->getData($this),
|
||||
],
|
||||
];
|
||||
|
||||
$result = $this->postJson(
|
||||
self::ENDPOINT_URL,
|
||||
$params,
|
||||
['Content-Type' => 'application/json; charset="UTF-8"']
|
||||
);
|
||||
if (200 != $result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
95
vendor/overtrue/easy-sms/src/Gateways/SendcloudGateway.php
vendored
Normal file
95
vendor/overtrue/easy-sms/src/Gateways/SendcloudGateway.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class SendcloudGateway.
|
||||
*
|
||||
* @see http://sendcloud.sohu.com/doc/sms/
|
||||
*/
|
||||
class SendcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://www.sendcloud.net/smsapi/%s';
|
||||
|
||||
/**
|
||||
* Send a short message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'smsUser' => $config->get('sms_user'),
|
||||
'templateId' => $message->getTemplate($this),
|
||||
'msgType' => $to->getIDDCode() ? 2 : 0,
|
||||
'phone' => $to->getZeroPrefixedNumber(),
|
||||
'vars' => $this->formatTemplateVars($message->getData($this)),
|
||||
];
|
||||
|
||||
if ($config->get('timestamp', false)) {
|
||||
$params['timestamp'] = time() * 1000;
|
||||
}
|
||||
|
||||
$params['signature'] = $this->sign($params, $config->get('sms_key'));
|
||||
|
||||
$result = $this->post(sprintf(self::ENDPOINT_TEMPLATE, 'send'), $params);
|
||||
|
||||
if (!$result['result']) {
|
||||
throw new GatewayErrorException($result['message'], $result['statusCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $vars
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTemplateVars(array $vars)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($vars as $key => $value) {
|
||||
$formatted[sprintf('%%%s%%', trim($key, '%'))] = $value;
|
||||
}
|
||||
|
||||
return json_encode($formatted, JSON_FORCE_OBJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sign($params, $key)
|
||||
{
|
||||
ksort($params);
|
||||
|
||||
return md5(sprintf('%s&%s&%s', $key, urldecode(http_build_query($params)), $key));
|
||||
}
|
||||
}
|
77
vendor/overtrue/easy-sms/src/Gateways/SmsbaoGateway.php
vendored
Normal file
77
vendor/overtrue/easy-sms/src/Gateways/SmsbaoGateway.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class SmsbaoGateway
|
||||
* @author iwindy <203962638@qq.com>
|
||||
* @see http://www.smsbao.com/openapi/
|
||||
*/
|
||||
class SmsbaoGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://api.smsbao.com/%s';
|
||||
|
||||
const SUCCESS_CODE = '0';
|
||||
|
||||
protected $errorStatuses = [
|
||||
'0' => '短信发送成功',
|
||||
'-1' => '参数不全',
|
||||
'-2' => '服务器空间不支持,请确认支持curl或者fsocket,联系您的空间商解决或者更换空间!',
|
||||
'30' => '密码错误',
|
||||
'40' => '账号不存在',
|
||||
'41' => '余额不足',
|
||||
'42' => '帐户已过期',
|
||||
'43' => 'IP地址限制',
|
||||
'50' => '内容含有敏感词'
|
||||
];
|
||||
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getContent($this);
|
||||
|
||||
if (is_null($to->getIDDCode()) || $to->getIDDCode() == '86') {
|
||||
$number = $to->getNumber();
|
||||
$action = 'sms';
|
||||
} else {
|
||||
$number = $to->getUniversalNumber();
|
||||
$action = 'wsms';
|
||||
}
|
||||
|
||||
$params = [
|
||||
'u' => $config->get('user'),
|
||||
'p' => md5($config->get('password')),
|
||||
'm' => $number,
|
||||
'c' => $data
|
||||
];
|
||||
|
||||
$result = $this->get($this->buildEndpoint($action), $params);
|
||||
|
||||
if ($result !== self::SUCCESS_CODE) {
|
||||
throw new GatewayErrorException($this->errorStatuses[$result], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function buildEndpoint($type)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_URL, $type);
|
||||
}
|
||||
}
|
88
vendor/overtrue/easy-sms/src/Gateways/SubmailGateway.php
vendored
Normal file
88
vendor/overtrue/easy-sms/src/Gateways/SubmailGateway.php
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class SubmailGateway.
|
||||
*
|
||||
* @see https://www.mysubmail.com/chs/documents/developer/index
|
||||
*/
|
||||
class SubmailGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://api.mysubmail.com/%s.%s';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint($this->inChineseMainland($to) ? 'message/xsend' : 'internationalsms/xsend');
|
||||
|
||||
$data = $message->getData($this);
|
||||
|
||||
$result = $this->post($endpoint, [
|
||||
'appid' => $config->get('app_id'),
|
||||
'signature' => $config->get('app_key'),
|
||||
'project' => !empty($data['project']) ? $data['project'] : $config->get('project'),
|
||||
'to' => $to->getUniversalNumber(),
|
||||
'vars' => json_encode($data, JSON_FORCE_OBJECT),
|
||||
]);
|
||||
|
||||
if ('success' != $result['status']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $function, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the phone number belongs to chinese mainland.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function inChineseMainland($to)
|
||||
{
|
||||
$code = $to->getIDDCode();
|
||||
|
||||
return empty($code) || 86 === $code;
|
||||
}
|
||||
}
|
84
vendor/overtrue/easy-sms/src/Gateways/TianyiwuxianGateway.php
vendored
Normal file
84
vendor/overtrue/easy-sms/src/Gateways/TianyiwuxianGateway.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class TianyiwuxianGateway.
|
||||
*
|
||||
* @author Darren Gao <realgaodacheng@gmail.com>
|
||||
*/
|
||||
class TianyiwuxianGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'http://jk.106api.cn/sms%s.aspx';
|
||||
|
||||
const ENDPOINT_ENCODE = 'UTF8';
|
||||
|
||||
const ENDPOINT_TYPE = 'send';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
const SUCCESS_STATUS = 'success';
|
||||
|
||||
const SUCCESS_CODE = '0';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$endpoint = $this->buildEndpoint();
|
||||
|
||||
$params = [
|
||||
'gwid' => $config->get('gwid'),
|
||||
'type' => self::ENDPOINT_TYPE,
|
||||
'rece' => self::ENDPOINT_FORMAT,
|
||||
'mobile' => $to->getNumber(),
|
||||
'message' => $message->getContent($this),
|
||||
'username' => $config->get('username'),
|
||||
'password' => strtoupper(md5($config->get('password'))),
|
||||
];
|
||||
|
||||
$result = $this->post($endpoint, $params);
|
||||
|
||||
$result = json_decode($result, true);
|
||||
|
||||
if (self::SUCCESS_STATUS !== $result['returnstatus'] || self::SUCCESS_CODE !== $result['code']) {
|
||||
throw new GatewayErrorException($result['remark'], $result['code']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint()
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, self::ENDPOINT_ENCODE);
|
||||
}
|
||||
}
|
85
vendor/overtrue/easy-sms/src/Gateways/TiniyoGateway.php
vendored
Normal file
85
vendor/overtrue/easy-sms/src/Gateways/TiniyoGateway.php
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class Tiniyo Gateway.
|
||||
*
|
||||
* @see https://tiniyo.com/sms.html
|
||||
*/
|
||||
class TiniyoGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://api.tiniyo.com/v1/Account/%s/Message';
|
||||
|
||||
const SUCCESS_CODE = '000000';
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'tiniyo';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$accountSid = $config->get('account_sid');
|
||||
$endpoint = $this->buildEndPoint($accountSid);
|
||||
|
||||
$params = [
|
||||
'dst' => $to->getUniversalNumber(),
|
||||
'src' => $config->get('from'),
|
||||
'text' => $message->getContent($this),
|
||||
];
|
||||
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'json' => $params,
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json;charset=utf-8',
|
||||
'Authorization' => base64_encode($config->get('account_sid').':'.$config->get('token')),
|
||||
],
|
||||
]);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['statusCode']) {
|
||||
throw new GatewayErrorException($result['statusCode'], $result['statusCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* build endpoint url.
|
||||
*
|
||||
* @param string $accountSid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndPoint($accountSid)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_URL, $accountSid);
|
||||
}
|
||||
}
|
77
vendor/overtrue/easy-sms/src/Gateways/TinreeGateway.php
vendored
Normal file
77
vendor/overtrue/easy-sms/src/Gateways/TinreeGateway.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
|
||||
/**
|
||||
* Class TinreeGateway.
|
||||
*
|
||||
* @see http://cms.tinree.com
|
||||
*/
|
||||
class TinreeGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'http://api.tinree.com/api/v2/single_send';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'accesskey' => $config->get('accesskey'),
|
||||
'secret' => $config->get('secret'),
|
||||
'sign' => $config->get('sign'),
|
||||
'templateId' => $message->getTemplate($this),
|
||||
'mobile' => $to->getNumber(),
|
||||
'content' => $this->buildContent($message),
|
||||
];
|
||||
|
||||
$result = $this->post(self::ENDPOINT_URL, $params);
|
||||
|
||||
if (0 != $result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建发送内容
|
||||
* 用 data 数据合成内容,或者直接使用 data 的值
|
||||
*
|
||||
* @param MessageInterface $message
|
||||
* @return string
|
||||
*/
|
||||
protected function buildContent(MessageInterface $message)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
if (is_array($data)) {
|
||||
return implode("##", $data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
91
vendor/overtrue/easy-sms/src/Gateways/TwilioGateway.php
vendored
Normal file
91
vendor/overtrue/easy-sms/src/Gateways/TwilioGateway.php
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class TwilioGateway.
|
||||
*
|
||||
* @see https://www.twilio.com/docs/api/messaging/send-messages
|
||||
*/
|
||||
class TwilioGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json';
|
||||
|
||||
protected $errorStatuses = [
|
||||
'failed',
|
||||
'undelivered',
|
||||
];
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'twilio';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$accountSid = $config->get('account_sid');
|
||||
$endpoint = $this->buildEndPoint($accountSid);
|
||||
|
||||
$params = [
|
||||
'To' => $to->getUniversalNumber(),
|
||||
'From' => $config->get('from'),
|
||||
'Body' => $message->getContent($this),
|
||||
];
|
||||
|
||||
try {
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'auth' => [
|
||||
$accountSid,
|
||||
$config->get('token'),
|
||||
],
|
||||
'form_params' => $params,
|
||||
]);
|
||||
if (in_array($result['status'], $this->errorStatuses) || !is_null($result['error_code'])) {
|
||||
throw new GatewayErrorException($result['message'], $result['error_code'], $result);
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
throw new GatewayErrorException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* build endpoint url.
|
||||
*
|
||||
* @param string $accountSid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndPoint($accountSid)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_URL, $accountSid);
|
||||
}
|
||||
}
|
130
vendor/overtrue/easy-sms/src/Gateways/UcloudGateway.php
vendored
Normal file
130
vendor/overtrue/easy-sms/src/Gateways/UcloudGateway.php
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class UcloudGateway.
|
||||
*/
|
||||
class UcloudGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://api.ucloud.cn';
|
||||
|
||||
const ENDPOINT_Action = 'SendUSMSMessage';
|
||||
|
||||
const SUCCESS_CODE = 0;
|
||||
|
||||
/**
|
||||
* Send Message.
|
||||
*
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = $this->buildParams($to, $message, $config);
|
||||
|
||||
$result = $this->get(self::ENDPOINT_URL, $params);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['RetCode']) {
|
||||
throw new GatewayErrorException($result['Message'], $result['RetCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Params.
|
||||
*
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function buildParams(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
$params = [
|
||||
'Action' => self::ENDPOINT_Action,
|
||||
'SigContent' => !empty($data['sig_content']) ? $data['sig_content'] : $config->get('sig_content', ''),
|
||||
'TemplateId' => $message->getTemplate($this),
|
||||
'PublicKey' => $config->get('public_key'),
|
||||
];
|
||||
$code = isset($data['code']) ? $data['code'] : '';
|
||||
if (is_array($code) && !empty($code)) {
|
||||
foreach ($code as $key => $value) {
|
||||
$params['TemplateParams.'.$key] = $value;
|
||||
}
|
||||
} else {
|
||||
if (!empty($code) || !is_null($code)) {
|
||||
$params['TemplateParams.0'] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
$mobiles = isset($data['mobiles']) ? $data['mobiles'] : '';
|
||||
if (!empty($mobiles) && !is_null($mobiles)) {
|
||||
if (is_array($mobiles)) {
|
||||
foreach ($mobiles as $key => $value) {
|
||||
$params['PhoneNumbers.'.$key] = $value;
|
||||
}
|
||||
} else {
|
||||
$params['PhoneNumbers.0'] = $mobiles;
|
||||
}
|
||||
} else {
|
||||
$params['PhoneNumbers.0'] = $to->getNumber();
|
||||
}
|
||||
|
||||
if (!is_null($config->get('project_id')) && !empty($config->get('project_id'))) {
|
||||
$params['ProjectId'] = $config->get('project_id');
|
||||
}
|
||||
|
||||
$signature = $this->getSignature($params, $config->get('private_key'));
|
||||
$params['Signature'] = $signature;
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Sign.
|
||||
*
|
||||
* @param array $params
|
||||
* @param string $privateKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getSignature($params, $privateKey)
|
||||
{
|
||||
ksort($params);
|
||||
|
||||
$paramsData = '';
|
||||
foreach ($params as $key => $value) {
|
||||
$paramsData .= $key;
|
||||
$paramsData .= $value;
|
||||
}
|
||||
$paramsData .= $privateKey;
|
||||
|
||||
return sha1($paramsData);
|
||||
}
|
||||
}
|
77
vendor/overtrue/easy-sms/src/Gateways/Ue35Gateway.php
vendored
Normal file
77
vendor/overtrue/easy-sms/src/Gateways/Ue35Gateway.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class Ue35Gateway.
|
||||
*
|
||||
* @see https://shimo.im/docs/380b42d8cba24521
|
||||
*/
|
||||
class Ue35Gateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_HOST = 'sms.ue35.cn';
|
||||
|
||||
const ENDPOINT_URI = '/sms/interface/sendmess.htm';
|
||||
|
||||
const SUCCESS_CODE = 1;
|
||||
|
||||
/**
|
||||
* Send message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$params = [
|
||||
'username' => $config->get('username'),
|
||||
'userpwd' => $config->get('userpwd'),
|
||||
'mobiles' => $to->getNumber(),
|
||||
'content' => $message->getContent($this),
|
||||
];
|
||||
|
||||
$headers = [
|
||||
'host' => static::ENDPOINT_HOST,
|
||||
'content-type' => 'application/json',
|
||||
'user-agent' => 'PHP EasySms Client',
|
||||
];
|
||||
|
||||
$result = $this->request('get', self::getEndpointUri().'?'.http_build_query($params), ['headers' => $headers]);
|
||||
if (is_string($result)) {
|
||||
$result = json_decode(json_encode(simplexml_load_string($result)), true);
|
||||
}
|
||||
|
||||
if (self::SUCCESS_CODE != $result['errorcode']) {
|
||||
throw new GatewayErrorException($result['message'], $result['errorcode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getEndpointUri()
|
||||
{
|
||||
return 'http://'.static::ENDPOINT_HOST.static::ENDPOINT_URI;
|
||||
}
|
||||
}
|
311
vendor/overtrue/easy-sms/src/Gateways/VolcengineGateway.php
vendored
Normal file
311
vendor/overtrue/easy-sms/src/Gateways/VolcengineGateway.php
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Psr7\Query;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use GuzzleHttp\Psr7;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class VolcengineGateway.
|
||||
*
|
||||
* @see https://www.volcengine.com/docs/6361/66704
|
||||
*/
|
||||
class VolcengineGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_ACTION = 'SendSms';
|
||||
const ENDPOINT_VERSION = '2020-01-01';
|
||||
const ENDPOINT_CONTENT_TYPE = 'application/json; charset=utf-8';
|
||||
const ENDPOINT_ACCEPT = 'application/json';
|
||||
const ENDPOINT_USER_AGENT = 'overtrue/easy-sms';
|
||||
const ENDPOINT_SERVICE = 'volcSMS';
|
||||
|
||||
const Algorithm = 'HMAC-SHA256';
|
||||
|
||||
const ENDPOINT_DEFAULT_REGION_ID = 'cn-north-1';
|
||||
|
||||
public static $endpoints = [
|
||||
'cn-north-1' => 'https://sms.volcengineapi.com',
|
||||
'ap-singapore-1' => 'https://sms.byteplusapi.com',
|
||||
];
|
||||
|
||||
private $regionId = self::ENDPOINT_DEFAULT_REGION_ID;
|
||||
protected $requestDate;
|
||||
|
||||
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
$signName = !empty($data['sign_name']) ? $data['sign_name'] : $config->get('sign_name');
|
||||
$smsAccount = !empty($data['sms_account']) ? $data['sms_account'] : $config->get('sms_account');
|
||||
$templateId = $message->getTemplate($this);
|
||||
$phoneNumbers = !empty($data['phone_numbers']) ? $data['phone_numbers'] : $to->getNumber();
|
||||
$templateParam = !empty($data['template_param']) ? $data['template_param'] : $message->getData($this);
|
||||
|
||||
$tag = !empty($data['tag']) ? $data['tag'] : '';
|
||||
|
||||
$payload = [
|
||||
'SmsAccount' => $smsAccount, // 消息组帐号,火山短信页面右上角,短信应用括号中的字符串
|
||||
'Sign' => $signName, // 短信签名
|
||||
'TemplateID' => $templateId, // 短信模板ID
|
||||
'TemplateParam' => json_encode($templateParam), // 短信模板占位符要替换的值
|
||||
'PhoneNumbers' => $phoneNumbers, // 手机号,如果有多个使用英文逗号分割
|
||||
];
|
||||
if ($tag) {
|
||||
$payload['Tag'] = $tag;
|
||||
}
|
||||
$queries = [
|
||||
'Action' => self::ENDPOINT_ACTION,
|
||||
'Version' => self::ENDPOINT_VERSION,
|
||||
];
|
||||
|
||||
try {
|
||||
$stack = HandlerStack::create();
|
||||
$stack->push($this->signHandle());
|
||||
$this->setGuzzleOptions([
|
||||
'headers' => [
|
||||
'Content-Type' => self::ENDPOINT_CONTENT_TYPE,
|
||||
'Accept' => self::ENDPOINT_ACCEPT,
|
||||
'User-Agent' => self::ENDPOINT_USER_AGENT
|
||||
],
|
||||
'timeout' => $this->getTimeout(),
|
||||
'handler' => $stack,
|
||||
'base_uri' => $this->getEndpoint(),
|
||||
]);
|
||||
|
||||
$response = $this->request('post', $this->getEndpoint().$this->getCanonicalURI(), [
|
||||
'query' => $queries,
|
||||
'json' => $payload,
|
||||
]);
|
||||
if ($response instanceof Psr7\Response) {
|
||||
$response = json_decode($response->getBody()->getContents(), true);
|
||||
}
|
||||
if (isset($response['ResponseMetadata']['Error'])) { // 请求错误参数,如果请求没有错误,则不存在该参数返回
|
||||
// 火山引擎错误码格式为:'ZJ'+ 5位数字,比如 ZJ20009,取出数字部分
|
||||
preg_match('/\d+/', $response['ResponseMetadata']['Error']['Code'], $matches);
|
||||
throw new GatewayErrorException($response['ResponseMetadata']['Error']['Code'].":".$response['ResponseMetadata']['Error']['Message'], $matches[0], $response);
|
||||
}
|
||||
return $response;
|
||||
} catch (ClientException $exception) {
|
||||
$responseContent = $exception->getResponse()->getBody()->getContents();
|
||||
$response = json_decode($responseContent, true);
|
||||
if (isset($response['ResponseMetadata']['Error']) && $error = $response['ResponseMetadata']['Error']) { // 请求错误参数,如果请求没有错误,则不存在该参数返回
|
||||
// 火山引擎公共错误码Error与业务错误码略有不同,比如:"Error":{"CodeN":100004,"Code":"MissingRequestInfo","Message":"The request is missing timestamp information."}
|
||||
// 此处错误码直接取 CodeN
|
||||
throw new GatewayErrorException($error["CodeN"].":".$error['Message'], $error["CodeN"], $response);
|
||||
}
|
||||
throw new GatewayErrorException($responseContent, $exception->getCode(), ['content' => $responseContent]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function signHandle()
|
||||
{
|
||||
return function (callable $handler) {
|
||||
return function (RequestInterface $request, array $options) use ($handler) {
|
||||
$request = $request->withHeader('X-Date', $this->getRequestDate());
|
||||
list($canonicalHeaders, $signedHeaders) = $this->getCanonicalHeaders($request);
|
||||
|
||||
$queries = Query::parse($request->getUri()->getQuery());
|
||||
$canonicalRequest = $request->getMethod()."\n"
|
||||
.$this->getCanonicalURI()."\n"
|
||||
.$this->getCanonicalQueryString($queries)."\n"
|
||||
.$canonicalHeaders."\n"
|
||||
.$signedHeaders."\n"
|
||||
.$this->getPayloadHash($request);
|
||||
|
||||
$stringToSign = $this->getStringToSign($canonicalRequest);
|
||||
|
||||
$signingKey = $this->getSigningKey();
|
||||
|
||||
$signature = hash_hmac('sha256', $stringToSign, $signingKey);
|
||||
$parsed = $this->parseRequest($request);
|
||||
|
||||
$parsed['headers']['Authorization'] = self::Algorithm.
|
||||
' Credential='.$this->getAccessKeyId().'/'.$this->getCredentialScope().', SignedHeaders='.$signedHeaders.', Signature='.$signature;
|
||||
|
||||
$buildRequest = function () use ($request, $parsed) {
|
||||
if ($parsed['query']) {
|
||||
$parsed['uri'] = $parsed['uri']->withQuery(Query::build($parsed['query']));
|
||||
}
|
||||
|
||||
return new Psr7\Request(
|
||||
$parsed['method'],
|
||||
$parsed['uri'],
|
||||
$parsed['headers'],
|
||||
$parsed['body'],
|
||||
$parsed['version']
|
||||
);
|
||||
};
|
||||
|
||||
return $handler($buildRequest(), $options);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private function parseRequest(RequestInterface $request)
|
||||
{
|
||||
$uri = $request->getUri();
|
||||
return [
|
||||
'method' => $request->getMethod(),
|
||||
'path' => $uri->getPath(),
|
||||
'query' => Query::parse($uri->getQuery()),
|
||||
'uri' => $uri,
|
||||
'headers' => $request->getHeaders(),
|
||||
'body' => $request->getBody(),
|
||||
'version' => $request->getProtocolVersion()
|
||||
];
|
||||
}
|
||||
|
||||
public function getPayloadHash(RequestInterface $request)
|
||||
{
|
||||
if ($request->hasHeader('X-Content-Sha256')) {
|
||||
return $request->getHeaderLine('X-Content-Sha256');
|
||||
}
|
||||
|
||||
return Utils::hash($request->getBody(), 'sha256');
|
||||
}
|
||||
|
||||
public function getRegionId()
|
||||
{
|
||||
return $this->config->get('region_id', self::ENDPOINT_DEFAULT_REGION_ID);
|
||||
}
|
||||
|
||||
public function getEndpoint()
|
||||
{
|
||||
$regionId = $this->getRegionId();
|
||||
if (!in_array($regionId, array_keys(self::$endpoints))) {
|
||||
$regionId = self::ENDPOINT_DEFAULT_REGION_ID;
|
||||
}
|
||||
return static::$endpoints[$regionId];
|
||||
}
|
||||
|
||||
public function getRequestDate()
|
||||
{
|
||||
return $this->requestDate ?: gmdate('Ymd\THis\Z');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 指代信任状,格式为:YYYYMMDD/region/service/request
|
||||
* @return string
|
||||
*/
|
||||
public function getCredentialScope()
|
||||
{
|
||||
return date('Ymd', strtotime($this->getRequestDate())).'/'.$this->getRegionId().'/'.self::ENDPOINT_SERVICE.'/request';
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算签名密钥
|
||||
* 在计算签名前,首先从私有访问密钥(Secret Access Key)派生出签名密钥(signing key),而不是直接使用私有访问密钥。具体计算过程如下:
|
||||
* kSecret = *Your Secret Access Key*
|
||||
* kDate = HMAC(kSecret, Date)
|
||||
* kRegion = HMAC(kDate, Region)
|
||||
* kService = HMAC(kRegion, Service)
|
||||
* kSigning = HMAC(kService, "request")
|
||||
* 其中Date精确到日,与RequestDate中YYYYMMDD部分相同。
|
||||
* @return string
|
||||
*/
|
||||
protected function getSigningKey()
|
||||
{
|
||||
$dateKey = hash_hmac('sha256', date("Ymd", strtotime($this->getRequestDate())), $this->getAccessKeySecret(), true);
|
||||
$regionKey = hash_hmac('sha256', $this->getRegionId(), $dateKey, true);
|
||||
$serviceKey = hash_hmac('sha256', self::ENDPOINT_SERVICE, $regionKey, true);
|
||||
return hash_hmac('sha256', 'request', $serviceKey, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建签名字符串
|
||||
* 签名字符串主要包含请求以及正规化请求的元数据信息,由签名算法、请求日期、信任状和正规化请求哈希值连接组成,伪代码如下:
|
||||
* StringToSign = Algorithm + '\n' + RequestDate + '\n' + CredentialScope + '\n' + HexEncode(Hash(CanonicalRequest))
|
||||
* @return string
|
||||
*/
|
||||
public function getStringToSign($canonicalRequest)
|
||||
{
|
||||
return self::Algorithm."\n".$this->getRequestDate()."\n".$this->getCredentialScope()."\n".hash('sha256', $canonicalRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessKeySecret()
|
||||
{
|
||||
return $this->config->get('access_key_secret');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessKeyId()
|
||||
{
|
||||
return $this->config->get('access_key_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 指代正规化后的Header。
|
||||
* 其中伪代码如下:
|
||||
* CanonicalHeaders = CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ... + CanonicalHeadersEntryN
|
||||
* 其中CanonicalHeadersEntry = Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n'
|
||||
* Lowcase代表将Header的名称全部转化成小写,Trimall表示去掉Header的值的前后多余的空格。
|
||||
* 特别注意:最后需要添加"\n"的换行符,header的顺序是以headerName的小写后ascii排序。
|
||||
* @return array
|
||||
*/
|
||||
public function getCanonicalHeaders(RequestInterface $request)
|
||||
{
|
||||
$headers = $request->getHeaders();
|
||||
ksort($headers);
|
||||
$canonicalHeaders = '';
|
||||
$signedHeaders = [];
|
||||
foreach ($headers as $key => $val) {
|
||||
$lowerKey = strtolower($key);
|
||||
$canonicalHeaders .= $lowerKey.':'.trim($val[0]).PHP_EOL;
|
||||
$signedHeaders[] = $lowerKey;
|
||||
}
|
||||
$signedHeadersString = implode(';', $signedHeaders);
|
||||
return [$canonicalHeaders, $signedHeadersString];
|
||||
}
|
||||
|
||||
/**
|
||||
* urlencode(注:同RFC3986方法)每一个querystring参数名称和参数值。
|
||||
* 按照ASCII字节顺序对参数名称严格排序,相同参数名的不同参数值需保持请求的原始顺序。
|
||||
* 将排序好的参数名称和参数值用=连接,按照排序结果将“参数对”用&连接。
|
||||
* 例如:CanonicalQueryString = "Action=ListUsers&Version=2018-01-01"
|
||||
* @return string
|
||||
*/
|
||||
public function getCanonicalQueryString(array $query)
|
||||
{
|
||||
ksort($query);
|
||||
return http_build_query($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指代正规化后的URI。
|
||||
* 如果URI为空,那么使用"/"作为绝对路径。
|
||||
* 在火山引擎中绝大多数接口的URI都为"/"。
|
||||
* 如果是复杂的path,请通过RFC3986规范进行编码。
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCanonicalURI()
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
}
|
101
vendor/overtrue/easy-sms/src/Gateways/YunpianGateway.php
vendored
Normal file
101
vendor/overtrue/easy-sms/src/Gateways/YunpianGateway.php
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class YunpianGateway.
|
||||
*
|
||||
* @see https://www.yunpian.com/doc/zh_CN/intl/single_send.html
|
||||
*/
|
||||
class YunpianGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s.yunpian.com/%s/%s/%s.%s';
|
||||
|
||||
const ENDPOINT_VERSION = 'v2';
|
||||
|
||||
const ENDPOINT_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$template = $message->getTemplate($this);
|
||||
$function = 'single_send';
|
||||
$option = [
|
||||
'form_params' => [
|
||||
'apikey' => $config->get('api_key'),
|
||||
'mobile' => $to->getUniversalNumber()
|
||||
],
|
||||
'exceptions' => false,
|
||||
];
|
||||
|
||||
if (!is_null($template)) {
|
||||
$function = 'tpl_single_send';
|
||||
$data = [];
|
||||
|
||||
$templateData = $message->getData($this);
|
||||
$templateData = isset($templateData) ? $templateData : [];
|
||||
foreach ($templateData as $key => $value) {
|
||||
$data[] = urlencode('#'.$key.'#') . '=' . urlencode($value);
|
||||
}
|
||||
|
||||
$option['form_params'] = array_merge($option['form_params'], [
|
||||
'tpl_id' => $template,
|
||||
'tpl_value' => implode('&', $data)
|
||||
]);
|
||||
} else {
|
||||
$content = $message->getContent($this);
|
||||
$signature = $config->get('signature', '');
|
||||
$option['form_params'] = array_merge($option['form_params'], [
|
||||
'text' => 0 === \stripos($content, '【') ? $content : $signature.$content
|
||||
]);
|
||||
}
|
||||
|
||||
$endpoint = $this->buildEndpoint('sms', 'sms', $function);
|
||||
$result = $this->request('post', $endpoint, $option);
|
||||
|
||||
if ($result['code']) {
|
||||
throw new GatewayErrorException($result['msg'], $result['code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $resource
|
||||
* @param string $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $resource, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $type, self::ENDPOINT_VERSION, $resource, $function, self::ENDPOINT_FORMAT);
|
||||
}
|
||||
}
|
123
vendor/overtrue/easy-sms/src/Gateways/YuntongxunGateway.php
vendored
Normal file
123
vendor/overtrue/easy-sms/src/Gateways/YuntongxunGateway.php
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class YuntongxunGateway.
|
||||
*
|
||||
* @see Chinese Mainland: http://doc.yuntongxun.com/pe/5a533de33b8496dd00dce07c
|
||||
* @see International: http://doc.yuntongxun.com/pe/604f29eda80948a1006e928d
|
||||
*/
|
||||
class YuntongxunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://%s:%s/%s/%s/%s/%s/%s?sig=%s';
|
||||
|
||||
const SERVER_IP = 'app.cloopen.com';
|
||||
|
||||
const DEBUG_SERVER_IP = 'sandboxapp.cloopen.com';
|
||||
|
||||
const DEBUG_TEMPLATE_ID = 1;
|
||||
|
||||
const SERVER_PORT = '8883';
|
||||
|
||||
const SDK_VERSION = '2013-12-26';
|
||||
|
||||
const SDK_VERSION_INT = 'v2';
|
||||
|
||||
const SUCCESS_CODE = '000000';
|
||||
|
||||
private $international = false; // if international SMS, default false means no.
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$datetime = date('YmdHis');
|
||||
|
||||
$data = [
|
||||
'appId' => $config->get('app_id'),
|
||||
];
|
||||
|
||||
if ($to->inChineseMainland()) {
|
||||
$type = 'SMS';
|
||||
$resource = 'TemplateSMS';
|
||||
$data['to'] = $to->getNumber();
|
||||
$data['templateId'] = (int) ($this->config->get('debug') ? self::DEBUG_TEMPLATE_ID : $message->getTemplate($this));
|
||||
$data['datas'] = $message->getData($this);
|
||||
} else {
|
||||
$type = 'international';
|
||||
$resource = 'send';
|
||||
$this->international = true;
|
||||
$data['mobile'] = $to->getZeroPrefixedNumber();
|
||||
$data['content'] = $message->getContent($this);
|
||||
}
|
||||
|
||||
$endpoint = $this->buildEndpoint($type, $resource, $datetime, $config);
|
||||
|
||||
$result = $this->request('post', $endpoint, [
|
||||
'json' => $data,
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json;charset=utf-8',
|
||||
'Authorization' => base64_encode($config->get('account_sid').':'.$datetime),
|
||||
],
|
||||
]);
|
||||
|
||||
if (self::SUCCESS_CODE != $result['statusCode']) {
|
||||
throw new GatewayErrorException($result['statusCode'], $result['statusCode'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build endpoint url.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $resource
|
||||
* @param string $datetime
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($type, $resource, $datetime, Config $config)
|
||||
{
|
||||
$serverIp = $this->config->get('debug') ? self::DEBUG_SERVER_IP : self::SERVER_IP;
|
||||
|
||||
if ($this->international) {
|
||||
$accountType = 'account';
|
||||
$sdkVersion = self::SDK_VERSION_INT;
|
||||
} else {
|
||||
$accountType = $this->config->get('is_sub_account') ? 'SubAccounts' : 'Accounts';
|
||||
$sdkVersion = self::SDK_VERSION;
|
||||
}
|
||||
|
||||
$sig = strtoupper(md5($config->get('account_sid').$config->get('account_token').$datetime));
|
||||
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $serverIp, self::SERVER_PORT, $sdkVersion, $accountType, $config->get('account_sid'), $type, $resource, $sig);
|
||||
}
|
||||
}
|
162
vendor/overtrue/easy-sms/src/Gateways/YunxinGateway.php
vendored
Normal file
162
vendor/overtrue/easy-sms/src/Gateways/YunxinGateway.php
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class YunxinGateway.
|
||||
*
|
||||
* @author her-cat <i@her-cat.com>
|
||||
*
|
||||
* @see https://dev.yunxin.163.com/docs/product/%E7%9F%AD%E4%BF%A1/%E7%9F%AD%E4%BF%A1%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97
|
||||
*/
|
||||
class YunxinGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://api.netease.im/%s/%s.action';
|
||||
|
||||
const ENDPOINT_ACTION = 'sendCode';
|
||||
|
||||
const SUCCESS_CODE = 200;
|
||||
|
||||
/**
|
||||
* Send a short message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
$action = isset($data['action']) ? $data['action'] : self::ENDPOINT_ACTION;
|
||||
|
||||
$endpoint = $this->buildEndpoint('sms', $action);
|
||||
|
||||
switch ($action) {
|
||||
case 'sendCode':
|
||||
$params = $this->buildSendCodeParams($to, $message, $config);
|
||||
|
||||
break;
|
||||
case 'verifyCode':
|
||||
$params = $this->buildVerifyCodeParams($to, $message);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new GatewayErrorException(sprintf('action: %s not supported', $action), 0);
|
||||
}
|
||||
|
||||
$headers = $this->buildHeaders($config);
|
||||
|
||||
try {
|
||||
$result = $this->post($endpoint, $params, $headers);
|
||||
|
||||
if (!isset($result['code']) || self::SUCCESS_CODE !== $result['code']) {
|
||||
$code = isset($result['code']) ? $result['code'] : 0;
|
||||
$error = isset($result['msg']) ? $result['msg'] : json_encode($result, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
throw new GatewayErrorException($error, $code);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new GatewayErrorException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $resource
|
||||
* @param $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($resource, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $resource, strtolower($function));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request headers.
|
||||
*
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function buildHeaders(Config $config)
|
||||
{
|
||||
$headers = [
|
||||
'AppKey' => $config->get('app_key'),
|
||||
'Nonce' => md5(uniqid('easysms')),
|
||||
'CurTime' => (string) time(),
|
||||
'Content-Type' => 'application/x-www-form-urlencoded;charset=utf-8',
|
||||
];
|
||||
|
||||
$headers['CheckSum'] = sha1("{$config->get('app_secret')}{$headers['Nonce']}{$headers['CurTime']}");
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function buildSendCodeParams(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
$template = $message->getTemplate($this);
|
||||
|
||||
return [
|
||||
'mobile' => $to->getUniversalNumber(),
|
||||
'authCode' => array_key_exists('code', $data) ? $data['code'] : '',
|
||||
'deviceId' => array_key_exists('device_id', $data) ? $data['device_id'] : '',
|
||||
'templateid' => is_string($template) ? $template : '',
|
||||
'codeLen' => $config->get('code_length', 4),
|
||||
'needUp' => $config->get('need_up', false),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
*/
|
||||
public function buildVerifyCodeParams(PhoneNumberInterface $to, MessageInterface $message)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
if (!array_key_exists('code', $data)) {
|
||||
throw new GatewayErrorException('"code" cannot be empty', 0);
|
||||
}
|
||||
|
||||
return [
|
||||
'mobile' => $to->getUniversalNumber(),
|
||||
'code' => $data['code'],
|
||||
];
|
||||
}
|
||||
}
|
121
vendor/overtrue/easy-sms/src/Gateways/YunzhixunGateway.php
vendored
Normal file
121
vendor/overtrue/easy-sms/src/Gateways/YunzhixunGateway.php
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class YunzhixunGateway.
|
||||
*
|
||||
* @author her-cat <i@her-cat.com>
|
||||
*
|
||||
* @see http://docs.ucpaas.com/doku.php?id=%E7%9F%AD%E4%BF%A1:sendsms
|
||||
*/
|
||||
class YunzhixunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const SUCCESS_CODE = '000000';
|
||||
|
||||
const FUNCTION_SEND_SMS = 'sendsms';
|
||||
|
||||
const FUNCTION_BATCH_SEND_SMS = 'sendsms_batch';
|
||||
|
||||
const ENDPOINT_TEMPLATE = 'https://open.ucpaas.com/ol/%s/%s';
|
||||
|
||||
/**
|
||||
* Send a short message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
$function = isset($data['mobiles']) ? self::FUNCTION_BATCH_SEND_SMS : self::FUNCTION_SEND_SMS;
|
||||
|
||||
$endpoint = $this->buildEndpoint('sms', $function);
|
||||
|
||||
$params = $this->buildParams($to, $message, $config);
|
||||
|
||||
return $this->execute($endpoint, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $resource
|
||||
* @param $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildEndpoint($resource, $function)
|
||||
{
|
||||
return sprintf(self::ENDPOINT_TEMPLATE, $resource, $function);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhoneNumberInterface $to
|
||||
* @param MessageInterface $message
|
||||
* @param Config $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function buildParams(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$data = $message->getData($this);
|
||||
|
||||
return [
|
||||
'sid' => $config->get('sid'),
|
||||
'token' => $config->get('token'),
|
||||
'appid' => $config->get('app_id'),
|
||||
'templateid' => $message->getTemplate($this),
|
||||
'uid' => isset($data['uid']) ? $data['uid'] : '',
|
||||
'param' => isset($data['params']) ? $data['params'] : '',
|
||||
'mobile' => isset($data['mobiles']) ? $data['mobiles'] : $to->getNumber(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $endpoint
|
||||
* @param $params
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GatewayErrorException
|
||||
*/
|
||||
protected function execute($endpoint, $params)
|
||||
{
|
||||
try {
|
||||
$result = $this->postJson($endpoint, $params);
|
||||
|
||||
if (!isset($result['code']) || self::SUCCESS_CODE !== $result['code']) {
|
||||
$code = isset($result['code']) ? $result['code'] : 0;
|
||||
$error = isset($result['msg']) ? $result['msg'] : json_encode($result, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
throw new GatewayErrorException($error, $code);
|
||||
}
|
||||
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
throw new GatewayErrorException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
}
|
63
vendor/overtrue/easy-sms/src/Gateways/ZzyunGateway.php
vendored
Normal file
63
vendor/overtrue/easy-sms/src/Gateways/ZzyunGateway.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Gateways;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\GatewayErrorException;
|
||||
use Overtrue\EasySms\Support\Config;
|
||||
use Overtrue\EasySms\Traits\HasHttpRequest;
|
||||
|
||||
/**
|
||||
* Class RongheyunGateway.
|
||||
*
|
||||
* @see https://zzyun.com/
|
||||
*/
|
||||
class ZzyunGateway extends Gateway
|
||||
{
|
||||
use HasHttpRequest;
|
||||
|
||||
const ENDPOINT_URL = 'https://zzyun.com/api/sms/sendByTplCode';
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param \Overtrue\EasySms\Support\Config $config
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\GatewayErrorException ;
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, Config $config)
|
||||
{
|
||||
$time = time();
|
||||
$user_id = $config->get('user_id');
|
||||
$token = md5($time . $user_id . $config->get('secret'));
|
||||
$params = [
|
||||
'user_id' => $user_id,
|
||||
'time' => $time,
|
||||
'token' => $token,
|
||||
'mobiles' => $to->getNumber(),// 手机号码,多个英文逗号隔开
|
||||
'tpl_code' => $message->getTemplate($this),
|
||||
'tpl_params' => $message->getData($this),
|
||||
'sign_name' => $config->get('sign_name'),
|
||||
];
|
||||
|
||||
$result = $this->post(self::ENDPOINT_URL, $params);
|
||||
|
||||
if ('Success' != $result['Code']) {
|
||||
throw new GatewayErrorException($result['Message'], $result['Code'], $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
187
vendor/overtrue/easy-sms/src/Message.php
vendored
Normal file
187
vendor/overtrue/easy-sms/src/Message.php
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
use Overtrue\EasySms\Contracts\GatewayInterface;
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
|
||||
/**
|
||||
* Class Message.
|
||||
*/
|
||||
class Message implements MessageInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $gateways = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $template;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Message constructor.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param string $type
|
||||
*/
|
||||
public function __construct(array $attributes = [], $type = MessageInterface::TEXT_MESSAGE)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
foreach ($attributes as $property => $value) {
|
||||
if (property_exists($this, $property)) {
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the message type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMessageType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return message content.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent(GatewayInterface $gateway = null)
|
||||
{
|
||||
return is_callable($this->content) ? call_user_func($this->content, $gateway) : $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the template id of message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate(GatewayInterface $gateway = null)
|
||||
{
|
||||
return is_callable($this->template) ? call_user_func($this->template, $gateway) : $this->template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $content
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $template
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Overtrue\EasySms\Contracts\GatewayInterface|null $gateway
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getData(GatewayInterface $gateway = null)
|
||||
{
|
||||
return is_callable($this->data) ? call_user_func($this->data, $gateway) : $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|callable $data
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getGateways()
|
||||
{
|
||||
return $this->gateways;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGateways(array $gateways)
|
||||
{
|
||||
$this->gateways = $gateways;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $property
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __get($property)
|
||||
{
|
||||
if (property_exists($this, $property)) {
|
||||
return $this->$property;
|
||||
}
|
||||
}
|
||||
}
|
92
vendor/overtrue/easy-sms/src/Messenger.php
vendored
Normal file
92
vendor/overtrue/easy-sms/src/Messenger.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
use Overtrue\EasySms\Contracts\MessageInterface;
|
||||
use Overtrue\EasySms\Contracts\PhoneNumberInterface;
|
||||
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
|
||||
|
||||
/**
|
||||
* Class Messenger.
|
||||
*/
|
||||
class Messenger
|
||||
{
|
||||
const STATUS_SUCCESS = 'success';
|
||||
|
||||
const STATUS_FAILURE = 'failure';
|
||||
|
||||
/**
|
||||
* @var \Overtrue\EasySms\EasySms
|
||||
*/
|
||||
protected $easySms;
|
||||
|
||||
/**
|
||||
* Messenger constructor.
|
||||
*
|
||||
* @param \Overtrue\EasySms\EasySms $easySms
|
||||
*/
|
||||
public function __construct(EasySms $easySms)
|
||||
{
|
||||
$this->easySms = $easySms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message.
|
||||
*
|
||||
* @param \Overtrue\EasySms\Contracts\PhoneNumberInterface $to
|
||||
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Overtrue\EasySms\Exceptions\NoGatewayAvailableException
|
||||
*/
|
||||
public function send(PhoneNumberInterface $to, MessageInterface $message, array $gateways = [])
|
||||
{
|
||||
$results = [];
|
||||
$isSuccessful = false;
|
||||
|
||||
foreach ($gateways as $gateway => $config) {
|
||||
try {
|
||||
$results[$gateway] = [
|
||||
'gateway' => $gateway,
|
||||
'status' => self::STATUS_SUCCESS,
|
||||
'template' => $message->getTemplate($this->easySms->gateway($gateway)),
|
||||
'result' => $this->easySms->gateway($gateway)->send($to, $message, $config),
|
||||
];
|
||||
$isSuccessful = true;
|
||||
|
||||
break;
|
||||
} catch (\Exception $e) {
|
||||
$results[$gateway] = [
|
||||
'gateway' => $gateway,
|
||||
'status' => self::STATUS_FAILURE,
|
||||
'template' => $message->getTemplate($this->easySms->gateway($gateway)),
|
||||
'exception' => $e,
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
$results[$gateway] = [
|
||||
'gateway' => $gateway,
|
||||
'status' => self::STATUS_FAILURE,
|
||||
'template' => $message->getTemplate($this->easySms->gateway($gateway)),
|
||||
'exception' => $e,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isSuccessful) {
|
||||
throw new NoGatewayAvailableException($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
126
vendor/overtrue/easy-sms/src/PhoneNumber.php
vendored
Normal file
126
vendor/overtrue/easy-sms/src/PhoneNumber.php
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms;
|
||||
|
||||
/**
|
||||
* Class PhoneNumberInterface.
|
||||
*
|
||||
* @author overtrue <i@overtrue.me>
|
||||
*/
|
||||
class PhoneNumber implements \Overtrue\EasySms\Contracts\PhoneNumberInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $number;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $IDDCode;
|
||||
|
||||
/**
|
||||
* PhoneNumberInterface constructor.
|
||||
*
|
||||
* @param int $numberWithoutIDDCode
|
||||
* @param string $IDDCode
|
||||
*/
|
||||
public function __construct($numberWithoutIDDCode, $IDDCode = null)
|
||||
{
|
||||
$this->number = $numberWithoutIDDCode;
|
||||
$this->IDDCode = $IDDCode ? intval(ltrim($IDDCode, '+0')) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 86.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getIDDCode()
|
||||
{
|
||||
return $this->IDDCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 18888888888.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNumber()
|
||||
{
|
||||
return $this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* +8618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUniversalNumber()
|
||||
{
|
||||
return $this->getPrefixedIDDCode('+').$this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 008618888888888.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getZeroPrefixedNumber()
|
||||
{
|
||||
return $this->getPrefixedIDDCode('00').$this->number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPrefixedIDDCode($prefix)
|
||||
{
|
||||
return $this->IDDCode ? $prefix.$this->IDDCode : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getUniversalNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify data which should be serialized to JSON.
|
||||
*
|
||||
* @see http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
*
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource
|
||||
*
|
||||
* @since 5.4.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->getUniversalNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the phone number belongs to chinese mainland.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function inChineseMainland()
|
||||
{
|
||||
return empty($this->IDDCode) || $this->IDDCode === 86;
|
||||
}
|
||||
}
|
32
vendor/overtrue/easy-sms/src/Strategies/OrderStrategy.php
vendored
Normal file
32
vendor/overtrue/easy-sms/src/Strategies/OrderStrategy.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Strategies;
|
||||
|
||||
use Overtrue\EasySms\Contracts\StrategyInterface;
|
||||
|
||||
/**
|
||||
* Class OrderStrategy.
|
||||
*/
|
||||
class OrderStrategy implements StrategyInterface
|
||||
{
|
||||
/**
|
||||
* Apply the strategy and return result.
|
||||
*
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply(array $gateways)
|
||||
{
|
||||
return array_keys($gateways);
|
||||
}
|
||||
}
|
34
vendor/overtrue/easy-sms/src/Strategies/RandomStrategy.php
vendored
Normal file
34
vendor/overtrue/easy-sms/src/Strategies/RandomStrategy.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Strategies;
|
||||
|
||||
use Overtrue\EasySms\Contracts\StrategyInterface;
|
||||
|
||||
/**
|
||||
* Class RandomStrategy.
|
||||
*/
|
||||
class RandomStrategy implements StrategyInterface
|
||||
{
|
||||
/**
|
||||
* @param array $gateways
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply(array $gateways)
|
||||
{
|
||||
uasort($gateways, function () {
|
||||
return mt_rand() - mt_rand();
|
||||
});
|
||||
|
||||
return array_keys($gateways);
|
||||
}
|
||||
}
|
147
vendor/overtrue/easy-sms/src/Support/Config.php
vendored
Normal file
147
vendor/overtrue/easy-sms/src/Support/Config.php
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Support;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
/**
|
||||
* Class Config.
|
||||
*/
|
||||
class Config implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Config constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an array using "dot" notation.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$config = $this->config;
|
||||
|
||||
if (isset($config[$key])) {
|
||||
return $config[$key];
|
||||
}
|
||||
|
||||
if (false === strpos($key, '.')) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (!is_array($config) || !array_key_exists($segment, $config)) {
|
||||
return $default;
|
||||
}
|
||||
$config = $config[$segment];
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a offset exists.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetexists.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* An offset to check for.
|
||||
* </p>
|
||||
*
|
||||
* @return bool true on success or false on failure.
|
||||
* </p>
|
||||
* <p>
|
||||
* The return value will be casted to boolean if non-boolean was returned
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return array_key_exists($offset, $this->config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to retrieve.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetget.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* The offset to retrieve.
|
||||
* </p>
|
||||
*
|
||||
* @return mixed Can return all value types
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->get($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to set.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetset.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* The offset to assign the value to.
|
||||
* </p>
|
||||
* @param mixed $value <p>
|
||||
* The value to set.
|
||||
* </p>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (isset($this->config[$offset])) {
|
||||
$this->config[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset to unset.
|
||||
*
|
||||
* @see http://php.net/manual/en/arrayaccess.offsetunset.php
|
||||
*
|
||||
* @param mixed $offset <p>
|
||||
* The offset to unset.
|
||||
* </p>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
if (isset($this->config[$offset])) {
|
||||
unset($this->config[$offset]);
|
||||
}
|
||||
}
|
||||
}
|
136
vendor/overtrue/easy-sms/src/Traits/HasHttpRequest.php
vendored
Normal file
136
vendor/overtrue/easy-sms/src/Traits/HasHttpRequest.php
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/easy-sms.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\EasySms\Traits;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Trait HasHttpRequest.
|
||||
*/
|
||||
trait HasHttpRequest
|
||||
{
|
||||
/**
|
||||
* Make a get request.
|
||||
*
|
||||
* @param string $endpoint
|
||||
* @param array $query
|
||||
* @param array $headers
|
||||
*
|
||||
* @return ResponseInterface|array|string
|
||||
*/
|
||||
protected function get($endpoint, $query = [], $headers = [])
|
||||
{
|
||||
return $this->request('get', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'query' => $query,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a post request.
|
||||
*
|
||||
* @param string $endpoint
|
||||
* @param array $params
|
||||
* @param array $headers
|
||||
*
|
||||
* @return ResponseInterface|array|string
|
||||
*/
|
||||
protected function post($endpoint, $params = [], $headers = [])
|
||||
{
|
||||
return $this->request('post', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'form_params' => $params,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a post request with json params.
|
||||
*
|
||||
* @param $endpoint
|
||||
* @param array $params
|
||||
* @param array $headers
|
||||
*
|
||||
* @return ResponseInterface|array|string
|
||||
*/
|
||||
protected function postJson($endpoint, $params = [], $headers = [])
|
||||
{
|
||||
return $this->request('post', $endpoint, [
|
||||
'headers' => $headers,
|
||||
'json' => $params,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a http request.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $endpoint
|
||||
* @param array $options http://docs.guzzlephp.org/en/latest/request-options.html
|
||||
*
|
||||
* @return ResponseInterface|array|string
|
||||
*/
|
||||
protected function request($method, $endpoint, $options = [])
|
||||
{
|
||||
return $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($endpoint, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return base Guzzle options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getBaseOptions()
|
||||
{
|
||||
$options = method_exists($this, 'getGuzzleOptions') ? $this->getGuzzleOptions() : [];
|
||||
|
||||
return \array_merge($options, [
|
||||
'base_uri' => method_exists($this, 'getBaseUri') ? $this->getBaseUri() : '',
|
||||
'timeout' => method_exists($this, 'getTimeout') ? $this->getTimeout() : 5.0,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return http client.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return \GuzzleHttp\Client
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function getHttpClient(array $options = [])
|
||||
{
|
||||
return new Client($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert response contents to json.
|
||||
*
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
*
|
||||
* @return ResponseInterface|array|string
|
||||
*/
|
||||
protected function unwrapResponse(ResponseInterface $response)
|
||||
{
|
||||
$contentType = $response->getHeaderLine('Content-Type');
|
||||
$contents = $response->getBody()->getContents();
|
||||
|
||||
if (false !== stripos($contentType, 'json') || stripos($contentType, 'javascript')) {
|
||||
return json_decode($contents, true);
|
||||
} elseif (false !== stripos($contentType, 'xml')) {
|
||||
return json_decode(json_encode(simplexml_load_string($contents)), true);
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
}
|
10
vendor/php-di/invoker/README.md
vendored
10
vendor/php-di/invoker/README.md
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
Generic and extensible callable invoker.
|
||||
|
||||
[](https://travis-ci.org/PHP-DI/Invoker)
|
||||
[](https://github.com/PHP-DI/Invoker/actions/workflows/ci.yml)
|
||||
[](https://packagist.org/packages/PHP-DI/invoker)
|
||||
[](https://packagist.org/packages/php-di/invoker)
|
||||
|
||||
@ -12,7 +12,7 @@ Who doesn't need an over-engineered `call_user_func()`?
|
||||
|
||||
### Named parameters
|
||||
|
||||
Does this [Silex](http://silex.sensiolabs.org) example look familiar:
|
||||
Does this [Silex](https://github.com/silexphp/Silex#readme) example look familiar:
|
||||
|
||||
```php
|
||||
$app->get('/project/{project}/issue/{issue}', function ($project, $issue) {
|
||||
@ -28,7 +28,7 @@ $app->command('greet [name] [--yell]', function ($name, $yell) {
|
||||
});
|
||||
```
|
||||
|
||||
Same pattern in [Slim](http://www.slimframework.com):
|
||||
Same pattern in [Slim](https://www.slimframework.com):
|
||||
|
||||
```php
|
||||
$app->get('/hello/:name', function ($name) {
|
||||
@ -66,7 +66,7 @@ $app->command('greet [name]', function ($name, OutputInterface $output) {
|
||||
});
|
||||
```
|
||||
|
||||
[PHP-DI](http://php-di.org/doc/container.html) provides a way to invoke a callable and resolve all dependencies from the container using type-hints:
|
||||
[PHP-DI](https://php-di.org/doc/container.html) provides a way to invoke a callable and resolve all dependencies from the container using type-hints:
|
||||
|
||||
```php
|
||||
$container->call(function (Logger $logger, EntityManager $em) {
|
||||
@ -230,4 +230,4 @@ $invoker->call('WelcomeController::home');
|
||||
|
||||
That feature can be used as the base building block for a framework's dispatcher.
|
||||
|
||||
Again, any [PSR-11](http://www.php-fig.org/psr/psr-11/) compliant container can be provided.
|
||||
Again, any [PSR-11](https://www.php-fig.org/psr/psr-11/) compliant container can be provided.
|
||||
|
4
vendor/phpmailer/phpmailer/README.md
vendored
4
vendor/phpmailer/phpmailer/README.md
vendored
@ -47,7 +47,7 @@ This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lg
|
||||
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
|
||||
|
||||
```json
|
||||
"phpmailer/phpmailer": "^6.8.0"
|
||||
"phpmailer/phpmailer": "^6.8.1"
|
||||
```
|
||||
|
||||
or run
|
||||
@ -150,7 +150,7 @@ PHPMailer defaults to English, but in the [language](https://github.com/PHPMaile
|
||||
$mail->setLanguage('fr', '/optional/path/to/language/directory/');
|
||||
```
|
||||
|
||||
We welcome corrections and new languages – if you're looking for corrections, run the [PHPMailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/PHPMailerLangTest.php) script in the tests folder and it will show any missing translations.
|
||||
We welcome corrections and new languages – if you're looking for corrections, run the [Language/TranslationCompletenessTest.php](https://github.com/PHPMailer/PHPMailer/blob/master/test/Language/TranslationCompletenessTest.php) script in the tests folder and it will show any missing translations.
|
||||
|
||||
## Documentation
|
||||
Start reading at the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, head for [the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting) as it's frequently updated.
|
||||
|
2
vendor/phpmailer/phpmailer/VERSION
vendored
2
vendor/phpmailer/phpmailer/VERSION
vendored
@ -1 +1 @@
|
||||
6.8.0
|
||||
6.8.1
|
4
vendor/phpmailer/phpmailer/composer.json
vendored
4
vendor/phpmailer/phpmailer/composer.json
vendored
@ -37,13 +37,13 @@
|
||||
"ext-hash": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
|
||||
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
||||
"phpcompatibility/php-compatibility": "^9.3.5",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"squizlabs/php_codesniffer": "^3.7.1",
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
"yoast/phpunit-polyfills": "^1.0.4"
|
||||
},
|
||||
"suggest": {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user