first commit
This commit is contained in:
180
芳林公司项目/www.zhiyuanhelp.com/application/api/service/UserToken.php
Normal file
180
芳林公司项目/www.zhiyuanhelp.com/application/api/service/UserToken.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Administrator
|
||||
* Date: 2019/5/25 0025
|
||||
* Time: 16:47
|
||||
*/
|
||||
|
||||
namespace app\api\service;
|
||||
|
||||
use app\lib\exception\ParamException;
|
||||
use think\Exception;
|
||||
use app\api\model\User as UserModel;
|
||||
use think\facade\Cache;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登陆
|
||||
* 思路1:每次调用登录接口都去微信刷新一次session_key,生成新的Token,不删除久的Token
|
||||
* 思路2:检查Token有没有过期,没有过期则直接返回当前Token
|
||||
* 思路3:重新去微信刷新session_key并删除当前Token,返回新的Token
|
||||
*/
|
||||
public function get($paramPost)
|
||||
{
|
||||
$result = curl_get($this->wxLoginUrl);
|
||||
|
||||
// 注意json_decode的第一个参数true
|
||||
// 这将使字符串被转化为数组而非对象
|
||||
|
||||
$wxResult = json_decode($result, true);
|
||||
|
||||
if (empty($wxResult)) {
|
||||
// 为什么以empty判断是否错误,这是根据微信返回
|
||||
// 规则摸索出来的
|
||||
// 这种情况通常是由于传入不合法的code
|
||||
throw new ParamException([
|
||||
'code'=>401,
|
||||
'msg' => '获取session_key及openID时异常,微信内部错误',
|
||||
'errorCode' => 10001
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// 建议用明确的变量来表示是否成功
|
||||
// 微信服务器并不会将错误标记为400,无论成功还是失败都标记成200
|
||||
// 这样非常不好判断,只能使用errcode是否存在来判断
|
||||
$loginFail = array_key_exists('errcode', $wxResult);
|
||||
if ($loginFail) {
|
||||
$this->processLoginError($wxResult);
|
||||
}
|
||||
else {
|
||||
return $this->grantToken($wxResult,$paramPost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 颁发令牌
|
||||
// 只要调用登陆就颁发新令牌
|
||||
// 但旧的令牌依然可以使用
|
||||
// 所以通常令牌的有效时间比较短
|
||||
// 目前微信的express_in时间是7200秒
|
||||
// 在不设置刷新令牌(refresh_token)的情况下
|
||||
// 只能延迟自有token的过期时间超过7200秒(目前还无法确定,在express_in时间到期后
|
||||
// 还能否进行微信支付
|
||||
// 没有刷新令牌会有一个问题,就是用户的操作有可能会被突然中断
|
||||
private function grantToken($wxResult)
|
||||
{
|
||||
// 此处生成令牌使用的是TP5自带的令牌
|
||||
// 如果想要更加安全可以考虑自己生成更复杂的令牌
|
||||
// 比如使用JWT并加入盐,如果不加入盐有一定的几率伪造令牌
|
||||
$openid = $wxResult['openid'];
|
||||
$user = UserModel::getByOpenID($openid);
|
||||
if (!$user)
|
||||
// 借助微信的openid作为用户标识
|
||||
// 但在系统中的相关查询还是使用自己的uid
|
||||
{
|
||||
$uid = $this->newUser($openid);
|
||||
}
|
||||
else {
|
||||
$uid = $user->id;
|
||||
}
|
||||
$cachedValue = $this->prepareCachedValue($wxResult, $uid);
|
||||
$token = $this->saveToCache($cachedValue);
|
||||
return $token;
|
||||
}
|
||||
|
||||
private function newUser($openid){
|
||||
$user = UserModel::create([
|
||||
'openid' =>$openid
|
||||
]);
|
||||
return $user->id;
|
||||
}
|
||||
|
||||
//生成token并缓存
|
||||
private function saveToCache($wxResult){
|
||||
|
||||
$key = self::generateToken();
|
||||
$value = json_encode($wxResult);
|
||||
$request = Cache::store('redis')->set($key,$value,2592000);
|
||||
if(!$request){
|
||||
throw new ParamException([
|
||||
'code' => 401,
|
||||
'msg' => '服务起缓存异常',
|
||||
'errorCode' => 10001
|
||||
]);
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
//缓存数据预处理
|
||||
private function prepareCachedValue($wxResult, $uid)
|
||||
{
|
||||
$cachedValue = $wxResult;
|
||||
$cachedValue['uid'] = $uid;
|
||||
return $cachedValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function processLoginError($wxResult){
|
||||
throw new ParamException([
|
||||
'msg' => $wxResult['errmsg'],
|
||||
'errorCode' => $wxResult['errcode']
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤微信昵称的特殊表情
|
||||
* @param $text
|
||||
* @param string $replaceTo
|
||||
* @return null|string|string[]
|
||||
*/
|
||||
public function filterEmoji($text, $replaceTo = 'x'){
|
||||
$clean_text = "";
|
||||
// Match Emoticons
|
||||
$regexEmoticons = '/[\x{1F600}-\x{1F64F}]/u';
|
||||
$clean_text = preg_replace($regexEmoticons, $replaceTo, $text);
|
||||
// Match Miscellaneous Symbols and Pictographs
|
||||
$regexSymbols = '/[\x{1F300}-\x{1F5FF}]/u';
|
||||
$clean_text = preg_replace($regexSymbols, $replaceTo, $clean_text);
|
||||
// Match Transport And Map Symbols
|
||||
$regexTransport = '/[\x{1F680}-\x{1F6FF}]/u';
|
||||
$clean_text = preg_replace($regexTransport, $replaceTo, $clean_text);
|
||||
// Match Miscellaneous Symbols
|
||||
$regexMisc = '/[\x{2600}-\x{26FF}]/u';
|
||||
$clean_text = preg_replace($regexMisc, $replaceTo, $clean_text);
|
||||
// Match Dingbats
|
||||
$regexDingbats = '/[\x{2700}-\x{27BF}]/u';
|
||||
$clean_text = preg_replace($regexDingbats, $replaceTo, $clean_text);
|
||||
return $clean_text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 非小程序登录token
|
||||
* @param $arr
|
||||
* @return string
|
||||
* @throws ParamException
|
||||
*/
|
||||
public function LoginToken($str)
|
||||
{
|
||||
$token = $this->saveToCache($str);
|
||||
return $token;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user