TP6微信公众号登陆授权

先做好准备工作

微信公众号获取用户信息地址: 网页授权
jssdk下载: 获取access_token bmwj
复制这段内容后打开百度网盘手机App,操作更方便哦

第一步先去公众号后端配置授权域名

域名必须是公网的
TP6微信公众号登陆授权_第1张图片
将下载好的验证文件, 放到能访问的路径, 例如: thinkphp6框架, 我们只需将 验证文件 放到 public
TP6微信公众号登陆授权_第2张图片
在基本配置中, 获取 appid 和 AppSecret
TP6微信公众号登陆授权_第3张图片

第二部在thinkphp中写获取code等接口

// 测试使用另一个种思路做 微信公众号登陆, 正式服务器上也在使用
    public function login(){
        //判断用户是否在微信里面打开
        $appid = '这个东西填写自己的';
        $secret = '这个东西填写自己的';
        // 判断是否存在 code
        if (isset($_GET['code'])) {
            $code = $_GET['code'];
            // 获取access_token
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";
            // curl请求, 我放在下面的封装方法
            $result = Curl::get($url);
            // 不加true 转为对象, 加上true 转为数组
            $decode = json_decode($result, true);
            // 如果用户openid 不存在数据库中
            if (!(new Personal())->where(['new_openid' => $decode['openid']])->find()){
                if (isset($decode['openid'])) {
                	// 跳转另一个方法进行存入session 和 入库
                    $url = $this->getUserCreateData($decode);
                    header("Location: $url");exit;
                } else {
                    // 可以跳转一个 404页面
                    header("HTTP/1.1 404 Not Found");exit;
                }
            } else {
            	// 存在也需要去更新用户头像和 session 的时间
                // 获取用户信息和添加入库
                $url = $this->getUserCreateData($decode);
                header("Location: $url");exit;
            }
        } else {
            // 不存在code 去微信获取code 回调地址填写当前方法, 反正是比较安全的做法, 不需要给前端传任何参数
            // 我说下这儿的逻辑, 放到当自己的当前方法微信已经在地址上面拼接了code.
            $redirect_uri = urlencode('https://test.com/api/personal/login');
            $response_type = 'code';
            $scope = 'snsapi_userinfo';
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=$response_type&scope=$scope&state=STATE#wechat_redirect";
            // 跳转微信地址获取code
            header("Location: $url");exit;
        }
    }

