微信小程序的Token获取,存入缓存,以及从缓存中获取Token携带的用户uid

       我们利用微信小程序给每一位用户生成的Code数字码,把这个Code码传递给我们的getToken接口,这个Code码是我们在微信服务器换取用户信息的标识,我们在getToken接口中接收到这个Code码之后,我们就需要向微信服务器发送一个请求并将Code码发送到微信服务器中,然后微信服务器就会返回一个openid和一个session_key,这个openid就是我们需要的用户身份的唯一标识,而且如果我们需要使用微信支付时,这个openid也是必需的。当我们获取了openid后,我们需要将其存到我们的的数据库中。而openid是一个比较隐秘的用户数据而且是固定不变且长久有效的,我们并不提倡将其返回到客户端去,解决这个问题的方法是生成一个具有有效期限的Token令牌返回到客户端中,下次访问时只需携带这个令牌并通过这个令牌找到对应的openid从而间接地获取openid,而Token令牌的存储,我们将其存放在缓存中,如果我们将其存放在数据库中,我们访问接口时,会对数据库产生一个相当大的压力,且大多数情况下,缓存的访问速度是要优于数据库的访问速度的。

Controller/Token.php

<?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($code);
        $token = $ut->get();
        return [
            'token' =>$token
        ];
    }
}

 service/Token.php

<?php


namespace app\api\service;


use app\lib\exception\TokenException;
use think\Cache;
use think\Exception;
use think\Request;

class Token
{
    //生成令牌
    public static function generateToken(){
        //32个字符组成一组随机字符串
        $rangChars = getRandChar(32);
        //用三组字符串,进行md5加密
        $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
        //salt 盐
        $salt = config('secure.token_salt');
        return md5($rangChars.$timestamp.$salt);
    }

    public static function getCurrentTokenVar($key){
        $token = Request::instance()
            ->header('token');//tp5的Request::instance()获取post、get、参数、表单上传的文件
        $vars = Cache::get($token);
        if(!$vars){
            throw new TokenException();
        }else{
            if(!is_array($vars)){
                $vars = json_decode($vars,true);
            }
            if(array_key_exists($key,$vars)){
                return $vars[$key];
            }else{
                throw new Exception('尝试获取的Token变量并不存在');
            }
        }
    }
    //由缓存的token获取Uid
    public static function getCurrentUid(){
        $uid = self::getCurrentTokenVar('uid');
        return $uid;
    }
}

service/UserToken.php

<?php


namespace app\api\service;


use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;
class UserToken extends Token
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct($code)
    {
        $this->code = $code;
        $this->wxAppID = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        //sprintf函数   把url中的s% 替换成想要的数据
        $this->wxLoginUrl = sprintf(config('wx.login_url'),
            $this->wxAppID,$this->wxAppSecret,$this->code);
    }

    public function get(){
        $result = curl_get($this->wxLoginUrl);
        $wxResult = json_decode($result,true);//result 变成json字符串
        if(empty($wxResult)){
            throw new Exception('获取session_key及openID时异常');
        }else{
            $loginFail = array_key_exists('errcode',$wxResult);
//            return $loginFail;
            if($loginFail){
                $this->processLoginError($wxResult);
            }else{
                return $this->grantToken($wxResult);
            }
        }
    }

    private function grantToken($wxResult){
        //拿到openid
        //数据库里看一下,这个openid是不是已经存在
        //如果存在,则不处理,如果不存在那么新增一条user记录
        //生成令牌,准备缓存数据,写入缓存
        //把令牌返回到客户端去
        //key:令牌
        //value:wxResult,uid,scope
        $openid = $wxResult['openid'];
        $user = UserModel::getByOpenID($openid);
        if($user){
            $uid = $user->id;
        }else{
            $uid = $this->newUser($openid);
        }
        $cachedValue = $this->prepareCachedValue($wxResult,$uid);
        $token = $this->saveToCache($cachedValue);
        return $token;
    }
    //写入缓存
    private function saveToCache($cachedValue){
        $key = self::generateToken();
        $value = json_encode($cachedValue);//把数组转换成字符串
        $expire_in = config('setting.token_expire_in');
        $request = cache($key,$value,$expire_in);
        if(!$request){
            throw new TokenException([
                'msg' => '服务器缓存异常',
                'errorCode' => 10005
            ]);
        }
        return $key;
    }
    //准备value的一系列数据
    private function prepareCachedValue($wxResult,$uid){
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        $cachedValue['scope'] = 16;//权限高低2,4,6,8,12,14,16
        return $cachedValue;
    }
    //openID不存在  则新增一条记录
    private function newUser($openid){
        $user = UserModel::create([
            'openid' => $openid
        ]);
        return $user->id;
    }
    //封装一个抛出异常的方法
    private function processLoginError($wxResult){
        throw new WeChatException(
            [
                'msg' => $wxResult['errmsg'],
                'errorCode' => $wxResult['errcode']
            ]);
    }
}

 model/User.php

<?php


namespace app\api\model;


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

validate/BaseValidate

<?php


namespace app\api\validate;
use app\lib\exception\ParameterException;
use think\Exception;
use think\Request;
use think\Validate;


class BaseValidate extends Validate
{
    public function goCheck()
    {
        $request = Request::instance();
        $params = $request->param();

        $result = $this->batch()->check($params);
        if(!$result){
            $e = new ParameterException([
                'msg' => $this->error,
        ]);
            throw $e;
        }else{
            return true;
        }
    }

    protected function isPositiveInteger($value,$rule = '',
                                         $data = '', $field = '')
    {

        if(is_numeric($value) && is_int($value + 0) && ($value + 0) > 0){
            return true;
        }else{
            return false;
        }
    }

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

validate/TokenGet

<?php


namespace app\api\validate;


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

    protected $message = [
        'code' => '没有code'
    ];
}
发布了9 篇原创文章 · 获赞 5 · 访问量 346

猜你喜欢

转载自blog.csdn.net/qq_43737121/article/details/103860087