实现功能:
将微信二维码事件用作微信扫码登陆!!!
背景思路:
1、微信公众号获取用户信息需要微信浏览器打开才能获取
2、pc端使用微信登陆,需要微信开发者这个,认证需要每年300,实际上只有扫码登陆功能是有用的
3、微信二维码事件,可以根据二维码的信息,用户扫码之后可以根据二维码记录的信息处理业务需求
4、使用微信公众号的二维码做PC端的扫码登陆,理论上是没问题的
思路一:
1、生成用户登陆二维码
2、用户扫码之后记录session
3、前端启用定时器,后台检测有session,返回跳转链接到前台,前台跳转
开发的时候发现,用户扫码之后,记录了session,登陆控制器并不能获取到这个session,what the fuck!
居然如此那就创建一张数据表来记录吧!
创建扫码登陆记录表 login
CREATE TABLE `login` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`openid` varchar(45) DEFAULT NULL,
`uid` int(11) DEFAULT NULL COMMENT '用户id',
`code` varchar(32) DEFAULT NULL COMMENT '唯一code',
`create_time` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
前端HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="icon" href="__HOME__/img/favicon.ico"/>
<title>微信登录</title>
<style>
.impowerBox{
display:inline-block;vertical-align:middle
}
p{margin:0;font-weight:400}
img{border:0}
body{font-family:"Microsoft Yahei";color:#fff;background:0 0}
.impowerBox{line-height:1.6;position:relative;width:100%;z-index:1;text-align:center}
.impowerBox .title{text-align:center;font-size:20px}
.impowerBox .qrcode{width:280px;margin-top:15px;border:1px solid #E2E2E2}
.impowerBox .info{width:280px;margin:0 auto}
.impowerBox .status{padding:7px 14px;text-align:left}
.impowerBox .status.normal{margin-top:15px;background-color:#232323;border-radius:100px;-moz-border-radius:100px;-webkit-border-radius:100px;box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444;-moz-box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444;-webkit-box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444}
.impowerBox .status.status_browser{text-align:center}
.impowerBox .status p{font-size:13px}
</style>
</head>
<body style="background-color: rgb(51, 51, 51); padding: 50px;">
<div class="impowerBox">
<div class="title">微信登录</div>
<img class="qrcode" src="{$login.img}" id="wxewm">
<input type="hidden" name="code" value="{$login.code}">
<div class="info">
<div class="status status_browser normal">
<p>1、请使用微信扫描二维码登录</p>
<p>2、关注“五五科技”公众号</p>
</div>
</div>
</div>
<script src="//cdn.bootcss.com/jquery/1.12.1/jquery.min.js"></script>
<script type="text/javascript">
var t1 ='';
$(function() {
//轮询扫码后的登录
t1 = window.setInterval("login()",2000);//使用字符串执行方法
setTimeout("end()",300000);
});
function end(){ //如果超过一定时间不扫码,停止轮询,提示过期
$('#wxewm').hide(); //隐藏二维码
clearInterval(t1); //停止轮询
$('.status_browser').html('<p>二维码已经过期,请刷新</p>'); //提示二维码过期
}
// window 失去焦点,停止输出
window.onblur = function() {
clearInterval(t1);
};
// window 每次获得焦点
window.onfocus = function() {
t1 = window.setInterval("login()",2000);//使用字符串执行方法
};
function login(){ //不停发送请求,获取扫码人的信息,如果扫码了获取信息停止轮询,
var code =$('input[name=code]').val();
var url = "{:U('Home/Login/checkLogin')}";
$.post(url,{code:code},function(data){
if(data.status){
window.location.href=data.url;
}
});
}
</script>
</body>
</html>
login控制器
#微信扫码登录
public function login(){
$code = "LOGIN_".substr(strtoupper(md5(date('Y-m-d H:i:s', time()) . mt_rand())), -16);
$img = $this->getqcode($code);
$data['code'] = $code;
$data['img'] = $img;
$this->assign('login',$data);
$this->display();
}
#获取二维码
public function getqcode($code){
$errmsg = $this->WechatAuth->qrcodeCreate('QR_STR_SCENE',$code,300);
if($errmsg['errcode']==0){
$img = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket='.$errmsg['ticket'];
return $img;
}else{
return false;
}
}
public function checkLogin(){
$code = trim(I('post.code'));
if(empty($code)){
$this->ajaxReturn(array('status'=>0,'msg'=>'code不存在'));
}
$uid = M('login')->where(['code'=>$code])->getField('uid');
$url = $this->backUrl();
if(!$url){
$url = C('DOMAIN').U('Home/Company/index');
}
if($uid){
//将code置为null 方便下次扫码
M('login')->where(['uid'=>$uid])->setField('code',null);
$user_info = M('user')->find($uid);
if($user_info){
session('user_info', $user_info);
session('user_uid',$user_info['id']);
$this->ajaxReturn(array('status'=>1,'msg'=>'登录成功,马上为您跳转..^_^','url'=>$url));
}
}
$this->ajaxReturn(array('status'=>0,'msg'=>'无登录信息'));
}
微信控制器
/**
* 微信入口
*/
public function index(){
$this->wechat->valid();//明文或兼容模式可以在接口验证通过后注释此句,但加密模式一定不能注释,否则会验证失败
$wx_data = $this->wechat->getRev()->getRevData(); //获取微信数据
$openid = $wx_data['FromUserName'];
$wx_userinfo = $this->getUserByopenid($openid);
if(!$wx_userinfo){
$wx_userinfo = $this->wechat->getUserInfo($openid);
if(!$wx_userinfo){
Log::write('miss userInfo', 'ERR', '', C('LOG_DATA_PATH') . 'weixin/error/' .date('Ym') .'/'. date('md') . '.log');
$this->WechatAuth->sendText(C('WX_JINGZHI'),"获取用户信息失败!");
M('access_token')->delete();
}
if($wx_userinfo){
//添加用户
$user_id = $this->addUser($wx_userinfo);
exit;
}
}
if(!$wx_userinfo){
exit;
}
$type = $wx_data['MsgType']; //消息类型
switch ($type) {
case Wechat::MSGTYPE_EVENT:
//事件消息类型
$event_type = $wx_data['Event'];
switch ($event_type) {
case Wechat::EVENT_SUBSCRIBE: //微信关注事件
$event_key = $wx_data['EventKey'];
if ($event_key != '') {
$event_key = strtoupper($event_key);
$event_key = str_replace('QRSCENE_', '', $event_key);
//带参二维码关注,跳转二维码事件
$this->qrcode($event_key,$wx_userinfo);
exit;
} else {
$this->wechat->text('Hi,'.$wx_userinfo['nickname'].'!欢迎关注五五科技!')->reply();exit;
}
break;
case Wechat::EVENT_SCAN: //关注后二维码事件
if ($wx_data['EventKey'] != '') {
$event_key = strtoupper($wx_data['EventKey']);
$this->qrcode($event_key,$wx_userinfo);
exit;
}
break;
}
break;
default:
$this->wechat->text('Hi,'.$wx_userinfo['nickname'].'!欢迎关注五五科技!')->reply();exit;
exit;
break;
}
}
/**
* 二维码扫描回复
* @param $qrkey 二维码所带参数
* @param $userInfo 用户信息
*/
public function qrcode($event_key,$wx_userinfo){
if(strstr($event_key, 'LOGIN_')){
$res = $this->login($event_key,$wx_userinfo);
$data['openid'] = $wx_userinfo['openid'];
$data['create_time'] = time();
if($res){
$data['project_name'] = "扫码登录成功";
$data['url'] = C('DOMAIN').U('Home/Company/index');
//发送微信模板消息
$this->wxMsg->organSend(1,$data);exit;
}else{
$data['project_name'] = "扫码失败,请稍后再试";
$this->wxMsg->organSend(1,$data);exit;
}
}
exit;
}
//登录
public function login($code,$userInfo){
$user_id = $this->getUserId($userInfo);
if(empty($user_id)){
return false;
}
if(empty($userInfo['openid'])){
return false;
}
$login_id=M('login')->field('id')->where(['openid'=>$userInfo['openid']])->getField('id');
if(!$login_id){
$data['openid'] = $userInfo['openid'];
$data['uid'] = $user_id;
$data['code'] = $code;
$data['create_time'] = time();
$res = M('login')->add($data);
}else{
$res = M('login')->where(['openid'=>$userInfo['openid']])->setField('code',$code);
}
if($res !== false){
return true;
}else{
return false;
}
}