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