uni-app 小程序免登录到后台简单教程

498 阅读2分钟

背景

在小程序中授权登录后,希望可以直接登录到后台,不需要再输入用户名和密码。然后可以访问后台的数据,在小程序显示。 本教程是在使用 uni-app 开发,后台是php 的 fastadmin 后台

第一步 需要申请小程序的账号

如何申请小程序的url

第二步 下载开发工具和创建项目(HBuilderX 和微信开发工具)

下载HBuilderX和微信工具, 使用HBuilderX创建项目

第三步 观察后台的 api 接口用户表 和 微信登录的api 接口

说明: 授权登录的通常做法,一般是获得小程序的 openid 或者uuid , 发到到后台, 有后台验证数据 验证数据没有问题后,查看 用户表是否有 openid ,如果没有新增,有就忽略表示已经有这个用户了, 然后直接登录,返回用户的数据给小程序. 小程序拿到token ,然后通过token ,访问后台。

  1. 后台api 用户表 需要增加以下几个字段

ALTER TABLE `__PREFIX__user`
    ADD COLUMN `country`  varchar(50) NULL COMMENT '国家-微信小程序' AFTER `verification`,
    ADD COLUMN `province`  varchar(50) NULL COMMENT '省会-微信小程序' AFTER `country`,
    ADD COLUMN `city`  varchar(50) NULL COMMENT '城市-微信小程序' AFTER `province`,
    ADD COLUMN `openid`  varchar(50) NULL COMMENT 'openid-微信小程序' AFTER `city`,
    ADD COLUMN `unionid`  varchar(50) NULL COMMENT 'unionid-微信小程序' AFTER `openid`
  1. 小程序登录相关接口 登录流程时序图

第四步 直接上代码

uni-app

`

<template>
	<view class="content">
		<image class="logo" :src="headerUrl"></image>
		<view>
			<button type="default" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">个人账号登录</button>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
			
			}
		},
		methods: {	
			getPhoneNumber(e){  
				var that = this;
				if(e.detail.errMsg=="getPhoneNumber:fail user deny"){       //用户决绝授权  
		            console.log("dddddddddddddd")
					//拒绝授权后弹出一些提示  
		
				}else{
					// 调用微信内部函数 login 获取 code, 传给后台 获取 
					uni.login({
						provider: 'weixin',
						success(loginAuth) {
							var data = {'code':loginAuth.code}
							var path = '/api/weixin/getCode'
							that.$http(path,data).then((response)=>{
						
								
								uni.setStorageSync('openid',response.data.openid)
								uni.request({
									url:"https://u15410227e.goho.co/api/weixin/getPhone?code="+e.detail.code,
									method: 'GET'
								}).then(data => {
									//data为一个数组,数组第一项为错误信息,第二项为返回数据
									const [error, res] = data;
					
									// 出错
									if (error) {
										uni.hideLoading()
										uni.showToast({
											title: '网络出错了,请稍后再试',
											image: "/static/error.png"
										})
										return Promise.reject('网络出错了,请稍后再试');
									}
								
									// statusCode判断
									if (res.statusCode == 200) {// 成功请求
									    uni.setStorageSync('mobile',res.data.data)
										// 登录系统
										uni.request({
											url:"https://u15410227e.goho.co/api/weixin/login",
											method: 'POST',
											data:{"openid":uni.getStorageSync('openid'),"mobile": uni.getStorageSync('mobile')}
										}).then(data=>{
											console.log(data);
										})
										return Promise.resolve(res.data);
									} else if (res.statusCode == 401 || res.statusCode == 403) {
										// Authorization问题 鉴权问题
									}
								})
			
							})
						}
					})
					console.log(e.detail.code)
				     
				}  
			}  
			
			

		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
	
	.button-style{
		width: 150rpx;
		height: 60rpx;
		background-color: #007AFF;
		border-radius: 10rpx;
		margin-top: 60rpx;
	}
</style>



`

后台逻辑处理

