关注公众号自动登录
上代码
前端部分代码
<script>
// 方便清除轮询
let timer = null
// 请求登录二维码
$('.wechat-login').click(function () {
$.get("{{ route('wechat.login.pic') }}", function (result) {
console.log(result)
// 显示二维码图片
$('.wechat-url').attr('src', result.url)
// 轮询登录状态
timer = setInterval(() => {
// 请求参数是二维码中的场景值
$.ajax({
type: "GET",
url: "{{ route('admin.login.check') }}",
data: {
'wechat_flag': result.weChatFlag
},
dataType: "json",
success: function (result) {
if (result.status == 'success') {
// alert(result.message)
window.location.href = result.data
} else if (result.status == 'error') {
alert(result.message)
window.location.reload()
}
},
error: function (e) {
console.log(e)
}
});
}, 2000)
})
})
// 返回时清除轮询
$('.wechat-back').click(function () {
clearInterval(timer)
})
</script>
后端部分代码
<?php
namespace App\Http\Controllers\Api;
use App\Models\AdminUser;
use Dcat\Admin\Models\Administrator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use App\Models\WeChatUser;
use Cache;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Dcat\Admin\Admin;
class WechatController extends Controller
{
//
protected $app;
/**
* Construct
*
* WeChatController constructor.
*/
public function __construct()
{
$this->app = app('wechat.official_account');
}
/**
* 获取二维码图片
*
* @param Request $request
*
* @return \Illuminate\Http\JsonResponse
* @throws \Exception
*/
public function getWxPic(Request $request)
{
// 查询 cookie,如果没有就重新生成一次
if (!$weChatFlag = $request->cookie(WeChatUser::WECHAT_FLAG)) {
$weChatFlag = (string)Str::uuid();
}
// // 缓存微信带参二维码
if (!$url = Cache::get(WeChatUser::QR_URL . $weChatFlag)) {
// // 有效期 1 天的二维码
$qrCode = $this->app->qrcode;
$result = $qrCode->temporary($weChatFlag, 3600 * 24);
// 图片链接
$url = $qrCode->url($result['ticket']);
Cache::put(WeChatUser::QR_URL . $weChatFlag, $url, now()->addDay());
}
return response(compact('url', 'weChatFlag'))
->cookie(WeChatUser::WECHAT_FLAG, $weChatFlag, 24 * 60);
}
/**
* 微信消息接入(这里拆分函数处理)
*
* @return \Symfony\Component\HttpFoundation\Response
* @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \ReflectionException
*/
public function serve()
{
$app = $this->app;
$app->server->push(function ($message) {
if ($message) {
$method = Str::camel('handle_' . $message['MsgType']);
if (method_exists($this, $method)) {
$this->openid = $message['FromUserName'];
return call_user_func_array([$this, $method], [$message]);
}
//Log::info('无此处理方法:' . $method);
}
});
return $app->server->serve();
}
/**
* 事件引导处理方法(事件有许多,拆分处理)
*
* @param $event
*
* @return mixed
*/
protected function handleEvent($event)
{
$method = Str::camel('event_' . $event['Event']);
if (method_exists($this, $method)) {
return call_user_func_array([$this, $method], [$event]);
}
//Log::info('无此事件处理方法:' . $method);
}
/**
* 取消订阅
*
* @param $event
*/
protected function eventUnsubscribe($event)
{
$weChatUser = WeChatUser::whereOpenid($this->openid)->first();
$weChatUser->subscribe = 0;
$weChatUser->subscribe_time = null;
$weChatUser->save();
}
/**
* 扫描带参二维码事件
*
* @param $event
*/
public function eventSCAN($event)
{
if ($weChatUser = WeChatUser::whereOpenid($this->openid)->first()) {
//Log::info($weChatUser);
// 标记前端可登陆
$this->markTheLogin($event, $weChatUser);
return '「'.$weChatUser->nickname . '」登录乐校系统成功!';
}
}
/**
* 订阅
*
* @param $event
*
* @throws \Throwable
*/
protected function eventSubscribe($event)
{
$openId = $this->openid;
$weChatUser = WeChatUser::whereOpenid($openId)->first();
if ($weChatUser) {
// 标记前端可登陆
$this->markTheLogin($event, $weChatUser);
return;
}
// 微信用户信息
$weChatUser = $this->app->user->get($openId);
// 注册
$result = DB::transaction(function () use ($openId, $event, $weChatUser) {
$nickname = filterEmoji($weChatUser['nickname']);
$uid = (string)Str::uuid();
// 用户
$user = AdminUser::create([
'username' => $uid,
'password' => Hash::make(time()),
'name' => $nickname,
'avatar' => $weChatUser['headimgurl'],
]);
// 用户信息
$weChatUser = $user->weChatUser()->create([
'openid' => $openId,
'nickname' => $nickname,
'subscribe' => $weChatUser['subscribe'],
'sex' => $weChatUser['sex'],
'city' => $weChatUser['city'],
'province' => $weChatUser['province'],
'country' => $weChatUser['country'],
'headimgurl' => $weChatUser['headimgurl'],
'subscribe_time' => date('Y-m-d H:i:s', $weChatUser['subscribe_time']),
'remark' => $weChatUser['remark']
]);
// 用户权限
DB::table('admin_role_users')->insert([
'role_id' => 4,
'user_id' => $user->id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
Log::info('用户注册成功 openid:' . $openId);
$this->markTheLogin($event, $weChatUser);
});
Log::debug('SQL 错误: ', [$result]);
}
/**
* 标记可登录
*
* @param $event
* @param $uid
*/
public function markTheLogin($event, $weChatUser)
{
if (empty($event['EventKey'])) {
return;
}
$eventKey = $event['EventKey'];
// 关注事件的场景值会带一个前缀需要去掉
if ($event['Event'] == 'subscribe') {
$eventKey = Str::after($event['EventKey'], 'qrscene_');
}
// 标记前端可登陆
Cache::put(WeChatUser::LOGIN_WECHAT . $eventKey, $weChatUser, now()->addMinute(30));
}
/**
* 微信用户登录检查
*
* @param Request $request
*
* @return bool|\Illuminate\Http\JsonResponse
*/
public function adminLoginCheck(Request $request)
{
// 判断请求是否有微信登录标识
if (!$flag = $request->wechat_flag) {
return $this->successResponse('二维码过期,请刷新页面重新扫描', false);
}
// 根据微信标识在缓存中获取需要登录用户的 UID
if (!$weChatUser = Cache::get(WeChatUser::LOGIN_WECHAT . $flag)) {
return $this->successResponse('请刷新页面重新扫描', false);
}
$user = $weChatUser->admin_user;
if (empty($user)) {
return $this->successResponse('请重新关注关注公众号', false);
}
Auth::guard(config('admin.auth.guard') ?: 'admin')->login($user, true);
Cache::forget(WeChatUser::LOGIN_WECHAT . $flag);
Cache::forget(WeChatUser::QR_URL . $flag);
return $this->successResponse('登陆成功', true);
}
/**
* 微信用户登录检查
*
* @param Request $request
*
* @return bool|\Illuminate\Http\JsonResponse
*/
public function loginCheck(Request $request)
{
}
}