PHP 扫描微信公众号二维码,关注并自动登录网站

摘要: 场景:用户扫描微信公众号的二维码,关注后自动登录网站,若已关注则直接登录。 逻辑: 1.系统生成带参数(此参数自定义为唯一值)的临时二维码(微信公众平台有提供该接口,可查看一下开发文档);

场景:用户扫描微信公众号的二维码,关注后自动登录网站,若已关注则直接登录。[如果有不明白的小伙伴可以添加:17762131 ]

逻辑:

1.系统生成带参数(此参数自定义为唯一值)的临时二维码(微信公众平台有提供该接口,可查看一下开发文档);

2.用户使用微信扫描该二维码,关注后微信服务器会将数据(自定义参数、openid...)返回到我们的服务器;

3.我们服务器将接收到的openid再次向微信服务器发起请求,获取该用户的信息(昵称、头像、地域、unionid(若绑定了微信开放平台,则有此参数));

4.我们将返回的用户信息存储到数据库,用作于登录。

5.测试号申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

准备工作:登录微信公众平台,在基本配置下,查看appid和设置appsecret、回调URL、token(token的验证方法上篇文章有提及[链接]),小编这里使用的是测试账号,因为正式的要审核(收费300个大洋),如下图:

1566701685670239.png

1566701835952943.png

下面直接贴上小编写的一个类WeChat.class.php:

<?php
// +----------------------------------------------------------------------
// | 微信公众平台开发
// | 1.发送模板短信
// | 2.获取微信用户信息
// | 3.微信授权登录获取openId和unionId
// | 4.关注微信公众号,并自动登录网站
// +----------------------------------------------------------------------
// | Copyright (c) 2019 http://bubukou.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: lrfun <17762131@qq.com>
// +----------------------------------------------------------------------
// | UpdateDate: 2019-8-25
// +----------------------------------------------------------------------

