- 定义路由
Route::post('api/:version/token/user', 'api/:version.Token/getToken');```
- 编写控制器Token.php
- .首先是在小程序端要获取code码来调用我们服务器的
token/user
的接口来获取令牌。 - 新建
TokenGet
验证类验证code
参数。 - 生成token的业务代码写到了
service\UserToken
类中。
<?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();
$wx = new UserToken($code);
$token = $wx->get();
return [
'token' => $token
];
}
}
service\UserToken.php
- .1,首先小程序的机制是用户调用我们的接口把code码发送到我们的服务器,我们将code,appid,appsecret,发送到微信的服务器来请求该用户的唯一标识(openid和session_key)。
- 我们拿到了微信服务器返回给我们的openid之后,首先去我们的数据库的user表里面查看一下属于该openid的用户是否存在,如果已经存在,那么就不需要处理。如果不存在,就需要新增一条user记录。并返回该用户的uid。
- 新增了一条user记录之后,我们就要为该用户生成令牌(一串无意义的字符串)
- 将令牌先存到缓存里面去,(存到缓存而不是数据库是因为用户的身份权限这个业务是需要设置有效时间的,不能让令牌永久有效,就应该存到缓存)。
- 我们调用tp5的缓存机制,把生成的令牌作为key,把从微信服务器返回的结果和,uid以及作用域scope作为value存到缓存里面。
<?php
namespace app\api\service;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use app\api\model\User as UserModel;
class UserToken extends Token {
protected $code;
protected $wxLoginUrl;
protected $wxAppID;
protected $wxAppSecret;
function __construct($code) {
$this->code = $code;
$this->wxAppID = config('wx.app_id');
$this->wxAppSecret = config('wx.app_secret');
$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);
if (empty($wxResult)) {
throw new Exception('获取session_key及openID时异常,微信内部错误');
} else {
$loginFail = array_key_exists('errcode', $wxResult);
echo '$loginFail这里';
if ($loginFail) {
$this->processLoginError($wxResult);
} else {
return $this->grantToken($wxResult);
}
}
}
private function grantToken($wxResult) {
$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;
}
private function prepareCachedValue($wxResult, $uid) {
$cachedValue = $wxResult;
$cachedValue['uid'] = $uid;
$cachedValue['scope'] = 16;
return $cachedValue;
}
private function newUser($openid) {
$user = UserModel::create([
'openid' => $openid
]);
}
private function processLoginError($wxResult) {
throw new WeChatException(
[
'msg' => $wxResult['errmsg'],
'errorCode' => $wxResult['errcode']
]);
}
}
service\Token
<?php
namespace app\api\service;
use app\lib\exception\TokenException;
class Token {
public static function generateToken() {
$randChars = getRandChar(32);
$timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
$salt = config('secure.token_salt');
return md5($randChars . $timestamp . $salt);
}
}