[PHP+WeChat開発] WeChatスキャンコードログイン

目次

1. データテーブル

2. トークンの取得

3. QRコードを生成する

4. コードをスキャンしてコールバックを受信します。

5. QRコードが正常に読み取られたか確認します


WeChat スキャン コード ログインの一般的な手順: 最初にトークンとチケットを取得し、WeChat QR コード生成インターフェイスを通じて QR コードを生成し、QR コード情報をデータ テーブルに追加し、ユーザーがコードをスキャンしたときに QR コード スキャン ステータスを検出します。スキャンが成功したら、QR コードのステータスを更新し、ページにジャンプします。

関連資料: WeChat 開発用の WeChat メッセージ テンプレート プッシュ + php

PHP WeChat 開発では QR コードを生成し、そのコードをスキャンして WeChat 公開アカウントをフォローします

 WeChat でドキュメントを開く

1. データテーブル

qrcord テーブルには、ユーザーが QR コード情報を保存します。QR コードが生成されるたびに、レコードが生成されます。openid フィールドは、スキャンが成功したかどうかを判断するために使用されます。openid が空でない場合、スキャンは成功します。それ以外の場合、スキャンが失敗したか、新しい QR コード ID です。フィールドは以下で使用する scene_id です。このフィールドは、QR コードを操作するためのキー フィールドとして常に存在します。

ID 追加時間 オープンID 作成時間 更新時間
ID QRコード生成時間 WeChat ID 作成時間 更新時間

2. トークンの取得

ロジックの説明: WeChat インターフェイスにトークンの取得を要求し、取得したトークンをサーバーに保存し、現在時刻を合わせて保存して、トークンの有効期限が切れているかどうかを判断します (トークンには有効期限があるため)。このメソッドを呼び出すときは、現在時刻とトークン データベースに保存されている時刻 (つまり、トークンが取得された時刻) を比較します。現在時刻 > データベース保存時間 + 7000 (秒単位) の場合、元のトークンの有効期限が切れていることを意味します。トークンを再度取得し、新しいトークンをデータベースに保存します。

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;
  }
  
}

3. QRコードを生成する

ロジック説明: ① QR コードを生成する前に、まずデータを生成し、それを qrcode テーブルに挿入して、QR コードのステータスを記録します. データには、QR コードの生成時間が含まれます. 挿入後、自己増加する主キー ID $scene_id, ② QR コードの生成開始: 結合パラメータ: Q​​R コードの有効期間、QR コードの種類、QR コードの詳細、結合 URL、生成する WeChat インターフェイスのリクエスト (2 つ) QRコード。

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';
    }
}

フロントエンド コード: ラベルを使用して QR コードを直接表示します。隠しフィールドは scene_id で、QR コード情報 (QR コードのスキャン ステータスを含む) をクエリするために使用されます。

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

4. コードをスキャンしてコールバックを受信します。

注: QR コードを生成した後、ユーザーは QR コードをスキャンできます。スキャンされると、WeChat サーバーはそれを受信し、情報を返します。これは、WeChat 公式アカウントに事前に入力されたコールバック アドレスに返されます。このアドレスはパブリックにアクセスできます。はい、検証できません。そうでないと、WeChat サーバーはコールバック アドレスにメッセージを返すことができません。

コールバック メソッド処理ロジック: WeChat サーバーから返されたメッセージを受信します。返されるメッセージの形式は、デフォルトでは xml です。オブジェクト形式に変換する必要があります。返される情報には、EventKey、FormUserName、ToUserName、および Event が含まれます。scene_id に基づいて QR コード テーブル情報を変更します。主に、QR コードがユーザーによって正常にスキャンされたことを示す 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()]);
	}

5. QRコードが正常に読み取られたか確認します

ロジックの説明: 関数を使用して 2 秒ごとに QR コードのスキャン ステータスをクエリし、バックエンドの scene_id を介して qrcode テーブルの openid をクエリします。対応する openid 列が空の場合、これは新しい QR コードであることを意味します。ユーザー スキャンがありません。対応する 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','非法请求');
         }
     }

おすすめ

転載: blog.csdn.net/qq_25285531/article/details/130823460