`

<?php


namespace app\api\controller;


use app\common\controller\Api;
use fast\Http;

/**
 * 微信登录
 * @ApiGroup (微信登录)
 */
class Weixin extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];
    protected $appid;
    protected $secret;
    protected $loginUrl='https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code&appid=%s&secret=%s&js_code=%s';

    public function __construct()
    {
        $this->appid = get_addon_config("winecalendar")['appId'];
        $this->secret = get_addon_config("winecalendar")['secretId'];
        parent::__construct();
    }


    /**
     * @ApiTitle    (授权)
     * @ApiMethod   (GET)
     * @ApiParams   (name="code", type="string", required=true, description="code 用来获取手机号")
     * @ApiRoute    (/api/weixin/getCode)
     * @ApiReturn   ({
    "code": 1,
    "msg": "成功",
    "time": "1592472641",
    "data": null
    })
     */
    public function getCode()
    {
        $code = $this->request->param('code');
        if (!$code) {
            $this->error('code不能为空');
        }
        self::getOpenid($code);
    }

    /**
     * 获取opPenId
     */
    public function getOpenid($code)
    {
        $url = sprintf($this->loginUrl, $this->appid, $this->secret, $code);
        $result = Http::get($url);
        $wxResult = json_decode($result, true);
        if (empty($wxResult)) {
            $this->error('获取sessin_key及openID时异常');
        }
        if (isset($wxResult['errcode']) && $wxResult['errcode'] != 0) {
            $this->error($wxResult['errmsg'],$this->appid);
        }
        $item = [
            'openid' => $wxResult['openid'],
            'session_key' => $wxResult['session_key']
        ];
        $this->success('成功', $item);
    }


    /**
     * @ApiTitle    (微信用户登录)
     * @ApiMethod   (POST)
     * @ApiParams   (name="code", type="string", required=true, description="code 用来获取手机号")
     * @ApiRoute    (/api/weixin/login)
     * @ApiBody     ({
    "openid": "440000006",
    "mobile": "13539854620"
    })
     * @ApiReturn   ({
    "code": 1,
    "msg": "登录成功",
    "time": "1592472641",
    "data": null
    })
     */
    public function login()
    {
        $openid = $this->request->post('openid');
        $mobile = $this->request->post('mobile');

        if( empty($openid) || empty($mobile)){
            $this->error('缺少参数');
        }
        $errCode = 0;
        if ($errCode == 0) {
            $userinfo = \app\admin\model\User::where(['openid' => $openid, 'mobile'=> $mobile ])->find();
            if ($userinfo) {
                $this->auth->direct($userinfo['id']);
            } else {
                $user = new \app\admin\model\User();
                $user->data([
                    'status' => 'normal',
                    'openid' => $openid,
                    'mobile' => $mobile
                ]);
                $user->save();
                $this->auth->direct($user->id);
            }
            $this->success('登录成功', $this->auth->getUserinfo());
        } else {
            $this->error('登录失败' . $errCode);
        }
    }


    /**
     * @ApiTitle    (获取手机号)
     * @ApiMethod   (GET)
     * @ApiParams   (name="code", type="string", required=true, description="code 用来获取手机号")
     * @ApiRoute    (/api/weixin/getPhone)
     * @ApiReturn   ({
    "code": 1,
    "msg": "成功",
    "time": "1592472641",
    "data": "13456789467"
    })
     */
    public function getPhone() {
        // 获取token
        $code = $this->request->param('code');
        if(empty($code)) {
            $this->error('缺少参数');
        }

        $tokenUrl = sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",$this->appid,$this->secret);
        $result = Http::get($tokenUrl);
        $wxResult = json_decode($result, true);
        $token = $wxResult['access_token'];
        if(empty($token)) {
            $this->error('获取token失败');
        }

        // 使用前端code获取手机号码
        $phoneUrl = sprintf("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=".$token);
        $result = Http::post($phoneUrl, json_encode(['code' => $code]));
        $wxResult = json_decode($result, true);

        if(isset($wxResult['phone_info']['phoneNumber'])) {
            $this->success('获取手机成功', $wxResult['phone_info']['phoneNumber']);
        }else {
            $this->error('获取手机失败', $wxResult);
        }

    }

 

}

`