微信公众号授权登录实战
框架:laravel
依赖:overtrue/wechat
首先安装一下easywechat依赖composerrequireovertrue/wechat:~4.0-vvv
安装完成后我们定义一个makeWechat方法public static functionmakeWechat(){$config= ['app_id'=> env('WECHAT_APPID'),'secret'=> env('WECHAT_APPSECRET'),'response_type'=>'array',];$app= Factory::officialAccount($config);return$app;}
我们return的$app后面要用到的地方很多,所以直接定义一个基础方法吧
写一个中间件,该中间件管理所有需要登录才能操作的接口
<?phpnamespaceApp \Http\Middleware;useApp\Libraries\AdminSend;useApp\Model\UserModel;useClosure;classCheckLogin{useAdminSend;public functionhandle($request,Closure$next){$url=$request->fullUrl();try{$key= env("TOKEN_KEY");$header=$request->cookie('authorization');$authorizationInfo=explode(":",openssl_decrypt(base64_decode($header),'DES-EDE3',$key,OPENSSL_RAW_DATA));if(!is_array($authorizationInfo) ||$authorizationInfo[0] <1)return self::returnLogin($url);$user= UserModel::get_by_id((int)$authorizationInfo[0]);if($userand!isset($user) ||$user['token'] !=$authorizationInfo[1])return self::returnLogin($url);$request->attributes->add(['uid'=>$authorizationInfo[0],'user'=>$user]);return$next($request);}catch(\Exception$e) {return self::returnLogin($url);}}}
主要逻辑是取request的cookie值,通过cookie值来判断用户是否登录了。
如果没有登录就returnLogin,该方法有一个参数为url,目的是为了跳转到微信公众号登录且登录成功后还继续跳回到之前用户想要访问的页面
看看returnLogin方法public static functionreturnLogin($url){Session::flash("redirect_url",$url);$app=self::makeWechat();$oauth=$app->oauth;return$oauth->scopes(['snsapi_userinfo'])->redirect(url("/user/login"));}
首先用了一个Session::falsh方法,这里就是通过seesion来缓存当前用户的来源地址,也就是为了上面提到了登录成功后继续跳转到登录之前的来路页面
然后跳转到user/login方法
来看看我们的login方法public functionlogin(Request$request){$app=self::makeWechat();$oauth=$app->oauth;$user_wechat=$oauth->user()->toArray();$user= UserModel::query()->where('openid',$user_wechat['id'])->first();if(!isset($user)) {$user=newUserModel();$user->name=$user_wechat['name'];$user->openid=$user_wechat['id'];$user->token=$user_wechat['token'];$user->avatar=$user_wechat['avatar'];$user->sex=$user_wechat['original']['sex'];$user->provider="wechat";$user->create_time= time();$user->save();}$token=self::TokenEncrypt($user['id'],$user['token'],env("TOKEN_KEY"));$url= Session::get("redirect_url");returnresponse()->redirectTo($url)->withCookie(cookie('authorization',$token));}
用户通过微信公众号授权后就会访问该方法,该方法拿到用户的openid去比对我们的数据库是否存在会员,如果存在就是登录,如果不存在那么就需要为该用户注册账号。
登录成功后返回登录cookie并且跳转到来路页面。
这里有一个TokenEncrypt的方法,其实就是生成我们的cookie一并分享出来吧
public functionTokenEncrypt(int$uid,$token,$key="UF((&)(&^#&)@!"){$encryptToken= base64_encode(openssl_encrypt("{$uid}:{$token}",'DES-EDE3',$key,OPENSSL_RAW_DATA));return$encryptToken;}
还有我们的数据库user表的结构#Host:(Version:5.7.32-log)
#Date:-12-3114:04:11
#Generator:MySQL-Front5.3(Build4.234)
/*!40101SETNAMESutf8*/;
#
#Structurefortable"user"
#
CREATETABLE`user`(
`id`int(11)NOTNULLAUTO_INCREMENT,
`name`varchar(50)NOTNULLDEFAULT''COMMENT'用户昵称',
`token`varchar(128)NOTNULLDEFAULT''COMMENT'微信token',
`create_time`int(11)NOTNULLDEFAULT'0'COMMENT'创建时间',
`pid`int(11)NOTNULLDEFAULT'0'COMMENT'邀请人',
`openid`varchar(255)NOTNULLDEFAULT''COMMENT'微信openid',
`avatar`varchar(255)NOTNULLDEFAULT''COMMENT'用户头像',
`sex`tinyint(3)NOTNULLDEFAULT'0'COMMENT'性别',
`provider`char(32)NOTNULLDEFAULT''COMMENT'用户渠道',
PRIMARYKEY(`id`),
KEY`openid`(`openid`)
)ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8mb4COMMENT='用户';