准备材料:
微信公众号-认证服务号,如果没有可以申请测试号
申请测试号链接https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
交互时序图:
权限说明:
①除认证服务号外,其他类型的没有生成带参数二维码的权限
②订阅号有接受事件通知的权限,可接受关注事件并完成后续流程,但关注过的粉丝就无法直接通过扫码使用了。理论上可准备大量新号(话说CSDN很长一段时间用这个操作给订阅号涨粉)。
准备工作
一.设置ip白名单
将ip白名单设置为你的服务器ip,如果在本地测试,则设置为本地外网ip
二.开启服务器配置
三、获取access_token,并保存到数据库,省得因为反复刷新导致获取失败!(前端生成二维码的页面处理)
注意点就是:保存的记录要7200秒(2个小时)之内的!一旦过期就重新查询!
//先把ACC_TOKEN存到数据库表里,两个字段,一个ACC_TOKEN,一个time;然后这里要判断下ACC_TOKEN是否过期,akui $pdo = new PDO("mysql:host=localhost;dbname=itbaiduwang_com","itbaiduwang_com","eEcBjMfbJJNmihk7"); $datetimea=date('Y-m-d H:i:s'); $pdo->query("set names utf8"); $sql="select * from acc_token"; $re=$pdo->query($sql); $re=$re->fetch(); if($re==null){//如果没有acc_token,那就去微信获取最新的ACC_TOKEN并插入acc_token到数据库 //echo "1";exit; $appid="wxdc8a5271050e6cf2";//要填akui $appsecret="a63159583b8447830a5e2f61af51ee9e";//要填akui $TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; $json=file_get_contents($TOKEN_URL); $result=json_decode($json); $ACC_TOKEN=$result->access_token; //echo $json;exit; //print($json);exit; $sql="insert into acc_token(acc_token,timea)values('".$ACC_TOKEN."','".time()."')"; $re=$pdo->query($sql); } $timeaaa=time()-300; $sql="select * from acc_token where timea>'".$timeaaa."'"; $re=$pdo->query($sql); $re=$re->fetch(); if($re==null){//如果不存在2个小时内的ACC_TOKEN,那就去微信获取最新的ACC_TOKEN并更新acc_token到数据库!如果有第二地方也请求同一个ACC_TOKEN的话,那么第一个ACC_TOKEN会在5分钟之内过期!!! //echo "2";exit; $appid="wxdc8a5271050e6cf2";//要填akui $appsecret="a63159583b8447830a5e2f61af51ee9e";//要填akui $TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; $json=file_get_contents($TOKEN_URL); $result=json_decode($json); $ACC_TOKEN=$result->access_token; //echo $ACC_TOKEN;exit; $sql="UPDATE acc_token SET acc_token = '".$ACC_TOKEN."',timea = '".time()."'"; $re=$pdo->query($sql); } else{//如果存在2个小时内的ACC_TOKEN,那就不用去微信获取最新的ACC_TOKEN,直接查询数据库里面的ACC_TOKEN就行了 //echo "3";exit; $ACC_TOKEN=$re['acc_token']; //echo $sql; //echo $ACC_TOKEN;exit; } //先把ACC_TOKEN存到数据库表里,两个字段,一个ACC_TOKEN,一个time;然后这里要判断下ACC_TOKEN是否过期,akui
四、获取带参数二维码(临时)(前端生成二维码的页面处理)
$num=mt_rand(111,9999999999999);//也叫scene_id,可以自定义akui,靠这个参数来判别谁登陆,不怕重复,因为后面有openid这个唯一值来判断是否重名;页面每次刷新一次(二维码变一次),$num会变化一次!不然如果页面没刷新,二维码的$num参数一直都是一样的! $data='{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id":'.$num.'}}}'; //$data = '{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": '.$num.'}}}'; $url ="https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$ACC_TOKEN;//ACC_TOKEN这个不要一直刷新,自己保存到数据库!2小时过去akui $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); 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); $res = json_decode($output, true); $t=$res['ticket']; /* echo $url."</br>"; echo $t;exit; */ $url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=".$t;
五、接受用户扫码事件通知(服务器配置的地址页面处理)
用户扫码之后,微信会向你填写的服务器配置的地址POST一段xml,如果忘了请看前面的准备工作。
格式如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[subscribe]]></Event> <EventKey><![CDATA[qrscene_123123]]></EventKey> <Ticket><![CDATA[TICKET]]></Ticket> </xml>
其中,FromUserName内容是用户id,即openid,EventKey和Ticket对应创建二维码时携带的参数,这些参数是你前端生成二维码的页面赋值的。当服务器收到这个推送的时候就意味该用户已经扫码并且关注公众号了,如果没有关注不会收到推送。
服务器配置的地址页面处理重要事情一:
然后服务器配置的地址文件里面会解析xml并保存准备给前端提供查询,你可以采用保存到文件的方式,也可以保存到数据库redis等等。
if( strtolower($postObj->Event) == 'subscribe'){ $num = substr(trim($postObj->EventKey), 8);//输出1984 } else { $num = trim($postObj->EventKey); } //连接mysql $pdo = new PDO("mysql:host=localhost;dbname=itbaiduwang_com","itbaiduwang_com","eEcBjMfbJJNmihk7"); $pdo->query("set names utf8"); //存入数据库,这里很可能经常会重复写入同一个openid的数据,没关系!因为以下的操作,已经让用户登录或者注册了!akui //如果你不想让用户每次登录都写一条消息到数据库,可以进行判断处理! $sql="select * from weixinpcsm where openid='".$fromUsername."'";//在weixinloginpcsma.php页面已经把$num自定义的参数写进数据库了! $re=$pdo->query($sql); $re=$re->fetch(); if($re==null){//如果没有对应的openid,那就插入$num跟openid $datetimea=date('Y-m-d H:i:s'); $sql="insert into weixinpcsm(num,timea,openid,datetimea)values('".$num."','".time()."','".$fromUsername."','".$datetimea."')"; $pdo->query($sql);//$fromUsername就是openid } else//如果有对应的openid,那就更新最新的$num跟time { $datetimea=date('Y-m-d H:i:s'); //$sql="insert into weixinpcsm(num,timea,openid,datetimea)values('".$num."','".time()."','".$fromUsername."','".$datetimea."')"; $sql="UPDATE weixinpcsm SET num = '".$num."',timea = '".time()."',datetimea='".$datetimea."' where openid='".$fromUsername."'"; $pdo->query($sql);//$fromUsername就是openid }
服务器配置的地址页面处理重要事情二:
判断用户有没有注册,没有的话注册一下
//获取用户信息 头像 昵称 自己存入数据库即可akui $url="https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$token."&openid=".$fromUsername."&lang=zh_CN"; $re=file_get_contents($url); $res=json_decode($re); //昵称:$res->nickname 头像:$res->headimgurl openid:$fromUsername 性别: $res->sex 城市: $res->city akui //把这些存入数据库 对应用户信息 下次先判断 数据库里有没有这个用户 这部分自己操作即可,就在这里写就行!插进去之后,就可以配合weixinloginpcsma.php里面的数据库查询是否有登录配合起来了!数据库查询akui //未关注的时候这里来自动注册,但是一定要注意,URL这里是不能实现自动网址跳转的,已经关注的在JS中来自动登录并让网站跳转页面 akui //根据openid来判断有没有,在用户表里面新建一个openid字段!akui if($res!=null) { //判断有没有openid这个用户,如果没有,那么插入 }
六、前端JS轮询获取登陆结果(前端生成二维码的页面处理)
if(!empty($_POST)){//最下面的js发送POST到该页面,如果有接收到POST的时候发生 //连接数据库查询 $pdo = new PDO("mysql:host=localhost;dbname=itbaiduwang_com","itbaiduwang_com","eEcBjMfbJJNmihk7"); $pdo->query("set names utf8"); $sql="select * from weixinpcsm where num='".$_POST['num']."'";//在token.php页面已经把$num自定义的参数写进数据库了! $re=$pdo->query($sql); $re=$re->fetch(); if($re!=null){//这里就登陆成功的判断 //阿魁加 $sql="select * from ask_user where openid='".$re['openid']."'"; $result=$pdo->query($sql); $result=$result->fetch(); $uid=$result['uid']; $user = get_user($uid); echo "1"; refresh($user); //阿魁加 exit();//这里跟最下面的js配合! } exit; }
<!--微信二维码扫描登陆--> <div style="height:500px;text-align:center"><img src="<?php echo $url?>"/></div> <script> var i=0; var num="<?php echo $num ?>"; window.onload = function(){ timing=window.setInterval("refresh()",3000); } function refresh(){ if(i=='180'){ window.clearInterval(timing); } $.ajax({ url:"/weixinloginpcsma.php", type:"post", data:{"num":num}, success:function(re){ if(re=='1'){ window.clearInterval(timing);//停止执行timing函数,并往下执行其他函数 alert('登录成功');//这里可以跳转网址了!已经关注或者已经扫描的时候这里来自动登录并让网站跳转页面,该页面不可能实现自动注册!因为用户信息都在服务器配置的文件里面处理;未关注的时候让返回url(服务器配置的文件)那里去自动注册,但是一定要注意,返回的url(服务器配置的文件)那里是不能实现自动网址跳转的 window.location.href='/'; } } }); i++; } </script> <!--微信二维码扫描登陆-->