• 全栈微信小程序商城 学习笔记9.1 新建登录接口


    创建一个登录接口

    相关知识

    简单的MVC就够了吗?浅谈Service、DAO层的引入 | 博客水木

    小程序登录流程

    相关表字段一览

    user表

    id	
    openid	
    nickname	
    extend	
    delete_time	
    create_time	注册时间
    update_time
    

    准备工作

    application oute.php,省略部分代码

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

    参数校验
    applicationapivalidateTokenGet.php

    <?php
    namespace appapivalidate;
    
    
    class TokenGet extends BaseValidate
    {
        protected $rule = [
            'code' => 'require|isNotEmpty'
        ];
        protected $message = [
            'code' => '没有code,不给你获取token'
        ];
    }
    

    applicationapivalidateBaseValidate.php,省略部分代码

    <?php
    class BaseValidate extends Validate
    {
        //...
        protected function isNotEmpty($value) {
            if (empty($value)) {
                return false;
            } else {
                return true;
            }
        }
    }
    

    异常处理

    applicationlibexceptionWeChatException.php

    <?php
    
    
    namespace applibexception;
    
    
    class WeChatException extends BaseException
    {
        public $code = 400;
        public $msg = 'wechat unknown error';
        public $errorCode = 999;
    }
    

    登录配置文件

    applicationextrawx.php

    <?php
    return [
        'app_id' => 'your app_id',
        'app_secret' => 'your appsecret',
        'login_url' => "https://api.weixin.qq.com/sns/jscode2session?" .
            "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
    ];
    

    封装http请求

    applicationapicommon.php

    <?php
    function curl_get($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;
    }
    

    UserToken服务层

    applicationapiserviceUserToken.php

    <?php
    
    
    namespace appapiservice;
    
    class UserToken
    {
        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');
            $this->wxLoginUrl = sprintf(config('wx.login_url'), $this->wxAppID, $this->wxAppSecret, $this->code);
        }
        // 主方法
        public function get() {
            
        }
    }
    

    Token控制器

    applicationapicontrollerv1Token.php

    <?php
    
    
    namespace appapicontrollerv1;
    
    
    use appapiserviceUserToken;
    use appapivalidateTokenGet;
    
    class Token
    {
        public function getToken($code = '') {
            (new TokenGet())->goCheck();
            $ut = new UserToken($code);
            $token = $ut->get($code);
            return [
                'token' => $token
            ];
        }
    }
    

    User模型

    applicationapimodelUser.php

    <?php
    
    
    namespace appapimodel;
    
    
    class User extends BaseModel
    {
        // 根据openid获取uid
        public static function getByOpenID($openid) {
            $user = User::where('openid', '=', $openid)->find();
            return $user;
        }
    }
    

    UserToken服务层

    <?php
    
    
    namespace appapiservice;
    
    use applibexceptionWeChatException;
    use thinkException;
    use appapimodelUser as UserModel;
    
    class UserToken
    {
        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');
            $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);
            if (empty($wxResult)) {
                // 返回的空结果,通常因为传入不合法的code导致
                // 使用框架的异常处理,将错误记录日志
                throw new Exception('获取session_key及openID时异常,微信内部错误');
            } else {
                $loginFail = array_key_exists('errcode', $wxResult);
                if ($loginFail) {
                    // 返回结果带有错误码,使用自己定义的异常类
                    $this->processLoginError($wxResult);
                } else {
                    return $this->grantToken($wxResult);
                }
            }
        }
        private function processLoginError($wxResult){
            throw new WeChatException([
                'msg' => $wxResult['errmsg'],
                'errorCode' => $wxResult['errcode']
            ]);
        }
        // 返回一个token
        private function grantToken($wxResult) {
            $openid = $wxResult['openid'];
            $user = UserModel::getByOpenID($openid);
            if ($user) {
                $uid = $user->id;
            } else {
                // 用户不存在
                $uid = $this->newUser($openid);
            }
            // 后续操作...
        }
        // 创建新用户
        private function newUser($openid) {
            $user = UserModel::create([
                'openid' => $openid
            ]);
            return $user->id;
        }
    }
    

    Token服务层

    applicationapiserviceToken.php

    <?php
    
    
    namespace appapiservice;
    
    
    class Token
    {
        public static function generateToken() {
            $randChar = getRandChar(32);
            $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
            $tokenSalt = config('secure.token_salt');
            return md5($randChar.$timestamp.$tokenSalt);
        }
    }
    

    获取随机字符串

    applicationapicommon.php

    <?php
    //..
    function getRandChar($length) {
        //参数:随机字符串的长度
        $str = null;
        $strPol = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
        $max = strlen($strPol) - 1;
        for ($i = 0; $i < $length; $i++) {
            $str .= $strPol[rand(0, $max)];
        }
        return $str;
    }
    

    敏感信息配置

    applicationextrasecure.php

    <?php
    return [
        //salt 盐,特殊加密信息
        'token_salt' => 'your salt'
    ];
    

    token缓存时间

    applicationextrasetting.php

    <?php
    return [
        //..
        'token_expire_in' => '7200'
    ];
    

    UserToken服务层

    applicationapiserviceUserToken.php,省略部分代码

    <?php
    
    
    namespace appapiservice;
    
    use applibexceptionTokenException;
    use applibexceptionWeChatException;
    use thinkException;
    use appapimodelUser as UserModel;
    
    class UserToken extends Token
    {
        // ...
        private function grantToken($wxResult) {
            $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;
        }
        // 组装缓存对象,scope代表用户权限
        private function prepareCachedValue($wxResult, $uid) {
            $cachedValue = $wxResult;
            $cachedValue['uid'] = $uid;
            $cachedValue['scope'] = 16;
            return $cachedValue;
        }
        // 将数据缓存并返回token用于对缓存数据的访问
        private function saveToCache($wxResult) {
            $key = self::generateToken();
            $value = json_encode($wxResult);
            $expire_in = config('setting.token_expire_in');
            $result = cache($key, $value, $expire_in);
            if (!$result) {
                throw new TokenException([
                    'msg' => '服务器缓存异常',
                    'errorCode' => 10005
                ]);
            }
            return $key;
        }
    }
    

    applicationlibexceptionTokenException.php

    <?php
    
    
    namespace applibexception;
    
    
    class TokenException extends BaseException
    {
        public $code = 401;
        public $msg = 'Token已过期或无效Token';
        public $errorCode = 10001;
    }
    

    测试

  • 相关阅读:
    【LeetCode-链表】环形链表
    【LeetCode-数学】快乐数
    【LeetCode-位运算】只出现一次的数字
    【LeetCode-查找】山脉数组中查找目标值
    【LeetCode-查找】寻找旋转排序数组中的最小值 II
    【LeetCode-查找】寻找旋转排序数组中的最小值
    Linux基础命令mount /umount
    磁盘分区(Gdisk分区)
    磁盘分区( Fdisk分区)
    Linux基础练习题7.31
  • 原文地址:https://www.cnblogs.com/Qyhg/p/14781024.html
Copyright © 2020-2023  润新知