通过小程序实现微信扫码授权登录,网站接入微信扫码登录功能(永久免费)

news2025/1/23 23:22:27

需求

网站如果想要实现微信扫码登录其实有很多种方案,常见的方案就是微信开放平台和微信公众号服务号。前者是目前大部分网站并且是微信认可的一种方式,后者是开发者发现服务号具备扫码关注后即可获取用户基本信息的能力后而开发的一种方式。

而这两者其实都是需要具备资质,例如认证,对于个人开发者来说,是有一定的门槛的,而我这次分享的是0门槛的,个人开发者一样可以实现。

原理

小程序也是具备获取用户基本信息的能力的,可以调用wx.login接口获取用户的openid实现登录。简单来说就是web端创建一个带参数的二维码同时向数据库插入一条登录记录,此时web端已经开始轮询数据库这条记录的扫码状态了,微信扫码后打开小程序并立即获取到这个参数,然后点击授权登录按钮请求wx.login这个接口获取到openid,然后将openid更新至数据库这个登录记录中并更新扫码状态,web端可以轮询到登录成功的状态码就展示登录成功。

在这里插入图片描述

代码

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");

?>

代码说明

1、creatqrcode.php是生成小程序码的界面,其中41行和42行的 a p p i d 和 appid和 appidappsecret要换成你的小程序的。以及92行的env_version在你的小程序上线后要改为release,如果是开发调试中,就保持现状。
2、login.php是小程序端向后端请求接口获取openid的,其中11行和12行的 a p p i d 和 appid和 appidappsecret要换成你的小程序的。
3、scanCode.php是扫码后告诉服务器你已经完成扫码的后端。
4、getstatus.php是轮询扫码状态的后端。
5、Db.php是数据库配置文件,需要进去配置你的数据库地址、账号、密码、数据库名称。

数据库创建

将这条SQL粘贴至你的数据库管理端进行创建数据库表。

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

在这里插入图片描述

Demo

在这里插入图片描述

在线体验
https://ma.liketube.cn/xcxqrcodelogin/creatqrcode.php

在这里插入图片描述

小程序端代码

以上仅为前端和后端的代码,小程序端的代码请点击这里下载。
小程序端代码:https://likeyun.lanzout.com/ii2Tp093wk6b

作者

TANKING
如需请教,可加WeChat: sansure2016

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1006835.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea创建一个微服务项目

idea创建一个微服务项目 前提&#xff1a;懂得创建基于pom 的 springboot项目 1.像平时创建Maven项目一样创建一个项目 2.删掉src文件&#xff0c;只剩下下面的东西 3.基于这个项目创建model&#xff0c;model也是一个Maven项目&#xff0c;基于springboot mvc 都行&#xff…

openGauss学习笔记-68 openGauss 数据库管理-创建和管理普通表-向表中插入数据

文章目录 openGauss学习笔记-68 openGauss 数据库管理-创建和管理普通表-向表中插入数据68.1 背景信息68.2 操作步骤68.2.1 向表customer_t1中插入一行68.2.2 向表中插入多行68.2.3 从指定表插入数据到当前表68.2.4 删除备份表 openGauss学习笔记-68 openGauss 数据库管理-创建…

Python 图形化界面基础篇:添加复选框( Checkbutton )到 Tkinter 窗口

Python 图形化界面基础篇&#xff1a;添加复选框&#xff08; Checkbutton &#xff09;到 Tkinter 窗口 引言什么是 Tkinter 复选框&#xff08; Checkbutton &#xff09;&#xff1f;步骤1&#xff1a;导入 Tkinter 模块步骤2&#xff1a;创建 Tkinter 窗口步骤3&#xff1a…

【数据分享】2006-2021年我国城市级别的排水和污水处理相关指标(20多项指标)

《中国城市建设统计年鉴》中细致地统计了我国城市市政公用设施建设与发展情况&#xff0c;在之前的文章中&#xff0c;我们分享过基于2006-2021年《中国城市建设统计年鉴》整理的2006—2021年我国城市级别的市政设施水平相关指标、2006-2021年我国城市级别的各类建设用地面积数…

Vue3表单

文章目录 Vue3表单1. 概念2. 输入框3. 复选框4. 单选按钮5. select下拉列表5.1 下拉列表单选5.1 下拉列表多选时绑定到数组5.3 使用 v-for 循环输出选项 6. 值绑定7. 修饰符7.1 .lazy7.2 .number7.3 .trim Vue3表单 1. 概念 可以用 v-model 指令在表单 、 及 等元素上创建双向…

微信内测新功能:“微信分期”来了!

微信作为一款社交 App&#xff0c;早已成为了现在人们日常生活中不可缺少的一部分。 随着生态不断完善&#xff0c;它所涵盖的功能也是越来越多。 据镭射财经&#xff0c;微信近日正在测试一款名为“微信分期”的全系消费信贷产品。功能入口位于微信钱包中&#xff0c;资金方为…

预约微信小程序源码系统制作搭建 适用于多场景 支持万能DIY功能

