微信扫码登录

11 篇文章 0 订阅
3 篇文章 0 订阅

前提:把前端域名和后端接口域名添加到微信公众号网页授权

我在wiondows系统服务器测试的。所以启动服务是点击运行文件 (vendor/GatewayWorker/start_for_win.bat  )

1. 前端(原生)

pc页面二维码页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>微信扫码登陆</title>
	    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .posthqrcode{
            width: 100vw;
            height: calc(100vh - 40px);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            position: relative;
        }
    </style>
</head>
<body>
	<div class="posthqrcode">
		<div id="qrcode"></div>
		<p>请使用微信扫码登陆</p>
    </div>
    <script src="./js/ajax.js"></script>
    <script src="./js/jquery.min.js"></script>
    <script src="./js/jquery.qrcode.min.js"></script>
    <script>
        // 扫码登陆
		let uuid = '';
		let p = document.querySelector('p');
        ajax({
            url:"http://liao.xddtuoguan.com/api/wechatParam",
            type:"GET",
            is_formdata:false
        },false).then(res=>{
            if(res.code == 200){
                let href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+res.data.appid+"&redirect_uri="+encodeURI('网址/home/wxwechat.html?uuid='+res.data.uuid)+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
				$("#qrcode").qrcode({width:200, height:200,text:href});
				// WebSocket 监听 扫码登陆
				let ws = new WebSocket("ws://网址:8282");
				ws.onopen = function(){
					// console.log("连接成功");
				};
				ws.onmessage = function(e){
					let data = JSON.parse(e.data);
					if(data.type === 'bind'){
						ajax({
							url:"网址/api/bind",
							type:"POST",
							is_formdata:false,
							data:{
								uuid:res.data.uuid,
								client_id:data.client_id
							}
						},false).then(res=>{
							if(res.code == 200){
							   console.log("绑定成功");
							}
						});
					}else if(data.type === 'scanned'){
						p.innerText = data.msg;
					}
					else if(data.type === 'OnLogin'){
						localStorage.setItem('home_token',data.token);
						window.location.href = "首页";
					}
				};
            }
        });

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

手机扫码页面

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>微信一键登录</title>
	<style>
		*{
			margin: 0;
			padding: 0;
		}
		body{
			background-color: #f5f5f5;
		}
		#empower{
			width: 80%;
			background-color: white;
			margin: 0 auto;
			margin-top: 20%;
			text-align: center;
			border-radius: 10px;
			padding: 20px;
		}
		.title{
			width: 80%;
			background-color: white;
			margin: 0 auto;
			margin-top: 20%;
			text-align: center;
			border-radius: 10px;
			padding: 20px;
			font-size: 20px;
			display: none;
		}
		.title img{
			width:90%;
			margin-bottom: 20px;
		}
		#empower p{
			font-size: 20px;
			margin-bottom: 20px;
		}
		#empowerBtn{
			width: 100%;
			height: 40px;
			background-color: #1AAD19;
			border-radius: 5px;
			color: white;
			font-size: 18px;
			border: none;
		}
	</style>
</head>
<body>
	<div class="title">
		<p></p>
	</div>
	<div id="empower">
		<p>是否确认登陆</p>
		<button id="empowerBtn">确认</button>
	</div>

	<script src="./js/ajax.js"></script>
	<script>
		//接受code
		var code = getUrlParam('code');
		var uuid = getUrlParam('uuid');
		var empower =  document.getElementById('empower');
		var btn =  document.getElementById('empowerBtn');
		var title = document.getElementsByClassName('title')[0];
		var titleP = title.getElementsByTagName('p')[0];
		// 确认授权
		btn.onclick = function(){
			ajax({
				url:"http://网址/api/wxwechat",
				type:"post",
				data:{code:code,uuid:uuid},
				is_formdata:false
			},false).then(res=>{
				empower.style.display = 'none';
				titleP.innerText = res.msg;
				title.style.display = 'block';	
				var img = document.createElement('img');
				if(res.code === 200){
					img.src = './images/wxsueecc.jpg';
					titleP.style.color = 'green';
				}else{
					img.src = './images/wxerror.jpg';
					titleP.style.color = 'red';
				}
				title.insertBefore(img,title.firstElementChild);
			});
		}
		// 修改扫码状态	
		ajax({
			url:"http://网址/api/set_status",
			type:"post",
			data:{uuid:uuid},
			is_formdata:false
		},false).then(res=>{
			if(res.code !== 200){
				empower.style.display = 'none';
				titleP.innerText = res.msg;
				title.style.display = 'block';	
				var img = document.createElement('img');
				img.src = './images/wxerror.jpg';
				titleP.style.color = 'red';
				title.insertBefore(img,title.firstElementChild);
			}
		});
	</script>
