route.php
Route::post('api/:version/token/user','api/:version.Token/getToken');
post:获取令牌 传递的code有一定的安全需求,所以稍微隐藏,放到post的body里面传递
\controller\Token.php
namespace app\api\controller\v1;
use app\api\service\UserToken;
use app\api\validate\TokenGet;
class Token
{
public function getToken($code = ''){
(new TokenGet())->goCheck();
$ut = new UserToken();
$token = $ut->get($code);
return $token;
}
}
\validate\TokenGet.php
namespace app\api\validate;
class TokenGet extends BaseValidate
{
protected $rule = [
'code' => 'require|isNotEmpty'
];
protected $message = [//传递错误信息
'code' => '没有code还想获取token,做梦'
];
}
isNotEmpty的作用:有参数名但是没有值,require会通过
\validate\BaseValidate.php
protected function isNotEmpty($value,$rule='',
$data='',$filed=''){
if (empty($value))
{
return false;
}
else
{
return true;
}
}
\model\User.php在数据库中有一个User表
namespace app\api\model;
class User extends BaseModel
{
}
由于业务比较复杂,在model上边封装一个service层,把
\service\UserToken.php
namespace app\api\service;
class UserToken
{
public function get($code){
}
}
model除了处理业务逻辑之外,还有很重要的功能——调用数据库访问层,实现数据库增删改查,而service是建立在model之上的。
model模型命名必须和我们的数据库名相同。否则不知道对应哪张表。
所有复杂的 放到service层,简单的粒度比较小的放到model层。
小程序通过wx.login()获取到的code,换取用户的登录状态信息,包括用户的唯一标志openid,以及本次登陆的会话密钥session_key。
微信小程序给一个接口地址,调用接口地址,获取openid。所需要传入的一系列参数appid(小程序id),secrect(小程序秘钥),js_code(code)。
分成了两大块:
小程序自己获取code码;
把code码发送到我们的服务器,再由我们的服务器调用微信给我们的接口,最终获取到openid和session_key。
\extra\wx.php
return [
'app_id' => '自己的小程序id',
'app_secret' => '自己的小程序秘钥',
'login_url' => "https://api.weixin.qq.com/sns/jscode2session?".
"appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
];
把需要传参的地方用%s占位符
service\UserToken.php
namespace app\api\service;
use think\Exception;
class UserToken
{
protected $code;
protected $wxAppID;
protected $wxAppSecrect;
protected $wxLoginUrl;
//在构造函数里面把这个wxLoginUrl配置完整
function __construct($code)
{
$this->$code = $code;
$this->wxAppID = config('wx.app_id');
$this->wxAppSecrect = config('wx.app_secret');
//调用sprintf占位符填写完整
$this->wxLoginUrl = sprintf(config('wx.login_url'),
$this->wxAppID,$this->wxAppSecrect,$this->code);
}
}
因为发送http请求是一个经常用到的,所以放到公共文件里面
common.php
($url,$httpCode = 0){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
//不做证书校验,部署在linux下请改为true
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;
}
\service\UserToken.php
在这里直接调用
public function get(){
$result = curl_get($this->wxLoginUrl);
$wxResult = json_decode($result,true);//把字符串变成数组:true:数组;false:对象
if (empty($wxResult)){//若为空,则微信调用失败
throw new Exception('获取session_key及openID时异常,微信内部错误');
//为什么使用框架的Exception而不是使用用户自定义的异常处理?
/*自定义的会作为结果返回到客户端去,但是这个是属于服务器内部的异常,这个会把它记录为日志。*/
}
else{//进一步的做判断
$LoginFail = array_key_exists('errcode',$wxResult);
//如果接口调用失败,微信会返回你一个errorcode码
if ($LoginFail){//失败,处理异常
$this->processLoginError($wxResyult);
}
else{//获取成功,颁发令牌
$this->grantToken();
}
}
}
\service\UserToken.php
private function processLoginError($wxResult){
throw new WeChatException([//做一个自定义参数设置
'msg' => $wxResult['errmsg'],
'errorCode' => $wxResult['errcode']
]);
}
在这里写一个异常处理函数:
为了扩展方便一些,比如发送邮件,记录日志
\exception\WeChatExceeption
namespace app\lib\exception;
class WeChatException extends BaseException
{
public $code = 400;
public $msg = '微信服务器接口调用失败';
public $errorCode = 999;
}
在这里自定义一个异常
\service\UserToken.php
private function grantToken($wxRssukt){
//拿到oppenid
//数据库里看一下,这个openid是不是已经存在
//如果存在,则不处理,如果不存在,那么新增一个user记录
//生成令牌,准备缓存数据,写入缓存
//把令牌返回到客户端去
$openid = $wxRssukt['openid'];
}
在微信小程序通过wx.login获取code码,在postman里面输入url,body-row-json里面输入{“code”:”“}
//数据库里看一下,这个openid是不是已经存在
//如果存在,则不处理,如果不存在,那么新增一个user记录
\model\Useer.php
查询数据库
namespace app\api\model;
class User extends BaseModel
{
public function getByOpenId($openid){
$user = self::where('openid','=',$openid)
->find();
return $user;
}
}
\service\Usertoken.php
private function grantToken($wxRssukt){
$openid = $wxRssukt['openid'];
//如果存在,则不处理,如果不存在,那么新增一个user记录
if ($user){
$uid = $user->id;
}
else{
$uid = $this->newUser($openid);//使用模型插入数据
}
//生成令牌,准备缓存数据,写入缓存
//缓存key:令牌
//value:wxRelsut(sessionkey openid);uid,scope(决定用户身份)
$cachedValue = $this->prepareCachedValue($wxRssukt,$uid);
}
private function prepareCachedValue($wxResult, $uid){//准备缓存value的数据
$cachedValue = $wxResult;
$cachedValue['uid'] = $uid;
$cachedValue['scope'] = 16;
return $cachedValue;
}
private function saveToCache($cachedValue){
$key = generateToken();
}
private function newUser($openid){//插入数据函数
$user = UserModel::create([
'openid' => $openid
]);
return $user->id;
}