Files
CompanyProject/芳林公司项目/www.zhiyuanhelp.com/application/api/service/UserToken.php
2024-09-27 01:32:49 +08:00

180 lines
5.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}