Skip to content

微信登录

向军大叔每晚八点在 抖音bilibli 直播

xj-small

微信登录是用户喜欢的登录方式,所以网站集成微信登录也是必备技能之一。

OAuth

测试帐号

使用测试帐号练习的目的是有些同学没有开放平台帐号。

首先需要配置微信公众号,然后配置 网页授权获取用户基本信息

image-20200816132316448

然后配置授权回调页面域名,注意不要添加 http 前缀

image-20200816132401590

登录流程

微信登录使用 OAuth 协议,具体操作步骤如下

image-20200816121707577
  1. 引导用户访问微信服务器
  2. 用户决定是否授权网站授权
  3. 用户同意后返回到网站回调页面并传递code 授权码
  4. 网站根据授权码访问微信服务器申请获取access_token
  5. 网站使用获取的 access_token 获取用户资料

code 授权码

下面来体验微信登录的流程,首先登录微信开发者工具

我们来首先来获取授权码

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

需要将地址中的以下参数进行替换

参数说明
appid测试号信息 appid
redirect_uri授权码获取成功后的跳转地址
scope授权作用域 snsapi_base 或 snsapi_userinfo

最终替换搂链接如下

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxcxxxxxxx&redirect_uri=https://dev.hdcms.com/wechat&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

然后在微信开发者工具中访问该地址来获取 code 授权码,最后会在回调地址中看到 code 授权码,请进行复制后面会用到。

image-20200816134256559

access_token

下面来通过上步中的 code 换取access_token,接口地址如下

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

需要将地址中的以下参数进行替换

参数说明
appid测试号信息 appid
secret测试号信息 appsecret
code上步中获取有 code 授权码

最后的地址类似如下

https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxcf44xxxxxx&secret=6fd451c0cff05b6cxxxxxxx&code=011vR2300F5P5K1XNt300wpsMK3vR23O&grant_type=authorization_code

然后使用 postman 或 curl 命令访问上面请求地址来获取 access_token

image-20200816135104969

用户资料

有了 access_token 后我们就可以来获取用户资料了,接口地址如下

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

需要将地址中的以下参数进行替换

参数说明
access_token上步中获取的 access_token

然后在 postman 中访问地址获取用户资料

image-20200816135451155

返回参数说明如下

