[更新]增加微信模块授权模块双模式

This commit is contained in:
Anyon 2018-03-19 13:29:54 +08:00
parent a09dce19a3
commit 6e18f7ff67
14 changed files with 248 additions and 105 deletions

View File

@ -44,21 +44,29 @@ class Config extends BasicAdmin
{
if ($this->request->isGet()) {
$code = encode(url('@admin', '', true, true) . '#' . $this->request->url());
$assign = [
return $this->fetch('', [
'title' => '微信接口配置',
'appuri' => url("@wechat/api.push", '', true, true),
'appid' => $this->request->get('appid', sysconf('wechat_appid')),
'appkey' => $this->request->get('appkey', sysconf('wechat_appkey')),
'appid' => $this->request->get('appid', sysconf('wechat_thr_appid')),
'appkey' => $this->request->get('appkey', sysconf('wechat_thr_appkey')),
'authurl' => "http://wm.cuci.cc/wechat/api.push/auth/{$code}.html",
'wechat' => WechatService::instance('config')->getConfig(),
];
return $this->fetch('', $assign);
]);
}
try {
// 接口对接类型
sysconf('wechat_type', $this->request->post('wechat_type'));
// 直接参数对应
sysconf('wechat_token', $this->request->post('wechat_token'));
sysconf('wechat_appid', $this->request->post('wechat_appid'));
sysconf('wechat_appkey', $this->request->post('wechat_appkey'));
$apiurl = $this->request->post('wechat_appurl');
if (!empty($apiurl)) {
sysconf('wechat_appsecret', $this->request->post('wechat_appsecret'));
sysconf('wechat_encodingaeskey', $this->request->post('wechat_encodingaeskey'));
// 第三方平台配置
sysconf('wechat_thr_appid', $this->request->post('wechat_thr_appid'));
sysconf('wechat_thr_appkey', $this->request->post('wechat_thr_appkey'));
// 第三方平台时设置远程平台通知接口
if ($this->request->post('wechat_type') === 'thr') {
$apiurl = url('@wechat/api.push', '', true, true);
if (!WechatService::instance('config')->setApiNotifyUri($apiurl)) {
$this->error('远程服务端接口更新失败,请稍候再试!');
}

View File

@ -50,26 +50,56 @@ class Push
/**
* 微信消息接口
* @return string
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public function __construct()
public function index()
{
$request = app('request');
$this->appid = $request->post('appid', '', null);
$this->openid = $request->post('openid', '', null);
$this->receive = unserialize($request->post('receive', '', null));
p($this->receive);
if (empty($this->appid) || empty($this->openid) || empty($this->receive)) {
throw new Exception('微信API实例缺失必要参数[appid,openid,event].');
}
if ($this->appid !== sysconf('wechat_appid')) {
return $this->call($this->openid, $this->appid, $this->receive);
}
/**
* 公众号直接对接
* @return string
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public function notify()
{
$wechat = WechatService::receive();
return $this->call(WechatService::getAppid(), $wechat->getOpenid(), $wechat->getReceive());
}
/**
* 初始化接口
* @param string $appid 公众号APPID
* @param string $openid 公众号OPENID
* @param array $revice 消息对象
* @return string
* @throws Exception
* @throws \think\exception\PDOException
*/
protected function call($appid, $openid, $revice)
{
$this->appid = $appid;
$this->openid = $openid;
$this->receive = $revice;
if ($this->appid !== WechatService::getAppid()) {
throw new Exception('微信API实例APPID验证失败.');
}
// text,event,image,location
if (method_exists($this, ($method = $this->receive['MsgType']))) {
$this->$method();
return $this->$method();
}
return 'success';
}
/**

View File

@ -35,7 +35,7 @@ class FansService
*/
public static function set(array $user)
{
$user['appid'] = sysconf('wechat_appid');
$user['appid'] = WechatService::getAppid();
if (!empty($user['subscribe_time'])) {
$user['subscribe_at'] = date('Y-m-d H:i:s', $user['subscribe_time']);
}
@ -58,7 +58,7 @@ class FansService
*/
public static function get($openid)
{
$map = ['openid' => $openid, 'appid' => sysconf('wechat_appid')];
$map = ['openid' => $openid, 'appid' => WechatService::getAppid()];
$user = Db::name('WechatFans')->where($map)->find();
foreach (['country', 'province', 'city', 'nickname', 'remark'] as $k) {
isset($user[$k]) && $user[$k] = ToolsService::emojiDecode($user[$k]);

View File

@ -84,7 +84,7 @@ class MediaService
*/
public static function uploadForeverMedia($local_url, $type = 'image', $video_info = [])
{
$map = ['md5' => md5($local_url), 'appid' => sysconf('wechat_appid')];
$map = ['md5' => md5($local_url), 'appid' => WechatService::getAppid()];
if (($media_id = Db::name('WechatNewsMedia')->where($map)->value('media_id'))) {
return $media_id;
}

View File

@ -54,7 +54,7 @@ class TagsService
*/
public static function sync()
{
$appid = sysconf('wechat_appid');
$appid = WechatService::getAppid();
$result = WechatService::tags()->getTags();
Db::name('WechatFansTags')->where(['appid' => $appid])->delete();
foreach (array_chunk($result['tags'], 100) as $list) {

View File

@ -1,15 +1,12 @@
{extend name='admin@public/content'}
{block name="button"}
<!--{if auth('wechat/block/backdel')}-->
<button data-update="" data-action="{:url('backdel')}" class='layui-btn layui-btn-sm'>移出黑名单</button>
<!--{/if}-->
<!--{if auth('wechat/fans/sync')}-->
<button data-load="{:url('wechat/fans/sync')}" class='layui-btn layui-btn-sm'>远程获取粉丝</button>
<!--{/if}-->
{/block}
{block name="content"}
@ -94,12 +91,12 @@
<!--{if empty($list)}-->
<p class="help-block text-center well"> 哦!</p>
<!--{else}-->
<input type="hidden" value="resort" name="action"/>
<input type="hidden" value="resort" name="action">
<table class="layui-table" lay-skin="line">
<thead>
<tr>
<th class='list-table-check-td'>
<input data-auto-none="" data-check-target='.list-check-box' type='checkbox'/>
<input data-auto-none="" data-check-target='.list-check-box' type='checkbox'>
</th>
<th class='text-left'>用户昵称</th>
<th class='text-left'>性别</th>
@ -113,10 +110,10 @@
{foreach $list as $key=>$vo}
<tr>
<td class='list-table-check-td'>
<input class="list-check-box" value='{$vo.id}' type='checkbox'/>
<input class="list-check-box" value='{$vo.id}' type='checkbox'>
</td>
<td class='text-left nowrap'>
<img data-tips-image class="headimg" src="{$vo.headimgurl}"/>
<img data-tips-image class="headimg" src="{$vo.headimgurl}">
{$vo.nickname|default='<span class="color-desc">未设置微信昵称</span>'}
</td>
<td class='text-left'>

View File

@ -3,9 +3,73 @@
{block name="content"}
<form onsubmit="return false;" action="{:request()->url()}" data-auto="true" method="post" class='form-horizontal layui-form padding-top-20'>
<div class="row form-group">
<label class="col-sm-2 control-label label-required">ApiType<br><span class="nowrap color-desc">对接模式</span></label>
<div class="col-sm-8">
{php}
$wechat_type=sysconf('wechat_type')?sysconf('wechat_type'):'api';
$wechat_type=request()->get('appkey')?'thr':'api';
{/php}
{foreach ['api'=>'普通接口参数','thr'=>'第三方授权对接'] as $k=>$v}
<label class="think-radio">
<!--{if $wechat_type eq $k}-->
<input checked type="radio" value="{$k}" name="wechat_type">
<!--{else}-->
<input type="radio" value="{$k}" name="wechat_type">
<!--{/if}-->
{$v}
</label>
{/foreach}
<p class="help-block">如果使用第三方授权对接需要ThinkService项目的支持。</p>
</div>
</div>
<div class="hr-line-dashed"></div>
<div data-api-type="api" class="hide">
<div class="row form-group">
<label class="col-sm-2 control-label">AppId<br><span class="nowrap color-desc">公众号AppId</span></label>
<div class="col-sm-8">
<input type="text" name="wechat_appid" title="请输入以wx开头的18位公众号APPID" placeholder="公众号APPID必填" pattern="^wx[0-9a-z]{16}$" maxlength="18" required="required" value="{:sysconf('wechat_appid')}" class="layui-input">
<p class="help-block">公众号应用ID是所有接口必要参数可以在公众号平台 [ 开发 > 基本配置 ] 页面获取。</p>
</div>
</div>
<div class="row form-group">
<label class="col-sm-2 control-label">AppSecret<br><span class="nowrap color-desc">应用密钥</span></label>
<div class="col-sm-8">
<input type="text" name="wechat_appsecret" required="required" title="请输入32位公众号AppSecret" placeholder="公众号AppSecret必填" value="{:sysconf('wechat_appsecret')}" maxlength="32" pattern="^[0-9a-z]{32}$" class="layui-input">
<p class="help-block">公众号应用密钥是所有接口必要参数,可以在公众号平台 [ 开发 > 基本配置 ] 页面授权后获取。</p>
</div>
</div>
<div class="row form-group">
<label class="col-sm-2 control-label">Token<br><span class="nowrap color-desc">令牌Token</span></label>
<div class="col-sm-8">
<input type="text" name="wechat_token" required="required" title="请输入接口Token(令牌)" placeholder="Token令牌" value="{:sysconf('wechat_token')}" class="layui-input">
<p class="help-block">公众号平台与系统对接认证Token请优先填写此参数并保存然后再在微信公众号平台操作对接。</p>
</div>
</div>
<div class="row form-group">
<label class="col-sm-2 control-label">Encoding<br><span class="nowrap color-desc">AESKey</span></label>
<div class="col-sm-8">
<input type="text" name="wechat_encodingaeskey" title="请输入43位消息加密密钥" placeholder="消息加密密钥,若开启了消息加密时必需填写(可选)" value="{:sysconf('wechat_encodingaeskey')}" maxlength="43" class="layui-input">
<p class="help-block">公众号平台接口设置为加密模式,消息加密密钥必需填写并保持与公众号平台一致。</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">AppUri<br><span class="nowrap color-desc">消息推送接口</span></label>
<div class='col-sm-8'>
<input type="text" name="wechat_appurl" required value="{:url('@wechat/api.push/notify','',true,true)}" title="请输入公众号接口通知URL" placeholder="公众号接口通知URL必填" class="layui-input layui-bg-gray">
<p class="help-block">公众号服务平台接口通知URL, 公众号消息接收与回复等。</p>
</div>
</div>
<div class="hr-line-dashed"></div>
</div>
<div data-api-type="thr" class="hide">
<!--{if !empty($wechat)}-->
<div class="row">
<div class="col-sm-2"></div>
<div class="col-sm-2 control-label">WechatQrc<br><span class="nowrap color-desc">公众号二维码</span></div>
<div class="col-sm-10 padding-bottom-20">
<div class="pull-left padding-right-15 notselect">
<img data-tips-image src="{$wechat.qrcode_url|local_image}" style="width:160px;margin-left:-15px">
@ -20,7 +84,7 @@
</div>
</div>
<div class="row">
<div class="col-sm-2"></div>
<div class="col-sm-2 control-label">TestQrc<br><span class="nowrap color-desc">测试二维码</span></div>
<div class="col-sm-10 padding-bottom-20">
<p class="help-block" style="margin-left:-5px">------- 公众号功能测试 -------</p>
<div class="pull-left padding-right-15 notselect">
@ -35,42 +99,37 @@
</div>
<div class="hr-line-dashed"></div>
<!--{/if}-->
<div class="row form-group">
<label class="col-sm-2 control-label text-right">Authorize<br><span class="nowrap color-desc">绑定授权</span></label>
<label class="col-sm-2 control-label">Authorize<br><span class="nowrap color-desc">绑定授权</span></label>
<div class="col-sm-8">
<button type="button" data-href='{$authurl}' class='layui-btn layui-btn-primary'>{$wechat?'重新绑定公众号':'立即绑定公众号'}</button>
<p class="help-block">点击连接将跳转到微信第三方平台进行公众号授权。</p>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="form-group">
<label class="col-sm-2 control-label">AppId<br><span class="nowrap color-desc">公众号AppId</span></label>
<div class='col-sm-8'>
<input type="text" name="wechat_appid" required value="{$appid}" title="请输入以wx开头的18位公众号APPID" placeholder="公众号APPID必填" pattern="^wx[0-9a-z]{16}$" maxlength="18" class="layui-input">
<input type="text" name="wechat_thr_appid" required value="{$appid}" title="请输入以wx开头的18位公众号APPID" placeholder="公众号APPID必填" pattern="^wx[0-9a-z]{16}$" maxlength="18" class="layui-input">
<p class="help-block">公众号 appid 通过微信第三方授权自动获取. 若没有值请进行微信第三方授权。</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">AppKey<br><span class="nowrap color-desc">应用接口密钥</span></label>
<div class='col-sm-8'>
<input type="text" name="wechat_appkey" required value="{$appkey}" title="请输入32位公众号AppSecret" placeholder="公众号AppSecret必填" maxlength="32" pattern="^[0-9a-z]{32}$" class="layui-input">
<input type="text" name="wechat_thr_appkey" required value="{$appkey}" title="请输入32位公众号AppSecret" placeholder="公众号AppSecret必填" maxlength="32" pattern="^[0-9a-z]{32}$" class="layui-input">
<p class="help-block">公众号服务平台接口密钥, 通过微信第三方授权自动获取, 若没有值请进行微信第三方授权。</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">AppUri<br><span class="nowrap color-desc">消息推送接口</span></label>
<div class='col-sm-8'>
<input type="text" name="wechat_appurl" required value="{$appuri}" title="请输入公众号接口通知URL" placeholder="公众号接口通知URL必填" class="layui-input layui-bg-gray">
<input type="text" name="wechat_thr_appurl" required value="{$appuri}" title="请输入公众号接口通知URL" placeholder="公众号接口通知URL必填" class="layui-input layui-bg-gray">
<p class="help-block">公众号服务平台接口通知URL, 公众号消息接收与回复等。</p>
</div>
</div>
<div class="hr-line-dashed"></div>
</div>
<div class="layui-form-item text-center" style="max-width:1000px">
<button class="layui-btn" type="submit">保存配置</button>
@ -78,4 +137,17 @@
</form>
<script>
$(function () {
updateViwe();
$('[name="wechat_type"]').on('click', updateViwe);
function updateViwe() {
var type = $('[name="wechat_type"]:checked').val();
console.log('[data-api-type="' + type + '"]');
$('[data-api-type]').not($('[data-api-type="' + type + '"]').removeClass('hide')).addClass('hide');
}
});
</script>
{/block}

View File

@ -1,15 +1,12 @@
{extend name='admin@public/content'}
{block name="button"}
<!--{if auth("$classuri/backadd")}-->
<button data-update data-action="{:url('backadd')}" class='layui-btn layui-btn-sm layui-btn-danger'>批量拉黑</button>
<!--{/if}-->
<!--{if auth("$classuri/sync")}-->
<button data-load="{:url('sync')}" class='layui-btn layui-btn-sm'>远程获取粉丝</button>
<!--{/if}-->
{/block}
{block name="content"}

View File

@ -14,9 +14,9 @@
{block name='content'}
<form onsubmit="return false;" data-auto="true" action="{:request()->url()}" method="post">
{if empty($list)}
<!--{if empty($list)}-->
<p class="help-block text-center well"> 哦!</p>
{else}
<!--{else}-->
<input type="hidden" value="resort" name="action"/>
<table class="layui-table" lay-skin="line">
<thead>
@ -94,7 +94,7 @@
</tbody>
</table>
{if isset($page)}<p>{$page|raw}</p>{/if}
{/if}
<!--{/if}-->
</form>
{/block}

View File

@ -15,6 +15,7 @@
namespace service;
use app\wechat\service\FansService;
use function Couchbase\defaultDecoder;
/**
* 微信数据服务
@ -40,8 +41,8 @@ use app\wechat\service\FansService;
* @method \WeChat\Template template() static 模板消息
* @method \WeChat\User user() static 微信粉丝管理
* @method \WeChat\Wifi wifi() static 门店WIFI管理
* @method void wechat static 第三方微信工具
* @method void config static 第三方配置工具
* @method void wechat() static 第三方微信工具
* @method void config() static 第三方配置工具
*/
class WechatService
{
@ -49,18 +50,36 @@ class WechatService
/**
* 获取微信实例ID
* @param string $name 实例对象名称
* @return SoapService
* @return SoapService|string
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public static function instance($name)
{
list($appid, $appkey) = [sysconf('wechat_appid'), sysconf('wechat_appkey')];
switch (strtolower(sysconf('wechat_type'))) {
case 'api':
$config = [
'token' => sysconf('wechat_token'),
'appid' => sysconf('wechat_appid'),
'appsecret' => sysconf('wechat_appsecret'),
'encodingaeskey' => sysconf('wechat_encodingaeskey'),
'mch_id' => sysconf('wechat_mch_id'),
'partnerkey' => sysconf('wechat_partnerkey'),
'ssl_cer' => sysconf('wechat_cert_cert'),
'ssl_key' => sysconf('wechat_cert_key'),
'cachepath' => env('cache_path') . 'wechat' . DIRECTORY_SEPARATOR,
];
$type = '\\WeChat\\' . ucfirst(strtolower($name));
return new $type($config);
case 'thr':
default:
list($appid, $appkey) = [sysconf('wechat_thr_appid'), sysconf('wechat_thr_appkey')];
$token = strtolower("{$name}-{$appid}-{$appkey}");
$location = config('wechat.service_url') . "/wechat/api.client/soap/param/{$token}.html";
$params = ['uri' => strtolower($name), 'location' => $location, 'trace' => true];
return new SoapService(null, $params);
}
}
/**
* 初始化进入授权
@ -71,7 +90,7 @@ class WechatService
*/
public static function webOauth($fullMode = 0)
{
$appid = sysconf('wechat_appid');
$appid = sysconf('wechat_thr_appid');
list($openid, $fansinfo) = [session("{$appid}_openid"), session("{$appid}_fansinfo")];
if ((empty($fullMode) && !empty($openid)) || (!empty($fullMode) && !empty($fansinfo))) {
empty($fansinfo) || FansService::set($fansinfo);
@ -90,6 +109,24 @@ class WechatService
}
}
/**
* 获取当前公众号的AppId
* @return bool|string
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public static function getAppid()
{
switch (strtolower(sysconf('wechat_type'))) {
case 'api':
return sysconf('wechat_appid');
case 'thr':
return sysconf('wechat_thr_appid');
default:
return '';
}
}
/**
* 魔术静态方法实现对象
* @param string $name

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitf5ccf8306b43a082cf18a5c251d77c48::getLoader();
return ComposerAutoloaderInitaf24f5f94ed079e6264991343eebb4cc::getLoader();

View File

@ -159,6 +159,7 @@ return array(
'app\\wechat\\controller\\Review' => $baseDir . '/application/wechat/controller/Review.php',
'app\\wechat\\controller\\Tags' => $baseDir . '/application/wechat/controller/Tags.php',
'app\\wechat\\controller\\api\\Push' => $baseDir . '/application/wechat/controller/api/Push.php',
'app\\wechat\\controller\\api\\Tools' => $baseDir . '/application/wechat/controller/api/Tools.php',
'app\\wechat\\service\\FansService' => $baseDir . '/application/wechat/service/FansService.php',
'app\\wechat\\service\\MediaService' => $baseDir . '/application/wechat/service/MediaService.php',
'app\\wechat\\service\\TagsService' => $baseDir . '/application/wechat/service/TagsService.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitf5ccf8306b43a082cf18a5c251d77c48
class ComposerAutoloaderInitaf24f5f94ed079e6264991343eebb4cc
{
private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInitf5ccf8306b43a082cf18a5c251d77c48
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitf5ccf8306b43a082cf18a5c251d77c48', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitaf24f5f94ed079e6264991343eebb4cc', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitf5ccf8306b43a082cf18a5c251d77c48', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitaf24f5f94ed079e6264991343eebb4cc', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInitaf24f5f94ed079e6264991343eebb4cc::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInitf5ccf8306b43a082cf18a5c251d77c48
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48::$files;
$includeFiles = Composer\Autoload\ComposerStaticInitaf24f5f94ed079e6264991343eebb4cc::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequiref5ccf8306b43a082cf18a5c251d77c48($fileIdentifier, $file);
composerRequireaf24f5f94ed079e6264991343eebb4cc($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequiref5ccf8306b43a082cf18a5c251d77c48($fileIdentifier, $file)
function composerRequireaf24f5f94ed079e6264991343eebb4cc($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48
class ComposerStaticInitaf24f5f94ed079e6264991343eebb4cc
{
public static $files = array (
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
@ -237,6 +237,7 @@ class ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48
'app\\wechat\\controller\\Review' => __DIR__ . '/../..' . '/application/wechat/controller/Review.php',
'app\\wechat\\controller\\Tags' => __DIR__ . '/../..' . '/application/wechat/controller/Tags.php',
'app\\wechat\\controller\\api\\Push' => __DIR__ . '/../..' . '/application/wechat/controller/api/Push.php',
'app\\wechat\\controller\\api\\Tools' => __DIR__ . '/../..' . '/application/wechat/controller/api/Tools.php',
'app\\wechat\\service\\FansService' => __DIR__ . '/../..' . '/application/wechat/service/FansService.php',
'app\\wechat\\service\\MediaService' => __DIR__ . '/../..' . '/application/wechat/service/MediaService.php',
'app\\wechat\\service\\TagsService' => __DIR__ . '/../..' . '/application/wechat/service/TagsService.php',
@ -251,9 +252,9 @@ class ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitf5ccf8306b43a082cf18a5c251d77c48::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInitaf24f5f94ed079e6264991343eebb4cc::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitaf24f5f94ed079e6264991343eebb4cc::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitaf24f5f94ed079e6264991343eebb4cc::$classMap;
}, null, ClassLoader::class);
}