分享一个预约微信小程序源码系统&#xff0c;适用于多种预约场景&#xff0c;含完整代码包前端后端详细的搭建教程&#xff0c;支持万能DIY功能&#xff0c;让你轻松开发制作一个属于自己的想要的预约小程序。 一、预约微信小程序源码系统制作搭建的基本步骤和注意事项&#xf…

【Flink实战】Flink 商品销量统计-实战Bahir Connetor实战存储 数据到Redis6.X

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680; 文章简介 &#xff1a;Flink 商品销量统计-实战Bahir Connetor实战存储 数据到Redis6.X &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 目录导航 Flink怎么操作RedisFlink 商品销量统…

宿舍考勤安全系数?这个答案全国统一!

在现代教育和住宿管理中&#xff0c;确保学生或员工的宿舍考勤管理变得越来越重要。传统的考勤方法可能受到人为错误和滥用的威胁&#xff0c;同时也可能耗费大量时间和资源。 人脸识别技术已经在各个领域展现了强大的潜力。它不仅提高了安全性&#xff0c;还改善了考勤管理的效…

GP08|财务估值因子过滤实盘小市值

量化策略开发&#xff0c;高质量社群&#xff0c;交易思路分享等相关内容 大家好&#xff0c;今天我们来分享gp08策略。千呼万唤始出来&#xff0c;由于xxx原因&#xff08;不便说&#xff0c;好奇的可以私聊我&#xff09;&#xff0c;我们从9月份开始&#xff0c;后面分享的策…

深入解析顺序表:揭开数据结构的奥秘,掌握顺序表的精髓

&#x1f493; 博客主页&#xff1a;江池俊的博客⏩ 收录专栏&#xff1a;数据结构探索&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f525;编译环境&#xff1a;Visual Studio 2022&#x1f38…

包装类、多线程的基本使用

包装类 1.基本数据类型对应的引用数据类型(包装类) 1.概述:所谓的包装类就是基本类型对应的类(引用类型),我们需要将基本类型转成包装类,从而让基本类型具有类的特性(说白了,就是将基本类型的数据转成包装类,就可以使用包装类中的方法来操作此数据)2.为啥要学包装类:a.将来有…

springboot上传文件到后台指定文件夹

第一步&#xff0c;在application.yml做一下配置&#xff0c;预设下载目录 files:upload:path: D:/SpringBootItem/springboot/files/ 其中有用到hutool工具依赖&#xff0c;如下在pom.xml中添加依赖&#xff0c;也可以选择不添加&#xff0c;自己修改下Controller中的代码即可…

批量采集头条号文章的工具-让我们更好地辨别信息好坏

大家好&#xff0c;今天我想和大家聊一聊一个在互联网时代备受瞩目的话题&#xff0c;那就是批量采集头条号的文章。作为一个热衷于信息获取和分享的人&#xff0c;我深知这一领域的挑战和机遇。 让我们来谈谈批量采集头条号的文章所面临的挑战。随着互联网的迅猛发展&#xff…

亚马逊API接口解析,实现获得AMAZON商品详情

要解析亚马逊API接口并实现获取亚马逊商品详情&#xff0c;你需要按照以下步骤进行操作&#xff1a; 了解亚马逊开发者中心&#xff1a;访问亚马逊开发者中心&#xff0c;并了解相关的API文档、开发者指南和规定。注册开发者账号&#xff1a;在亚马逊开发者中心上注册一个开发…

Java“牵手”京东商品详情数据,京东商品详情接口,京东API接口申请指南

京东商品详情API是京东平台提供给开发者的应用程序编程接口&#xff0c;通过API可以获取京东平台上商品详情信息。 京东商品详情API可以获取到商品的标题、价格、销量、评价、详情页等信息。开发者在京东开放平台注册开发者账号&#xff0c;并获得访问API接口的密钥后&#xf…

代码随想录算法训练营day46|139.单词拆分|多重背包基础理论| 背包总结

139.单词拆分 力扣题目链接 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明&#xff1a; 拆分时可以重复使用字典中的单词。 你可以假设字典中没有重复的单词。 示例 1&#xff1a…

关于批量安装多个apk

for %i in (apks地址/*.apk); do adb install %i https://www.cnblogs.com/lihongtaoya/p/15084378.html adb install -r apks地址/1.apk && adb install -r apks地址/2.apk install-multi-package - 暂时nok https://adbshell.com/commands 最新版本的platform-tool…

Dinky上路之旅

1、部署flink集群 1.1、flink-conf.yaml cat > flink-conf.yaml << EOF jobmanager.rpc.address: boshi-146 jobmanager.rpc.port: 6123 jobmanager.bind-host: 0.0.0.0 jobmanager.memory.process.size: 1600m taskmanager.bind-host: 0.0.0.0 # 修改为本机ip tas…

今日宜分享:科技十足主页面的高校官网颜值排行榜

科技十足主页面的高校官网颜值排行榜 全国985名单&#xff08;最新&#xff09;1. 北京&#xff08;8所&#xff09;2. 上海&#xff08;4所&#xff09;3. 湖南&#xff08;3所&#xff09;4. 陕西&#xff08;3所&#xff09;5. 湖北&#xff08;2所&#xff09;6. 山东&…