杰克工作室 发表于 2023-2-27 17:41

PC端生成小程序二维码,手机端扫码二维码登录

<p>微信官方api接口地址:<a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html">https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html</a></p>

<h2>前言</h2>

<p>目前微信扫码登录的实现有以下2种方式:<br />
1、微信服务号扫码网页授权登录<br />
2、微信开放平台Oauth2.0授权登录</p>

<p>以上2种方式少不了微信认证,都是需要交300元认证后才可以获得开发能力。所以我就想到了微信小程序,个人开发者无需认证也可以获得用户信息,授权登录,就可以简单实现一样的功能。</p>

<h2>流程</h2>

<p>1、PC端生成小程序码,携带唯一参数scene<br />
2、微信扫码,进入小程序,获得唯一参数scene,小程序进行授权获取用户信息(头像、昵称)<br />
3、确认登录,把当前获得的用户信息(头像、昵称、scene)一起插入数据库进行注册用户。<br />
4、注册后,网页端保持连接(ajax轮询或者websocket)获得扫码状态,如果小程序端点击确认登录,则PC网页端就显示登录成功,显示头像和昵称。</p>

<p><img alt="image.png" src="data/attachment/forum/202302/27/2023-02-27_20-42-19_371.jpg" title="image.png" /></p>

<h2>演示</h2>

<p><img alt="GIF 2020-6-9 23-49-01.gif" src="data/attachment/forum/202302/27/2023-02-27_20-42-19_636.jpg" title="GIF 2020-6-9 23-49-01.gif" /></p>

<p><img alt="微信图片_20200609235030.jpg" src="data/attachment/forum/202302/27/2023-02-27_20-42-20_282.jpg" title="微信图片_20200609235030.jpg" /></p>

<h2>体验</h2>

<p><a href="https://www.likeyun.cn/api/xcx/creatqrcode.php" target="_blank">点击体验</a></p>

<h2>后端代码</h2>
xcx_login.php

