思路
请求->服务器获取code 再请求->服务器access_token 再请求->服务器userinfo
先获取code:微信给了一个url,里面有scope/appid/redict_url,拼接之后进行向微信请求,跳转至redirect_url里面;
callback:微信会给我们返回code;
然后通过code/appid等再拼接一个url,进行curl请求;
微信返回给我们的信息就有openid、access_token等;
我们在通过access_token,组装一个url,curl请求,就会获取我们需要的用户信息。
概述
微信登录三种登录方法(授权登录、静默登录、扫码登录)
静默登录
用appid去获取code然后获取用户的openid,拿到openid之后就可以进行自己业务处理了,从体验上来说用户无感,没有上面那个授权页,个人认为此种授权方式比较适合较为独立或者正在考虑脱离微信的网站,
以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
授权登录
此方式可以获取比较多的信息,例如头像、昵称、openid、unionid、是否关注公众号等信息
以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
扫码登录
此种方式一般适用于电商网站的PC登录,如下图
源码
步骤
代码
class OauthController extends BaseController {
public function actionLogin(){
$scope = $this->get( "scope","snsapi_base" );
$appid = \Yii::$app->params['weixin']['appid'];
$redirect_uri = UrlService::buildMUrl( "/oauth/callback" );
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$redirect_uri}&response_type=code&scope={$scope}&state=#wechat_redirect";
return $this->redirect( $url );
}
public function actionCallback(){
// 会返回一个code 通过code获取access_token
$code = $this->get( "code","" );
if( !$code ){
return $this->goHome();
}
//通过code 获取网页授权的access_token
$appid = \Yii::$app->params['weixin']['appid'];
$sk = \Yii::$app->params['weixin']['sk'];
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$sk}&code={$code}&grant_type=authorization_code";
// 进行get请求
$ret = HttpClient::get( $url );
$ret = @json_decode( $ret,true );
// 返回的token值
$ret_token = isset( $ret['access_token'] )?$ret['access_token']:'';
if( !$ret_token ){
return $this->goHome();
}
$openid = isset( $ret['openid'] )?$ret['openid']:'';
$scope = isset( $ret['scope'] )?$ret['scope']:'';
$this->setCookie( $this->auth_cookie_current_openid,$openid );
$reg_bind = OauthMemberBind::find()->where([ 'openid' => $openid,'type' => ConstantMapService::$client_type_wechat ])->one();
if( $reg_bind ){
$member_info = Member::findOne( [ 'id' => $reg_bind['member_id'],'status' => 1 ] );
if( !$member_info ){
$reg_bind->delete();
return $this->goHome();
}
if( $scope == "snsapi_userinfo" ){
$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$ret_token}&openid={$openid}&lang=zh_CN";
$wechat_user_info = HttpClient::get( $url );
$wechat_user_info = @json_decode( $wechat_user_info,true );
//这个时候做登录特殊处理,例如更新用户名和头像等等新
if( $member_info->avatar == ConstantMapService::$default_avatar ){
//需要做一个队列数据库了
//$wechat_user_info['headimgurl']
QueueListService::addQueue( "member_avatar",[
'member_id' => $member_info['id'],
'avatar_url' => $wechat_user_info['headimgurl'],
] );
}
if( $member_info['nickname'] == $member_info['mobile'] ){
$member_info->nickname = isset( $wechat_user_info['nickname'] )?$wechat_user_info['nickname']:$member_info->nickname;
$member_info->update( 0 );
}
}
//设置登录态
$this->setLoginStatus( $member_info );
}else{
$this->removeLoginStatus();
}
return $this->redirect( UrlService::buildMUrl( "/default/index" ) );
}
public function actionLogout(){
$this->removeLoginStatus();
$this->removeCookie( $this->auth_cookie_current_openid );
return $this->goHome();
}