这个功能需要有个一个已认证的公众号,厉害的是!在下没有~
当然~我们可以通过微信测试号来完成这些开发,测试账号拥有公众号所有的接口,不管是订阅号还是服务号,只是不能群发信息。用来开发带参数的二维码也是绰绰有余~
一、开发准备
打开注册网址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/login
点击登录,使用微信扫一扫即可进入你的微信公众测试平台
如图,你会看到测试平台的微信号,appID,appsecret,其中appID和appsecret这两个对于公众号来说十分重要,请不要随便给他人看或者使用~
二、接入
接下来我们启用公众号服务器配置
此动作对应了正常公众号中开发->基本配置操作
我们用测试平台开发的话,默认是明文模式,所以消息加解密密钥是没有的,并且下方所有的信息都是明文模式,如需要加密,可阅读微信接入说明和下载微信加密解密代码。微信接入链接
这里的URL对应的是微信推送接入地址,第一次接入的话,我们需要代码认证一下才能接入完成,之后所有的微信公众号的操作,微信方都会推送信息到这个链接中,我们可以根据推送的信息来处理自己的逻辑,和发送信息。(微信推送的信息是XML格式)
如第一次接入,微信会传递signature(接入签名),timestamp(时间戳),nonce(随机数),echostr(随机字符串),当我们接收到这4个参数后,需要时间戳和随机数成数组,排序,数字转字符串,sha1加密操作,与signature比较,一致的话代表是微信端发来的信息,并输出nonce,代表接入完成。
$signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $echostr = $_GET["echostr"]; $tmpArr = array($timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); if( $signature == $tmpStr ){ echo $echostr; }else{ echo "false"; }
此操作仅仅在第一次接入执行即可,后续就不会用到它了,可以回家喝茶了
接入完成后,就可以开始我们的带参数二维码的开发了。
三、基础方法
class WeChatUnit { public function curlPostFun($url, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // post数据 curl_setopt($ch, CURLOPT_POST, 1); // post的变量 curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $output = curl_exec($ch); curl_close($ch); return $output; } }
四、获取access_token
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
private $AppId = ""; private $Secret = ""; public function getAccessToken() { //res是数据库记录的accessToken $res = []; //数据库中获取 if ($res['accessToken'] !== null && $res['deadlineTime'] !== null && time() - $res['deadline_time'] > 7200 ) { return ["success" => true, "data" => $res['accessToken'], "message" => ""]; } //微信请求 $get_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->AppId}&secret={$this->Secret}"; $res = $this->curlPostFun($get_token_url, []); $res = json_decode($res, true); if (!empty($res['errcode'])) { return ["success" => false, "data" => null, "message" => $res['errmsg']]; } //更新数据库accessToken return ["success" => true, "data" => $res['access_token'], "message" => ""]; }
在开发中,不管什么接口都需要access_token,注意这个获取access_token的接口是有每日次数限制的,并且还有有效时间(7200秒),在使用时需要记录下来。
五、生成带参数的二维码
生成带参数的二维码大体步骤是:获取accessToken,通过accessToken获取二维码ticket,再通过二维码ticket得到二维码图片。
public function getImageUrlAndId() { $tokenRes = $this->getAccessToken(); if (!$tokenRes["success"]) { return ["success" => false, "data" => null, "message" => $tokenRes['message']]; } //获取 $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" . $tokenRes["data"]; $postData = [ "expire_seconds" => 300,//有效时间(秒) "action_name" => "QR_STR_SCENE",//scene_str标识类型,QR_STR_SCENE临时的字符串 "action_info" => ["scene" => ["scene_str" => "quickLogin"]] //scene_str是扫描后回传给服务器地址中的 ]; $postData = json_encode($postData); $res = json_decode($this->curlPostFun($url ,$postData), true); if (!empty($res['errcode'])) { return ["success" => false, "data" => null, "message" => $res['errmsg']]; } $ticketId = 记录账号标识($res['ticket']); if ($ticketId == 0) { return ["success" => false, "data" => null, "message" => "添加失败"]; } //这个链接是二维码的连接 $ticket_url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" . $res['ticket']; return ["success" => true, "data" => ["url" => $ticket_url, "id" => $ticketId], "message" => ""]; }
为了做扫码登录,需要记录当前二维码的ticket值,存到数据库中
前台得到这个二维码的链接显示出来就行,并轮询使用得到的id请求数据库是否被扫描(懒,不想写了,大概就是查看是否扫描了,扫描事件在下面)。
六、接收微信扫描事件
还记得我们配的那个接入url吗?不记得的话看下第二步就行~
微信扫描二维码后,微信服务端会推送事件给接入url。
已关注公众号推送信息
<xml><ToUserName><![CDATA[gh_xxxxxxxxx]]></ToUserName>
<FromUserName><![CDATA[odK-ct46AaD9ZL-YXHSJa231]]></FromUserName>
<CreateTime>1534757213</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[SCAN]]></Event>
<EventKey><![CDATA[quickLogin]]></EventKey>
<Ticket><![CDATA[gQGG7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyYTJ2NUJZUUxhc1QxcC1EWSDxsdXCS]]></Ticket>
</xml>
未关注公众号推送信息
<xml><ToUserName><![CDATA[gh_xxxxxxxxx]]></ToUserName>
<FromUserName><![CDATA[odK-ct46AaD9ZL-YXHSJa231-Q0]]></FromUserName>
<CreateTime>1534759544</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[qrscene_quickLogin]]></EventKey>
<Ticket><![CDATA[gQGG7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyYTJ2NUJZUUxhc1QxcC1EWSDxsdXCS]]></Ticket>
ToUserName:发起人(公众号的微信号)
FromUserName:用户的openId
CreateTime:请求时间戳
MsgType:信息类型(event:事件)
Event:事件类型
EventKey:事件标识
Ticket:扫描事件带的ticket,与上面的ticket一致
接收url接收并解析:
$xmldata=file_get_contents("php://input"); $postObj = simplexml_load_string($xmldata, 'SimpleXMLElement', LIBXML_NOCDATA);
确认是扫码关注登录信息
$msgType = $postObj->MsgType; if ($msgType == "event") { $eventKey = $postObj->EventKey; $event = $postObj->Event; $openId = $postObj->FromUserName; if (($event == "SCAN" || $event == "subscribe") && ($eventKey == "quickLogin" || $eventKey = "qrscene_quickLogin")) { //实现逻辑 $ticket = $postObj->Ticket; //ticket是在生产二维码是的ticket //根据ticket,$openId处理登录信息 } }
前台轮询查看此二维码是否扫码,扫描登陆
微信的基于公众号第三方登录大体就完成了
关于为什么使用带参数的二维码来做微信的第三方登录:
在开发公众号网站的时候,通常会用到openID来作为用户的识别,用户扫描带参数的二维码后微信推过来的数据中也带有openID,这样比较方便数据互通(虽然unionID也是这个功能)。
在用户扫描二维码时,微信端会判断用户是否关注公众号,关注则进入公众号,未关注则让他关注,加强对公众号的推广。何乐而不为呢~
COMMENTS | NOTHING