PHP微信扫码登录

微信扫码登录总体说明:先获取token和ticket,通过微信生成二维码接口生成二维码,把二维码信息添加到数据表中,用户扫码时检测二维码扫描状态,扫描成功后更新二维码状态,跳转页面。 

微信开放文档

一、数据表

qrcord表,用户存储二维码信息,每生成一个二维码生成一条记录,通过openid字段判断是否扫描成功,如果openid不为空说明扫描成功,否则扫描失败或者是一条新的二维码,id字段就是下面使用的scene_id,此字段一直存在,作为操作二维码的关键字段。

id    addtime    openid    createtime    updatetime
ID    二维码生成时间    微信id    创建时间    更新时间

二、获取token

逻辑说明:请求微信接口获取token,把获取到token存储到服务器上,并把当前时间一并存储,用于判定token是否失效(因为token是有失效时间的),在调用此方法的时候,把当前时间和token数据库存储的时间(就是获取token的时间)对比,如果当前时间 > 数据库存储时间+7000,单位是秒,说明原来的token已经失效了,需要再重新获取token,并把新的存储到数据库中。

public function access_token()
{
  $time = time();
  $access_token = db::table('access_token')->find();
  $up_time = $access_token['update_time']+7000;
  if($time < $up_time){
    return $access_token;
  }else{
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".AppID."&secret=".AppSecret;
    // $access_token =  http_curl($url,'get');
    $access_token =  http_get_json($url);
    $save['update_time'] = time();
    $save['access_token'] = $access_token['access_token'];
    db::table('access_token')->where('id',1)->update($save);
    return $access_token;
  }

}

三、生成二维码
逻辑说明:① 在生成二维码前,首先生成一条数据插入qrcode表,用于记录二维码状态,数据包括二维码生成时间,插入后返回自增主键ID,把返回的ID赋给变量$scene_id,② 开始生成二维码:拼凑参数:二维码有效时间、二维码类型、二维码详细信息,拼接URL,请求(两个)微信接口生成二维码。

public function qrcode()
{
    //先删除openid为空的垃圾数据 
    Db::table('qrcode')->where(['openid'=>''])->delete();
    //插入数据 - 二维码记录
    $data_insert = [
        'addtime'=>  time(),
    ];

    // 插入新记录,并返回记录id
    $scene_id = Db::table('qrcode')->insertGetId($data_insert); 

    if(!$scene_id){
        return false;
    }
    $token = $this->access_token();
    $access_token = $token['access_token'];
    $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=$access_token";
    // 参数
    $param = array();
    $param['expire_seconds'] = 3600 * 24; //有效时间 
    $param['action_name'] = 'QR_SCENE'; //二维码类型 
    $param['action_info']['scene']['scene_id'] = $scene_id;  //二维码详细信息
    $param = json_encode($param,true);

    // 返回二维码的ticket和二维码图片解析地址
    $ticket_arr = $this->http_curl($url, 'post', 'json', $param);
    //拿ticket换取二维码
    if (empty($ticket_arr['errcode'])) { 
        $ticket = $ticket_arr['ticket'];
       // 通过ticket换取二维码
       $qrcode = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=".$ticket_arr['ticket'];

        $api = array();
        $api['qrcode'] = $qrcode;
        $api['scene_id'] = $scene_id;
        return $api;

    }else { 

       //echo '发生错误:错误代码 ' . $ticket_arr['errcode'] . ',微信返回错误信息:' . $ticket_arr['errmsg']; 
       //   return   apiResponse(110,$ticket_arr['errcode'],$ticket_arr['errmsg']);
       return '110';
    }
}

前端代码:用标签直接显示二维码,隐藏域为scene_id,用于查询二维码信息(包括二维码扫描状态)。

<img src="{$qrcode.qrcode}"  style="width: 250px;box-shadow:0 0 10px #F1F3F4">
<input type="hidden" name="scene_id" id="" value="{$qrcode.scene_id}" />

四、扫码,并接收回调
说明:生成二维码后,用户可以扫描二维码,如果扫描之后,微信服务器会收到,并返回信息,就是返回到事先填写在微信公众号上的回调地址,注意这个地址是可以公开访问的,不能有验证,否则微信服务器无法返回消息给回调地址。

回调方法处理逻辑:接收微信服务器返回的消息,返回的消息格式默认是xml,需要把它转换成对象格式,返回的信息包括EventKey,FormUserName,ToUserName,Event。根据scene_id修改qrcode表信息,主要是添加openid,表示该二维码已被用户扫码成功。