</body>
</html>

2. 后端thinkphp

<?php
namespace app\api\controller;
use think\cache\driver\Redis;
use app\model\Users;
use app\auth\Jwtauth;
use GatewayClient\Gateway;

class WxLogin extends common
{
    /**
     * @return void
     */
    public function initialize()
    {
        parent::initialize();
        $this->appid = config('weixin.appid');
        $this->appsecret = config('weixin.appsecret');
		//redis
		$this->_redis = new Redis();
		
		Gateway::$registerAddress = '127.0.0.1:1238';
    }
	
	/**
     * gatewayworker 通知
     */
	public function  sendToUid($uuid,$type,$msg,$token=''){
		$data =  [
			'type'=>$type,
			'msg'=>$msg,
			'token'=>$token
		];	
		Gateway::sendToUid($uuid,json_encode($data));
	}

    /**
     * 微信扫码
     * 获取appid appsecret
     */
    public function  wechatParam(){
        // 生成uuid
        $uuid = $this->uuid_create();
        // 存入redis
        $this->_redis->set('uuid_'.$uuid,time(),300);
        // 返回
        return return_json(200,'获取成功',['appid'=>$this->appid,'uuid'=>$uuid]);
    }
	
	/**
	*	修改状态扫码中
	*
	*/
	public function set_status(){
		$uuid = Request()->param('uuid');
		if(!$uuid){
			//通知
			$this->sendToUid($uuid,'scanned','参数错误,请刷新二维码');
			return return_json(201,'参数错误,请刷新二维码');
		}
		// 判断redis uuid是否存在
		if(!$this->_redis->has('uuid_'.$uuid)){
			//通知
			$this->sendToUid($uuid,'scanned','二维码失效,请刷新二维码');
			return return_json(201,'二维码失效,请重新扫码!');
		}
		//通知
		$this->sendToUid($uuid,'scanned','已扫码成功,未确定登陆');
		return return_json(201);
	}
	    /**
     * @return void
     *  
     */
    public function wxwechat(){
        //获取code
        $code = getinput('code');
        $uuid = getinput('uuid');
		// 判断redis uuid是否存在
		if(!$this->_redis->has('uuid_'.$uuid)){
			return return_json(201,'二维码失效,请重新扫码!');
		}
        //获取access_token openid
        $return_data = json_decode($this->curl_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->appsecret."&code=".$code."&grant_type=authorization_code"),true);
        $access_token = $return_data['access_token'];
        $openid = $return_data['openid'];
		
        //查询是否已绑定
		
        $users_id = Users::where('openid',$openid)->value('users_id');
        if($users_id){
            // jwt
            $token = Jwtauth::getToken($users_id);
			
        }else{
            //获取信息
            $user_info = json_decode($this->curl_get_contents("https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN"),true);
            $insert_data = [
                'openid'=>$user_info['openid'],
                'users_name'=>$user_info['nickname'],
                'img_url'=>$user_info['headimgurl']
            ];
            //新增
            $insert_status = Users::create($insert_data);
            if (!$insert_status){
                return return_json(201,'登陆失败,请重新扫码');
            }
            // jwt
            $token = Jwtauth::getToken($insert_status->id);

        }
		$this->sendToUid($uuid,'OnLogin','登录成功',$token);
		return return_json(200,'登录成功');
    }
	
	//绑定user_id
	public function bind(){
		$uuid = request()->param('uuid');
		$client_id = request()->param('client_id');
		Gateway::bindUid($client_id,$uuid);
		return return_json(200,'绑定成功');
	}
	

    //生成uuid
    public function uuid_create(){
        $charid = strtoupper(md5(uniqid(mt_rand(), true)));
        $uuid = substr($charid, 0, 8)
        .substr($charid, 8, 4)
        .substr($charid,12, 4)
        .substr($charid,16, 4)
        .substr($charid,20,12);
        return $uuid;
    }
	
	
    /**
     * 远程获取
     */
    public function curl_get_contents($url) {
        $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_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
}