参数描述
openid用户的唯一标识
nickname用户昵称
sex用户的性别,值为 1 时是男性,值为 2 时是女性,值为 0 时是未知
province用户个人资料填写的省份
city普通用户个人资料填写的城市
country国家,如中国为 CN
headimgurl用户头像,最后一个数值代表正方形头像大小(有 0、46、64、96、132 数值可选,0 代表 640*640 正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像 URL 将失效。
privilege用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
unionid只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

开放平台

使用开放平台处理登录,可以将网站/小程序/App 等使用微信登录的用户,获取到统一的帐号。

使用微信登录网站需要先在微信开发平台进行配置,你可以访问[后盾人文档微信开放平台](https://doc.houdunren.com/tencent/3 开放平台.html) 学习怎么配置开发平台。

配置资料

在微信开放平台 管理中心>网站应用 中查看密钥资料

image-20200816164922244

然后正确配置回调域,要求设置二级域名

image-20200816165119644

编写代码

下面实现以开放平台完成网站登录的业务代码。

安装扩展

下面我们在 LARAVEL 框架的项目中集成微信登录。

laravel 为我们提供了方便的 [laravel/socialite](https://doc.houdunren.com/手册/laravel/10 官方扩展包/6 Socialite.html) 组件,同时也要安装 socialiteproviders/weixin-web

composer require laravel/socialite

composer require socialiteproviders/weixin-web

app/Providers/EventServiceProvider 中添加事件监听

protected $listen = [
  \SocialiteProviders\Manager\SocialiteWasCalled::class => [
    'SocialiteProviders\\WeixinWeb\\WeixinWebExtendSocialite@handle',
  ],
];

配置

修改.env 配置文件

WECHATWEB_CLIENT_ID=wx9704xxxxx
WECHATWEB_CLIENT_SECRET=fc112xxxxxxxxxxx0c
WECHATWEB_REDIRECT_URI=https://dev.hdcms.com/login/wechat/callback

然后修改config/services.php配置文件

'weixinweb' => [
    'client_id' => env('WECHATWEB_CLIENT_ID'),
    'client_secret' => env('WECHATWEB_CLIENT_SECRET'),
    'redirect' => env('WECHATWEB_REDIRECT_URI')
],

配置项说明如下

配置说明
client_id开放平台网站应用中的 AppID
client_secret开放平台网站应用中的 AppSecret
redirect登录回调地址

控制器

我们来创建控制器实现业务代码

php artisan make:controller Auth/WeChatController

具体内容如下

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Socialite;
use App\Models\User;
use Auth;

class WeChatController extends Controller
{
    /**
     * 将用户重定向到授权页面
     * @return \Illuminate\Http\Response
     */
    public function redirectToProvider()
    {
        return Socialite::driver('weixinweb')->redirect();
    }

    /**
     * 获取用户信息
     * 下面有数据表操作,请根据你项目进行修改
     * @return \Illuminate\Http\Response
     */
    public function handleProviderCallback()
    {
        $account = Socialite::driver('weixinweb')->user();
        $unionid = $account->unionid ?? null;
        if ($unionid) {
            $user = User::where('unionid', $account->unionid)->first();
        } else {
            $user = User::where('openid', $account->getId())->first();
        }
        if (!$user) {
            $user =  User::create([
                'avatar' => $account->user['headimgurl'],
                'openid' => $account->getId(),
                'unionid' => $unionid,
                'name' => $account['nickname']
            ]);
            Auth::login($user);
        }
        return redirect()->intended('/');
    }
}

路由配置

下面来配置访问控制器的路由

Route::get('login/wechat', 'WeChatController@redirectToProvider');

Route::get('login/wechat/callback', 'WeChatController@handleProviderCallback');

登录测试

在浏览器中访问 https://dev.hdcms.com/login/wechat 就会看到登录二维码,扫码后就可以登录网站了。

Socialite::driver('weixinweb')->user() 得到的用户资料结果如下

SocialiteProviders\Manager\OAuth2\User {#1821 ▼
  +accessTokenResponseBody: array:6 [▶]
  +token: "36_MSfhsdpnY-f7D1laAqN9X5X8l8kMxxxxxxPN-ZpuqsJlB-oxnCaNZ9h--Fa6GocYrMyo"
  +refreshToken: "36__wV-kvO5wUd5JoolfF1a8_XPExxxxxvz3mz4uxxxxQxxxxl0H4uJjYkQ"
  +expiresIn: 7200
  +id: "o4Cir0jmRruZWAKOKb4VB4mZO9s8"
  +nickname: "向军"
  +name: null
  +email: null
  +avatar: "http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLia0aejribtQMzsP3SFiaSn3jCwgIQhrNGh9ibuuS3kWGJf4PxMbPGujWkVlYCKbdwpjrz38iaw4lNp0w/132"
  +user: array:10 [▼
    "openid" => "o4Cir0jmRruZWAKOxxxxxs8"
    "nickname" => "向军"
    "sex" => 1
    "language" => "zh_CN"
    "city" => "朝阳"
    "province" => "北京"
    "country" => "中国"
    "headimgurl" => "http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLia0aejribtQMzsP3SFiaSn3jCwgIQhrNGh9ibuuS3kWGJf4PxMbPGujWkVlYCKbdwpjrz38iaw4lNp0w/132"
    "privilege" => []
    "unionid" => "otxxt7Pm6jryw-xxxx4"
  ]
  +"unionid": "otCIzxxxxxxw-SfOxxxujaxxx"
}

常见错误

  • redirect_uri 参数错误

    登录微信开放平台 > 网站应用 > 开发信息 > 设置授权回调域

    image-20200917131047496

客户端登录

微信客户端登录指在微信 APP 内进行微信登录的操作。具体流程已经在上面的登录流程测试部分讲解过。

实例开发中我们使用第三方扩展包可以提升开发效率,是推荐的解决方案。

安装扩展

下面我们在 LARAVEL 框架的项目中集成微信登录。

laravel 为我们提供了方便的laravel/socialite组件,同时也要安装socialiteproviders/weixin

composer require laravel/socialite

composer require socialiteproviders/weixin

app/Providers/EventServiceProvider中添加事件监听

protected $listen = [
  \SocialiteProviders\Manager\SocialiteWasCalled::class => [
    'SocialiteProviders\\Weixin\\WeixinExtendSocialite@handle',
  ],
];

配置

修改.env 配置文件

WECHATWEB_CLIENT_ID=wx9704xxxxx
WECHATWEB_CLIENT_SECRET=fc112xxxxxxxxxxx0c
WECHATWEB_REDIRECT_URI=https://dev.hdcms.com/login/wechat/callback

然后修改config/services.php配置文件

'weixin' => [
    'client_id' => env('WECHATWEB_CLIENT_ID'),
    'client_secret' => env('WECHATWEB_CLIENT_SECRET'),
    'redirect' => env('WECHATWEB_REDIRECT_URI')
],

配置项说明如下

配置说明
client_id微信公众号的 appID
client_secret微信公众号的 appsecret
redirect登录回调地址

控制器

我们来创建控制器

php artisan make:controller Auth/WeChatController

具体内容如下

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Socialite;
use App\Models\User;
use Auth;

class WeChatController extends Controller
{
    /**
     * 将用户重定向到授权页面
     *
     * @return \Illuminate\Http\Response
     */
    public function redirectToProvider()
    {
        return Socialite::driver('weixin')->redirect();
    }

    /**
     * 获取用户信息
     * 下面有数据表操作,请根据你项目进行修改
     * @return \Illuminate\Http\Response
     */
    public function handleProviderCallback()
    {
        $account = Socialite::driver('weixin')->user();
        $unionid = $account->unionid ?? null;
        if ($unionid) {
            $user = User::where('unionid', $account->unionid)->first();
        } else {
            $user = User::where('openid', $account->getId())->first();
        }
        if (!$user) {
            $user =  User::create([
                'avatar' => $account->user['headimgurl'],
                'openid' => $account->getId(),
                'unionid' => $unionid,
                'name' => $account['nickname']
            ]);
            Auth::login($user);
        }
        return redirect()->intended('/');
    }
}

路由配置

下面来配置访问控制器的路由

Route::get('login/wechat', 'WeChatController@redirectToProvider');

Route::get('login/wechat/callback', 'WeChatController@handleProviderCallback');

登录测试

在微信客户端或微信开发者工具中访问 https://dev.hdcms.com/login/wechat 进行微信登录。

image-20200917125234209

Socialite::driver('weixin')->user() 得到的用户资料结果如下

SocialiteProviders\Manager\OAuth2\User {#1821 ▼
  +accessTokenResponseBody: array:6 [▶]
  +token: "36_MSfhsdpnY-f7D1laAqN9X5X8l8kMxxxxxxPN-ZpuqsJlxxxxxxxxxxxxxxxxxxx"
  +refreshToken: "36__wV-kvO5wUd5JoolfF1a8_XPExxxxxvz3mzxxxxxxxxxxxxxxxxxxxxx"
  +expiresIn: 7200
  +id: "o4Cir0jxxxxxxxxxxxxxxxx"
  +nickname: "向军"
  +name: null
  +email: null
  +avatar: "http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLia0aejribtQMzsP3SFiaSn3jCwgIQhrxxxxxxxxxxxxxxxxxxxxx"
  +user: array:10 [▼
    "openid" => "o4Cxxxxxxxxxxxxxx"
    "nickname" => "向军"
    "sex" => 1
    "language" => "zh_CN"
    "city" => "朝阳"
    "province" => "北京"
    "country" => "中国"
    "headimgurl" => "http://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLia0aejribtQMzsP3SFiaSn3jCwgIQhrNGh9ibuuxxxxxxxxxxxxx"
    "privilege" => []
    "unionid" => "otxxxxxxxxxxxxxx"
  ]
  +"unionid": "otCIxxxxxxxxxxxxxxx"
}

常见错误

redirect_uri 参数错误

登录微信公众号(或测试公众号) > 接口权限表 > 网页帐号

image-20200917131412670

然后设置授权回调页面域名

image-20200917131506992

scope 参数错误或没有 scope 权限

这个问题和上面的情况差不多,是因为没有设置网页帐号的 授权回调域名

image-20200917131412670

兼容操作

上面分别介绍了微信在网站与微信客户端的登录场景。其实我们可以通过判断设备来动态处理,而不需要写多个控制器与路径分别处理。

下面是微信客户端的检测函数

function is_wechat()
{
    return isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false);
}

通过上面的函数判断后来使用不同的驱动即可。