public function wxBack()
    {
        $postStr = file_get_contents('php://input'); // 获取请求体

        //写入文件
       // file_put_contents('./uploads/weixin.log', $postStr."\r\n", FILE_APPEND); // 将信息追加到文件末尾
        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);

        $scene_id = $postObj->EventKey;

        $openid = $postObj->FromUserName;   //openid

        $ToUserName = $postObj->ToUserName;  //公众号

        $Event = strtolower($postObj->Event);   //事件类型

        //添加扫码记录
        $res = Db::table('qrcode')->where('id',$scene_id)->update(['openid'=>$openid,'createtime'=>time()]);
    }

五、检测二维码是否扫描成功
逻辑说明:使用函数每隔2秒执行一次查询一次二维码扫描状态,在后端通过scene_id查询qrcode表里的openid,如果对应的openid列为空,说明这是一个新的二维码,还没有用户扫描,如果对应的openid列不为空说明已经被扫描,扫码成功,那就推送消息并跳转页面。

前端代码 

// 每2秒查询一次数据表用户是否已经扫码
$(document).ready(function(){
    c = setInterval(check_login,2000);   //每2秒执行一次
});

//检测用户是否已扫描
function check_login() { 

        var scene_id=$("input[name='scene_id']").val();

        $.ajax({
            url:'check_login2',   //请求地址
            data:{scene_id:scene_id},   //发送的数据
            type:'POST',     //请求的方式
            dataType:'JSON',
            success:function(res){
                // console.log(res)
                if(res.code == '200'){  //已完成推送
                    layer.msg(res.message, {
                      icon: 1,
                      time: 2000 //2秒关闭(如果不配置,默认是3秒)
                    }, function(){
                      window.location.href='/teacher/index/index';
                    });
                    window.clearInterval(c); //终止
                }else if(res.code == '110'){
                    layer.msg(res.message, {
                      icon: 2,
                      time: 2000 //2秒关闭(如果不配置,默认是3秒)
                    })

                    window.clearInterval(c); //终止

                    setTimeout(function(){
                        window.location.reload();//刷新当前页面. 100s
                    },3000)

                }
            }     
       })
}

后端代码

    public function check_login2(){
         if (request()->isPost()) {

             $scene_id = input('post.scene_id');
             // 获取二维码信息
            $res = model('Login')->getQrcodeInfo($scene_id);
            if (!empty($res['openid'])) {

                        //推送登录成功消息
                        $token = access_token();
                        $access_token = $token['access_token'];
                      //  微信推送
                        $url="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access_token;

                        $post_data = array(

                            "touser"=>$user['openid'], //推送给谁,openid

                            "template_id"=>"xxxxxx", //微信后台的模板信息id      

                            "data"=> array(
                                "first" => array(
                                    "value"=>"账号登录成功 - 首医中医药研学平台",
                                    "color"=>"#888"
                                ),
                                "keyword1"=>array(
                                    "value"=>$user['name'], //传的变量
                                    "color"=>"#888"
                                ),
                                 "keyword2"=>array(
                                    "value"=> date("Y.m.d H:i:s",time()),
                                    "color"=>"#888"
                                ), 
                                "keyword3"=>array(
                                    "value"=>'教师', //传的变量
                                    "color"=>"#888"
                                ),
                                "remark"=>array(
                                    "value"=> '您已成功登录!',
                                    "color"=>"#888"
                                ),  
                            )

                        );
                        //将上面的数组数据转为json格式
                        $post_data = json_encode($post_data);

                        //发送数据,post方式
                        //配置curl请求
                        $ch = curl_init();
                        curl_setopt($ch,CURLOPT_URL,$url);
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设置有返回值,0,直接显示
                        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0); //禁用证书验证
                        curl_setopt($ch,CURLOPT_POST,1);
                        curl_setopt($ch,CURLOPT_POSTFIELDS,$post_data);

                        //接收执行返回的数据
                        $res = curl_exec($ch);

                        //关闭句柄
                        curl_close($ch);

                        // return apiResponse('200','登录成功');
                        return apiResponse('200','登陆成功,正在跳转...');
                    }


            }else{
                return apiResponse('100','操作失败,请刷新页面重试!');
            }

         }else{
             return apiResponse('110','非法请求');
         }
     }

 

PHP微信扫码登录

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值