添加到数据库中


    
    /**
     * 获取用户信息和添加入库
     * @param $decode
     * @return string|void
     * @throws ApiServiceException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected function getUserCreateData($decode)
    {
        $userInfo = $this->getConfigUserInfo($decode['access_token'], $decode['openid']);
        // 如果获取成功, 添加入库
        if (array_key_exists('openid',$userInfo) && array_key_exists('nickname',$userInfo)) {
        	// 添加方法也在下方
            $data = (new Personal())->createUserInfo($userInfo);
            // 开启session 会话才能使用 使用可能我是用的框架问题;
            session_start();
            $_SESSION['name'] = $data['new_token'];
            // 跳转微信地址获取code
            return "https://test.com/water/";
            //
        } else {
            // 可以跳转一个 404页面
            header("HTTP/1.1 404 Not Found");exit;
        }
    }

	/**
     * 添加用户信息
     * @param array $data
     * @return array
     * @throws ApiServiceException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
	public function createUserInfo(array $data) : array
    {
        // 生成token
        $token = sha1(md5(uniqid(md5(microtime(true)), true)));
        $param['new_openid'] = $data['openid'];
        $param['nickname'] = $data['nickname'];
        $param['new_sex'] = $data['sex'];
        $param['avatar'] = $data['headimgurl'];
        $param['new_token'] = $token;
        // 查询用户是否注册
        $userInfoFind = Db::name('user')->field('id, new_openid, new_sex, mobile, avatar, status, delete_time')
            ->where([
                'new_openid' => $data['openid']
            ])
            ->find();
        if ($userInfoFind) {
            // 修改用户的头像和昵称
            $param['update_time'] = time();
            self::where(['new_openid' => $data['openid']])->update($param);
            // 判断用户头像地址是否含有http https
            if (!preg_match('/(http|https):\/\/([\w.]+\/?)\S*/', $userInfoFind['avatar'])) {
                $userInfoFind['domain'] = request()->domain();
            }
            $userInfoFind['new_token'] = $param['new_token'];
            // 缓存时间 180天
            if (!Cache::set($param['new_token'], $userInfoFind, 1296000)) throw new ApiServiceException('登陆失败');
            return $userInfoFind->toArray();
        } else {
            //用户第一次注册进来
            $param['update_time'] = $param['create_time'] = time();
            $save = Db::('user')->insertGetId($param);
            if ($save) {
                $param['id'] = $save;
                $param['mobile'] = '';
                $param['status'] = 1;
                $param['delete_time'] = 0;
                // 缓存时间 180天
                if (!Cache::set($param['new_token'], $param, 1296000)) throw new ApiServiceException('添加失败');
                return $param;
            } else {
                throw new ApiServiceException('添加失败');
            }
        }
    }

    /**
     * 获取用户基本信息
     * @param $access_token
     * @param $openid
     * @return mixed
     */
    protected function getConfigUserInfo($access_token, $openid)
    {
        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
        $result = Curl::get($url);
        // 不加true 转为对象, 加上true 转为数组
        return json_decode($result, true);
    }
    /**
     * 该函数理由三个执行方法
     * 1 先用code 获取access_token
     * 2 在用 access_token 换取 refresh_token 有效时间为30天
     * 3 使用access_token和openid 获取用户的基本信息
     * @return Json
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getAccessToken() :Json
    {
        session_start();
        // 获取session
        $token = $_SESSION['name'];
        // 获取用户信息
        $data = Cache::get($token);
        // 不为数组转为数组返回
        ( !is_array($data) ) && ( $data = $data->toArray() );

        if ($data) {
            return api_success($data);
        } else {
            return api_error('请从新登陆', ['url' => "https://test.com/api/personal/login"], 500, 2);
        }
    }

这是封装的 curl

class Curl
{
    /**
     * @param string $url   请求地址
     * @param array $params 请求参数
     * @param array $header 请求头
     * @param int $timeOut  请求时间
     * @return bool|string
     */
    public static function delete(string $url, array $params = [], array $header = [], int $timeOut = 10)
    {
        return self::curlRequest($url, 'DELETE', $params, '', $header, $timeOut);
    }

    /**
     * @param string $url   请求地址
     * @param array $header 请求头
     * @param int $timeOut  请求时间
     * @return bool|string
     */
    public static function get(string $url, array $header = [], int $timeOut = 10)
    {
        return self::curlRequest($url, 'GET', [], '', $header, $timeOut);
    }

    /**
     * @param string $url   请求地址
     * @param array $params 请求参数
     * @param string $paramsType    请求数据类型
     * @param array $header     请求头
     * @param int $timeOut      请求时间
     * @return bool|string
     */
    public static function post(string $url, array $params = [], string $paramsType = '', array $header = [], int $timeOut = 10)
    {
        return self::curlRequest($url, 'POST', $params, $paramsType, $header, $timeOut);
    }

    /**
     * @param string $url   请求地址
     * @param string $method    请求方式
     * @param array $params     请求参数
     * @param string $paramsType    请求数据类型
     * @param array $header     请求头
     * @param int $timeOut      请求时间
     * @return bool|string
     */
    private static function curlRequest(string $url, string $method = '', array $params = [], string $paramsType = '', array $header = [], int $timeOut)
    {
        $resHeader = [];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);    // 地址
        curl_setopt($ch, CURLOPT_HEADER, 0);    // 请求头
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);    //获取的信息以文件流的形式放回, 而不是直接输出
        curl_setopt($ch, CURLINFO_HEADER_OUT, true);    // TRUE 时追踪句柄的请求字符串, 这个很关键,就是允许你查看请求header
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeOut);    // 告诉成功 PHP 从服务器接收缓冲完成前需要等待多长时间,如果目标是个巨大的文件,生成内容速度过慢或者链路速度过慢,这个参数就会很有用
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeOut);     //  告诉 PHP 在成功连接服务器前等待多久(连接成功之后就会开始缓冲输出),这个参数是为了应对目标服务器的过载,下线,或者崩溃等可能状况
        curl_setopt($ch, CURLOPT_FAILONERROR, false);  // PHP在发生错误(HTTP代码返回大于等于300)时,不显示,设置这个选项为一人非零值。默认行为是返回一个正常页,忽略代码。
        if (1 == strpos('$'.$url, "https://")) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        if ($method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($paramsType == 'JSON') {
                $resHeader[] = 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8';
                $resParams = json_encode($params);
            } else {
                $resParams = http_build_query($params);
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $resParams);
        } else if ($method == 'PUT') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        } else if ($method == 'DELETE') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        }
        $resHeader = array_merge($resHeader, $header);
        if ($resHeader) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $resHeader);
        }
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}

第三部 查看前端代码

使用的uniapp做的将下面代码放到 App.vue文件中
``

onLaunch: function() {
	this.getToken({}).then((res) => {
			console.log(res);
			if (res.data.code == 200) {
				// 头像
				let headImg = res.data.data.avatar
				// 绑定户号状态
				let accountType = res.data.data.default_type
				// token
				let Token = res.data.data.new_token
			
				uni.setStorage({
					key: 'userinfo',
					data: {
						headImg: headImg,
						accountType: accountType,
						Token: Token,
					},
					success: function() {
						console.log('success');
					}
				});
				uni.getStorage({
					key: 'userinfo',
					success: function(res) {
						console.log(res.data);
					}
				});
			} else {
				window.location.href = res.data.data.url
			}
		})
	},
	methods: {
		// 访问后端方法即可
		getToken() {
			uni.request({
				// 携带 cookie
				xhrFields: {
					withCredentials: true
				},
				url: 'https://test.com/api/personal/getAccessToken',
				methods: 'POST',
				success: (res) => {
					return res
				}
			})
		},
	}

第四部 将 uni-app 打包上传到服务器上面

我们使用的是 thinkphp 在public 下建一个 test 文件夹, 将打包好的 static和index.html 放在当中. 访问项目直接 https://test.com/api/personal/login, 就能访问成功

你可能感兴趣的:(THINKPHP6,微信公众号,微信,php,uni-app)