<pre>
&lt;?php
header(&quot;Content-type:application/json&quot;);
header(&#39;Access-Control-Allow-Origin:*&#39;);&nbsp;//&nbsp;*代表允许任何网址请求
&nbsp;
$nickName&nbsp;=&nbsp;$_GET[&quot;nickName&quot;];
$avatarUrl&nbsp;=&nbsp;$_GET[&quot;avatarUrl&quot;];
$scene&nbsp;=&nbsp;$_GET[&quot;scene&quot;];
&nbsp;
//&nbsp;连接数据库
$con&nbsp;=&nbsp;mysql_connect(&quot;数据库地址&quot;,&quot;数据库账号&quot;,&quot;数据库密码&quot;);
if&nbsp;(!$con){die(&#39;Could&nbsp;not&nbsp;connect:&nbsp;&#39;&nbsp;.&nbsp;mysql_error());}
mysql_select_db(&quot;数据库名&quot;,&nbsp;$con);
mysql_query(&quot;SET&nbsp;NAMES&nbsp;UTF8&quot;);
&nbsp;
mysql_query(&quot;INSERT&nbsp;INTO&nbsp;表名&nbsp;(nickName,&nbsp;avatarUrl,&nbsp;scene)&nbsp;VALUES&nbsp;(&#39;$nickName&#39;,&nbsp;&#39;$avatarUrl&#39;,&nbsp;&#39;$scene&#39;)&quot;);
mysql_close($con);
?&gt;
</pre>
<br />
lunxun.php
<pre>
&lt;?php
header(&quot;Content-type:application/json&quot;);
header(&#39;Access-Control-Allow-Origin:*&#39;);&nbsp;//&nbsp;*代表允许任何网址请求
&nbsp;
//get&nbsp;scene
$scene&nbsp;=&nbsp;$_GET[&quot;scene&quot;];
&nbsp;
//连接数据库
$con&nbsp;=&nbsp;mysql_connect(&quot;数据库地址&quot;,&quot;账号&quot;,&quot;密码&quot;);
if&nbsp;(!$con){die(&#39;Could&nbsp;not&nbsp;connect:&nbsp;&#39;&nbsp;.&nbsp;mysql_error());}
mysql_select_db(&quot;数据库名&quot;,&nbsp;$con);
mysql_query(&quot;SET&nbsp;NAMES&nbsp;UTF8&quot;);
&nbsp;
//校验
$scan_status&nbsp;=&nbsp;mysql_query(&quot;SELECT&nbsp;*&nbsp;FROM&nbsp;表名&nbsp;WHERE&nbsp;scene=&quot;.$scene);
$check_scene&nbsp;=&nbsp;mysql_num_rows($scan_status);
if&nbsp;($check_scene)&nbsp;{
&nbsp;&nbsp;//如果存在,就代表登陆成功
&nbsp;&nbsp;//获取当前scene的用户信息
&nbsp;&nbsp;while&nbsp;($row&nbsp;=&nbsp;mysql_fetch_array($scan_status))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;$nickname&nbsp;=&nbsp;$row[&quot;nickName&quot;];
&nbsp;&nbsp;&nbsp;&nbsp;$headimg&nbsp;=&nbsp;$row[&quot;avatarUrl&quot;];
&nbsp;&nbsp;}
&nbsp;&nbsp;echo&nbsp;json_encode(array(&#39;result&#39;=&gt;&#39;success&#39;,&#39;nickName&#39;=&gt;$nickname,&#39;avatarUrl&#39;=&gt;$headimg),true);
}else{
&nbsp;&nbsp;echo&nbsp;json_encode(array(&#39;result&#39;=&gt;&#39;loading&#39;),true);
}
&nbsp;
//断开数据库连接
mysql_close($con);
?&gt;
</pre>
creatqrcode.php

<pre>
&lt;!DOCTYPE&nbsp;html&gt;
&lt;html&gt;
&lt;head&gt;
&nbsp;&nbsp;&lt;title&gt;微信小程序扫码登录&lt;/title&gt;
&nbsp;&nbsp;&lt;meta&nbsp;charset=&quot;utf-8&quot;&gt;
&nbsp;&nbsp;&lt;script&nbsp;src=&quot;https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js&quot;&gt;&lt;/script&gt;
&nbsp;&nbsp;&lt;style&nbsp;type=&quot;text/css&quot;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;*{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;margin:0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;padding:0;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;#ewm{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;200px;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;margin:50px&nbsp;auto&nbsp;10px;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;#ewm&nbsp;img{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;200px;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;h2{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color:#333;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text-align:center;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;#shujuliu{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;500px;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:300px;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;background:&nbsp;#000;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;margin:50px&nbsp;auto;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;padding:&nbsp;20px&nbsp;20px;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;border-top:20px&nbsp;solid&nbsp;#ccc;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&nbsp;
&lt;/body&gt;
&lt;/html&gt;
&lt;?php
//设置&nbsp;header&nbsp;
header(&quot;Content-type:text/html;charset=utf-8&quot;);
&nbsp;
//获取access_token
function&nbsp;getToken(){
&nbsp;&nbsp;&nbsp;&nbsp;$file&nbsp;=&nbsp;file_get_contents(&quot;access_token.json&quot;,true);//读取access_token.json里面的数据
&nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;json_decode($file,true);
&nbsp;
    //判断access_token是否在有效期内,如果在有效期则获取缓存的access_token
       //如果过期了则请求接口生成新的access_token并且缓存access_token.json
       if&nbsp;(time()&nbsp;&gt;&nbsp;$result[&#39;expires&#39;]){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data&nbsp;=&nbsp;array();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data[&#39;access_token&#39;]&nbsp;=&nbsp;getNewToken();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$data[&#39;expires&#39;]&nbsp;=&nbsp;time()+7000;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$jsonStr&nbsp;=&nbsp;&nbsp;json_encode($data);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$fp&nbsp;=&nbsp;fopen(&quot;access_token.json&quot;,&nbsp;&quot;w&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fwrite($fp,&nbsp;$jsonStr);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fclose($fp);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$data[&#39;access_token&#39;];
&nbsp;&nbsp;&nbsp;&nbsp;}else{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$result[&#39;access_token&#39;];
&nbsp;&nbsp;&nbsp;&nbsp;}
}
&nbsp;&nbsp;
//获取新的access_token
function&nbsp;getNewToken($appid,$appsecret){
&nbsp;&nbsp;&nbsp;&nbsp;global&nbsp;$appid;
&nbsp;&nbsp;&nbsp;&nbsp;global&nbsp;$appsecret;
&nbsp;&nbsp;&nbsp;&nbsp;$url&nbsp;=&nbsp;&quot;https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=小程序appid&amp;secret=小程序secret&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;$access_token_Arr&nbsp;=&nbsp;&nbsp;file_get_contents($url);
&nbsp;&nbsp;&nbsp;&nbsp;$token_jsonarr&nbsp;=&nbsp;json_decode($access_token_Arr,&nbsp;true);
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$token_jsonarr[&quot;access_token&quot;];
}

$access_token&nbsp;=&nbsp;getToken();

//初始化&nbsp;CURL
$ch&nbsp;=&nbsp;curl_init();
//目标服务器地址&nbsp;
curl_setopt($ch,&nbsp;CURLOPT_URL,&nbsp;&#39;https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=&#39;.$access_token);
//提交方式为POST
curl_setopt($ch,&nbsp;CURLOPT_POST,&nbsp;true);

//生成scene
$scene&nbsp;=&nbsp;rand(1111111111,9999999999);

//POST&nbsp;DATA
$data&nbsp;=&nbsp;array(
&nbsp;&nbsp;&nbsp;&nbsp;&#39;page&#39;&nbsp;=&gt;&nbsp;&#39;pages/queding/index&#39;,
&nbsp;&nbsp;&nbsp;&nbsp;&#39;scene&#39;&nbsp;=&gt;&nbsp;$scene
);
//把DATA转为json
$jsondata&nbsp;=&nbsp;json_encode($data,true);
curl_setopt($ch,&nbsp;CURLOPT_POSTFIELDS,&nbsp;$jsondata);
//&nbsp;对认证证书来源的检查
curl_setopt($ch,&nbsp;CURLOPT_SSL_VERIFYPEER,&nbsp;0);
//&nbsp;从证书中检查SSL加密算法是否存在
curl_setopt($ch,&nbsp;CURLOPT_SSL_VERIFYHOST,&nbsp;2);
//获取的信息以文件流的形式返回,而不是直接输出
curl_setopt($ch,&nbsp;CURLOPT_RETURNTRANSFER,&nbsp;true);

//发起请求
$result&nbsp;=&nbsp;curl_exec($ch);

//生成二维码
file_put_contents(&quot;qrcode.png&quot;,$result);
$base64_image&nbsp;=&quot;data:image/jpeg;base64,&quot;.base64_encode($result);

//断开数据库连接
mysql_close($con);

echo&nbsp;&quot;&lt;div&nbsp;id=&#39;ewm&#39;&gt;&quot;;
echo&nbsp;&quot;&lt;img&nbsp;src=&#39;&quot;.$base64_image.&quot;&#39;/&gt;&quot;;
echo&nbsp;&quot;&lt;/div&gt;&quot;;
echo&nbsp;&quot;&lt;h2&nbsp;id=\&quot;username\&quot;&gt;请使用微信扫码授权登录&lt;/h2&gt;&quot;;
echo&nbsp;&quot;&lt;h1&nbsp;id=\&quot;success\&quot;&nbsp;style=&#39;color:#07c160;text-align:center;&#39;&gt;&lt;/h1&gt;&quot;;
echo&nbsp;&quot;&lt;input&nbsp;type=&#39;hidden&#39;&nbsp;value=&#39;$scene&#39;&nbsp;id=&#39;scene&#39;/&gt;&quot;;
//实时数据流
echo&nbsp;&quot;&lt;div&nbsp;id=&#39;shujuliu&#39;&gt;&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;&lt;div&nbsp;class=&#39;title&#39;&nbsp;style=&#39;color:#07c160;font-size:14px;line-height:30px;&#39;&gt;实时数据流&lt;/div&gt;&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;&lt;div&nbsp;class=&#39;creatcode&#39;&gt;&lt;/div&gt;&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;&lt;div&nbsp;class=&#39;loadingscan&#39;&gt;&lt;/div&gt;&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;&lt;div&nbsp;class=&#39;nickname&#39;&gt;&lt;/div&gt;&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;&lt;div&nbsp;class=&#39;headimg&#39;&gt;&lt;/div&gt;&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;&quot;&lt;div&nbsp;class=&#39;scansuccess&#39;&gt;&lt;/div&gt;&quot;;
echo&nbsp;&quot;&lt;/div&gt;&quot;;
//关闭请求
curl_close($ch);
?&gt;
&nbsp;
&lt;!--&nbsp;异步查询状态&nbsp;--&gt;
&lt;script&gt;
var&nbsp;lunxun&nbsp;=setInterval(&quot;test()&quot;,1000);
function&nbsp;test()&nbsp;{
&nbsp;&nbsp;var&nbsp;scene&nbsp;=&nbsp;$(&quot;#scene&quot;).val();
&nbsp;&nbsp;$.ajax({
&nbsp;&nbsp;&nbsp;&nbsp;type:&nbsp;&quot;GET&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;url:&nbsp;&quot;lunxun.php?scene=&quot;+scene,
&nbsp;&nbsp;&nbsp;&nbsp;dataType:&quot;json&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;processData:&nbsp;false,
&nbsp;&nbsp;&nbsp;&nbsp;success:&nbsp;function(data,&nbsp;textStatus)&nbsp;{&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(data.result&nbsp;==&nbsp;&quot;success&quot;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;扫码完成&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clearInterval(lunxun);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#shujuliu&nbsp;.nickname&quot;).html(&quot;&lt;p&nbsp;style=&#39;color:#07c160;font-size:14px;line-height:30px;&#39;&gt;微信昵称:&quot;+data.nickName+&quot;&lt;/p&gt;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#shujuliu&nbsp;.scansuccess&quot;).html(&quot;&lt;p&nbsp;style=&#39;color:#07c160;font-size:14px;line-height:30px;&#39;&gt;扫码完成,登录成功&lt;/p&gt;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//获取头像
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#ewm&quot;).html(&quot;&lt;img&nbsp;src=&#39;&quot;+data.avatarUrl+&quot;&#39;&nbsp;style=&#39;width:200px;border-radius:100px;&#39;/&gt;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//获取昵称
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#username&quot;).html(data.nickName);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//修改登录结果
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#success&quot;).text(&quot;登录成功&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else&nbsp;if&nbsp;(data.result&nbsp;==&nbsp;&quot;loading&quot;)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;正在监听扫码状态&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#shujuliu&nbsp;.creatcode&quot;).html(&quot;&lt;p&nbsp;style=&#39;color:#07c160;font-size:14px;line-height:30px;&#39;&gt;创建小程序码&lt;/p&gt;&lt;p&nbsp;style=&#39;color:#07c160;font-size:14px;line-height:30px;&#39;&gt;携带参数scene:&quot;+scene+&quot;&lt;/p&gt;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(&quot;#shujuliu&nbsp;.loadingscan&quot;).html(&quot;&lt;p&nbsp;style=&#39;color:#07c160;font-size:14px;line-height:30px;&#39;&gt;等待扫码...&lt;/p&gt;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;lunxun.php出现错误&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;error:function(){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(&quot;执行错误&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;});
}
&lt;/script&gt;&nbsp;</pre>

<p>后端使用说明<br />
xcx_login.php是小程序的wx.request的后端服务<br />
lunxun.php是网页端的轮询扫码结果接口,我这里使用的是ajax轮询<br />
creatqrcode.php是网页端创建小程序码的页面</p>

<p>数据库结构<br />
<img alt="微信截图_20200610111452.png" src="data/attachment/forum/202302/27/2023-02-27_20-42-20_85.jpg" title="微信截图_20200610111452.png" /></p>

<h2>小程序源码</h2>

<p><img alt="微信截图_20200610111840.png" src="data/attachment/forum/202302/27/2023-02-27_20-42-21_199.jpg" title="微信截图_20200610111840.png" /></p>

<p>小程序端只需修改后端的URL即可。</p>

<p>微信扫码获取小程序端源码<br />
<img alt="微信小程序扫码登录源码_分享.png" src="data/attachment/forum/202302/27/2023-02-27_20-42-22_299.jpg" title="微信小程序扫码登录源码_分享.png" /></p>

<p>原文地址:https://segmentfault.com/a/1190000022886425 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
页: [1]
查看完整版本: PC端生成小程序二维码,手机端扫码二维码登录