3. gatewayworker 修改

 vendor/GatewayWorker/applocations/start_gateway.php

// gateway 进程,这里使用Text协议,可以用telnet测试
$gateway = new Gateway("Websocket://网址:8282");
// gateway名称,status方便查看
$gateway->name = 'WuMingHaoGateway';

4.启动服务

 vendor/GatewayWorker/start_for_win.bat  双击运行

微信扫码登录Angular是一种基于微信开放平台提供的二维码扫描技术,在Angular应用中实现场景化认证的过程。这种方式使得用户可以通过微信扫码的方式快速完成身份验证并登录到应用程序中,无需手动输入用户名和密码。 ### 实现步骤: #### 1. 注册微信开放平台账号 首先需要在微信公众平台上注册一个账号,并创建一个小程序或公众号,获取AppID和AppSecret。 #### 2. 配置Angular项目 在Angular项目中引入微信支付和授权的相关依赖库,如`ngx-wechat-login`等。这通常涉及安装相应的npm包。 ```bash # 使用 npm 安装示例 npm install ngx-wechat-login --save ``` #### 3. 引入服务 在 Angular 应用中引入微信登录相关的服务,并注入到需要使用此功能的组件中。 ```typescript import { WechatLoginService } from 'ngx-wechat-login'; constructor(private wechatLoginService: WechatLoginService) {} ``` #### 4. 创建登录功能 在组件中创建微信扫码登录的功能实现。通常包括调用微信登录接口、处理回调结果以及展示加载状态。 ```typescript export class LoginPage { loading = false; constructor(private wechatLoginService: WechatLoginService) {} startWechatLogin() { this.loading = true; // 调用微信登录API,此处假设调用的是wechatLoginService.startLogin() this.wechatLoginService.startLogin().subscribe( (response) => { console.log('成功响应', response); this.handleSuccess(response); }, (error) => { console.error('登录失败', error); this.handleFailure(error); } ); } handleSuccess(data) { // 处理成功的回调数据,可能包含用户信息等 console.log('登录成功', data); // 根据实际情况,可以跳转至主页面或其他操作 } handleFailure(err) { // 处理错误情况 console.log('登录失败', err); } } ``` #### 5. 显示二维码界面 在前端渲染界面中,添加一个按钮触发微信登录请求,然后展示一个二维码供用户扫码。 ```html <button (click)="startWechatLogin()">微信扫码登录</button> <div #qrCode></div> <!-- 添加模板引用 --> <ng-template #qrCode> <!-- 渲染二维码图片 --> <img src="{{ qrCodeUrl }}" alt="二维码"> </ng-template> ``` #### 6. 后端对接 后端需要设置好路由和控制器,用于接收来自微信的回调数据,验证用户身份并返回对应的信息给前端。 #### 7. 用户权限管理 根据用户通过微信登录获得的信息,更新或创建用户的会话状态和相关信息存储于数据库中。 ### 相关问题: 1. **如何优化微信扫码登录的用户体验?** 提高加载速度、简化交互流程、增强安全防护措施、提供反馈提示等都是优化体验的关键点。 2. **Angular中如何处理微信扫码登录的异常情况?** 对应的错误处理逻辑应该覆盖所有可能发生的异常场景,比如网络错误、服务器响应延迟、用户取消扫码等,避免应用崩溃。 3. **为什么选择微信扫码登录而非其他第三方登录方式?** 主要考虑的因素有安全性、用户基数大、易于集成、用户体验良好等。微信作为中国的主流社交软件之一,拥有庞大的用户群体和良好的品牌认知度,适合多种应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_最初の心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值