zoukankan      html  css  js  c++  java
  • 微信开发核心AccessToken实现

    Common

    <?php
    namespace ProxyAction;
    
    use ThinkAction;
    use VendorFuncRed;
    
    class CommonAction extends Action
    {
        public $red;
        public function _initialize(){
            $this->red = Red::create();
            header('Content-type: text/html; charset=utf-8');
        }
    
        /**
         * 错误的json
         * @param $code
         * @param string $message
         * @param array $data
         */
        public function jsonError($code, $message = 'error', $data = [])
        {
            $returnData = [
                'code' => $code,
                'message' => $message,
                'data' => $data
            ];
        
            header('Content-type:application/json;charset=utf-8');
            echo json_encode($returnData);
            exit;
            
        }
    
        /**
         * 正确的json
         * @param int $code
         * @param string $message
         * @param array $data
         */
        public function jsonSuccess($code = 1, $message = 'success', $data = [])
        {
            $returnData = [
                'code' => $code,
                'message' => $message,
                'data' => $data
            ];
            
            header('Content-type:application/json;charset=utf-8');
            echo json_encode($returnData);
            exit;
             
        }
    
        /**
         * 设置Redis
         * @param $k
         * @param $v
         * @param int $expires
         * @return mixed
         */
        public function setCache($k, $v, $expires = -1)
        {
            if ($expires === -1) {
                return $this->red->set($k, $v);
            } else {
                return $this->red->setex($k, $expires, $v);
            }
        }
    
        /**
         * 获取Redis
         * @param $k
         * @return mixed
         */
        public function getCache($k)
        {
            return $this->red->get($k);
        }
    
    
        /**
         * 删除Redis
         * @param $k
         * @return mixed
         */
        public function delCache($k)
        {
            return $this->red->delete($k);
        }
    
    
        /**
         * 获取过期时间
         * @param $k
         * @return bool
         */
        public function getCacheTtl($k)
        {
            $ttl = $this->red->ttl($k);
            if ($ttl != '-2') {
                return $ttl;
            } else {
                return false;
            }
        }
    
        /**
         * 检查是否存在
         * @param $k
         * @return mixed
         */
        public function cacheExists($k)
        {
            return $this->red->exists($k);
        }
    }
    
    

    AccessToken

    <?php
    namespace ProxyAction;
    
    use VendorFuncHttp;
    
    /***
     * 基础支持的access_token,每日两千次
     * @package ProxyAction
     */
    class AccessTokenAction extends CommonAction
    {
    
        const API_TOKEN = 'https://api.weixin.qq.com/cgi-bin/token';
        const API_TICKET = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket';
        const TOKEN_EXPIRES = 1500;
        const TICKET_EXPIRES = 1500;
    
        protected $access_token_key = ''; // access_token Redis 键值名
        protected $js_ticket_key = ''; // 凭证 Redis 键值名
    
        public function __construct()
        {
            parent::__construct();
            $this->access_token_key = C('WX_APP_ID').':access_token';
            $this->js_ticket_key = C('WX_APP_ID').':js_ticket';
        }
    
        /**
         * 获取全局access_token
         */
        public function get()
        {
            // step1 判是存在
            $exists = $this->cacheExists($this->access_token_key);
    
            // step2 是否强制刷新或者已过期
            if ((isset($_GET['flush']) & $_GET['flush']) || !$exists) {
                $data = $this->reload();
            } else {
                $data = [
                    'access_token' => $this->getCache($this->access_token_key),
                    'expires_in'   => $this->getCacheTtl($this->access_token_key)
                ];
            }
    
            if (!$data['access_token']) {
                $this->ajaxReturn($this->jsonError(10002, '接口请求失败'));
            }
    
    		$this->ajaxReturn($this->jsonSuccess(1, '成功', $data));
        }
    
        /**
         * 公众号用于调用微信JS接口的临时票据
         * @return bool
         */
        public function jsTicket()
        {
            // step1 判是存在
            $exists = $this->cacheExists($this->js_ticket_key);
            if (!$exists) {
                // 获取token
                $token = $this->getCache($this->access_token_key);
                setlog($token,[],'token');
                // 如果token不存在,重新生成
                if (!$token) {
                    // 重新加载一次Token
                    $this->reload();
                    $token = $this->getCache($this->access_token_key);
                }
    
                $params = [
                    'access_token' => $token,
                    'type' => 'jsapi',
                ];
    
                $data = Http::newDoGet(self::API_TICKET, $params);
    
                $data = json_decode($data, true);
    
                if ((int)$data['errcode'] !== 0) {
                    $this->delCache($this->access_token_key);
                    return false;
                }
    
                // 减少1500秒过期时间,提前过期
                $this->setCache($this->js_ticket_key, $data['ticket'], $data['expires_in'] - self::TICKET_EXPIRES);
            } else {
                $data['ticket'] = $this->getCache($this->js_ticket_key);
            }
    
            return $data['ticket'];
        }
    
        /**
         * 获取JS-SDK配置信息
         */
        public function getConfig()
        {
            if (!isset($_GET['uri'])) {
                $this->ajaxReturn($this->jsonError(0, '参数错误'));
            }
    
            $url = $_GET['uri'];
            $ticket = $this->jsTicket();
            setlog($ticket,[],'ticket');
    
            while (!$ticket) {
                $this->reload();
                $ticket = $this->jsTicket();
            }
    
            $data = [
                'jsapi_ticket' => $ticket,
                'nonceStr' => (string)mt_rand(),
                'timestamp' => time(),
                'url' => $url
            ];
    
            $sign = $this->getSign($data);
    
            $data['signature'] = $sign;
    		$data['appId'] = C('WX_APP_ID');
    
    		$this->ajaxReturn($this->jsonSuccess(1, '成功', $data));
        }
    
        /**
         * 重新载入 access_token
         */
        protected function reload()
        {
            if ($this->cacheExists($this->access_token_key)) {
                $data = [
                    'access_token' => $this->getCache($this->access_token_key),
                    'expires_in'   => $this->getCacheTtl($this->access_token_key)
                ];
                return $data;
            }
            $params = [
                'grant_type' => 'client_credential',
                'appid' => C('WX_APP_ID'),
                'secret' => C('WX_APP_SECRET')
            ];
            $data = Http::newDoGet(self::API_TOKEN, $params);
            if (!$data) {
                $this->ajaxReturn($this->jsonError(10002, '接口请求失败'));
            }
            $data = json_decode($data, true);
            if (isset($data['errcode'])) {
                $this->ajaxReturn($this->jsonError($data['errcode']), $data['errmsg']);
            }
            $this->setCache($this->access_token_key, $data['access_token'], $data['expires_in'] - self::TOKEN_EXPIRES);
            return $data;
        }
    
        /**
         * 签名算法
         * @param $data
         * @return string
         */
        protected function getSign($data)
        {
            $str = '';
            foreach ($data as $k => $v) {
                $str .= strtolower($k) .'='.$v;
                $str .= '&';
            }
    
            $str = trim($str, '&');
            $str = sha1($str);
    
            return $str;
        }
    
    }
    
    
  • 相关阅读:
    设计原则
    最小路径和--p64--动态规划
    ssm实现数据库关键信息的动态加载
    最大二叉树--p654--递归构造
    城市天际线--p807
    长url转短url--p535
    从中序与后序遍历中构造二叉树-p106--数组,二叉树遍历
    n皇后问题--p52--回溯
    Markdown(editormd)语法解析成HTML
    NFA的实现
  • 原文地址:https://www.cnblogs.com/jiqing9006/p/11022261.html
Copyright © 2011-2022 走看看