5
头图

need

If a website wants to implement WeChat scan code login, there are actually many solutions. The common solutions are the WeChat open platform and the WeChat public account service account. The former is a method approved by most websites at present, and the latter is a method developed by developers after discovering that the service account has the ability to obtain basic user information after scanning the code to follow.

Both of these actually require qualifications, such as certification. For individual developers, there are certain thresholds, and what I am sharing this time is 0 thresholds, which can be achieved by individual developers.

principle

The applet also has the ability to obtain the basic information of the user. You can call wx.login接口 to obtain the user's openid to log in. Simply put, the web side creates a QR code with parameters and inserts a login record into the database. At this time, the web side has started to poll the scan code status of this record in the database. After WeChat scans the code, open the applet and get it immediately. To this parameter, then click the authorize login button to request the wx.login interface to obtain the openid, then update the openid to the login record of the database and update the scan code status. The web side can poll the status code of the successful login to show that the login is successful. .

image.png

code

creatqrcode.php

 <!DOCTYPE html>
<html>
<head>
    <title>小程序扫码登录示例</title>
    <meta charset="utf-8">
    <script type="text/javascript" src="./jquery.min.js"></script>
    <link rel="stylesheet" type="text/css" href="./bootstrap.min.css">
    <style>
        *{
            padding:0;
            margin:0;
        }
        #xcxqrcode{
            width: 200px;
            height: 200px;
            margin:50px auto;
            display: block;
        }
        #lgtext{
            text-align: center;
            padding:20px 20px;
            background: #f1f1f1;
            border-radius: 100px;
        }
        #openid{
            text-align: center;
            padding:20px 20px;
        }
    </style>
</head>
<body>
<?php
// Header
header("Content-type:text/html;charset=utf-8");

// 获取access_token
function getToken(){
    /**
     * 这里替换为你的小程序的appid和appsecret
     */
    $appid='xxx';
    $appsecret='xxx';
    // 读取access_token
    include 'access_token.php';
    // 判断是否过期
    if (time() > $access_token['expires']){
        // 如果已经过期就得重新获取并缓存
        $access_token = array();
        $access_token['access_token'] = getNewToken($appid,$appsecret);
        $access_token['expires']=time()+7000;
        // 将数组写入php文件
        $arr = '<?php'.PHP_EOL.'$access_token = '.var_export($access_token,true).';'.PHP_EOL.'?>';
        $arrfile = fopen("./access_token.php","w");
        fwrite($arrfile,$arr);
        fclose($arrfile);
        // 返回当前的access_token
        return $access_token['access_token'];

    }else{
        // 如果没有过期就直接读取缓存文件
        return $access_token['access_token'];
    }
}

// 获取新的access_token
function getNewToken($appid,$appsecret){
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
    $access_token_Arr =  https_request($url);
    return $access_token_Arr['access_token'];
}

// curl请求函数
function https_request ($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $out = curl_exec($ch);
    curl_close($ch);
    return  json_decode($out,true);
}

// 创建小程序码
function creatQrcode(){
    // 请求小程序接口创建小程序码
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.getToken());
    curl_setopt($ch, CURLOPT_POST, true);
    $sc = uniqid(); // 生成scene
    $data = array(
        "scene" => $sc,
        "env_version" => "develop" // 小程序审核通过后需要修改参数为release
    );
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    // 图片buffer转本地图片
    $img = file_put_contents($sc.'.png', $result);
    // 引入数据库配置
    include './Db.php';
    // 将二维码的scene写入数据库
    $add_scene = "INSERT INTO xcxqrcodelogin (scene) VALUES ('$sc')";
    if ($conn->query($add_scene) === TRUE) {
        $file = $sc.'.png';
        if($fp = fopen($file,"rb", 0)) 
        { 
            $gambar = fread($fp,filesize($file)); 
            fclose($fp);
            $base64_qrcode = 'data:image/jpg/png/gif;base64,'.chunk_split(base64_encode($gambar)); 
            // 以JSON的方式返回小程序码及scene
            return json_encode(array('xcxqrcode'=>$base64_qrcode,'scene'=>$sc));
        }
    }
    // 断开连接
    curl_close($ch);
    $conn->close();
}

?>

<!-- 获取到小程序码的base64数据 -->
<?php 
    $qrcodebase64json = json_decode(creatQrcode());
    $xcxqrcode = $qrcodebase64json->xcxqrcode;
    $scene = $qrcodebase64json->scene;
    // 删除本地的图片
    unlink('./'.$scene.'.png');
?>
<!-- 展示二维码及扫码结果 -->
<div style="width:300px;margin:50px auto;">
    <img src="<?php echo $xcxqrcode; ?>" id="xcxqrcode">
    <input type="hidden" value="<?php echo $scene; ?>" id="sc"/>
    <h4 id="lgtext">请使用微信扫码</h4>
    <p id="openid"></p>
</div>

<!-- 轮询扫码结果 -->
<script type="text/javascript">

// 从0秒开始轮询
let TimeOut = 0;
let checklogin = setInterval('CheckStatus()', 1000);

