首页> 实战笔录 >PHP开发笔记 >ThinkPHP ThinkPHP

TP5.1实现微信小程序用户登录后端代码分享

作者:小萝卜 2019-11-22 浏览 1264

简介先来看官方提供的流程图:客户端:小程序客户端通过 wx.login() 获取登录code , 然后将code当做参数传递到服务器、

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

客户端:

小程序客户端通过 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 

很赞哦! (0)

文章评论

    高端网站建设