背景
在小程序中授权登录后,希望可以直接登录到后台,不需要再输入用户名和密码。然后可以访问后台的数据,在小程序显示。 本教程是在使用 uni-app 开发,后台是php 的 fastadmin 后台
第一步 需要申请小程序的账号
第二步 下载开发工具和创建项目(HBuilderX 和微信开发工具)
下载HBuilderX和微信工具, 使用HBuilderX创建项目
第三步 观察后台的 api 接口用户表 和 微信登录的api 接口
说明: 授权登录的通常做法,一般是获得小程序的 openid 或者uuid , 发到到后台, 有后台验证数据 验证数据没有问题后,查看 用户表是否有 openid ,如果没有新增,有就忽略表示已经有这个用户了, 然后直接登录,返回用户的数据给小程序. 小程序拿到token ,然后通过token ,访问后台。
- 后台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`
- 小程序登录相关接口
第四步 直接上代码
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);
}
}
}
`