微信扫码关注公众号登录PC网站思路详解(||使用开放平台)
方案一:使用微信开放平台
1)具体实现方法请看我前两天的文章。
方案二:使用微信公众号
客户有一个PC端网站,想在网站加上扫码登录为公众号引流,怎么实现?使用第一种方法,扫码登录可以,但是引不了流啊。下面介绍如何使用微信公众号实现扫码登录网站。
1)首先,登录微信的管理平台 https://mp.weixin.qq.com
2)开发 - 基本配置 - 服务器配置,你想办法给启用咯
如果不知道咋启用就去百度搜搜去,记得之前写过如何启用的文章,可以翻翻找找 (服务器配置启用后,用户的关注,取关,发消息等等事件都会被微信服务器转发到你自己设置的URL上,需要你在处理后,返回给用户相应的信息,且自动回复,自定义菜单等都会失效)
3)开始写API (这 是 一 个 划 水 的 标 题)
4)生成登录二维码(使用微信带参数的二维码功能来实现)
use EasyWeChat\Factory;
// 创建登录二维码
public function createMpLoginQrCode()
{
$ip = Request::ip();
$id = self::createID($ip);
$config = [
'app_id' => '你的app id',
'secret' => '你的app srcret',
];
$app = Factory::officialAccount($config);
$result = $app->qrcode->temporary($id, 600); // 生成临时二维码 有效时间10分钟,这里是秒数,可以自己修改,临时最高为1个月
if (!isset($result['ticket'])) error('二维码请求失败,网络繁忙');
$url = $app->qrcode->url($result['ticket']);
$content = file_get_contents($url); // 得到二进制图片内容
success(['qrcode' => base64_encode($content), 'id' => $id]);
}
private function createID($ip)
{
$id = md5(time() . $ip . rand(0, 999));
if (Cache::has($id)) {
return self::createID($ip);
}
return $id;
}
// 查询登录结果
public function getLoginResult()
{
$id = input('id') ?? error('参数错误:id');
if (Cache::has($id)) {
success(Cache::get($id));
}
success(['status' => 0]);
}
注意:
API返回的二维码是base64的,需要前端加个base64图片头 jpg png都行
ID是前端请求扫码状态的唯一依据,需要前端页面每隔1秒 查询一次登录结果
5)处理微信服务器通知
<?php
namespace app\index\controller;
use EasyWeChat\Factory;
use think\Db;
use think\facade\Cache;
class Wechat
{
// 这里是你设定的微信扫码通知URL
public function index()
{
$config = [
'app_id' => '你的app id',
'secret' => '你的app secret',
'token' => '你的服务器配置的 token',
// 'aes_key' => '你的 aes_key ,如果服务器配置 是非明文模式,这个需要填上',
'response_type' => 'array',
];
$app = Factory::officialAccount($config);
$app->server->push(function ($message) {
switch ($message['MsgType']) {
case 'event':
self::event($message);
return '欢迎关注super!';
break;
default:
return '欢迎关注super!';
break;
}
});
$response = $app->server->serve();
$empty = strpos($response, '<Content></Content>');
$success = strpos($response, 'success');
if (!$empty && !$success) {
return $response;
} else {
echo '';
}
exit;
}
public function event($data)
{
$event = $data['Event'];
$open_id = $data['FromUserName'];
switch ($event) {
case 'subscribe':
$id = explode('_', $data['EventKey'])[1];
self::userLogin($open_id, $id);
break;
case 'unsubscribe':
break;
case 'SCAN':
self::userLogin($open_id, $data['EventKey']);
break;
}
}
// 这里的$id 是咱们在第4步生成的id(用来请求登录状态那个),它通过微信的二维码带过来了,是贯穿全局的唯一标识
public function userLogin($open_id, $id)
{
// 查询用户是否注册
$user_info = Db::name('users')
->where('open_id', $open_id)
->field(['user_id'])
->find();
if ($user_info) {
// 修改缓存内容,前端获取登录结果
Cache::set($id, ['status' => 1, 'user_id' => $user_info['user_id']]);
} else {
$array = [
'type' => 1,
'open_id' => $open_id,
'reg_time' => time()
];
$user_id = Db::name('users')->insertGetId($array);
if ($user_id) {
// 修改缓存内容,前端获取登录结果
Cache::set($id, ['status' => 1, 'user_id' => $user_id]);
} else {
// 修改缓存内容,前端获取登录结果
Cache::set($id, ['status' => 2, 'msg' => '网络繁忙,请稍后重试']);
}
}
}
}
6)业务场景区分
vue:其实可以在最后一步中 生成token 存到缓存里面,而不用返回user_id,前端页面在拿到token后直接存进本地存储
普通html:在前端拿到user_id(或者可以生成一个随机不重复的秘钥,存到user表里面,不直接返回给前端user_id)后,可以跳转一个中间页,user_id作为参数找到用户信息把session存上,然后再进行刷新操作。
但是这样风险太高,用户网速过慢就能清楚的看到中间页地址栏中的user_id,那恰好这个叼毛是一个程序员,特意在控制台中调慢网速,截图记录你的中间页路由,那么他就可以使用路由+user_id随意的登录了,user_id试个遍想登谁的登谁的。这样肯定是不安全的,所以说,还是不建议直接返回user_id,在最后一步生成一个不重复的秘钥,跳转到中间页的时候,参数也使用秘钥去查用户信息,然后再存session,秘钥长一点不容易试出来。
(咳咳,如果你觉得这个文章有用,标题和文章正文中间的那什么,帮忙点一下啦,好兄弟gkd)