微信小程序 用戶登錄 服務器端(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 app\common\service;
use app\common\model\User;
/**
 * 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 \app\common\exception\BaseException([
                '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 app\common\service;
use think\Facade\Request;

// 這里將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 \app\common\exception\BaseException(['msg' => '請先登錄']);
        }
        $identity = cache($token);
        if ($identity) {
            return $identity;
        } else {
            throw new \app\common\exception\BaseException(['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 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM