123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- <?php
- /**
- * lemocms
- * ============================================================================
- * 版权所有 2018-2027 lemocms,并保留所有权利。
- * 网站地址: https://www.lemocms.com
- * ----------------------------------------------------------------------------
- * 采用最新Thinkphp6实现
- * ============================================================================
- * Author: yuege
- * Date: 2019/10/3
- */
- namespace lemo\api;
- use think\facade\Request;
- use lemo\api\Send;
- use lemo\api\Oauth;
- use think\facade\Cache;
- use app\api\util\wxBizDataCrypt;
- use app\common\model\WxFans;
- use think\facade\Db;
- /**
- * 生成token
- */
- class Token
- {
- use Send;
- /**
- * 请求时间差
- */
- public static $timeDif = 10000;
- public static $accessTokenPrefix = 'accessToken_';
- public static $refreshAccessTokenPrefix = 'refreshAccessToken_';
- public static $expires = 7200;
- public static $refreshExpires = 3600*24*30; //刷新token过期时间
- /**
- * 测试appid,正式请数据库进行相关验证
- */
- public static $appid = '';
- /**
- * appsecret
- */
- public static $appsecret = '';
- /**
- * 构造方法
- * @param Request $request Request对象
- */
- public function __construct(Request $request)
- {
- $this->request = Request::instance();
- $appid = Request::post('appid');
- $oauth2_client = Db::name('oauth2_client')->where('appid', $appid)->find();
- if (!$oauth2_client) {
- return self::returnMsg(401, 'Invalid authorization credentials');
- }
- self::$appid = $oauth2_client['appid'];
- self::$appsecret = $oauth2_client['appsecret'];
- }
- /**
- * 生成token $accessToken
- */
- public function accessToken(Request $request)
- {
- //参数验证
- $validate = new \lemo\api\validate\Token;
- if (!$validate->check(Request::post())) {
- return self::returnMsg(401, $validate->getError());
- }
- self::checkParams(Request::post()); //参数校验
- //数据库已经有一个用户,这里需要根据input('mobile')去数据库查找有没有这个用户
- $userInfo = self::getUser(Request::post('mobile'));
- //虚拟一个uid返回给调用方
- try {
- $accessToken = self::setAccessToken(array_merge($userInfo, Request::post())); //传入参数应该是根据手机号查询改用户的数据
- return self::returnMsg(200, 'success', $accessToken);
- } catch (\Exception $e) {
- return self::returnMsg(500, 'fail', $e);
- }
- }
- /** 小程序
- * @param string $code
- * @param string $encryptedData
- * @param string $iv
- * @param array $appInfo
- */
- public function getOpenId($code = '',$encryptedData = '',$iv = '',$appInfo = [])
- {
- $result = json_decode(file_get_contents("https://api.weixin.qq.com/sns/jscode2session?appid=" . $appInfo['wx_appid'] . "&secret=" . $appInfo['wx_appsecret'] . "&js_code=" . $code . "&grant_type=authorization_code"), true);
- if(empty($result['session_key'])){
- return $this->returnmsg(401,'获取token失败!'.$result['errmsg']);
- }else{
- $pc = new wxBizDataCrypt($appInfo['wx_appid'], $result['session_key']);
- $data = $pc->decryptData($encryptedData, $iv); //解密用户基础信息
- $data = json_decode($data, true);
- if (!empty($data['openId'])) {
- if (isset($data['unionId'])) { //含有unionid
- $is_unionid['is_unionid'] = true;
- $userInfo = WxFans::get(['unionid' => $data['unionId']]); //按照unionid查找
- if(empty($userInfo)){
- $userInfo = WxFans::get(['openid' => $data['openId']]); //按照openid查找
- }
- } else {
- $is_unionid['is_unionid'] = false;
- $userInfo = WxFans::get(['openid' => $data['openId']]); //按照openid查找
- }
- $userAdd['openid'] = $data['openId'];
- $userAdd['unionid'] = isset($data['unionId']) ? $data['unionId'] : '';
- $userAdd['nickname'] = $data['nickName'];
- $userAdd['headimgurl'] = $data['avatarUrl'];
- $userAdd['sex'] = $data['gender'];
- $userAdd['province'] = $data['province'];
- $userAdd['country'] = $data['country'];
- if(empty($userInfo)){ //用户没有在fans表里面
- $userAdd['subscribe_scene'] = 'WEIXIN';
- $userAdd['source'] = 2;
- WxFans::create($userAdd); //插入到粉丝表
- }else{
- $userAdd['update_time'] = time();
- WxFans::where('fans_id',$userInfo['fans_id'])->update($userAdd);
- $userAdd['uid'] = $userInfo['id'];
- }
- return $userAdd;
- }else{
- return $this->returnmsg(401,'获取token失败!解析数据失败');
- }
- }
- }
- /**
- * token 过期 刷新token
- */
- public function refresh($refresh_token = '', $appid = '')
- {
- $cache_refresh_token = Cache::get(self::$refreshAccessTokenPrefix . $appid); //查看刷新token是否存在
- if (!$cache_refresh_token) {
- return self::returnMsg(401, 'fail', 'refresh_token is null');
- } else {
- if ($cache_refresh_token !== $refresh_token) {
- return self::returnMsg(401, 'fail', 'refresh_token is error');
- } else { //重新给用户生成调用token
- $data['appid'] = $appid;
- $accessToken = self::setAccessToken($data);
- return self::returnMsg(200, 'success', $accessToken);
- }
- }
- }
- /**
- * 参数检测和验证签名
- */
- public static function checkParams($params = [])
- {
- //时间戳校验
- if (abs($params['timestamp'] - time()) > self::$timeDif) {
- return self::returnMsg(401, '请求时间戳与服务器时间戳异常', 'timestamp:' . time());
- }
- //appid检测,这里是在本地进行测试,正式的应该是查找数据库或者redis进行验证
- if ($params['appid'] !== self::$appid) {
- return self::returnMsg(401, 'appid 错误');
- }
- //签名检测
- $sign = Oauth::makeSign($params, self::$appsecret);
- if ($sign !== $params['sign']) {
- return self::returnMsg(401, 'sign错误', 'sign:' . $sign);
- }
- }
- /**
- * 设置AccessToken
- * @param $clientInfo
- * @return int
- */
- protected function setAccessToken($clientInfo)
- {
- //生成令牌
- $accessToken = self::buildAccessToken();
- $refresh_token = self::getRefreshToken($clientInfo['appid']);
- $accessTokenInfo = [
- 'access_token' => $accessToken,//访问令牌
- 'expires_time' => time() + self::$expires, //过期时间时间戳
- 'refresh_token' => $refresh_token,//刷新的token
- 'refresh_expires_time' => time() + self::$refreshExpires, //过期时间时间戳
- 'client' => $clientInfo,//用户信息
- ];
- self::saveAccessToken($accessToken, $accessTokenInfo); //保存本次token
- self::saveRefreshToken($refresh_token, $clientInfo['appid']);
- return $accessTokenInfo;
- }
- /**
- * 刷新用的token检测是否还有效
- */
- public static function getRefreshToken($appid = '')
- {
- return Cache::get(self::$refreshAccessTokenPrefix . $appid) ? Cache::get(self::$refreshAccessTokenPrefix . $appid) : self::buildAccessToken();
- }
- /**
- * 生成AccessToken
- * @return string
- */
- protected static function buildAccessToken($lenght = 32)
- {
- //生成AccessToken
- $str_pol = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmnopqrstuvwxyz";
- return substr(str_shuffle($str_pol), 0, $lenght);
- }
- /**
- * 存储token
- * @param $accessToken
- * @param $accessTokenInfo
- */
- protected static function saveAccessToken($accessToken, $accessTokenInfo)
- {
- //存储accessToken
- cache(self::$accessTokenPrefix . $accessToken, $accessTokenInfo, self::$expires);
- }
- /**
- * 刷新token存储
- * @param $accessToken
- * @param $accessTokenInfo
- */
- protected static function saveRefreshToken($refresh_token, $appid)
- {
- //存储RefreshToken
- cache(self::$refreshAccessTokenPrefix . $appid, $refresh_token, self::$refreshExpires);
- }
- protected static function getUser($mobile)
- {
- $user = Db::name('user')->where('mobile', $mobile)->find();
- if ($user) {
- $user['uid'] = $user['id'];
- return $user;
- } else {
- return self::returnMsg(401, '用户不存在');
- }
- }
- }
|