一、前言
这篇文章所学到来自七月的小程序教学,同时我也是为了再次巩固下对微信的登录以及PHP后台生成的token的过程。以下是我的感受和心得。
二、准备
1.微信小程序的appID,appKey(app_secret)用来对微信服务器获取用户的openId以及其他信息。
2.后台使用到Tp5框架。
3.MySQL数据库。
三、思考
1.在微信的开发者文档中向我们介绍了微信登录的流程图,让我们先来解读一下这个
在小程序的内部,会通过wx.login()获取code码 ,同时将获取到的code码发送到后台。
接下来,开发者服务器也就是你的后台,将从前台获取的code码加上你的appid+appsecret拼接成一个url去向微信服务器获取到seeion_key以及用户的openid等。
在后台,我们将用获取到的用户信息,同时生成token(自定义登录令牌),将token和用户的信息存入在缓存之中,方便用户获取服务时的身份确认。
此时后台仅仅将token信息返回到微信小程序,切记不能够暴露用户的openid以及其他信息,
微信小程序端,将获取的token保存在本地。
在接下来的一些需要用户身份的请求中,都要携带token去请求后台。
后台获取到微信小程序端传来的token,读取缓存,拿到用户的openid,在进行相关的业务逻辑
四、code
关于3-1中,微信小程序端如何获取code,并向后台发起请求。
wx.login({
success: function(res) {
var code = res.code; //通过回调函数获取code
wx.request({ //向后台发起请求 POST
url: 'index.php',
data: {
code: code
},
method: 'POST',
success: function(res) {
//TODO
},
fail: function(res) {
//TODO
}
})
},
fail: function(res) {
//TODO
}
})
3-2 后台部分代码
1)首先建立一个配置文件wx.php
return [
'app_id' => '你的appid',
'app_secret' => '你的appkey(app_secret)',
'login_url' => 'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code',]
2)接下来在controller中建立类文件Token.php
namespace app\api\controller\v1;
use app\api\service\UserToken;
use app\api\validate\TokenGet;
class Token
{
//自己设置路由,这是获取到微信小程序端向后台发送的code
public function getToken($code='')
{
//这一步是验证参数
(new TokenGet())->goCheck();
//获取token
$ut = new UserToken($code);
$token = $ut->get();
//向微信小程序端返回token
return [
'token'=>$token
];
}
}
3)新建一个service文件夹,首先建立UserToken.php,这一步的主题思路就是,要将获取的code拿来,拼接上自己的appid和appkey去先微信服务器获取用户的信息,并且同时生成随机字符串,存入缓存中。
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);
}
public function get(){
//curl_get是一个请求方法,通过url去请求,这个方法我会放在最后
$result = curl_get($this->wxLoginUrl);
$wxResult = json_decode($result,true);
if (empty($wxResult)){
throw new Exception('获取session_key以及open_id时异常,微信内部错误');
}else{
$loginFail = array_key_exists('errcode',$wxResult);
if ($loginFail){
$this->processLoginError($wxResult);
}else{
return $this->grantToken($wxResult);
}
}
}
private function grantToken($wxResult){
//拿到open_id
//在数据库查看,这个open_id是否存在
//在、不在新增记录
//生成令牌 准备的缓存数据 写入缓存
//把令牌返回去
//key:令牌
//value:wxResult uid scope
$openid = $wxResult['openid'];
$user = User::getByOpenID($openid);
if (!$user){
$uid = $this->newUser($openid);
}else{
$uid = $user->id;
}
$cachedValue = $this->prepareCachedValue($wxResult,$uid);
$token = $this->saveToCache($cachedValue);
return $token;
}
//写缓存,key = token value = user
private function saveToCache($wxRequest){
$key = self::generateToken();
$value = json_encode($wxRequest);
$expire_in = config('setting.token_expire_in');
//$expire_in 表示token的有效时间 我卸载配置中了,也可以直接设置
$result = cache($key,$value,$expire_in);
if (!$result){
throw new TokenException([
'msg' => '服务器缓存异常',
'errorCode' => 10005,
]);
}
return $key;
}
//缓存写入前的准备,写入权限信息,以后可以通过不同权限来访问不同的接口
private function prepareCachedValue($wxResult,$uid){
$cachedValue = $wxResult;
$cachedValue['uid'] = $uid;
//scope=16 代表App用户的权限数值 ScopeEnum后面给出
$cachedValue['scope'] = \ScopeEnum::User;
return $cachedValue;
}
//利用model层,创建一个新用户
private function newUser($openid){
$user = User::create([
'openid' => $openid
]);
return $user->id;
}
private function processLoginError($wxResult){
throw new WeChatException([
'msg' =>$wxResult['error msg'],
'errorCode' => $wxResult['error code']
]);
}
}
4)token的生成,新建Token.php文件,代码如下:
5)公共的方法
// +----------------------------------------------------------------------
// 应用公共文件
/**
*
*/
function curl_get($url, &$httpCode = 0){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
$file_contents = curl_exec($ch);
$httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
return $file_contents;
}
function getRandChars($length){
$str = null;
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max = strlen($strPol)-1;
for ($i = 0; $i
6)tp5目录
五、个人总结
其实也没啥总结,就是要在分析代码的需求上,逻辑要更紧密,多看看大佬的代码,提升思维的方向。还有,多撸哦O(∩_∩)O哈哈~。