微信小程序服务器tp5开发,TP5 + 微信小程序实现微信登陆

1、微信开发中openid用于唯一标记用户身份,但是openid关系用户隐私,没有过期时间,一旦丢失后果严重;

2、小程序官方文档已经给出了微信登录获取openid的相关接口,但是由于出于安全考虑,不能直接将openid返回给客户端;

3、思路简述:小程序登录获取code,传入code调用服务端程序UserToken获取openid、session_key,可以存在服务端,比如缓存中;为用户生成token用于后续请求的身份验证。

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()

{

$result = curl_get($this->wxLoginUrl);

// 注意json_decode的第二个参数true

// 这将使字符串被转化为数组而非对象

$wxResult = json_decode($result, true);

if (empty($wxResult)) {

// 为什么以empty判断是否错误,这是根据微信返回

// 规则摸索出来的

// 这种情况通常是由于传入不合法的code

throw new Exception('获取session_key及openID时异常,微信内部错误');

}

else {

// 建议用明确的变量来表示是否成功

// 微信服务器并不会将错误标记为400,无论成功还是失败都标记成200

// 这样非常不好判断,只能使用errcode是否存在来判断

$loginFail = array_key_exists('errcode', $wxResult);

if ($loginFail) {

$this->processLoginError($wxResult);

}

else {

return $this->grantToken($wxResult);

}

}

}

// 处理微信登陆异常

// 那些异常应该返回客户端,哪些异常不应该返回客户端

// 需要认真思考

private function processLoginError($wxResult)

{

throw new WeChatException(

[

'msg' => $wxResult['errmsg'],

'errorCode' => $wxResult['errcode']

]);

}

// 写入缓存

private function saveToCache($wxResult)

{

$key = self::generateToken();

$value = json_encode($wxResult);

$expire_in = config('setting.token_expire_in');

$result = cache($key, $value, $expire_in);

if (!$result){

throw new TokenException([

'msg' => '服务器缓存异常',

'errorCode' => 10005

]);

}

return $key;

}

// 颁发令牌

// 只要调用登陆就颁发新令牌

// 但旧的令牌依然可以使用

// 所以通常令牌的有效时间比较短

// 目前微信的express_in时间是7200秒

// 在不设置刷新令牌(refresh_token)的情况下

// 只能延迟自有token的过期时间超过7200秒(目前还无法确定,在express_in时间到期后

// 还能否进行微信支付

// 没有刷新令牌会有一个问题,就是用户的操作有可能会被突然中断

private function grantToken($wxResult)

{

// 此处生成令牌使用的是TP5自带的令牌

// 如果想要更加安全可以考虑自己生成更复杂的令牌

// 比如使用JWT并加入盐,如果不加入盐有一定的几率伪造令牌

// $token = Request::instance()->token('token', 'md5');

$openid = $wxResult['openid'];

$user = User::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 prepareCachedValue($wxResult, $uid)

{

$cachedValue = $wxResult;

$cachedValue['uid'] = $uid;

$cachedValue['scope'] = ScopeEnum::User;

return $cachedValue;

}

// 创建新用户

private function newUser($openid)

{

// 有可能会有异常,如果没有特别处理

// 这里不需要try——catch

// 全局异常处理会记录日志

// 并且这样的异常属于服务器异常

// 也不应该定义BaseException返回到客户端

$user = User::create(

[

'openid' => $openid

]);

return $user->id;

}

}

你可能感兴趣的:(微信小程序服务器tp5开发)