zoukankan      html  css  js  c++  java
  • 微信小程序 用户登录 服务器端(TP5.1)实现

    先来看官方提供的流程图:

    客户端:

    小程序客户端通过 wx.login() 获取登录code , 然后将code当做参数传递到服务器、

    getToken(){
          var that = this;
          wx.login({
              success: function (res) {
                  wx.request({
                      url: 'http://wx.shop.com/api/v1/token',    //服务器获取token的api   
                      method:'POST',
                      data: {
                          code : res.code
                      },
                      success: function (res) {
                          console.log(res)
                      }
                  })
              }
          })
      }

    服务器端(ThinkPHP5.1):

    1. 根据客户端传递的 code , 请求微信提供 api 换取该用户的 openid 和 session_key ,同一个用户在同一个小程序中的 openid 是不变的

    <?php
    namespace appcommonservice;
    use appcommonmodelUser;
    /**
     * UserToken类用作颁发微信令牌,继承与Token
     */
    class UserToken extends Token {
        protected $code;
        protected $Appid;
        protected $AppSecret;
        protected $LoginUrl;
    
        public function __construct($code) {
            $this->code = $code;
    
            //从服务器换取 openid 需要传递三个参数
            // Appid、Appsecret、Code
            $this->Appid = config('wx.app_id');
            $this->AppSecret = config('wx.app_secret');
    
            //sprintf的作用是将字符串中占位符用特定值按顺序替换
            $this->LoginUrl = sprintf(config('wx.login_url'), $this->Appid, $this->AppSecret, $this->code);
        }
        /**
         * 根据用户传递 code 去微信服务器换取 openid 
         */
        public function get() {
            $result = curl_get($this->LoginUrl);
            $wxResult = json_decode($result, true);
            if (empty($wxResult)) {
                throw new Exception("获取session_key和open_id失败,微信内部错误");
            }
            //验证获取令牌是否成功
            if (array_key_exists('errcode', $wxResult)) {
                throw new appcommonexceptionBaseException([
                    'errorCode' => $wxResult['errcode'],
                    'msg' => $wxResult['errmsg'],
                ]);
            } else {
                return $this->grantToken($wxResult['openid']);
            }
        }
        /**
         * 颁发令牌 并将用户信息序列化成json,已token为键保存在本地缓存
         * 作用是 当用户不存在时创建用户   存在时返回用户 id
         */
        private function grantToken($openid) {
            //查找User表,查看该openid对应用户是否存在,如是则返回uid,否则生成新用户,返回uid
            $user = User::where('openid', $openid)->find();
            if (!$user) {
                $uid = User::create([
                    'openid' => $openid,
                ]);
            } else {
                $uid = $user->id;
            }
            //存入缓存 key:生成返回客户端的令牌 value:openid + uid
            $key = $this->generateToken();
            $cache_value['openid'] = $openid;
            $cache_value['uid'] = $uid;
            $expire = config('token.expire');
            if (!cache($key, $cache_value, $expire)) {
                throw new Exception("缓存客户令牌时出现错误");
            } else {
                return $key;
            }
        }
    }

    使用前需要先定位配置文件

    <?php
    
    return [
        //  +---------------------------------
        //  微信相关配置
        //  +---------------------------------
    
        // 小程序app_id
        'app_id' => 'wx0a1d95f443204af2',
        // 小程序app_secret
        'app_secret' => 'a29462308699ae469d5fb6cc54a9a95a',
    
        // 微信使用code换取用户openid及session_key的url地址
        'login_url' => "https://api.weixin.qq.com/sns/jscode2session?" .
        "appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
    
        // 微信获取access_token的url地址
        'access_token_url' => "https://api.weixin.qq.com/cgi-bin/token?" .
        "grant_type=client_credential&appid=%s&secret=%s",
    
        //支付状态
        'unpaid' => 1,
        'paid' => 2,
        'shipped' => 3,
    ];

    基类Token

    <?php
    namespace appcommonservice;
    use thinkFacadeRequest;
    
    // 这里将token的相关操作放在service层
    // 定义了一个Token基类,基类中存放生成 token、根据token从缓存中获取用户数据操作
    
    class Token {
        /**
         * 生成随机字符串 作为 token
         */
        public function generateToken() {
            $randChar = getRandChar(32);
            $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
            return md5($randChar . $timestamp);
        }
        /**
         * 根据用户携带的 token ,从缓存中读取用户信息
         */
        public static function getCurrentIdentity() {
            $token = Request::header('token');
            if (!$token) {
                throw new appcommonexceptionBaseException(['msg' => '请先登录']);
            }
            $identity = cache($token);
            if ($identity) {
                return $identity;
            } else {
                throw new appcommonexceptionBaseException(['msg' => '身份已过期,请重新登录']);
            }
        }
        /**
         * 获得保存在缓存指定键的值
         */
        public static function getCurrentTokenVar($var) {
            $indentity = self::getCurrentIdentity();
            if (!$indentity[$var]) {
                throw new Exception(['msg' => '尝试获取的Token变量并不存在']);
            } else {
                return $indentity[$var];
            }
        }
    }

    控制器中使用

    class Token extends Controller {
    
        public function getToken() {
            $code = $this->request->param('code');
            (new TokenValidate())->getToken($code);
            $ut = new UserToken($code);
            return json([
                'token' => $ut->get(),
            ]);
        }
    
    }

    微信支付等操作都依赖于 openid 

  • 相关阅读:
    redis集群报错,(error) MOVED 15495 127.0.0.1:7003
    在云服务器上时候,我关闭了防火墙还是不能连接!
    redis 集群安装 3主3从3台云主机
    ajax完成团队信息异步添加【实际项目】
    众创项目首页推荐需求
    添加删除表格(js完成)【自己实际项目】
    【JPA 级联保存/级联删除】@OneToMany (双向) 一对多【转】
    页面提交 string数组和list对象集合举例
    Form表单如何传递List数组对象到后台的解决办法(转)
    实现同时提交多个form(基础方法) 收集(转)
  • 原文地址:https://www.cnblogs.com/xiaoliwang/p/9380503.html
Copyright © 2011-2022 走看看