私たちは、生成されたすべてのユーザーは、私たちの入手トークン・インターフェース、我々はマイクロチャネルサーバ内のユーザ情報を識別するリターンコードコードにこのコードコードを渡すコードデジタルコードのためのマイクロチャネルアプレットを使用して、我々は入手トークンインターフェイスでコードを受け取りますコードの後に、我々は、マイクロチャネルサーバに要求し、コードのコードを送信する必要がマイクロチャネルサーバに送信され、その後、マイクロチャネルサーバは、OpenIDのとSESSION_KEYを返しますが、このOpenIDのは、我々はユーザーのIDを必要とし、私たちが必要な場合は、固有の識別でありますマイクロチャネルの賃金を使用している場合、このOpenIDのも必要です。私たちはOpenIDのを取得すると、私達は私達のデータベースを維持する必要があります。OpenIDのは、秘密主義のユーザデータで一定と長期的な効果がある、我々はこの問題を解決するために、それをクライアントに返す提唱していない有効期間を生成することで、クライアントトークントークンに戻ってきました我々はデータベースに格納した場合、ちょうどこのトークンの次の訪問を運び、このトークンすることにより、間接的に取得、保存、トークントークンによって対応のOpenID openidのを見つけ、我々は、キャッシュに格納します、我々はインターフェイスにアクセスすると、データベースはたくさんのストレスを生成しますが、ほとんどの状況では、キャッシュのアクセス速度は、データベースのアクセス速度よりも優れています。
コントローラ/ Token.php
<?php
namespace app\api\controller\v1;
use app\api\service\UserToken;
use app\api\validate\TokenGet;
class Token
{
public function getToken($code = '')
{
(new TokenGet())->goCheck();
$ut = new UserToken($code);
$token = $ut->get();
return [
'token' =>$token
];
}
}
サービス/ Token.php
<?php
namespace app\api\service;
use app\lib\exception\TokenException;
use think\Cache;
use think\Exception;
use think\Request;
class Token
{
//生成令牌
public static function generateToken(){
//32个字符组成一组随机字符串
$rangChars = getRandChar(32);
//用三组字符串,进行md5加密
$timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
//salt 盐
$salt = config('secure.token_salt');
return md5($rangChars.$timestamp.$salt);
}
public static function getCurrentTokenVar($key){
$token = Request::instance()
->header('token');//tp5的Request::instance()获取post、get、参数、表单上传的文件
$vars = Cache::get($token);
if(!$vars){
throw new TokenException();
}else{
if(!is_array($vars)){
$vars = json_decode($vars,true);
}
if(array_key_exists($key,$vars)){
return $vars[$key];
}else{
throw new Exception('尝试获取的Token变量并不存在');
}
}
}
//由缓存的token获取Uid
public static function getCurrentUid(){
$uid = self::getCurrentTokenVar('uid');
return $uid;
}
}
サービス/ UserToken.php
<?php
namespace app\api\service;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;
class UserToken extends Token
{
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');
//sprintf函数 把url中的s% 替换成想要的数据
$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);//result 变成json字符串
if(empty($wxResult)){
throw new Exception('获取session_key及openID时异常');
}else{
$loginFail = array_key_exists('errcode',$wxResult);
// return $loginFail;
if($loginFail){
$this->processLoginError($wxResult);
}else{
return $this->grantToken($wxResult);
}
}
}
private function grantToken($wxResult){
//拿到openid
//数据库里看一下,这个openid是不是已经存在
//如果存在,则不处理,如果不存在那么新增一条user记录
//生成令牌,准备缓存数据,写入缓存
//把令牌返回到客户端去
//key:令牌
//value:wxResult,uid,scope
$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;
}
//写入缓存
private function saveToCache($cachedValue){
$key = self::generateToken();
$value = json_encode($cachedValue);//把数组转换成字符串
$expire_in = config('setting.token_expire_in');
$request = cache($key,$value,$expire_in);
if(!$request){
throw new TokenException([
'msg' => '服务器缓存异常',
'errorCode' => 10005
]);
}
return $key;
}
//准备value的一系列数据
private function prepareCachedValue($wxResult,$uid){
$cachedValue = $wxResult;
$cachedValue['uid'] = $uid;
$cachedValue['scope'] = 16;//权限高低2,4,6,8,12,14,16
return $cachedValue;
}
//openID不存在 则新增一条记录
private function newUser($openid){
$user = UserModel::create([
'openid' => $openid
]);
return $user->id;
}
//封装一个抛出异常的方法
private function processLoginError($wxResult){
throw new WeChatException(
[
'msg' => $wxResult['errmsg'],
'errorCode' => $wxResult['errcode']
]);
}
}
モデル/ User.php
<?php
namespace app\api\model;
class User extends BaseModel
{
public static function getByOpenID($openid){
$user = self::where('openid','=',$openid)
->find();
return $user;
}
}
検証/ BaseValidate
<?php
namespace app\api\validate;
use app\lib\exception\ParameterException;
use think\Exception;
use think\Request;
use think\Validate;
class BaseValidate extends Validate
{
public function goCheck()
{
$request = Request::instance();
$params = $request->param();
$result = $this->batch()->check($params);
if(!$result){
$e = new ParameterException([
'msg' => $this->error,
]);
throw $e;
}else{
return true;
}
}
protected function isPositiveInteger($value,$rule = '',
$data = '', $field = '')
{
if(is_numeric($value) && is_int($value + 0) && ($value + 0) > 0){
return true;
}else{
return false;
}
}
protected function isNotEmpty($value,$rule = '',
$data = '', $field = '')
{
if(empty($value)){
return false;
}else{
return true;
}
}
}
検証/ TokenGet
<?php
namespace app\api\validate;
class TokenGet extends BaseValidate
{
protected $rule = [
'code' => 'require|isNotEmpty'
];
protected $message = [
'code' => '没有code'
];
}