PHP对接微信公众号 进行登录操作

1.准备好公众号的appid和appsecret,以及IP白名单

2.php代码写入


 
    public function login_wx()
    {
        
        $data = Db::name('config')->where('config_key','WECHAT_CONFIG')->find();
        $value = json_decode($data['value'],true);
        $appid = $value['appid'];
        $appsecret =  $value['appsecret'];
        
        $sceneId = uniqid();
        $token = bin2hex(random_bytes(16));
 


      
        $url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        $access_token = $this->getAccessToken($appid, $appsecret);
        $ticket = $this->getQRTicket($access_token,'604800',$sceneId);
        $qrCodeURL = $this->getQRCode($ticket);
 
        $data = [
          'sceneid'=>$sceneId,  
          'token'=>$token,
           'ctime'=>time(),
           'dtime'=>time() + 300,
        ];
        $res = Db::name('wxlogin')->insert($data);
        
        $returns = [
          'token'=>$token,  
          'url'=>$qrCodeURL,
        ];
        
        if($res){
            return json_encode($returns);
        }

    }
    
    //验证用户
    public function checkLogin() {
        
        var_dump($_REQUEST);die;
        $token = $_REQUEST['token'];
        
        $data = Db::name('wxlogin')->where('token',$token)->find();
        
        if($data['status'] == 1){  //已经登录
            $returns = [
               'code'=>1,
               'msg'=>'已登录',  
            ];
        }
        if($data['status'] == 3){  //二维码已过期
            $returns = [
               'code'=>3,
               'msg'=>'二维码已过期',  
            ];
        }
        if($data['status'] == 2){  //未登录
             $returns = [
               'code'=>2,
               'msg'=>'未登录',  
            ];
        }
        return json_encode($returns);
   
   
    }

    
    

    public function getQRCode($ticket) {
        $url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" . urlencode($ticket);
        return $url; // 这个URL即为二维码图片的URL
    }


    public function getAccessToken($appid, $appsecret) {
        $access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret";
        $access_token_data = json_decode(file_get_contents($access_token_url), true);
     
  
        return $access_token_data['access_token'];
    }
    
     // 生成二维码Ticket
    public function getQRTicket($accessToken, $expireSeconds = 604800, $sceneId = 1) {
        $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={$accessToken}";
        $data = json_encode([
            'expire_seconds' => $expireSeconds, 
            'action_name' => 'QR_SCENE', 
            'action_info' => ['scene' => ['scene_id' => $sceneId]]
        ]);
        $options = [
            'http' => [
                'method' => 'POST',
                'header' => "Content-Type: application/json",
                'content' => $data,
                'timeout' => 60
            ]
        ];
        $context = stream_context_create($options);
        $response = json_decode(file_get_contents($url, false, $context), true);
        return $response['ticket'];
    }
 
 

3.在公众号的 服务器配置的服务器地址(URL)里面写

   $data = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
       if ( $data->Event == 'subscribe' ||  $data->Event == 'SCAN'  ) {   // 关注公众号  或者  已关注用户扫码 
            if (!empty($data->EventKey)) {
                // 这里的qrscene_为前缀,后面跟的是你设置的参数值
                $scene_id = str_replace('qrscene_', '', $data->EventKey);
                //检测场景值是否过期
                //没过期就 查询数据库wxlogin对饮的token返回给前端顺利登陆
                $cinfo = Db::name('wxlogin')->where('sceneid',$scene_id)->find();
                if(time() < $cinfo['dtime']){  //执行登录
                    $res = Db::name('wxlogin')->where('sceneid',$scene_id)->update(['status'=>'1']);
                    if($res){
                        // 向用户发送消息123
                        $this->sendTextMessage($data->FromUserName, $data->ToUserName, '恭喜您已经成功登录');  
                    }  
                }else{  //已经过期。执行过期状态
                    $res = Db::name('wxlogin')->where('sceneid',$scene_id)->update(['status'=>'3']);
                    
                }
            }
        }
           
 
        
        
        
        if ( $data->Event == 'unsubscribe' ) {   // 用户取消关注公众号
       
        }
        


4.微信给 服务器地址返回的信息 :这里做详细解释

这是接收到的数据

{"ToUserName":"gh_32219ed1e2ea","FromUserName":"o0czO6dbV0cfDFy96tHPr99m3Lxg","CreateTime":"1717421428","MsgType":"event","Event":"SCAN","EventKey":"1","Ticket":"gQEN8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyNVh6RVlXaGNmZUYxdVNZQ05DMW8AAgQ2wl1mAwSAOgkA"}

$data->MsgType

   这是一个描述消息类型的字段。MsgType用来指示消息的种类,比如:
     text 表示文本消息。
     image 表示图片消息。
     event 表示事件推送。       
 当MsgType的值为event时,表示接收到的是一个事件推送。事件推送不是用户直接发送的消息,而是某些用户行为或微信行为触发的通知,比如用户关注或取消关注公众号、用户扫描二维码等。

$data->Event:

当MsgType为event时,Event字段用来进一步指定事件的类型。例如:
 subscribe 表示用户关注公众号事件。
 unsubscribe 表示用户取消关注公众号。
 SCAN 表示用户已关注公众号后扫描二维码。
CLICK 表示用户点击了自定义菜单。
 在你的例子中,$data->Event == 'subscribe' 指的是用户关注公众号的事件。当用户首次关注公众号,或者之前取消关注后再次关注时,你的服务器会接收到这个事件

$data->EventKey

 EventKey是与特定事件相关联的一个参数,主要用在事件推送(event)中。这个参数的值取决于具体的事件类型:

 关于二维码扫描:
 当用户扫描带参数的二维码时,无论是已关注还是未关注用户,微信都会将事件推送到你的服务器。这时,EventKey将包含与该二维码相关的信息:
 对于未关注用户扫描后关注的事件(subscribe),EventKey会以qrscene_为前缀,后接你创建二维码时定义的场景值(scene_id或scene_str)。例如,如果场景值是123,EventKey就会是qrscene_123。
 对于已关注用户扫描二维码的事件(SCAN),EventKey直接是二维码的场景值,比如123。
 自定义菜单事件:
 如果用户点击了自定义菜单项,且该菜单项是点击类型(click),则EventKey是与该菜单项相关联的key值,这个值是在设置自定义菜单时由开发者指定的。

$data->Ticket

 Ticket参数通常与二维码扫描事件相关联。当用户扫描一个带参数的二维码时,微信会在推送的事件信息中包含一个Ticket值。这个Ticket可以视为该次扫描事件的一个唯一标识符。具体来说:
 二维码扫描事件:
 当用户扫描带参数二维码时,无论是关注还是未关注,事件推送中都会包含Ticket参数。这个Ticket是在生成二维码时由微信生成并提供的,可以用来获取扫描者和二维码的详细信息。
posted @ 2024-06-03 23:00  79524795  阅读(4)  评论(0编辑  收藏  举报