// 查询扫码状态
function CheckStatus() {
    // 获取scene
    var sc = $('#sc').val();
    $.ajax({
        type: "POST",
        url: "./getstatus.php?scene="+sc,
        success:function(data){
            // code==200即授权登录成功
            if (data.code == 200) {
                console.log(data.msg)
                $('#lgtext').html('<span style="color:#07c160;">'+data.msg+'</span>')
                $('#openid').text(data.openid)
                $('#xcxqrcode').css('filter','blur(5px)')
                clearTimeout(checklogin);
            }else{
                console.log(data.msg)
                if(data.code == 201){
                    $('#lgtext').html('<span style="color:#666;">'+data.msg+'</span>')
                }else if(data.code == 202){
                    $('#lgtext').html('<span style="color:#07c160;">'+data.msg+'</span>')
                }
            }
            guoqi();
        },
        error:function(data) {
          console.log('服务器发生错误')
          $('#lgtext').text('服务器发生错误')
        }
    });
}

// 小程序码过期检测
function guoqi(){
    TimeOut += 1;
    // 60秒后过期
    if(TimeOut >= 60){
        // 过期后停止轮询
        clearTimeout(checklogin);
        $('#lgtext').text('已过期,请刷新页面')
        $('#xcxqrcode').css('filter','blur(5px)')
    }
}

</script>
</body>
</html>

getstatus.php

 <?php
header("Content-type:application/json");

// 小程序扫码后解析小程序码获取到的scene
$scene = $_GET['scene'];

// 引入数据库配置
include './Db.php';

// 查询当前scene的扫码状态
$getstatusinfo = "SELECT * FROM xcxqrcodelogin WHERE scene='$scene'";
$result_statusinfo = $conn->query($getstatusinfo);

// 如果scene存在
if ($result_statusinfo->num_rows > 0) {
    while($row_statusinfo = $result_statusinfo->fetch_assoc()) {
        $status = $row_statusinfo['status'];
        $openid = $row_statusinfo['openid'];
    }
    // 当scene=1的时候代表还没扫码
    if($status == '1'){
        $ret = array(
            'code' => 201,
            'msg' => '请使用微信扫码'
        );
    }else if($status == '2'){
        // 当scene=2的时候代表已扫码未登录
        $ret = array(
            'code' => 202,
            'msg' => '已扫码,请授权登录'
        );
    }else if($status == '3'){
        // 当scene=3的时候代表已登录
        $ret = array(
            'code' => 200,
            'msg' => '登录成功',
            'openid' => $openid
        );
    }
}else{
    $ret = array(
        'code' => 203,
        'msg' => '请刷新重试'
    );
}

// 断开数据库连接
$conn->close();

// 输出结果
echo json_encode($ret,JSON_UNESCAPED_UNICODE);

?>

scanCode.php

 <?php
/**
 * 告诉数据库我已经扫码了
 */
header("Content-type:application/json");
$scene = $_GET['scene'];
// 引入数据库配置
include './Db.php';
mysqli_query($conn,"UPDATE xcxqrcodelogin SET status='2' WHERE scene='$scene'");
$conn->close();
?>

login.php

 <?php
header("content-type:application/json");

// 通过wx.login获取到的code
$code = $_GET["code"];
$scene = $_GET['scene'];

/**
 * 这里替换为你的小程序的appid和appsecret
 */
$appid = "xxx";
$secret = "xxx";

// 请求接口进行登录获取到openid
$api = "https://api.weixin.qq.com/sns/jscode2session?appid=$appid&secret=$secret&js_code=$code&grant_type=authorization_code";
$result = file_get_contents($api);
$arr_result = json_decode($result, true);
$openid = $arr_result["openid"];

// 引入数据库配置
include './Db.php';
// 更新登录状态
mysqli_query($conn,"UPDATE xcxqrcodelogin SET openid='$openid',status='3' WHERE scene='$scene'");
$ret = array(
    'code' => 200,
    'msg' => '登录成功',
    'openid' => $openid
);
$conn->close();

// 返回结果
echo json_encode($ret,JSON_UNESCAPED_UNICODE);
?>

Db.php

 <?php

/**
 * 数据库配置
 * BY TANKING 2022-08-06
 * https://segmentfault.com/u/tanking
 */
$db_url = "XXX"; // 数据库服务器地址
$db_user = "XXX"; // 数据库账号
$db_pwd = "XXX"; // 数据库账号
$db_name = "XXX"; // 数据库名称

// 连接数据库
$conn = new mysqli($db_url, $db_user, $db_pwd, $db_name);
mysqli_query($conn, "SET NAMES UTF-8");

?>

code description

1. creatqrcode.php is the interface for generating applet code, in which $appid and $appsecret in lines 41 and 42 should be replaced with your applet. And the env_version of line 92 should be changed to release after your applet goes online. If it is developing and debugging, keep the status quo.
2. login.php is that the applet requests the interface to the backend to obtain the openid. The $appid and $appsecret in lines 11 and 12 should be replaced with those of your applet.
3. scanCode.php is the backend that tells the server that you have finished scanning the code after scanning the code.
4. getstatus.php is the backend for polling the scan code status.
5. Db.php is the database configuration file, you need to configure your database address, account number, password, and database name.

database creation

Paste this SQL into your database manager to create database tables.

 CREATE TABLE `xcxqrcodelogin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `scene` varchar(32) DEFAULT '',
  `openid` varchar(32) DEFAULT '',
  `status` varchar(2) DEFAULT '1' COMMENT '1未扫码2已扫码3已登录',
  `creat_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=148 DEFAULT CHARSET=utf8mb4

image.png

Demo

image.png
image.png
image.png
image.png

applet code

The above is only the front-end and back-end code. Please click here to download the code of the applet.
Mini program code: https://likeyun.lanzout.com/ii2Tp093wk6b

author

TANKING
If you want to ask, you can add WeChat: sansure2016


TANKING
4.9k 声望545 粉丝

热爱分享,热爱创作,热爱研究。