jwt, sms
This commit is contained in:
parent
7fe327b14e
commit
483e2759d1
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)
|
||||
{
|
||||
//先校验验证码
|
||||
|
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);
|
||||
}
|
||||
}
|
@ -16,17 +16,33 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.0.0",
|
||||
"topthink/framework": "^8.0.1",
|
||||
"topthink/think-orm": "^3.0",
|
||||
"php": ">=7.1.0",
|
||||
"topthink/framework": "^6.0.0",
|
||||
"topthink/think-orm": "^2.0",
|
||||
"topthink/think-multi-app": "^1.0",
|
||||
"topthink/think-view": "^2.0",
|
||||
"taoser/think-auth": "^1.0",
|
||||
"topthink/think-view": "^1.0",
|
||||
"topthink/think-captcha": "^3.0",
|
||||
"taoser/think-auth": "^2.0",
|
||||
"taoser/think-addons": "^2.0",
|
||||
"taoser/think-setarr": "^0.0.5",
|
||||
"phpmailer/phpmailer": "^6.8",
|
||||
"yzh52521/easyhttp": "^1.0"
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"taoser/think-addons": "^1.0",
|
||||
"liliuwei/thinkphp-social": "^1.3",
|
||||
"taoser/think-setarr": "^0.0.3",
|
||||
"topthink/think-migration": "^3.0",
|
||||
"workerman/workerman": "^4.0",
|
||||
"endroid/qr-code": "^4.4",
|
||||
"yansongda/pay": "~3.1.0",
|
||||
"guzzlehttp/guzzle": "7.0",
|
||||
"php-di/php-di": "^6.4",
|
||||
"workerman/phpsocket.io": "^1.1",
|
||||
"jaeger/querylist": "^4.2",
|
||||
"symfony/var-exporter": "^5.4",
|
||||
"yzh52521/easyhttp": "^1.0",
|
||||
"firebase/php-jwt": "^6.8",
|
||||
"overtrue/easy-sms": "^2.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^4.2",
|
||||
"topthink/think-trace":"^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
2404
composer.lock
generated
2404
composer.lock
generated
File diff suppressed because it is too large
Load Diff
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);
|
||||
|
12
vendor/composer/autoload_files.php
vendored
12
vendor/composer/autoload_files.php
vendored
@ -9,9 +9,19 @@ 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',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.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',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',
|
||||
'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',
|
||||
'6b998e7ad3182c0d21d23780badfa07b' => $vendorDir . '/yansongda/supports/src/Functions.php',
|
||||
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
|
||||
'223fa6f9b46fbe5d6b44c5ff847bfceb' => $vendorDir . '/taoser/think-addons/src/helper.php',
|
||||
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
|
||||
'8c783b3a3de2f6d9177022b5ccdcc841' => $vendorDir . '/yansongda/pay/src/Functions.php',
|
||||
'd421242fd42b2ea6cd13f802bcf18a6e' => $baseDir . '/extend/taoler/com/form.php',
|
||||
);
|
||||
|
39
vendor/composer/autoload_psr4.php
vendored
39
vendor/composer/autoload_psr4.php
vendored
@ -8,20 +8,53 @@ $baseDir = dirname($vendorDir);
|
||||
return array(
|
||||
'yzh52521\\EasyHttp\\' => array($vendorDir . '/yzh52521/easyhttp/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-template/src', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/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'),
|
||||
'liliuwei\\social\\' => array($vendorDir . '/liliuwei/thinkphp-social/src'),
|
||||
'app\\' => array($baseDir . '/app'),
|
||||
'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'),
|
||||
'Yansongda\\Pay\\' => array($vendorDir . '/yansongda/pay/src'),
|
||||
'Workerman\\' => array($vendorDir . '/workerman/workerman'),
|
||||
'Tightenco\\Collect\\' => array($vendorDir . '/tightenco/collect/src/Collect'),
|
||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'),
|
||||
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
|
||||
'QL\\' => array($vendorDir . '/jaeger/querylist/src'),
|
||||
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
|
||||
'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'),
|
||||
'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'),
|
||||
'Jaeger\\' => array($vendorDir . '/jaeger/g-http/src'),
|
||||
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
|
||||
'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'),
|
||||
'Channel\\' => array($vendorDir . '/workerman/channel/src'),
|
||||
'Cache\\TagInterop\\' => array($vendorDir . '/cache/tag-interop'),
|
||||
'Cache\\Adapter\\Filesystem\\' => array($vendorDir . '/cache/filesystem-adapter'),
|
||||
'Cache\\Adapter\\Common\\' => array($vendorDir . '/cache/adapter-common'),
|
||||
'BaconQrCode\\' => array($vendorDir . '/bacon/bacon-qr-code/src'),
|
||||
);
|
||||
|
254
vendor/composer/autoload_static.php
vendored
254
vendor/composer/autoload_static.php
vendored
@ -4,16 +4,26 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
{
|
||||
public static $files = array (
|
||||
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
|
||||
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.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',
|
||||
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',
|
||||
'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',
|
||||
'6b998e7ad3182c0d21d23780badfa07b' => __DIR__ . '/..' . '/yansongda/supports/src/Functions.php',
|
||||
'b33e3d135e5d9e47d845c576147bda89' => __DIR__ . '/..' . '/php-di/php-di/src/functions.php',
|
||||
'223fa6f9b46fbe5d6b44c5ff847bfceb' => __DIR__ . '/..' . '/taoser/think-addons/src/helper.php',
|
||||
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
|
||||
'8c783b3a3de2f6d9177022b5ccdcc841' => __DIR__ . '/..' . '/yansongda/pay/src/Functions.php',
|
||||
'd421242fd42b2ea6cd13f802bcf18a6e' => __DIR__ . '/../..' . '/extend/taoler/com/form.php',
|
||||
);
|
||||
|
||||
@ -25,19 +35,47 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
't' =>
|
||||
array (
|
||||
'think\\view\\driver\\' => 18,
|
||||
'think\\trace\\' => 12,
|
||||
'think\\migration\\' => 16,
|
||||
'think\\composer\\' => 15,
|
||||
'think\\captcha\\' => 14,
|
||||
'think\\app\\' => 10,
|
||||
'think\\' => 6,
|
||||
'taoser\\think\\' => 13,
|
||||
'taoser\\' => 7,
|
||||
),
|
||||
'l' =>
|
||||
array (
|
||||
'liliuwei\\social\\' => 16,
|
||||
),
|
||||
'a' =>
|
||||
array (
|
||||
'app\\' => 4,
|
||||
),
|
||||
'Y' =>
|
||||
array (
|
||||
'Yansongda\\Supports\\' => 19,
|
||||
'Yansongda\\Pay\\' => 14,
|
||||
),
|
||||
'W' =>
|
||||
array (
|
||||
'Workerman\\' => 10,
|
||||
),
|
||||
'T' =>
|
||||
array (
|
||||
'Tightenco\\Collect\\' => 18,
|
||||
),
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||
'Symfony\\Polyfill\\Php72\\' => 23,
|
||||
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||
'Symfony\\Component\\VarExporter\\' => 30,
|
||||
'Symfony\\Component\\VarDumper\\' => 28,
|
||||
),
|
||||
'Q' =>
|
||||
array (
|
||||
'QL\\' => 3,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
@ -45,15 +83,62 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
'Psr\\Http\\Client\\' => 16,
|
||||
'Psr\\EventDispatcher\\' => 20,
|
||||
'Psr\\Container\\' => 14,
|
||||
'Psr\\Cache\\' => 10,
|
||||
'PhpDocReader\\' => 13,
|
||||
'Phinx\\' => 6,
|
||||
'PHPSocketIO\\' => 12,
|
||||
'PHPMailer\\PHPMailer\\' => 20,
|
||||
),
|
||||
'O' =>
|
||||
array (
|
||||
'Overtrue\\EasySms\\' => 17,
|
||||
),
|
||||
'L' =>
|
||||
array (
|
||||
'League\\MimeTypeDetection\\' => 25,
|
||||
'League\\Flysystem\\' => 17,
|
||||
'Laravel\\SerializableClosure\\' => 28,
|
||||
),
|
||||
'J' =>
|
||||
array (
|
||||
'Jaeger\\' => 7,
|
||||
),
|
||||
'I' =>
|
||||
array (
|
||||
'Invoker\\' => 8,
|
||||
),
|
||||
'G' =>
|
||||
array (
|
||||
'GuzzleHttp\\Psr7\\' => 16,
|
||||
'GuzzleHttp\\Promise\\' => 19,
|
||||
'GuzzleHttp\\' => 11,
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'Firebase\\JWT\\' => 13,
|
||||
),
|
||||
'E' =>
|
||||
array (
|
||||
'Endroid\\QrCode\\' => 15,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'DI\\' => 3,
|
||||
'DASPRiD\\Enum\\' => 13,
|
||||
),
|
||||
'C' =>
|
||||
array (
|
||||
'Channel\\' => 8,
|
||||
'Cache\\TagInterop\\' => 17,
|
||||
'Cache\\Adapter\\Filesystem\\' => 25,
|
||||
'Cache\\Adapter\\Common\\' => 21,
|
||||
),
|
||||
'B' =>
|
||||
array (
|
||||
'BaconQrCode\\' => 12,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
@ -65,6 +150,18 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-view/src',
|
||||
),
|
||||
'think\\trace\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-trace/src',
|
||||
),
|
||||
'think\\migration\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-migration/src',
|
||||
),
|
||||
'think\\composer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-installer/src',
|
||||
),
|
||||
'think\\captcha\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-captcha/src',
|
||||
@ -75,10 +172,10 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
),
|
||||
'think\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-template/src',
|
||||
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
||||
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
||||
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
|
||||
3 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
||||
3 => __DIR__ . '/..' . '/topthink/think-template/src',
|
||||
),
|
||||
'taoser\\think\\' =>
|
||||
array (
|
||||
@ -89,39 +186,122 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
0 => __DIR__ . '/..' . '/taoser/think-addons/src',
|
||||
1 => __DIR__ . '/..' . '/taoser/think-setarr/src',
|
||||
),
|
||||
'liliuwei\\social\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/liliuwei/thinkphp-social/src',
|
||||
),
|
||||
'app\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/app',
|
||||
),
|
||||
'Yansongda\\Supports\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/yansongda/supports/src',
|
||||
),
|
||||
'Yansongda\\Pay\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/yansongda/pay/src',
|
||||
),
|
||||
'Workerman\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/workerman/workerman',
|
||||
),
|
||||
'Tightenco\\Collect\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/tightenco/collect/src/Collect',
|
||||
),
|
||||
'Symfony\\Polyfill\\Php80\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||
),
|
||||
'Symfony\\Polyfill\\Php72\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
|
||||
),
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||
),
|
||||
'Symfony\\Component\\VarExporter\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/var-exporter',
|
||||
),
|
||||
'Symfony\\Component\\VarDumper\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/var-dumper',
|
||||
),
|
||||
'QL\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/jaeger/querylist/src',
|
||||
),
|
||||
'Psr\\SimpleCache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/src',
|
||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||
),
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
1 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||
),
|
||||
'Psr\\Http\\Client\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
||||
),
|
||||
'Psr\\EventDispatcher\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
),
|
||||
'Psr\\Cache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/cache/src',
|
||||
),
|
||||
'PhpDocReader\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-di/phpdoc-reader/src/PhpDocReader',
|
||||
),
|
||||
'Phinx\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-migration/phinx/src/Phinx',
|
||||
),
|
||||
'PHPSocketIO\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/workerman/phpsocket.io/src',
|
||||
),
|
||||
'PHPMailer\\PHPMailer\\' =>
|
||||
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',
|
||||
),
|
||||
'League\\Flysystem\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/flysystem/src',
|
||||
),
|
||||
'Laravel\\SerializableClosure\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/laravel/serializable-closure/src',
|
||||
),
|
||||
'Jaeger\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/jaeger/g-http/src',
|
||||
),
|
||||
'Invoker\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-di/invoker/src',
|
||||
),
|
||||
'GuzzleHttp\\Psr7\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
||||
@ -134,6 +314,42 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
||||
),
|
||||
'Firebase\\JWT\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
|
||||
),
|
||||
'Endroid\\QrCode\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/endroid/qr-code/src',
|
||||
),
|
||||
'DI\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-di/php-di/src',
|
||||
),
|
||||
'DASPRiD\\Enum\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/dasprid/enum/src',
|
||||
),
|
||||
'Channel\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/workerman/channel/src',
|
||||
),
|
||||
'Cache\\TagInterop\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/cache/tag-interop',
|
||||
),
|
||||
'Cache\\Adapter\\Filesystem\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/cache/filesystem-adapter',
|
||||
),
|
||||
'Cache\\Adapter\\Common\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/cache/adapter-common',
|
||||
),
|
||||
'BaconQrCode\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/bacon/bacon-qr-code/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $fallbackDirsPsr0 = array (
|
||||
@ -141,16 +357,34 @@ class ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Callback' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'CallbackBody' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'CallbackParam' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'CallbackParameterToReference' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'CallbackReturnReference' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'CallbackReturnValue' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'DOMDocumentWrapper' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'DOMEvent' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'ICallbackNamed' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
'phpQuery' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'phpQueryEvents' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'phpQueryObject' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
'phpQueryPlugins' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0::$prefixDirsPsr4;
|
||||
$loader->fallbackDirsPsr0 = ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0::$fallbackDirsPsr0;
|
||||
$loader->classMap = ComposerStaticInitbd5d3d6d2646baf3ad0aa6db972a53b0::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$prefixDirsPsr4;
|
||||
$loader->fallbackDirsPsr0 = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$fallbackDirsPsr0;
|
||||
$loader->classMap = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
2710
vendor/composer/installed.json
vendored
2710
vendor/composer/installed.json
vendored
File diff suppressed because it is too large
Load Diff
427
vendor/composer/installed.php
vendored
427
vendor/composer/installed.php
vendored
@ -1,42 +1,204 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'taoser/taoler',
|
||||
'pretty_version' => '3.0.x-dev',
|
||||
'version' => '3.0.9999999.9999999-dev',
|
||||
'reference' => '0c2f0154a81dd0a6268da627982d1bf41c0ef231',
|
||||
'pretty_version' => '2.3.10.x-dev',
|
||||
'version' => '2.3.10.9999999-dev',
|
||||
'reference' => 'ae0b97d6173365b32d51adc748c7bf4317edd571',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'bacon/bacon-qr-code' => array(
|
||||
'pretty_version' => '2.0.8',
|
||||
'version' => '2.0.8.0',
|
||||
'reference' => '8674e51bb65af933a5ffaf1c308a660387c35c22',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'cache/adapter-common' => array(
|
||||
'pretty_version' => '1.3.0',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => '8788309be72aa7be69b88cdc0687549c74a7d479',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../cache/adapter-common',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'cache/filesystem-adapter' => array(
|
||||
'pretty_version' => '1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => 'f1faaae40aaa696ef899cef6f6888aedb90b419b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../cache/filesystem-adapter',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'cache/tag-interop' => array(
|
||||
'pretty_version' => '1.1.0',
|
||||
'version' => '1.1.0.0',
|
||||
'reference' => 'b062b1d735357da50edf8387f7a8696f3027d328',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../cache/tag-interop',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dasprid/enum' => array(
|
||||
'pretty_version' => '1.0.5',
|
||||
'version' => '1.0.5.0',
|
||||
'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dasprid/enum',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'endroid/qr-code' => array(
|
||||
'pretty_version' => '4.6.1',
|
||||
'version' => '4.6.1.0',
|
||||
'reference' => 'a75c913b0e4d6ad275e49a2c1de1cacffc6c2184',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../endroid/qr-code',
|
||||
'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.7.0',
|
||||
'version' => '7.7.0.0',
|
||||
'reference' => 'fb7566caccf22d74d1ab270de3551f72a58399f5',
|
||||
'pretty_version' => '7.0.0',
|
||||
'version' => '7.0.0.0',
|
||||
'reference' => '414c24961042f6616fb43e23fa69a785f9fc053e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/promises' => array(
|
||||
'pretty_version' => '2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => '3a494dc7dc1d7d12e511890177ae2d0e6c107da6',
|
||||
'pretty_version' => '1.5.3',
|
||||
'version' => '1.5.3.0',
|
||||
'reference' => '67ab6e18aaa14d753cc148911d273f6e6cb6721e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/psr7' => array(
|
||||
'pretty_version' => '2.5.0',
|
||||
'version' => '2.5.0.0',
|
||||
'reference' => 'b635f279edd83fc275f822a1188157ffea568ff6',
|
||||
'pretty_version' => '1.9.1',
|
||||
'version' => '1.9.1.0',
|
||||
'reference' => 'e4490cabc77465aaee90b20cfc9a770f8c04be6b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jaeger/g-http' => array(
|
||||
'pretty_version' => 'V1.7.2',
|
||||
'version' => '1.7.2.0',
|
||||
'reference' => '82585ddd5e2c6651e37ab1d8166efcdbb6b293d4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jaeger/g-http',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jaeger/phpquery-single' => array(
|
||||
'pretty_version' => '1.1.1',
|
||||
'version' => '1.1.1.0',
|
||||
'reference' => '39a650ade692a6b480c22220dce0c198d6a946fb',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jaeger/phpquery-single',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'jaeger/querylist' => array(
|
||||
'pretty_version' => 'V4.2.8',
|
||||
'version' => '4.2.8.0',
|
||||
'reference' => '39dc0ca9c668bec7a793e20472ccd7d26ef89ea4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../jaeger/querylist',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'laravel/serializable-closure' => array(
|
||||
'pretty_version' => 'v1.3.1',
|
||||
'version' => '1.3.1.0',
|
||||
'reference' => 'e5a3057a5591e1cfe8183034b0203921abe2c902',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../laravel/serializable-closure',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/flysystem' => array(
|
||||
'pretty_version' => '1.1.10',
|
||||
'version' => '1.1.10.0',
|
||||
'reference' => '3239285c825c152bcc315fe0e87d6b55f5972ed1',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/flysystem',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/mime-type-detection' => array(
|
||||
'pretty_version' => '1.13.0',
|
||||
'version' => '1.13.0.0',
|
||||
'reference' => 'a6dfb1194a2946fcdc1f38219445234f65b35c96',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/mime-type-detection',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'liliuwei/thinkphp-social' => array(
|
||||
'pretty_version' => 'v1.3',
|
||||
'version' => '1.3.0.0',
|
||||
'reference' => '2067fc2c2cc3b3d109602bc19c3e5a99c5f4c970',
|
||||
'type' => 'think-extend',
|
||||
'install_path' => __DIR__ . '/../liliuwei/thinkphp-social',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'overtrue/easy-sms' => array(
|
||||
'pretty_version' => '2.5.0',
|
||||
'version' => '2.5.0.0',
|
||||
'reference' => '81d4deec69bbb6de6e5fdd7ab90cc933bd3e3046',
|
||||
'type' => 'library',
|
||||
'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',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-di/invoker',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'php-di/php-di' => array(
|
||||
'pretty_version' => '6.4.0',
|
||||
'version' => '6.4.0.0',
|
||||
'reference' => 'ae0f1b3b03d8b29dff81747063cbfd6276246cc4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-di/php-di',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'php-di/phpdoc-reader' => array(
|
||||
'pretty_version' => '2.2.1',
|
||||
'version' => '2.2.1.0',
|
||||
'reference' => '66daff34cbd2627740ffec9469ffbac9f8c8185c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../php-di/phpdoc-reader',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpmailer/phpmailer' => array(
|
||||
'pretty_version' => 'v6.8.0',
|
||||
'version' => '6.8.0.0',
|
||||
@ -46,15 +208,45 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/cache' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/cache',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/cache-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '^1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
|
||||
'pretty_version' => '1.1.2',
|
||||
'version' => '1.1.2.0',
|
||||
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/container',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/container-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '^1.0',
|
||||
),
|
||||
),
|
||||
'psr/event-dispatcher' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/event-dispatcher',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client' => array(
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
@ -70,21 +262,6 @@
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-factory' => array(
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-factory-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.1',
|
||||
'version' => '1.1.0.0',
|
||||
@ -101,23 +278,29 @@
|
||||
),
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/simple-cache' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '764e0b3939f5ca87cb904f570ef9be2d78a07865',
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/simple-cache',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/simple-cache-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '^1.0',
|
||||
),
|
||||
),
|
||||
'ralouphie/getallheaders' => array(
|
||||
'pretty_version' => '3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
@ -127,64 +310,100 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => 'v3.3.0',
|
||||
'version' => '3.3.0.0',
|
||||
'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf',
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '42292d99c55abe617799667f454222c54c60e229',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php72' => array(
|
||||
'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.28.0',
|
||||
'version' => '1.28.0.0',
|
||||
'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/var-dumper' => array(
|
||||
'pretty_version' => 'v4.4.47',
|
||||
'version' => '4.4.47.0',
|
||||
'reference' => '1069c7a3fca74578022fab6f81643248d02f8e63',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/var-exporter' => array(
|
||||
'pretty_version' => 'v6.3.2',
|
||||
'version' => '6.3.2.0',
|
||||
'reference' => '3400949782c0cb5b3e73aa64cfd71dde000beccc',
|
||||
'pretty_version' => 'v5.4.26',
|
||||
'version' => '5.4.26.0',
|
||||
'reference' => '11401fe94f960249b3c63a488c63ba73091c1e4a',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/var-exporter',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'taoser/taoler' => array(
|
||||
'pretty_version' => '3.0.x-dev',
|
||||
'version' => '3.0.9999999.9999999-dev',
|
||||
'reference' => '0c2f0154a81dd0a6268da627982d1bf41c0ef231',
|
||||
'pretty_version' => '2.3.10.x-dev',
|
||||
'version' => '2.3.10.9999999-dev',
|
||||
'reference' => 'ae0b97d6173365b32d51adc748c7bf4317edd571',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'taoser/think-addons' => array(
|
||||
'pretty_version' => 'v2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => 'ef97225aca7f0ec1da275c4ae025686899a91ad2',
|
||||
'pretty_version' => 'v1.0.9',
|
||||
'version' => '1.0.9.0',
|
||||
'reference' => '00112adf200b897deecbd1bbabc33ad22377b008',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../taoser/think-addons',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'taoser/think-auth' => array(
|
||||
'pretty_version' => 'v2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => 'db57156530dd8e2c020afc6e64abc1ad64e9e06c',
|
||||
'pretty_version' => 'v1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => 'd3aa853b7d2a34624bcc566150105f2815e68ad0',
|
||||
'type' => 'think-extend',
|
||||
'install_path' => __DIR__ . '/../taoser/think-auth',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'taoser/think-setarr' => array(
|
||||
'pretty_version' => 'v0.0.5',
|
||||
'version' => '0.0.5.0',
|
||||
'reference' => 'e436e2d855c2014dae19cbdecfd3d6c57c04aca8',
|
||||
'pretty_version' => 'v0.0.3',
|
||||
'version' => '0.0.3.0',
|
||||
'reference' => '6651c31ef42417a6294ef08e6fb970917b7e7f86',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../taoser/think-setarr',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tightenco/collect' => array(
|
||||
'pretty_version' => 'v8.83.27',
|
||||
'version' => '8.83.27.0',
|
||||
'reference' => '07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../tightenco/collect',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/framework' => array(
|
||||
'pretty_version' => 'v8.0.1',
|
||||
'version' => '8.0.1.0',
|
||||
'reference' => '23101f0ad7581de32442553e045cffd7686a337b',
|
||||
'pretty_version' => 'v6.1.4',
|
||||
'version' => '6.1.4.0',
|
||||
'reference' => '66eb9cf4d627df12911344cd328faf9bb596bf2c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/framework',
|
||||
'aliases' => array(),
|
||||
@ -208,6 +427,24 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-installer' => array(
|
||||
'pretty_version' => 'v2.0.5',
|
||||
'version' => '2.0.5.0',
|
||||
'reference' => '38ba647706e35d6704b5d370c06f8a160b635f88',
|
||||
'type' => 'composer-plugin',
|
||||
'install_path' => __DIR__ . '/../topthink/think-installer',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-migration' => array(
|
||||
'pretty_version' => 'v3.0.6',
|
||||
'version' => '3.0.6.0',
|
||||
'reference' => '82c4226cb14f973b9377c7fc6e89c525cbb8b030',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-migration',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-multi-app' => array(
|
||||
'pretty_version' => 'v1.0.17',
|
||||
'version' => '1.0.17.0',
|
||||
@ -218,32 +455,86 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-orm' => array(
|
||||
'pretty_version' => 'v3.0.11',
|
||||
'version' => '3.0.11.0',
|
||||
'reference' => '38a6da3ae03bcae4ea2f484a4cf05687a88a5488',
|
||||
'pretty_version' => 'v2.0.61',
|
||||
'version' => '2.0.61.0',
|
||||
'reference' => '10528ebf4a5106b19c3bac9c6deae7a67ff49de6',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-orm',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-template' => array(
|
||||
'pretty_version' => 'v3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '4352d2cf627abfb8b49f830686c25c02f59c23f2',
|
||||
'pretty_version' => 'v2.0.9',
|
||||
'version' => '2.0.9.0',
|
||||
'reference' => '6d25642ae0e306166742fd7073dc7a159e18073c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-template',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-trace' => array(
|
||||
'pretty_version' => 'v1.6',
|
||||
'version' => '1.6.0.0',
|
||||
'reference' => '136cd5d97e8bdb780e4b5c1637c588ed7ca3e142',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-trace',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
'topthink/think-view' => array(
|
||||
'pretty_version' => 'v2.0.0',
|
||||
'version' => '2.0.0.0',
|
||||
'reference' => 'd2a076011c96d2edd8016703a827fb54b2683c62',
|
||||
'pretty_version' => 'v1.0.14',
|
||||
'version' => '1.0.14.0',
|
||||
'reference' => 'edce0ae2c9551ab65f9e94a222604b0dead3576d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-view',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'workerman/channel' => array(
|
||||
'pretty_version' => 'v1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => 'fbfb81c7ebc5858c4053f226cbb5d15fe670ff6e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../workerman/channel',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'workerman/phpsocket.io' => array(
|
||||
'pretty_version' => 'v1.1.18',
|
||||
'version' => '1.1.18.0',
|
||||
'reference' => 'b89b3f2ed44f6f79fd9895e2d198b52b3fb4783b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../workerman/phpsocket.io',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'workerman/workerman' => array(
|
||||
'pretty_version' => 'v4.1.13',
|
||||
'version' => '4.1.13.0',
|
||||
'reference' => '807780ff672775fcd08f89e573a2824e939021ce',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../workerman/workerman',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yansongda/pay' => array(
|
||||
'pretty_version' => 'v3.1.12',
|
||||
'version' => '3.1.12.0',
|
||||
'reference' => '7ff004f05f9d6e288ff9b4deef585d30395f37f2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../yansongda/pay',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yansongda/supports' => array(
|
||||
'pretty_version' => 'v3.2.5',
|
||||
'version' => '3.2.5.0',
|
||||
'reference' => 'c3f736efe169696cef94730976e604a61c345b5c',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../yansongda/supports',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yzh52521/easyhttp' => array(
|
||||
'pretty_version' => 'v1.0.7',
|
||||
'version' => '1.0.7.0',
|
||||
|
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.
|
30
vendor/firebase/php-jwt/LICENSE
vendored
Normal file
30
vendor/firebase/php-jwt/LICENSE
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
Copyright (c) 2011, Neuman Vong
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
424
vendor/firebase/php-jwt/README.md
vendored
Normal file
424
vendor/firebase/php-jwt/README.md
vendored
Normal file
@ -0,0 +1,424 @@
|
||||
![Build Status](https://github.com/firebase/php-jwt/actions/workflows/tests.yml/badge.svg)
|
||||
[![Latest Stable Version](https://poser.pugx.org/firebase/php-jwt/v/stable)](https://packagist.org/packages/firebase/php-jwt)
|
||||
[![Total Downloads](https://poser.pugx.org/firebase/php-jwt/downloads)](https://packagist.org/packages/firebase/php-jwt)
|
||||
[![License](https://poser.pugx.org/firebase/php-jwt/license)](https://packagist.org/packages/firebase/php-jwt)
|
||||
|
||||
PHP-JWT
|
||||
=======
|
||||
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to [RFC 7519](https://tools.ietf.org/html/rfc7519).
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Use composer to manage your dependencies and download PHP-JWT:
|
||||
|
||||
```bash
|
||||
composer require firebase/php-jwt
|
||||
```
|
||||
|
||||
Optionally, install the `paragonie/sodium_compat` package from composer if your
|
||||
php is < 7.2 or does not have libsodium installed:
|
||||
|
||||
```bash
|
||||
composer require paragonie/sodium_compat
|
||||
```
|
||||
|
||||
Example
|
||||
-------
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
$key = 'example_key';
|
||||
$payload = [
|
||||
'iss' => 'http://example.org',
|
||||
'aud' => 'http://example.com',
|
||||
'iat' => 1356999524,
|
||||
'nbf' => 1357000000
|
||||
];
|
||||
|
||||
/**
|
||||
* IMPORTANT:
|
||||
* You must specify supported algorithms for your application. See
|
||||
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
|
||||
* for a list of spec-compliant algorithms.
|
||||
*/
|
||||
$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:
|
||||
*/
|
||||
|
||||
$decoded_array = (array) $decoded;
|
||||
|
||||
/**
|
||||
* You can add a leeway to account for when there is a clock skew times between
|
||||
* the signing and verifying servers. It is recommended that this leeway should
|
||||
* not be bigger than a few minutes.
|
||||
*
|
||||
* Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
|
||||
*/
|
||||
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
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
$privateKey = <<<EOD
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
|
||||
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
|
||||
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
|
||||
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
|
||||
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
|
||||
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
|
||||
wQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
EOD;
|
||||
|
||||
$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";
|
||||
|
||||
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
|
||||
|
||||
/*
|
||||
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:
|
||||
*/
|
||||
|
||||
$decoded_array = (array) $decoded;
|
||||
echo "Decode:\n" . print_r($decoded_array, true) . "\n";
|
||||
```
|
||||
|
||||
Example with a passphrase
|
||||
-------------------------
|
||||
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
// Your passphrase
|
||||
$passphrase = '[YOUR_PASSPHRASE]';
|
||||
|
||||
// Your private key file with passphrase
|
||||
// Can be generated with "ssh-keygen -t rsa -m pem"
|
||||
$privateKeyFile = '/path/to/key-with-passphrase.pem';
|
||||
|
||||
// Create a private key of type "resource"
|
||||
$privateKey = openssl_pkey_get_private(
|
||||
file_get_contents($privateKeyFile),
|
||||
$passphrase
|
||||
);
|
||||
|
||||
$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";
|
||||
|
||||
// Get public key from the private key, or pull from from a file.
|
||||
$publicKey = openssl_pkey_get_details($privateKey)['key'];
|
||||
|
||||
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
|
||||
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
|
||||
```
|
||||
|
||||
Example with EdDSA (libsodium and Ed25519 signature)
|
||||
----------------------------
|
||||
```php
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
|
||||
// Public and private keys are expected to be Base64 encoded. The last
|
||||
// non-empty line is used so that keys can be generated with
|
||||
// sodium_crypto_sign_keypair(). The secret keys generated by other tools may
|
||||
// need to be adjusted to match the input expected by libsodium.
|
||||
|
||||
$keyPair = sodium_crypto_sign_keypair();
|
||||
|
||||
$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
|
||||
|
||||
$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
|
||||
|
||||
$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";
|
||||
|
||||
$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
|
||||
----------
|
||||
|
||||
```php
|
||||
use Firebase\JWT\JWK;
|
||||
use Firebase\JWT\JWT;
|
||||
|
||||
// Set of keys. The "keys" key is required. For example, the JSON response to
|
||||
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
|
||||
$jwks = ['keys' => []];
|
||||
|
||||
// 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));
|
||||
```
|
||||
|
||||
Using Cached Key Sets
|
||||
---------------------
|
||||
|
||||
The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
|
||||
This has the following advantages:
|
||||
|
||||
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.
|
||||
|
||||
```php
|
||||
use Firebase\JWT\CachedKeySet;
|
||||
use Firebase\JWT\JWT;
|
||||
|
||||
// The URI for the JWKS you wish to cache the results from
|
||||
$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
|
||||
|
||||
// Create an HTTP client (can be any PSR-7 compatible HTTP client)
|
||||
$httpClient = new GuzzleHttp\Client();
|
||||
|
||||
// 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
|
||||
-----
|
||||
Run the tests using phpunit:
|
||||
|
||||
```bash
|
||||
$ pear install PHPUnit
|
||||
$ phpunit --configuration phpunit.xml.dist
|
||||
PHPUnit 3.7.10 by Sebastian Bergmann.
|
||||
.....
|
||||
Time: 0 seconds, Memory: 2.50Mb
|
||||
OK (5 tests, 5 assertions)
|
||||
```
|
||||
|
||||
New Lines in private keys
|
||||
-----
|
||||
|
||||
If your private key contains `\n` characters, be sure to wrap it in double quotes `""`
|
||||
and not single quotes `''` in order to properly interpret the escaped characters.
|
||||
|
||||
License
|
||||
-------
|
||||
[3-Clause BSD](http://opensource.org/licenses/BSD-3-Clause).
|
42
vendor/firebase/php-jwt/composer.json
vendored
Normal file
42
vendor/firebase/php-jwt/composer.json
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"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": [
|
||||
"php",
|
||||
"jwt"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Neuman Vong",
|
||||
"email": "neuman+pear@twilio.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Anant Narayanan",
|
||||
"email": "anant@php.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"require": {
|
||||
"php": "^7.4||^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
|
||||
"ext-sodium": "Support EdDSA (Ed25519) signatures"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
7
vendor/firebase/php-jwt/src/BeforeValidException.php
vendored
Normal file
7
vendor/firebase/php-jwt/src/BeforeValidException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
class BeforeValidException extends \UnexpectedValueException
|
||||
{
|
||||
}
|
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;
|
||||
}
|
||||
}
|
||||
}
|
7
vendor/firebase/php-jwt/src/ExpiredException.php
vendored
Normal file
7
vendor/firebase/php-jwt/src/ExpiredException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
class ExpiredException extends \UnexpectedValueException
|
||||
{
|
||||
}
|
349
vendor/firebase/php-jwt/src/JWK.php
vendored
Normal file
349
vendor/firebase/php-jwt/src/JWK.php
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
use DomainException;
|
||||
use InvalidArgumentException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* JSON Web Key implementation, based on this spec:
|
||||
* https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Authentication
|
||||
* @package Authentication_JWT
|
||||
* @author Bui Sy Nguyen <nguyenbs@gmail.com>
|
||||
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
|
||||
* @link https://github.com/firebase/php-jwt
|
||||
*/
|
||||
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<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<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
|
||||
* @throws DomainException OpenSSL failure
|
||||
*
|
||||
* @uses parseKey
|
||||
*/
|
||||
public static function parseKeySet(array $jwks, string $defaultAlg = null): 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, $defaultAlg)) {
|
||||
$keys[(string) $kid] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === \count($keys)) {
|
||||
throw new UnexpectedValueException('No supported algorithms found in JWK Set');
|
||||
}
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a JWK key
|
||||
*
|
||||
* @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 Key The key object for the JWK
|
||||
*
|
||||
* @throws InvalidArgumentException Provided JWK is empty
|
||||
* @throws UnexpectedValueException Provided JWK was invalid
|
||||
* @throws DomainException OpenSSL failure
|
||||
*
|
||||
* @uses createPemFromModulusAndExponent
|
||||
*/
|
||||
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'])) {
|
||||
throw new UnexpectedValueException('RSA private keys are not supported');
|
||||
}
|
||||
if (!isset($jwk['n']) || !isset($jwk['e'])) {
|
||||
throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
|
||||
}
|
||||
|
||||
$pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
|
||||
$publicKey = \openssl_pkey_get_public($pem);
|
||||
if (false === $publicKey) {
|
||||
throw new DomainException(
|
||||
'OpenSSL error: ' . \openssl_error_string()
|
||||
);
|
||||
}
|
||||
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:
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a public key represented in PEM format from RSA modulus and exponent information
|
||||
*
|
||||
* @param string $n The RSA modulus encoded in Base64
|
||||
* @param string $e The RSA exponent encoded in Base64
|
||||
*
|
||||
* @return string The RSA public key represented in PEM format
|
||||
*
|
||||
* @uses encodeLength
|
||||
*/
|
||||
private static function createPemFromModulusAndExponent(
|
||||
string $n,
|
||||
string $e
|
||||
): string {
|
||||
$mod = JWT::urlsafeB64Decode($n);
|
||||
$exp = JWT::urlsafeB64Decode($e);
|
||||
|
||||
$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($modulus) + \strlen($publicExponent)),
|
||||
$modulus,
|
||||
$publicExponent
|
||||
);
|
||||
|
||||
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
|
||||
$rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
||||
$rsaPublicKey = \chr(0) . $rsaPublicKey;
|
||||
$rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;
|
||||
|
||||
$rsaPublicKey = \pack(
|
||||
'Ca*a*',
|
||||
48,
|
||||
self::encodeLength(\strlen($rsaOID . $rsaPublicKey)),
|
||||
$rsaOID . $rsaPublicKey
|
||||
);
|
||||
|
||||
return "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
\chunk_split(\base64_encode($rsaPublicKey), 64) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
}
|
||||
|
||||
/**
|
||||
* DER-encode the length
|
||||
*
|
||||
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
|
||||
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
|
||||
*
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
private static function encodeLength(int $length): string
|
||||
{
|
||||
if ($length <= 0x7F) {
|
||||
return \chr($length);
|
||||
}
|
||||
|
||||
$temp = \ltrim(\pack('N', $length), \chr(0));
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
662
vendor/firebase/php-jwt/src/JWT.php
vendored
Normal file
662
vendor/firebase/php-jwt/src/JWT.php
vendored
Normal file
@ -0,0 +1,662 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
use ArrayAccess;
|
||||
use DateTime;
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use OpenSSLAsymmetricKey;
|
||||
use OpenSSLCertificate;
|
||||
use stdClass;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* JSON Web Token implementation, based on this spec:
|
||||
* https://tools.ietf.org/html/rfc7519
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Authentication
|
||||
* @package Authentication_JWT
|
||||
* @author Neuman Vong <neuman@twilio.com>
|
||||
* @author Anant Narayanan <anant@php.net>
|
||||
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
|
||||
* @link https://github.com/firebase/php-jwt
|
||||
*/
|
||||
class JWT
|
||||
{
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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|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 stdClass The JWT's payload as a PHP object
|
||||
*
|
||||
* @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'
|
||||
* @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
|
||||
* @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
|
||||
*
|
||||
* @uses jsonDecode
|
||||
* @uses urlsafeB64Decode
|
||||
*/
|
||||
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) {
|
||||
throw new UnexpectedValueException('Wrong number of segments');
|
||||
}
|
||||
list($headb64, $bodyb64, $cryptob64) = $tks;
|
||||
$headerRaw = static::urlsafeB64Decode($headb64);
|
||||
if (null === ($header = static::jsonDecode($headerRaw))) {
|
||||
throw new UnexpectedValueException('Invalid header encoding');
|
||||
}
|
||||
if ($headers !== null) {
|
||||
$headers = $header;
|
||||
}
|
||||
$payloadRaw = static::urlsafeB64Decode($bodyb64);
|
||||
if (null === ($payload = static::jsonDecode($payloadRaw))) {
|
||||
throw new UnexpectedValueException('Invalid claims 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');
|
||||
}
|
||||
if (empty(static::$supported_algs[$header->alg])) {
|
||||
throw new UnexpectedValueException('Algorithm not supported');
|
||||
}
|
||||
|
||||
$key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null);
|
||||
|
||||
// Check the algorithm
|
||||
if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) {
|
||||
// See issue #351
|
||||
throw new UnexpectedValueException('Incorrect key for this algorithm');
|
||||
}
|
||||
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 (!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) && floor($payload->nbf) > ($timestamp + static::$leeway)) {
|
||||
throw new BeforeValidException(
|
||||
'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->nbf) && isset($payload->iat) && floor($payload->iat) > ($timestamp + static::$leeway)) {
|
||||
throw new BeforeValidException(
|
||||
'Cannot handle token with iat prior to ' . \date(DateTime::ISO8601, (int) $payload->iat)
|
||||
);
|
||||
}
|
||||
|
||||
// Check if this token has expired.
|
||||
if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) {
|
||||
throw new ExpiredException('Expired token');
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts and signs a PHP array into a JWT string.
|
||||
*
|
||||
* @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(
|
||||
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 = [];
|
||||
$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);
|
||||
$segments[] = static::urlsafeB64Encode($signature);
|
||||
|
||||
return \implode('.', $segments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a string with a given key and algorithm.
|
||||
*
|
||||
* @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(
|
||||
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); // @phpstan-ignore-line
|
||||
if (!$success) {
|
||||
throw new DomainException('OpenSSL unable to sign data');
|
||||
}
|
||||
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')) {
|
||||
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((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|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(
|
||||
string $msg,
|
||||
string $signature,
|
||||
$keyMaterial,
|
||||
string $alg
|
||||
): bool {
|
||||
if (empty(static::$supported_algs[$alg])) {
|
||||
throw new DomainException('Algorithm not supported');
|
||||
}
|
||||
|
||||
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||
switch ($function) {
|
||||
case 'openssl':
|
||||
$success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line
|
||||
if ($success === 1) {
|
||||
return true;
|
||||
}
|
||||
if ($success === 0) {
|
||||
return false;
|
||||
}
|
||||
// returns 1 on success, 0 on failure, -1 on error.
|
||||
throw new DomainException(
|
||||
'OpenSSL error: ' . \openssl_error_string()
|
||||
);
|
||||
case 'sodium_crypto':
|
||||
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:
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a JSON string into a PHP object.
|
||||
*
|
||||
* @param string $input JSON string
|
||||
*
|
||||
* @return mixed The decoded JSON string
|
||||
*
|
||||
* @throws DomainException Provided string was invalid JSON
|
||||
*/
|
||||
public static function jsonDecode(string $input)
|
||||
{
|
||||
$obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
|
||||
|
||||
if ($errno = \json_last_error()) {
|
||||
self::handleJsonError($errno);
|
||||
} elseif ($obj === null && $input !== 'null') {
|
||||
throw new DomainException('Null result with non-null input');
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a PHP array into a JSON string.
|
||||
*
|
||||
* @param array<mixed> $input A PHP array
|
||||
*
|
||||
* @return string JSON representation of the PHP array
|
||||
*
|
||||
* @throws DomainException Provided object could not be encoded to valid JSON
|
||||
*/
|
||||
public static function jsonEncode(array $input): string
|
||||
{
|
||||
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()) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a string with URL-safe Base64.
|
||||
*
|
||||
* @param string $input A Base64 encoded string
|
||||
*
|
||||
* @return string A decoded string
|
||||
*
|
||||
* @throws InvalidArgumentException invalid base64 characters
|
||||
*/
|
||||
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 \strtr($input, '-_', '+/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a string with URL-safe Base64.
|
||||
*
|
||||
* @param string $input The string you want encoded
|
||||
*
|
||||
* @return string The base64 encode of what you passed in
|
||||
*/
|
||||
public static function urlsafeB64Encode(string $input): string
|
||||
{
|
||||
return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if an algorithm has been provided for each Key
|
||||
*
|
||||
* @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray
|
||||
* @param string|null $kid
|
||||
*
|
||||
* @throws UnexpectedValueException
|
||||
*
|
||||
* @return Key
|
||||
*/
|
||||
private static function getKey(
|
||||
$keyOrKeyArray,
|
||||
?string $kid
|
||||
): Key {
|
||||
if ($keyOrKeyArray instanceof Key) {
|
||||
return $keyOrKeyArray;
|
||||
}
|
||||
|
||||
if (empty($kid) && $kid !== '0') {
|
||||
throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
|
||||
}
|
||||
|
||||
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 The string of known length to compare against
|
||||
* @param string $right The user-supplied string
|
||||
* @return bool
|
||||
*/
|
||||
public static function constantTimeEquals(string $left, string $right): bool
|
||||
{
|
||||
if (\function_exists('hash_equals')) {
|
||||
return \hash_equals($left, $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 |= (self::safeStrlen($left) ^ self::safeStrlen($right));
|
||||
|
||||
return ($status === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a JSON error.
|
||||
*
|
||||
* @param int $errno An error number from json_last_error()
|
||||
*
|
||||
* @throws DomainException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function handleJsonError(int $errno): void
|
||||
{
|
||||
$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]
|
||||
: 'Unknown JSON error: ' . $errno
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes in cryptographic strings.
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function safeStrlen(string $str): int
|
||||
{
|
||||
if (\function_exists('mb_strlen')) {
|
||||
return \mb_strlen($str, '8bit');
|
||||
}
|
||||
return \strlen($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an ECDSA signature to an ASN.1 DER sequence
|
||||
*
|
||||
* @param string $sig The ECDSA signature to convert
|
||||
* @return string The encoded DER object
|
||||
*/
|
||||
private static function signatureToDER(string $sig): string
|
||||
{
|
||||
// Separate the signature into r-value and s-value
|
||||
$length = max(1, (int) (\strlen($sig) / 2));
|
||||
list($r, $s) = \str_split($sig, $length);
|
||||
|
||||
// Trim leading zeros
|
||||
$r = \ltrim($r, "\x00");
|
||||
$s = \ltrim($s, "\x00");
|
||||
|
||||
// Convert r-value and s-value from unsigned big-endian integers to
|
||||
// signed two's complement
|
||||
if (\ord($r[0]) > 0x7f) {
|
||||
$r = "\x00" . $r;
|
||||
}
|
||||
if (\ord($s[0]) > 0x7f) {
|
||||
$s = "\x00" . $s;
|
||||
}
|
||||
|
||||
return self::encodeDER(
|
||||
self::ASN1_SEQUENCE,
|
||||
self::encodeDER(self::ASN1_INTEGER, $r) .
|
||||
self::encodeDER(self::ASN1_INTEGER, $s)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a value into a DER object.
|
||||
*
|
||||
* @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 signature from a DER object.
|
||||
*
|
||||
* @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(string $der, int $keySize): string
|
||||
{
|
||||
// OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
|
||||
list($offset, $_) = self::readDER($der);
|
||||
list($offset, $r) = self::readDER($der, $offset);
|
||||
list($offset, $s) = self::readDER($der, $offset);
|
||||
|
||||
// Convert r-value and s-value from signed two's compliment to unsigned
|
||||
// big-endian integers
|
||||
$r = \ltrim($r, "\x00");
|
||||
$s = \ltrim($s, "\x00");
|
||||
|
||||
// Pad out r and s so that they are $keySize bits long
|
||||
$r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT);
|
||||
$s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT);
|
||||
|
||||
return $r . $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads binary DER-encoded data and decodes into a single object
|
||||
*
|
||||
* @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{int, string|null} the new offset and the decoded object
|
||||
*/
|
||||
private static function readDER(string $der, int $offset = 0): array
|
||||
{
|
||||
$pos = $offset;
|
||||
$size = \strlen($der);
|
||||
$constructed = (\ord($der[$pos]) >> 5) & 0x01;
|
||||
$type = \ord($der[$pos++]) & 0x1f;
|
||||
|
||||
// Length
|
||||
$len = \ord($der[$pos++]);
|
||||
if ($len & 0x80) {
|
||||
$n = $len & 0x1f;
|
||||
$len = 0;
|
||||
while ($n-- && $pos < $size) {
|
||||
$len = ($len << 8) | \ord($der[$pos++]);
|
||||
}
|
||||
}
|
||||
|
||||
// Value
|
||||
if ($type === self::ASN1_BIT_STRING) {
|
||||
$pos++; // Skip the first contents octet (padding indicator)
|
||||
$data = \substr($der, $pos, $len - 1);
|
||||
$pos += $len - 1;
|
||||
} elseif (!$constructed) {
|
||||
$data = \substr($der, $pos, $len);
|
||||
$pos += $len;
|
||||
} else {
|
||||
$data = null;
|
||||
}
|
||||
|
||||
return [$pos, $data];
|
||||
}
|
||||
}
|
64
vendor/firebase/php-jwt/src/Key.php
vendored
Normal file
64
vendor/firebase/php-jwt/src/Key.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OpenSSLAsymmetricKey;
|
||||
use OpenSSLCertificate;
|
||||
use TypeError;
|
||||
|
||||
class Key
|
||||
{
|
||||
/** @var string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate */
|
||||
private $keyMaterial;
|
||||
/** @var string */
|
||||
private $algorithm;
|
||||
|
||||
/**
|
||||
* @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial
|
||||
* @param string $algorithm
|
||||
*/
|
||||
public function __construct(
|
||||
$keyMaterial,
|
||||
string $algorithm
|
||||
) {
|
||||
if (
|
||||
!\is_string($keyMaterial)
|
||||
&& !$keyMaterial instanceof OpenSSLAsymmetricKey
|
||||
&& !$keyMaterial instanceof OpenSSLCertificate
|
||||
&& !\is_resource($keyMaterial)
|
||||
) {
|
||||
throw new TypeError('Key material must be a string, resource, or OpenSSLAsymmetricKey');
|
||||
}
|
||||
|
||||
if (empty($keyMaterial)) {
|
||||
throw new InvalidArgumentException('Key material must not be empty');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the algorithm valid for this key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAlgorithm(): string
|
||||
{
|
||||
return $this->algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate
|
||||
*/
|
||||
public function getKeyMaterial()
|
||||
{
|
||||
return $this->keyMaterial;
|
||||
}
|
||||
}
|
7
vendor/firebase/php-jwt/src/SignatureInvalidException.php
vendored
Normal file
7
vendor/firebase/php-jwt/src/SignatureInvalidException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
|
||||
class SignatureInvalidException extends \UnexpectedValueException
|
||||
{
|
||||
}
|
49
vendor/league/mime-type-detection/CHANGELOG.md
vendored
Normal file
49
vendor/league/mime-type-detection/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# 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
|
||||
|
||||
- Added Flysystem v1 inconclusive mime-types and made it configurable as a constructor parameter.
|
||||
|
||||
## 1.9.0 - 2021-11-21
|
||||
|
||||
### Updated
|
||||
|
||||
- Updated lookup
|
||||
|
||||
## 1.8.0 - 2021-09-25
|
||||
|
||||
### Added
|
||||
|
||||
- Added the decorator `OverridingExtensionToMimeTypeMap` which allows you to override values.
|
||||
|
||||
## 1.7.0 - 2021-01-18
|
||||
|
||||
### Added
|
||||
|
||||
- Added a `bufferSampleSize` parameter to the `FinfoMimeTypeDetector` class that allows you to send a reduced content sample which costs less memory.
|
||||
|
||||
## 1.6.0 - 2021-01-18
|
||||
|
||||
### Changes
|
||||
|
||||
- Updated generated mime-type map
|
19
vendor/league/mime-type-detection/LICENSE
vendored
Normal file
19
vendor/league/mime-type-detection/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
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
|
||||
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.
|
34
vendor/league/mime-type-detection/composer.json
vendored
Normal file
34
vendor/league/mime-type-detection/composer.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "league/mime-type-detection",
|
||||
"description": "Mime-type detection for Flysystem",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Frank de Jonge",
|
||||
"email": "info@frankdejonge.nl"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "vendor/bin/phpunit",
|
||||
"phpstan": "vendor/bin/phpstan analyse -l 6 src"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"ext-fileinfo": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0",
|
||||
"phpstan/phpstan": "^0.12.68",
|
||||
"friendsofphp/php-cs-fixer": "^3.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\MimeTypeDetection\\": "src"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"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;
|
||||
}
|
56
vendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.php
vendored
Normal file
56
vendor/league/mime-type-detection/src/ExtensionMimeTypeDetector.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\MimeTypeDetection;
|
||||
|
||||
use const PATHINFO_EXTENSION;
|
||||
|
||||
class ExtensionMimeTypeDetector implements MimeTypeDetector, ExtensionLookup
|
||||
{
|
||||
/**
|
||||
* @var ExtensionToMimeTypeMap
|
||||
*/
|
||||
private $extensions;
|
||||
|
||||
public function __construct(ExtensionToMimeTypeMap $extensions = null)
|
||||
{
|
||||
$this->extensions = $extensions ?: new GeneratedExtensionToMimeTypeMap();
|
||||
}
|
||||
|
||||
public function detectMimeType(string $path, $contents): ?string
|
||||
{
|
||||
return $this->detectMimeTypeFromPath($path);
|
||||
}
|
||||
|
||||
public function detectMimeTypeFromPath(string $path): ?string
|
||||
{
|
||||
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
|
||||
return $this->extensions->lookupMimeType($extension);
|
||||
}
|
||||
|
||||
public function detectMimeTypeFromFile(string $path): ?string
|
||||
{
|
||||
return $this->detectMimeTypeFromPath($path);
|
||||
}
|
||||
|
||||
public function detectMimeTypeFromBuffer(string $contents): ?string
|
||||
{
|
||||
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)
|
||||
: [];
|
||||
}
|
||||
}
|
106
vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php
vendored
Normal file
106
vendor/league/mime-type-detection/src/FinfoMimeTypeDetector.php
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\MimeTypeDetection;
|
||||
|
||||
use const FILEINFO_MIME_TYPE;
|
||||
|
||||
use const PATHINFO_EXTENSION;
|
||||
use finfo;
|
||||
|
||||
class FinfoMimeTypeDetector implements MimeTypeDetector, ExtensionLookup
|
||||
{
|
||||
private const INCONCLUSIVE_MIME_TYPES = [
|
||||
'application/x-empty',
|
||||
'text/plain',
|
||||
'text/x-asm',
|
||||
'application/octet-stream',
|
||||
'inode/x-empty',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var finfo
|
||||
*/
|
||||
private $finfo;
|
||||
|
||||
/**
|
||||
* @var ExtensionToMimeTypeMap
|
||||
*/
|
||||
private $extensionMap;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $bufferSampleSize;
|
||||
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
private $inconclusiveMimetypes;
|
||||
|
||||
public function __construct(
|
||||
string $magicFile = '',
|
||||
ExtensionToMimeTypeMap $extensionMap = null,
|
||||
?int $bufferSampleSize = null,
|
||||
array $inconclusiveMimetypes = self::INCONCLUSIVE_MIME_TYPES
|
||||
) {
|
||||
$this->finfo = new finfo(FILEINFO_MIME_TYPE, $magicFile);
|
||||
$this->extensionMap = $extensionMap ?: new GeneratedExtensionToMimeTypeMap();
|
||||
$this->bufferSampleSize = $bufferSampleSize;
|
||||
$this->inconclusiveMimetypes = $inconclusiveMimetypes;
|
||||
}
|
||||
|
||||
public function detectMimeType(string $path, $contents): ?string
|
||||
{
|
||||
$mimeType = is_string($contents)
|
||||
? (@$this->finfo->buffer($this->takeSample($contents)) ?: null)
|
||||
: null;
|
||||
|
||||
if ($mimeType !== null && ! in_array($mimeType, $this->inconclusiveMimetypes)) {
|
||||
return $mimeType;
|
||||
}
|
||||
|
||||
return $this->detectMimeTypeFromPath($path);
|
||||
}
|
||||
|
||||
public function detectMimeTypeFromPath(string $path): ?string
|
||||
{
|
||||
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
|
||||
|
||||
return $this->extensionMap->lookupMimeType($extension);
|
||||
}
|
||||
|
||||
public function detectMimeTypeFromFile(string $path): ?string
|
||||
{
|
||||
return @$this->finfo->file($path) ?: null;
|
||||
}
|
||||
|
||||
public function detectMimeTypeFromBuffer(string $contents): ?string
|
||||
{
|
||||
return @$this->finfo->buffer($this->takeSample($contents)) ?: null;
|
||||
}
|
||||
|
||||
private function takeSample(string $contents): string
|
||||
{
|
||||
if ($this->bufferSampleSize === null) {
|
||||
return $contents;
|
||||
}
|
||||
|
||||
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)
|
||||
: [];
|
||||
}
|
||||
}
|
2291
vendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.php
vendored
Normal file
2291
vendor/league/mime-type-detection/src/GeneratedExtensionToMimeTypeMap.php
vendored
Normal file
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;
|
||||
}
|
||||
}
|
6
vendor/services.php
vendored
6
vendor/services.php
vendored
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
// This file is automatically generated at:2023-08-02 19:37:01
|
||||
// This file is automatically generated at:2023-08-29 11:04:42
|
||||
declare (strict_types = 1);
|
||||
return array (
|
||||
0 => 'taoser\\addons\\Service',
|
||||
1 => 'think\\captcha\\CaptchaService',
|
||||
2 => 'think\\app\\Service',
|
||||
2 => 'think\\migration\\Service',
|
||||
3 => 'think\\app\\Service',
|
||||
4 => 'think\\trace\\Service',
|
||||
);
|
19
vendor/symfony/polyfill-mbstring/LICENSE
vendored
Normal file
19
vendor/symfony/polyfill-mbstring/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-present Fabien Potencier
|
||||
|
||||
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.
|
947
vendor/symfony/polyfill-mbstring/Mbstring.php
vendored
Normal file
947
vendor/symfony/polyfill-mbstring/Mbstring.php
vendored
Normal file
@ -0,0 +1,947 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Mbstring;
|
||||
|
||||
/**
|
||||
* Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
|
||||
*
|
||||
* Implemented:
|
||||
* - mb_chr - Returns a specific character from its Unicode code point
|
||||
* - mb_convert_encoding - Convert character encoding
|
||||
* - mb_convert_variables - Convert character code in variable(s)
|
||||
* - mb_decode_mimeheader - Decode string in MIME header field
|
||||
* - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
|
||||
* - mb_decode_numericentity - Decode HTML numeric string reference to character
|
||||
* - mb_encode_numericentity - Encode character to HTML numeric string reference
|
||||
* - mb_convert_case - Perform case folding on a string
|
||||
* - mb_detect_encoding - Detect character encoding
|
||||
* - mb_get_info - Get internal settings of mbstring
|
||||
* - mb_http_input - Detect HTTP input character encoding
|
||||
* - mb_http_output - Set/Get HTTP output character encoding
|
||||
* - mb_internal_encoding - Set/Get internal character encoding
|
||||
* - mb_list_encodings - Returns an array of all supported encodings
|
||||
* - mb_ord - Returns the Unicode code point of a character
|
||||
* - mb_output_handler - Callback function converts character encoding in output buffer
|
||||
* - mb_scrub - Replaces ill-formed byte sequences with substitute characters
|
||||
* - mb_strlen - Get string length
|
||||
* - mb_strpos - Find position of first occurrence of string in a string
|
||||
* - mb_strrpos - Find position of last occurrence of a string in a string
|
||||
* - mb_str_split - Convert a string to an array
|
||||
* - mb_strtolower - Make a string lowercase
|
||||
* - mb_strtoupper - Make a string uppercase
|
||||
* - mb_substitute_character - Set/Get substitution character
|
||||
* - mb_substr - Get part of string
|
||||
* - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
|
||||
* - mb_stristr - Finds first occurrence of a string within another, case insensitive
|
||||
* - mb_strrchr - Finds the last occurrence of a character in a string within another
|
||||
* - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
|
||||
* - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
|
||||
* - mb_strstr - Finds first occurrence of a string within another
|
||||
* - mb_strwidth - Return width of string
|
||||
* - mb_substr_count - Count the number of substring occurrences
|
||||
*
|
||||
* Not implemented:
|
||||
* - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
|
||||
* - mb_ereg_* - Regular expression with multibyte support
|
||||
* - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
|
||||
* - mb_preferred_mime_name - Get MIME charset string
|
||||
* - mb_regex_encoding - Returns current encoding for multibyte regex as string
|
||||
* - mb_regex_set_options - Set/Get the default options for mbregex functions
|
||||
* - mb_send_mail - Send encoded mail
|
||||
* - mb_split - Split multibyte string using regular expression
|
||||
* - mb_strcut - Get part of string
|
||||
* - mb_strimwidth - Get truncated string with specified width
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Mbstring
|
||||
{
|
||||
public const MB_CASE_FOLD = \PHP_INT_MAX;
|
||||
|
||||
private const SIMPLE_CASE_FOLD = [
|
||||
['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
|
||||
['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
|
||||
];
|
||||
|
||||
private static $encodingList = ['ASCII', 'UTF-8'];
|
||||
private static $language = 'neutral';
|
||||
private static $internalEncoding = 'UTF-8';
|
||||
|
||||
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
|
||||
{
|
||||
if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) {
|
||||
$fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
|
||||
} else {
|
||||
$fromEncoding = self::getEncoding($fromEncoding);
|
||||
}
|
||||
|
||||
$toEncoding = self::getEncoding($toEncoding);
|
||||
|
||||
if ('BASE64' === $fromEncoding) {
|
||||
$s = base64_decode($s);
|
||||
$fromEncoding = $toEncoding;
|
||||
}
|
||||
|
||||
if ('BASE64' === $toEncoding) {
|
||||
return base64_encode($s);
|
||||
}
|
||||
|
||||
if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
|
||||
if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
|
||||
$fromEncoding = 'Windows-1252';
|
||||
}
|
||||
if ('UTF-8' !== $fromEncoding) {
|
||||
$s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
|
||||
return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
|
||||
}
|
||||
|
||||
if ('HTML-ENTITIES' === $fromEncoding) {
|
||||
$s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
|
||||
$fromEncoding = 'UTF-8';
|
||||
}
|
||||
|
||||
return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
|
||||
}
|
||||
|
||||
public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
|
||||
{
|
||||
$ok = true;
|
||||
array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
|
||||
if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
|
||||
$ok = false;
|
||||
}
|
||||
});
|
||||
|
||||
return $ok ? $fromEncoding : false;
|
||||
}
|
||||
|
||||
public static function mb_decode_mimeheader($s)
|
||||
{
|
||||
return iconv_mime_decode($s, 2, self::$internalEncoding);
|
||||
}
|
||||
|
||||
public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
|
||||
{
|
||||
trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
|
||||
}
|
||||
|
||||
public static function mb_decode_numericentity($s, $convmap, $encoding = null)
|
||||
{
|
||||
if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
|
||||
trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $encoding && !\is_scalar($encoding)) {
|
||||
trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||
|
||||
return ''; // Instead of null (cf. mb_encode_numericentity).
|
||||
}
|
||||
|
||||
$s = (string) $s;
|
||||
if ('' === $s) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$encoding = self::getEncoding($encoding);
|
||||
|
||||
if ('UTF-8' === $encoding) {
|
||||
$encoding = null;
|
||||
if (!preg_match('//u', $s)) {
|
||||
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
} else {
|
||||
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
|
||||
$cnt = floor(\count($convmap) / 4) * 4;
|
||||
|
||||
for ($i = 0; $i < $cnt; $i += 4) {
|
||||
// collector_decode_htmlnumericentity ignores $convmap[$i + 3]
|
||||
$convmap[$i] += $convmap[$i + 2];
|
||||
$convmap[$i + 1] += $convmap[$i + 2];
|
||||
}
|
||||
|
||||
$s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
|
||||
$c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
|
||||
for ($i = 0; $i < $cnt; $i += 4) {
|
||||
if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
|
||||
return self::mb_chr($c - $convmap[$i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
return $m[0];
|
||||
}, $s);
|
||||
|
||||
if (null === $encoding) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
return iconv('UTF-8', $encoding.'//IGNORE', $s);
|
||||
}
|
||||
|
||||
public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
|
||||
{
|
||||
if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
|
||||
trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $encoding && !\is_scalar($encoding)) {
|
||||
trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||
|
||||
return null; // Instead of '' (cf. mb_decode_numericentity).
|
||||
}
|
||||
|
||||
if (null !== $is_hex && !\is_scalar($is_hex)) {
|
||||
trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$s = (string) $s;
|
||||
if ('' === $s) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$encoding = self::getEncoding($encoding);
|
||||
|
||||
if ('UTF-8' === $encoding) {
|
||||
$encoding = null;
|
||||
if (!preg_match('//u', $s)) {
|
||||
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
} else {
|
||||
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
|
||||
static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
|
||||
|
||||
$cnt = floor(\count($convmap) / 4) * 4;
|
||||
$i = 0;
|
||||
$len = \strlen($s);
|
||||
$result = '';
|
||||
|
||||
while ($i < $len) {
|
||||
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
|
||||
$uchr = substr($s, $i, $ulen);
|
||||
$i += $ulen;
|
||||
$c = self::mb_ord($uchr);
|
||||
|
||||
for ($j = 0; $j < $cnt; $j += 4) {
|
||||
if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
|
||||
$cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
|
||||
$result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$result .= $uchr;
|
||||
}
|
||||
|
||||
if (null === $encoding) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return iconv('UTF-8', $encoding.'//IGNORE', $result);
|
||||
}
|
||||
|
||||
public static function mb_convert_case($s, $mode, $encoding = null)
|
||||
{
|
||||
$s = (string) $s;
|
||||
if ('' === $s) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$encoding = self::getEncoding($encoding);
|
||||
|
||||
if ('UTF-8' === $encoding) {
|
||||
$encoding = null;
|
||||
if (!preg_match('//u', $s)) {
|
||||
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
} else {
|
||||
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
|
||||
if (\MB_CASE_TITLE == $mode) {
|
||||
static $titleRegexp = null;
|
||||
if (null === $titleRegexp) {
|
||||
$titleRegexp = self::getData('titleCaseRegexp');
|
||||
}
|
||||
$s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
|
||||
} else {
|
||||
if (\MB_CASE_UPPER == $mode) {
|
||||
static $upper = null;
|
||||
if (null === $upper) {
|
||||
$upper = self::getData('upperCase');
|
||||
}
|
||||
$map = $upper;
|
||||
} else {
|
||||
if (self::MB_CASE_FOLD === $mode) {
|
||||
static $caseFolding = null;
|
||||
if (null === $caseFolding) {
|
||||
$caseFolding = self::getData('caseFolding');
|
||||
}
|
||||
$s = strtr($s, $caseFolding);
|
||||
}
|
||||
|
||||
static $lower = null;
|
||||
if (null === $lower) {
|
||||
$lower = self::getData('lowerCase');
|
||||
}
|
||||
$map = $lower;
|
||||
}
|
||||
|
||||
static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
|
||||
|
||||
$i = 0;
|
||||
$len = \strlen($s);
|
||||
|
||||
while ($i < $len) {
|
||||
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
|
||||
$uchr = substr($s, $i, $ulen);
|
||||
$i += $ulen;
|
||||
|
||||
if (isset($map[$uchr])) {
|
||||
$uchr = $map[$uchr];
|
||||
$nlen = \strlen($uchr);
|
||||
|
||||
if ($nlen == $ulen) {
|
||||
$nlen = $i;
|
||||
do {
|
||||
$s[--$nlen] = $uchr[--$ulen];
|
||||
} while ($ulen);
|
||||
} else {
|
||||
$s = substr_replace($s, $uchr, $i - $ulen, $ulen);
|
||||
$len += $nlen - $ulen;
|
||||
$i += $nlen - $ulen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $encoding) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
return iconv('UTF-8', $encoding.'//IGNORE', $s);
|
||||
}
|
||||
|
||||
public static function mb_internal_encoding($encoding = null)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
return self::$internalEncoding;
|
||||
}
|
||||
|
||||
$normalizedEncoding = self::getEncoding($encoding);
|
||||
|
||||
if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
|
||||
self::$internalEncoding = $normalizedEncoding;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (80000 > \PHP_VERSION_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
|
||||
}
|
||||
|
||||
public static function mb_language($lang = null)
|
||||
{
|
||||
if (null === $lang) {
|
||||
return self::$language;
|
||||
}
|
||||
|
||||
switch ($normalizedLang = strtolower($lang)) {
|
||||
case 'uni':
|
||||
case 'neutral':
|
||||
self::$language = $normalizedLang;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (80000 > \PHP_VERSION_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
|
||||
}
|
||||
|
||||
public static function mb_list_encodings()
|
||||
{
|
||||
return ['UTF-8'];
|
||||
}
|
||||
|
||||
public static function mb_encoding_aliases($encoding)
|
||||
{
|
||||
switch (strtoupper($encoding)) {
|
||||
case 'UTF8':
|
||||
case 'UTF-8':
|
||||
return ['utf8'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function mb_check_encoding($var = null, $encoding = null)
|
||||
{
|
||||
if (PHP_VERSION_ID < 70200 && \is_array($var)) {
|
||||
trigger_error('mb_check_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null === $encoding) {
|
||||
if (null === $var) {
|
||||
return false;
|
||||
}
|
||||
$encoding = self::$internalEncoding;
|
||||
}
|
||||
|
||||
if (!\is_array($var)) {
|
||||
return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var);
|
||||
}
|
||||
|
||||
foreach ($var as $key => $value) {
|
||||
if (!self::mb_check_encoding($key, $encoding)) {
|
||||
return false;
|
||||
}
|
||||
if (!self::mb_check_encoding($value, $encoding)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
|
||||
{
|
||||
if (null === $encodingList) {
|
||||
$encodingList = self::$encodingList;
|
||||
} else {
|
||||
if (!\is_array($encodingList)) {
|
||||
$encodingList = array_map('trim', explode(',', $encodingList));
|
||||
}
|
||||
$encodingList = array_map('strtoupper', $encodingList);
|
||||
}
|
||||
|
||||
foreach ($encodingList as $enc) {
|
||||
switch ($enc) {
|
||||
case 'ASCII':
|
||||
if (!preg_match('/[\x80-\xFF]/', $str)) {
|
||||
return $enc;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'UTF8':
|
||||
case 'UTF-8':
|
||||
if (preg_match('//u', $str)) {
|
||||
return 'UTF-8';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (0 === strncmp($enc, 'ISO-8859-', 9)) {
|
||||
return $enc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function mb_detect_order($encodingList = null)
|
||||
{
|
||||
if (null === $encodingList) {
|
||||
return self::$encodingList;
|
||||
}
|
||||
|
||||
if (!\is_array($encodingList)) {
|
||||
$encodingList = array_map('trim', explode(',', $encodingList));
|
||||
}
|
||||
$encodingList = array_map('strtoupper', $encodingList);
|
||||
|
||||
foreach ($encodingList as $enc) {
|
||||
switch ($enc) {
|
||||
default:
|
||||
if (strncmp($enc, 'ISO-8859-', 9)) {
|
||||
return false;
|
||||
}
|
||||
// no break
|
||||
case 'ASCII':
|
||||
case 'UTF8':
|
||||
case 'UTF-8':
|
||||
}
|
||||
}
|
||||
|
||||
self::$encodingList = $encodingList;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function mb_strlen($s, $encoding = null)
|
||||
{
|
||||
$encoding = self::getEncoding($encoding);
|
||||
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||
return \strlen($s);
|
||||
}
|
||||
|
||||
return @iconv_strlen($s, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
|
||||
{
|
||||
$encoding = self::getEncoding($encoding);
|
||||
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||
return strpos($haystack, $needle, $offset);
|
||||
}
|
||||
|
||||
$needle = (string) $needle;
|
||||
if ('' === $needle) {
|
||||
if (80000 > \PHP_VERSION_ID) {
|
||||
trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iconv_strpos($haystack, $needle, $offset, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
|
||||
{
|
||||
$encoding = self::getEncoding($encoding);
|
||||
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||
return strrpos($haystack, $needle, $offset);
|
||||
}
|
||||
|
||||
if ($offset != (int) $offset) {
|
||||
$offset = 0;
|
||||
} elseif ($offset = (int) $offset) {
|
||||
if ($offset < 0) {
|
||||
if (0 > $offset += self::mb_strlen($needle)) {
|
||||
$haystack = self::mb_substr($haystack, 0, $offset, $encoding);
|
||||
}
|
||||
$offset = 0;
|
||||
} else {
|
||||
$haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
|
||||
}
|
||||
}
|
||||
|
||||
$pos = '' !== $needle || 80000 > \PHP_VERSION_ID
|
||||
? iconv_strrpos($haystack, $needle, $encoding)
|
||||
: self::mb_strlen($haystack, $encoding);
|
||||
|
||||
return false !== $pos ? $offset + $pos : false;
|
||||
}
|
||||
|
||||
public static function mb_str_split($string, $split_length = 1, $encoding = null)
|
||||
{
|
||||
if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
|
||||
trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (1 > $split_length = (int) $split_length) {
|
||||
if (80000 > \PHP_VERSION_ID) {
|
||||
trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new \ValueError('Argument #2 ($length) must be greater than 0');
|
||||
}
|
||||
|
||||
if (null === $encoding) {
|
||||
$encoding = mb_internal_encoding();
|
||||
}
|
||||
|
||||
if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
|
||||
$rx = '/(';
|
||||
while (65535 < $split_length) {
|
||||
$rx .= '.{65535}';
|
||||
$split_length -= 65535;
|
||||
}
|
||||
$rx .= '.{'.$split_length.'})/us';
|
||||
|
||||
return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$length = mb_strlen($string, $encoding);
|
||||
|
||||
for ($i = 0; $i < $length; $i += $split_length) {
|
||||
$result[] = mb_substr($string, $i, $split_length, $encoding);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function mb_strtolower($s, $encoding = null)
|
||||
{
|
||||
return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strtoupper($s, $encoding = null)
|
||||
{
|
||||
return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_substitute_character($c = null)
|
||||
{
|
||||
if (null === $c) {
|
||||
return 'none';
|
||||
}
|
||||
if (0 === strcasecmp($c, 'none')) {
|
||||
return true;
|
||||
}
|
||||
if (80000 > \PHP_VERSION_ID) {
|
||||
return false;
|
||||
}
|
||||
if (\is_int($c) || 'long' === $c || 'entity' === $c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
|
||||
}
|
||||
|
||||
public static function mb_substr($s, $start, $length = null, $encoding = null)
|
||||
{
|
||||
$encoding = self::getEncoding($encoding);
|
||||
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||
return (string) substr($s, $start, null === $length ? 2147483647 : $length);
|
||||
}
|
||||
|
||||
if ($start < 0) {
|
||||
$start = iconv_strlen($s, $encoding) + $start;
|
||||
if ($start < 0) {
|
||||
$start = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $length) {
|
||||
$length = 2147483647;
|
||||
} elseif ($length < 0) {
|
||||
$length = iconv_strlen($s, $encoding) + $length - $start;
|
||||
if ($length < 0) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return (string) iconv_substr($s, $start, $length, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
|
||||
{
|
||||
[$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [
|
||||
self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding),
|
||||
self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding),
|
||||
]);
|
||||
|
||||
return self::mb_strpos($haystack, $needle, $offset, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
|
||||
{
|
||||
$pos = self::mb_stripos($haystack, $needle, 0, $encoding);
|
||||
|
||||
return self::getSubpart($pos, $part, $haystack, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
|
||||
{
|
||||
$encoding = self::getEncoding($encoding);
|
||||
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||
$pos = strrpos($haystack, $needle);
|
||||
} else {
|
||||
$needle = self::mb_substr($needle, 0, 1, $encoding);
|
||||
$pos = iconv_strrpos($haystack, $needle, $encoding);
|
||||
}
|
||||
|
||||
return self::getSubpart($pos, $part, $haystack, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
|
||||
{
|
||||
$needle = self::mb_substr($needle, 0, 1, $encoding);
|
||||
$pos = self::mb_strripos($haystack, $needle, $encoding);
|
||||
|
||||
return self::getSubpart($pos, $part, $haystack, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
|
||||
{
|
||||
$haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding);
|
||||
$needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding);
|
||||
|
||||
$haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack);
|
||||
$needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle);
|
||||
|
||||
return self::mb_strrpos($haystack, $needle, $offset, $encoding);
|
||||
}
|
||||
|
||||
public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
|
||||
{
|
||||
$pos = strpos($haystack, $needle);
|
||||
if (false === $pos) {
|
||||
return false;
|
||||
}
|
||||
if ($part) {
|
||||
return substr($haystack, 0, $pos);
|
||||
}
|
||||
|
||||
return substr($haystack, $pos);
|
||||
}
|
||||
|
||||
public static function mb_get_info($type = 'all')
|
||||
{
|
||||
$info = [
|
||||
'internal_encoding' => self::$internalEncoding,
|
||||
'http_output' => 'pass',
|
||||
'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
|
||||
'func_overload' => 0,
|
||||
'func_overload_list' => 'no overload',
|
||||
'mail_charset' => 'UTF-8',
|
||||
'mail_header_encoding' => 'BASE64',
|
||||
'mail_body_encoding' => 'BASE64',
|
||||
'illegal_chars' => 0,
|
||||
'encoding_translation' => 'Off',
|
||||
'language' => self::$language,
|
||||
'detect_order' => self::$encodingList,
|
||||
'substitute_character' => 'none',
|
||||
'strict_detection' => 'Off',
|
||||
];
|
||||
|
||||
if ('all' === $type) {
|
||||
return $info;
|
||||
}
|
||||
if (isset($info[$type])) {
|
||||
return $info[$type];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function mb_http_input($type = '')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function mb_http_output($encoding = null)
|
||||
{
|
||||
return null !== $encoding ? 'pass' === $encoding : 'pass';
|
||||
}
|
||||
|
||||
public static function mb_strwidth($s, $encoding = null)
|
||||
{
|
||||
$encoding = self::getEncoding($encoding);
|
||||
|
||||
if ('UTF-8' !== $encoding) {
|
||||
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||
}
|
||||
|
||||
$s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
|
||||
|
||||
return ($wide << 1) + iconv_strlen($s, 'UTF-8');
|
||||
}
|
||||
|
||||
public static function mb_substr_count($haystack, $needle, $encoding = null)
|
||||
{
|
||||
return substr_count($haystack, $needle);
|
||||
}
|
||||
|
||||
public static function mb_output_handler($contents, $status)
|
||||
{
|
||||
return $contents;
|
||||
}
|
||||
|
||||
public static function mb_chr($code, $encoding = null)
|
||||
{
|
||||
if (0x80 > $code %= 0x200000) {
|
||||
$s = \chr($code);
|
||||
} elseif (0x800 > $code) {
|
||||
$s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
|
||||
} elseif (0x10000 > $code) {
|
||||
$s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
|
||||
} else {
|
||||
$s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
|
||||
}
|
||||
|
||||
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
|
||||
$s = mb_convert_encoding($s, $encoding, 'UTF-8');
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
public static function mb_ord($s, $encoding = null)
|
||||
{
|
||||
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
|
||||
$s = mb_convert_encoding($s, 'UTF-8', $encoding);
|
||||
}
|
||||
|
||||
if (1 === \strlen($s)) {
|
||||
return \ord($s);
|
||||
}
|
||||
|
||||
$code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
|
||||
if (0xF0 <= $code) {
|
||||
return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
|
||||
}
|
||||
if (0xE0 <= $code) {
|
||||
return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
|
||||
}
|
||||
if (0xC0 <= $code) {
|
||||
return (($code - 0xC0) << 6) + $s[2] - 0x80;
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, string $encoding = null): string
|
||||
{
|
||||
if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
|
||||
throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
|
||||
}
|
||||
|
||||
if (null === $encoding) {
|
||||
$encoding = self::mb_internal_encoding();
|
||||
}
|
||||
|
||||
try {
|
||||
$validEncoding = @self::mb_check_encoding('', $encoding);
|
||||
} catch (\ValueError $e) {
|
||||
throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding));
|
||||
}
|
||||
|
||||
// BC for PHP 7.3 and lower
|
||||
if (!$validEncoding) {
|
||||
throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding));
|
||||
}
|
||||
|
||||
if (self::mb_strlen($pad_string, $encoding) <= 0) {
|
||||
throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string');
|
||||
}
|
||||
|
||||
$paddingRequired = $length - self::mb_strlen($string, $encoding);
|
||||
|
||||
if ($paddingRequired < 1) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
switch ($pad_type) {
|
||||
case \STR_PAD_LEFT:
|
||||
return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string;
|
||||
case \STR_PAD_RIGHT:
|
||||
return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
|
||||
default:
|
||||
$leftPaddingLength = floor($paddingRequired / 2);
|
||||
$rightPaddingLength = $paddingRequired - $leftPaddingLength;
|
||||
|
||||
return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
|
||||
}
|
||||
}
|
||||
|
||||
private static function getSubpart($pos, $part, $haystack, $encoding)
|
||||
{
|
||||
if (false === $pos) {
|
||||
return false;
|
||||
}
|
||||
if ($part) {
|
||||
return self::mb_substr($haystack, 0, $pos, $encoding);
|
||||
}
|
||||
|
||||
return self::mb_substr($haystack, $pos, null, $encoding);
|
||||
}
|
||||
|
||||
private static function html_encoding_callback(array $m)
|
||||
{
|
||||
$i = 1;
|
||||
$entities = '';
|
||||
$m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
|
||||
|
||||
while (isset($m[$i])) {
|
||||
if (0x80 > $m[$i]) {
|
||||
$entities .= \chr($m[$i++]);
|
||||
continue;
|
||||
}
|
||||
if (0xF0 <= $m[$i]) {
|
||||
$c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
||||
} elseif (0xE0 <= $m[$i]) {
|
||||
$c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
||||
} else {
|
||||
$c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
|
||||
}
|
||||
|
||||
$entities .= '&#'.$c.';';
|
||||
}
|
||||
|
||||
return $entities;
|
||||
}
|
||||
|
||||
private static function title_case(array $s)
|
||||
{
|
||||
return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
|
||||
}
|
||||
|
||||
private static function getData($file)
|
||||
{
|
||||
if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
|
||||
return require $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function getEncoding($encoding)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
return self::$internalEncoding;
|
||||
}
|
||||
|
||||
if ('UTF-8' === $encoding) {
|
||||
return 'UTF-8';
|
||||
}
|
||||
|
||||
$encoding = strtoupper($encoding);
|
||||
|
||||
if ('8BIT' === $encoding || 'BINARY' === $encoding) {
|
||||
return 'CP850';
|
||||
}
|
||||
|
||||
if ('UTF8' === $encoding) {
|
||||
return 'UTF-8';
|
||||
}
|
||||
|
||||
return $encoding;
|
||||
}
|
||||
}
|
119
vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php
vendored
Normal file
119
vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'İ' => 'i̇',
|
||||
'µ' => 'μ',
|
||||
'ſ' => 's',
|
||||
'ͅ' => 'ι',
|
||||
'ς' => 'σ',
|
||||
'ϐ' => 'β',
|
||||
'ϑ' => 'θ',
|
||||
'ϕ' => 'φ',
|
||||
'ϖ' => 'π',
|
||||
'ϰ' => 'κ',
|
||||
'ϱ' => 'ρ',
|
||||
'ϵ' => 'ε',
|
||||
'ẛ' => 'ṡ',
|
||||
'ι' => 'ι',
|
||||
'ß' => 'ss',
|
||||
'ʼn' => 'ʼn',
|
||||
'ǰ' => 'ǰ',
|
||||
'ΐ' => 'ΐ',
|
||||
'ΰ' => 'ΰ',
|
||||
'և' => 'եւ',
|
||||
'ẖ' => 'ẖ',
|
||||
'ẗ' => 'ẗ',
|
||||
'ẘ' => 'ẘ',
|
||||
'ẙ' => 'ẙ',
|
||||
'ẚ' => 'aʾ',
|
||||
'ẞ' => 'ss',
|
||||
'ὐ' => 'ὐ',
|
||||
'ὒ' => 'ὒ',
|
||||
'ὔ' => 'ὔ',
|
||||
'ὖ' => 'ὖ',
|
||||
'ᾀ' => 'ἀι',
|
||||
'ᾁ' => 'ἁι',
|
||||
'ᾂ' => 'ἂι',
|
||||
'ᾃ' => 'ἃι',
|
||||
'ᾄ' => 'ἄι',
|
||||
'ᾅ' => 'ἅι',
|
||||
'ᾆ' => 'ἆι',
|
||||
'ᾇ' => 'ἇι',
|
||||
'ᾈ' => 'ἀι',
|
||||
'ᾉ' => 'ἁι',
|
||||
'ᾊ' => 'ἂι',
|
||||
'ᾋ' => 'ἃι',
|
||||
'ᾌ' => 'ἄι',
|
||||
'ᾍ' => 'ἅι',
|
||||
'ᾎ' => 'ἆι',
|
||||
'ᾏ' => 'ἇι',
|
||||
'ᾐ' => 'ἠι',
|
||||
'ᾑ' => 'ἡι',
|
||||
'ᾒ' => 'ἢι',
|
||||
'ᾓ' => 'ἣι',
|
||||
'ᾔ' => 'ἤι',
|
||||
'ᾕ' => 'ἥι',
|
||||
'ᾖ' => 'ἦι',
|
||||
'ᾗ' => 'ἧι',
|
||||
'ᾘ' => 'ἠι',
|
||||
'ᾙ' => 'ἡι',
|
||||
'ᾚ' => 'ἢι',
|
||||
'ᾛ' => 'ἣι',
|
||||
'ᾜ' => 'ἤι',
|
||||
'ᾝ' => 'ἥι',
|
||||
'ᾞ' => 'ἦι',
|
||||
'ᾟ' => 'ἧι',
|
||||
'ᾠ' => 'ὠι',
|
||||
'ᾡ' => 'ὡι',
|
||||
'ᾢ' => 'ὢι',
|
||||
'ᾣ' => 'ὣι',
|
||||
'ᾤ' => 'ὤι',
|
||||
'ᾥ' => 'ὥι',
|
||||
'ᾦ' => 'ὦι',
|
||||
'ᾧ' => 'ὧι',
|
||||
'ᾨ' => 'ὠι',
|
||||
'ᾩ' => 'ὡι',
|
||||
'ᾪ' => 'ὢι',
|
||||
'ᾫ' => 'ὣι',
|
||||
'ᾬ' => 'ὤι',
|
||||
'ᾭ' => 'ὥι',
|
||||
'ᾮ' => 'ὦι',
|
||||
'ᾯ' => 'ὧι',
|
||||
'ᾲ' => 'ὰι',
|
||||
'ᾳ' => 'αι',
|
||||
'ᾴ' => 'άι',
|
||||
'ᾶ' => 'ᾶ',
|
||||
'ᾷ' => 'ᾶι',
|
||||
'ᾼ' => 'αι',
|
||||
'ῂ' => 'ὴι',
|
||||
'ῃ' => 'ηι',
|
||||
'ῄ' => 'ήι',
|
||||
'ῆ' => 'ῆ',
|
||||
'ῇ' => 'ῆι',
|
||||
'ῌ' => 'ηι',
|
||||
'ῒ' => 'ῒ',
|
||||
'ῖ' => 'ῖ',
|
||||
'ῗ' => 'ῗ',
|
||||
'ῢ' => 'ῢ',
|
||||
'ῤ' => 'ῤ',
|
||||
'ῦ' => 'ῦ',
|
||||
'ῧ' => 'ῧ',
|
||||
'ῲ' => 'ὼι',
|
||||
'ῳ' => 'ωι',
|
||||
'ῴ' => 'ώι',
|
||||
'ῶ' => 'ῶ',
|
||||
'ῷ' => 'ῶι',
|
||||
'ῼ' => 'ωι',
|
||||
'ff' => 'ff',
|
||||
'fi' => 'fi',
|
||||
'fl' => 'fl',
|
||||
'ffi' => 'ffi',
|
||||
'ffl' => 'ffl',
|
||||
'ſt' => 'st',
|
||||
'st' => 'st',
|
||||
'ﬓ' => 'մն',
|
||||
'ﬔ' => 'մե',
|
||||
'ﬕ' => 'մի',
|
||||
'ﬖ' => 'վն',
|
||||
'ﬗ' => 'մխ',
|
||||
];
|
151
vendor/symfony/polyfill-mbstring/bootstrap.php
vendored
Normal file
151
vendor/symfony/polyfill-mbstring/bootstrap.php
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Mbstring as p;
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
return require __DIR__.'/bootstrap80.php';
|
||||
}
|
||||
|
||||
if (!function_exists('mb_convert_encoding')) {
|
||||
function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }
|
||||
}
|
||||
if (!function_exists('mb_decode_mimeheader')) {
|
||||
function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); }
|
||||
}
|
||||
if (!function_exists('mb_encode_mimeheader')) {
|
||||
function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }
|
||||
}
|
||||
if (!function_exists('mb_decode_numericentity')) {
|
||||
function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_encode_numericentity')) {
|
||||
function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }
|
||||
}
|
||||
if (!function_exists('mb_convert_case')) {
|
||||
function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_internal_encoding')) {
|
||||
function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_language')) {
|
||||
function mb_language($language = null) { return p\Mbstring::mb_language($language); }
|
||||
}
|
||||
if (!function_exists('mb_list_encodings')) {
|
||||
function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
|
||||
}
|
||||
if (!function_exists('mb_encoding_aliases')) {
|
||||
function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_check_encoding')) {
|
||||
function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_detect_encoding')) {
|
||||
function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); }
|
||||
}
|
||||
if (!function_exists('mb_detect_order')) {
|
||||
function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_parse_str')) {
|
||||
function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }
|
||||
}
|
||||
if (!function_exists('mb_strlen')) {
|
||||
function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strpos')) {
|
||||
function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtolower')) {
|
||||
function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtoupper')) {
|
||||
function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substitute_character')) {
|
||||
function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); }
|
||||
}
|
||||
if (!function_exists('mb_substr')) {
|
||||
function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stripos')) {
|
||||
function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stristr')) {
|
||||
function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrchr')) {
|
||||
function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrichr')) {
|
||||
function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strripos')) {
|
||||
function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrpos')) {
|
||||
function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strstr')) {
|
||||
function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_get_info')) {
|
||||
function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
|
||||
}
|
||||
if (!function_exists('mb_http_output')) {
|
||||
function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strwidth')) {
|
||||
function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substr_count')) {
|
||||
function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_output_handler')) {
|
||||
function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); }
|
||||
}
|
||||
if (!function_exists('mb_http_input')) {
|
||||
function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_convert_variables')) {
|
||||
function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ord')) {
|
||||
function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_chr')) {
|
||||
function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_scrub')) {
|
||||
function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_str_split')) {
|
||||
function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_str_pad')) {
|
||||
function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
|
||||
}
|
||||
|
||||
if (extension_loaded('mbstring')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('MB_CASE_UPPER')) {
|
||||
define('MB_CASE_UPPER', 0);
|
||||
}
|
||||
if (!defined('MB_CASE_LOWER')) {
|
||||
define('MB_CASE_LOWER', 1);
|
||||
}
|
||||
if (!defined('MB_CASE_TITLE')) {
|
||||
define('MB_CASE_TITLE', 2);
|
||||
}
|
147
vendor/symfony/polyfill-mbstring/bootstrap80.php
vendored
Normal file
147
vendor/symfony/polyfill-mbstring/bootstrap80.php
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Mbstring as p;
|
||||
|
||||
if (!function_exists('mb_convert_encoding')) {
|
||||
function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); }
|
||||
}
|
||||
if (!function_exists('mb_decode_mimeheader')) {
|
||||
function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); }
|
||||
}
|
||||
if (!function_exists('mb_encode_mimeheader')) {
|
||||
function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); }
|
||||
}
|
||||
if (!function_exists('mb_decode_numericentity')) {
|
||||
function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_encode_numericentity')) {
|
||||
function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); }
|
||||
}
|
||||
if (!function_exists('mb_convert_case')) {
|
||||
function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_internal_encoding')) {
|
||||
function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_language')) {
|
||||
function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); }
|
||||
}
|
||||
if (!function_exists('mb_list_encodings')) {
|
||||
function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); }
|
||||
}
|
||||
if (!function_exists('mb_encoding_aliases')) {
|
||||
function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_check_encoding')) {
|
||||
function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_detect_encoding')) {
|
||||
function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }
|
||||
}
|
||||
if (!function_exists('mb_detect_order')) {
|
||||
function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_parse_str')) {
|
||||
function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }
|
||||
}
|
||||
if (!function_exists('mb_strlen')) {
|
||||
function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strpos')) {
|
||||
function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtolower')) {
|
||||
function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtoupper')) {
|
||||
function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substitute_character')) {
|
||||
function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); }
|
||||
}
|
||||
if (!function_exists('mb_substr')) {
|
||||
function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stripos')) {
|
||||
function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stristr')) {
|
||||
function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrchr')) {
|
||||
function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrichr')) {
|
||||
function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strripos')) {
|
||||
function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrpos')) {
|
||||
function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strstr')) {
|
||||
function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_get_info')) {
|
||||
function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); }
|
||||
}
|
||||
if (!function_exists('mb_http_output')) {
|
||||
function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strwidth')) {
|
||||
function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substr_count')) {
|
||||
function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_output_handler')) {
|
||||
function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); }
|
||||
}
|
||||
if (!function_exists('mb_http_input')) {
|
||||
function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_convert_variables')) {
|
||||
function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ord')) {
|
||||
function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_chr')) {
|
||||
function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_scrub')) {
|
||||
function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_str_split')) {
|
||||
function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_str_pad')) {
|
||||
function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
|
||||
}
|
||||
|
||||
if (extension_loaded('mbstring')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('MB_CASE_UPPER')) {
|
||||
define('MB_CASE_UPPER', 0);
|
||||
}
|
||||
if (!defined('MB_CASE_LOWER')) {
|
||||
define('MB_CASE_LOWER', 1);
|
||||
}
|
||||
if (!defined('MB_CASE_TITLE')) {
|
||||
define('MB_CASE_TITLE', 2);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user