Class WeChat{
   
 protected $appid;
 protected $secret;
 protected $accessToken;
   
 function __construct(){
 $this->appid       = "***";
 $this->secret      = "***";
 $this->accessToken = $this->getAccessToken();
   }
   
 /***
    * 获取access_token
    * token的有效时间为2小时,这里可以做下处理,提高效率不用每次都去获取,
    * 将token存储到缓存中,每2小时更新一下,然后从缓存取即可
    * @return
 **/
 private function getAccessToken(){
 $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appid."&secret=".$this->secret;
 $res = json_decode($this->httpRequest($url),true);
 return $res['access_token'];
   }
   
 /***
    * POST或GET请求
    * @url 请求url
    * @data POST数据
    * @return
 **/
 private function httpRequest($url, $data = ""){
 $curl = curl_init();
 curl_setopt($curl, CURLOPT_URL, $url);
 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
 if(!empty($data)){ //判断是否为POST请求
 curl_setopt($curl, CURLOPT_POST, 1);
 curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
      }
 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
 $output = curl_exec($curl);
 curl_close($curl);
 return $output;
   }
   
 /***
    * 获取openID和unionId
    * @code 微信授权登录返回的code
    * @return
 **/
 public function getOpenIdOrUnionId($code){
 $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->secret."&code=".$code."&grant_type=authorization_code";
 $data = $this->httpRequest($url);
 return $data;
   }
   
 /***
    * 通过openId获取用户信息
    * @openId
 * @return
 **/
 public function getUserInfo($openId){
 $url  = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$this->accessToken."&openid=".$openId."&lang=zh_CN";
 $data = $this->httpRequest($url);
 return $data;
   }
   
 /***
    * 发送模板短信
    * @data 请求数据
    * @return
 **/
 public function sendTemplateMessage($data = ""){
 $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$this->accessToken;
 $result = $this->httpRequest($url, $data);
 return $result;
   }
   
 /***
    * 生成带参数的二维码
    * @scene_id 自定义参数(整型)
    * @return
 **/
 public function getQrcode($scene_id){
 $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$this->accessToken;
 $data = array(
 "expire_seconds" => 3600, //二维码的有效时间(1小时)
 "action_name" => "QR_SCENE",
 "action_info" => array("scene" => array("scene_id" => $scene_id))
      );
 $result = $this->httpRequest($url, json_encode($data));
 return $result;
   }
   
 /***
    * 生成带参数的二维码
    * @scene_str 自定义参数(字符串)
    * @return
 **/
 public function getQrcodeByStr($scene_str){
 $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$this->accessToken;
 $data = array(
 "expire_seconds" => 3600, //二维码的有效时间(1小时)
 "action_name" => "QR_STR_SCENE",
 "action_info" => array("scene" => array("scene_str" => $scene_str))
      );
 $result = $this->httpRequest($url, json_encode($data));
 return $result;
   }
   
 /**
    * 换取二维码
    * @ticket
 * @return
 */
 public function generateQrcode($ticket){
 return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=".$ticket;
   }
   
 /***
    * 回调函数
    **/
 public function callback(){
 $callbackXml = file_get_contents('php://input'); //获取返回的xml
 $data = json_decode(json_encode(simplexml_load_string($callbackXml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); //将返回的xml转为数组

 if(count($data)){
 if($data['Event'] && $data['Event'] == 'subscribe') {
 $toUser = $data['FromUserName'];
 $fromUser = $data['ToUserName'];
 $time = time();
 $msgType = 'text';
 $content = '好嗨哟,您终于来啦!';
 $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
            $info = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
            echo $info;
         }
         $userInfo = $this->getUserInfo($data['FromUserName']); //获取用户信息
         //这里把返回的数据写入数据库(注:务必将“EventKey”也存到数据表中,后面检测登录需用到此唯一值查询记录)
         //用于前台做检测该用户扫码之后是否有关注公众号,关注了就自动登录网站
         //原理:前台通过自定义的参数(最好设成值唯一)查询数据标是否有此记录,若有则登录。
         return $userInfo;
      }
   }
   
   public function callback_(){
//    $postStr = file_get_contents('php://input');
      $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
      $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
      $scene_id = str_replace("qrscene_", "", $postObj->EventKey);
      
      $openid = $postObj->FromUserName; //openid
      $ToUserName = $postObj->ToUserName;  //转换角色
      $Event = strtolower($postObj->Event);
   
      $data = array(
         'scene_id'=>$scene_id,
         'openid'=>$openid,
         'ToUserName'=>$ToUserName,
         'is_first'=>'1',
         'Event'=>$Event
      );
      return json_encode($data);
   }
   
   //消息回复
   function responseMsg() {
      //1.获取到微信推送过来post数据(xml格式)
      $postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
      //2.处理消息类型,并设置回复类型和内容
      $postObj = simplexml_load_string($postArr, 'SimpleXMLElement', LIBXML_NOCDATA);
      //判断该数据包是否是订阅de事件推送
      if (strtolower($postObj->MsgType) == 'event') {
         //如果是关注 subscribe事件
         if (strtolower($postObj->Event) == 'subscribe') {
            $toUser = $postObj->FromUserName;
            $fromUser = $postObj->ToUserName;
            $time = time();
            $msgType = 'text';
            $content = '欢迎关注我的微信公众号!';
            $template = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            </xml>";
            $info = sprintf($template, $toUser, $fromUser, $time, $msgType, $content);
            echo $info;
         }
      }
   }

   // 开发者模式绑定校验
   function bindServerCheck($token) {
      $signature = $_GET["signature"];
      $timestamp = $_GET["timestamp"];
      $nonce = $_GET["nonce"];
      $tmpArr = array(
         $token,
         $timestamp,
         $nonce
      );
      sort($tmpArr);
      $tmpStr = implode($tmpArr);
      $tmpStr = sha1($tmpStr);
      if ($tmpStr == $signature) {
         return true;
      } else {
         return false;
      }
   }
}

        生成二维码:

<?php
    header("Content-type:text/html;charset=utf-8");
    require_once('WeChat.class.php');
    $WeChat = new WeChat();
    $scene_str = "d1blog190825"; //"d1blog.com" . time(); //这里建议设唯一值(如:随机字符串+时间戳)
    $result = json_decode($WeChat->getQrcodeByStr($scene_str), true);
    $qrcode = $WeChat->generateQrcode($result['ticket']); //生成二维码
     
    echo "自定义参数:".$scene_str;
    echo "<br/><img src=\"$qrcode\">";
?>
<script type="text/javascript" src="./js/jquery.min.js"></script>
<script type="text/javascript">
    setInterval("checkLogin()", 2000); //每2秒发送一次请求
    function checkLogin(){
        $.post("checkLogin.php", {scene_str:"<?=$scene_str?>"}, function(data){
            if(data){
                //做逻辑判断,登录跳转
            }
        },"Json");
    }
</script>


回调函数 微信的基本配置-》接口地址【用户关注和取消关注微信返回服务器的数据接收地址】:

require_once('WeChat.class.php');
$WeChat = new WeChat();
$result = $WeChat->callback();

检查登录状态:

if(isset($_POST['scene_str']) && $_POST['scene_str']){
   //根据scene_str查询数据库,是否有此记录
   echo "true";
}else{
   echo "false";
}


本文由 帝一博客 原创发布。用户在本站发布的原创内容(包括但不仅限于回答、文章和评论),著作权均归用户本人所有。独家文章转载,请联系邮箱:17762131@qq.com。获得授权后,须注明本文地址: https://bubukou.com/phpjiqiao/1341.html

网友留言评论

0条评论