- 继续对上节loginFail的结果进行处理,编写一个异常处理方法proccessLoginError和单发令牌grantToken方法(只所以写多一个方法是为了提高扩展性)。这里选择返回客户端,所以要一个自定义异常WeChatException异常。
<?php
namespace app\lib\exception;
class WechatExcetion extends BaseException
{
public $code = 404;
public $msg = '微信服务器接口调用失败';
public $error_code = 999;
}
- 编写微信服务器接口调用失败方法
public function prepareCacheValue($wxResult,$uid)
{
$cacheValue = $wxResult;
$cacheValue['uid'] = $uid;
$cacheValue['scope'] = 16;
return $cacheValue;
}
- 编写微信服务器接口调用成功方法
public function grantToken($wxResult)
{
$openid = $wxResult['openid'];
$user = User::getByOpenid($openid);
if ($user) {
$uid = $user->id;
} else {
$uid = $this->newUser($openid);
}
$cacheValue = $this->prepareCacheValue($wxResult,$uid);
$token = $this->saveToCache($cacheValue);
return $token;
}
- 在User模型下查询该用户,创建一个newUser方法添加用户并返回用户id。
public static function getByOpenid($openid)
{
return self::where('openid','=',$openid)->find();
}
- preareCachedValue方法:
public function prepareCacheValue($wxResult,$uid)
{
$cacheValue = $wxResult;
$cacheValue['uid'] = $uid;
$cacheValue['scope'] = 16;
return $cacheValue;
}
- SaveToCache方法:
public function saveToCache($cacheValue)
{
$key = self::generateToken();
$value= json_encode($cacheValue);
$expire_in = config('setting.token_expire_in');
$request = cache($key,$value,$expire_in);
if(!$request){
throw new TokenException();
}
return $key;
}
- generateToken方法(在Token这个基类中,该UserToken去继承即可),在service目录下创建Token类
<?php
namespace app\api\service;
class Token
{
public static function generateToken()
{
$randChars = getRandChar(32);
return $randChars;
}
}
- getRandchar方法写在公共方法文件中(common)
function getRandChar($length)
{
$str = null;
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max = strlen($strPol)-1;
for($i=0;$i<$length;$i++)
{
$str .=$strPol[rand(0,$max)];
};
return $str;
}
- newUser方法
public function newUser($openid)
{
$user = User::create([
'openid' => $openid
]);
return $user->id;
}
- 在自定义setting.php配置文件中,定义缓存过期时间
<?php
return [
'token_expire_in' => 7200
];
- 最终Token控制器的调用
public function getToken($code='')
{
(new TokenGet())->goCheck();
$ut = new UserToken($code);
$token = $ut->get();
return ['token'=>$token];
}
- 接口测试遵守流程:用户登录小程序然后获取到code并将code发给我们的服务器接口地址,服务器获取到该code后使用该code向微信服务器发起请求从而获取该用户的openid和seesion_key,通过判断获取是否成功来决定是否为该用户分配token令牌。
由于做此笔记的时候没有实际的小程序测试工具所以我们模拟调试,最终获取到了token值