tp5微信小程序全栈开发九——微信登录与令牌

1、初识Token–意义与作用

tp5微信小程序全栈开发九——微信登录与令牌_第1张图片

2、微信身份体系设计

生成
tp5微信小程序全栈开发九——微信登录与令牌_第2张图片
校验
tp5微信小程序全栈开发九——微信登录与令牌_第3张图片

3、实现Token身份权限体系①

route.php

Route::post('api/:version/token/user','api/:version.Token/getToken');

post:获取令牌 传递的code有一定的安全需求,所以稍微隐藏,放到post的body里面传递

\controller\Token.php



namespace app\api\controller\v1;


use app\api\service\UserToken;
use app\api\validate\TokenGet;

class Token
{
    public function getToken($code = ''){
        (new TokenGet())->goCheck();
        $ut = new UserToken();
        $token = $ut->get($code);
        return $token;
    }
}

\validate\TokenGet.php



namespace app\api\validate;


class TokenGet extends BaseValidate
{
    protected $rule = [
        'code' => 'require|isNotEmpty'
    ];

    protected $message = [//传递错误信息
        'code' => '没有code还想获取token,做梦'
    ];

}

isNotEmpty的作用:有参数名但是没有值,require会通过

\validate\BaseValidate.php

protected function isNotEmpty($value,$rule='',
                                  $data='',$filed=''){
        if (empty($value))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

\model\User.php在数据库中有一个User表



namespace app\api\model;


class User extends BaseModel
{

}

由于业务比较复杂,在model上边封装一个service层,把

\service\UserToken.php



namespace app\api\service;


class UserToken
{
    public function get($code){

    }
}

model、service总结

model除了处理业务逻辑之外,还有很重要的功能——调用数据库访问层,实现数据库增删改查,而service是建立在model之上的。
model模型命名必须和我们的数据库名相同。否则不知道对应哪张表。
所有复杂的 放到service层,简单的粒度比较小的放到model层。

4、实现Token身份权限体系②

如何通过小程序传来的code码,到微信小程序里面获取到openid

小程序通过wx.login()获取到的code,换取用户的登录状态信息,包括用户的唯一标志openid,以及本次登陆的会话密钥session_key。
微信小程序给一个接口地址,调用接口地址,获取openid。所需要传入的一系列参数appid(小程序id),secrect(小程序秘钥),js_code(code)。

分成了两大块:
小程序自己获取code码;
把code码发送到我们的服务器,再由我们的服务器调用微信给我们的接口,最终获取到openid和session_key。

\extra\wx.php


return [
    'app_id' => '自己的小程序id',
    'app_secret' => '自己的小程序秘钥',
    'login_url' => "https://api.weixin.qq.com/sns/jscode2session?".
        "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
];

把需要传参的地方用%s占位符

service\UserToken.php



namespace app\api\service;


use think\Exception;

class UserToken
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecrect;
    protected $wxLoginUrl;

    //在构造函数里面把这个wxLoginUrl配置完整  
    function __construct($code)
    {
        $this->$code = $code;
        $this->wxAppID = config('wx.app_id');
        $this->wxAppSecrect = config('wx.app_secret');
        //调用sprintf占位符填写完整
        $this->wxLoginUrl = sprintf(config('wx.login_url'),
            $this->wxAppID,$this->wxAppSecrect,$this->code);
    }


    }

因为发送http请求是一个经常用到的,所以放到公共文件里面
common.php

($url,$httpCode = 0){
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

    //不做证书校验,部署在linux下请改为true
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
    $file_contents = curl_exec($ch);
    $httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
    curl_close($ch);
    return $file_contents;
}

\service\UserToken.php
在这里直接调用

public function get(){
        $result = curl_get($this->wxLoginUrl);
        $wxResult = json_decode($result,true);//把字符串变成数组:true:数组;false:对象
        if (empty($wxResult)){//若为空,则微信调用失败
            throw new Exception('获取session_key及openID时异常,微信内部错误');
            //为什么使用框架的Exception而不是使用用户自定义的异常处理?
            /*自定义的会作为结果返回到客户端去,但是这个是属于服务器内部的异常,这个会把它记录为日志。*/
        }
        else{//进一步的做判断
            $LoginFail = array_key_exists('errcode',$wxResult);
            //如果接口调用失败,微信会返回你一个errorcode码
            if ($LoginFail){//失败,处理异常
                $this->processLoginError($wxResyult);
            }
            else{//获取成功,颁发令牌
                $this->grantToken();
            }
        }
     }

5、实现Token身份权限体系③

\service\UserToken.php

private function processLoginError($wxResult){
        throw new WeChatException([//做一个自定义参数设置
            'msg' => $wxResult['errmsg'],
            'errorCode' => $wxResult['errcode']
        ]);
    }

在这里写一个异常处理函数:
为了扩展方便一些,比如发送邮件,记录日志

\exception\WeChatExceeption



namespace app\lib\exception;


class WeChatException extends BaseException
{
    public $code = 400;
    public $msg = '微信服务器接口调用失败';
    public $errorCode = 999;

}

在这里自定义一个异常

\service\UserToken.php

private function grantToken($wxRssukt){
        //拿到oppenid
        //数据库里看一下,这个openid是不是已经存在
        //如果存在,则不处理,如果不存在,那么新增一个user记录
        //生成令牌,准备缓存数据,写入缓存
        //把令牌返回到客户端去
        $openid = $wxRssukt['openid'];
    }

在微信小程序通过wx.login获取code码,在postman里面输入url,body-row-json里面输入{“code”:”“}

6、实现Token身份权限体系④

//数据库里看一下,这个openid是不是已经存在
//如果存在,则不处理,如果不存在,那么新增一个user记录

\model\Useer.php
查询数据库



namespace app\api\model;


class User extends BaseModel
{
    public function getByOpenId($openid){
        $user = self::where('openid','=',$openid)
            ->find();
        return $user;
    }
}

\service\Usertoken.php

private function grantToken($wxRssukt){
        $openid = $wxRssukt['openid'];

        //如果存在,则不处理,如果不存在,那么新增一个user记录
        if ($user){
            $uid = $user->id;
        }
        else{
            $uid = $this->newUser($openid);//使用模型插入数据
        }

        //生成令牌,准备缓存数据,写入缓存
            //缓存key:令牌
            //value:wxRelsut(sessionkey openid);uid,scope(决定用户身份)
        $cachedValue = $this->prepareCachedValue($wxRssukt,$uid);

    }

    private function prepareCachedValue($wxResult, $uid){//准备缓存value的数据
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        $cachedValue['scope'] = 16;
        return $cachedValue;
    }

    private function saveToCache($cachedValue){
        $key = generateToken();
    }

    private function newUser($openid){//插入数据函数
        $user = UserModel::create([
            'openid' => $openid
        ]);
        return $user->id;
    }

你可能感兴趣的:(tp5微信小程序)