微信授权登录
一、构建项目
1 环境安装
2.框架安装
注意扩展的安装以及版本:
- PHP >= 7.2.5
- BCMath PHP 拓展
- Ctype PHP 拓展
- JSON PHP 拓展
- Mbstring PHP 拓展
- OpenSSL PHP 拓展
- PDO PHP 拓展
- Tokenizer PHP 拓展
- XML PHP 拓展
Laravel 使用 Composer 来管理项目依赖。因此,在使用 Laravel 之前,请确保你的机器已经安装了 Composer。
//laravel安装命令
composer create-project --prefer-dist laravel/laravel blog "6.*"
代码可以打包通过ftp传输到虚拟机环境中。也可在本地进行测试开发,并不强制要求大家环境一致,但是版本请注意版本之前的兼容问题
3.虚拟机环境
虚拟机的环境建议可以直接安装宝塔:通过宝塔快速安装所需要的数据库以及PHP
需要安装的软件:
- mysql8.0
- redis
- Nginx
- php
- composer
3.1 前端环境安装
liunx安装node.js
Node.js 安装包及源码下载地址为:https://nodejs.org/en/download/。
Node 官网已经把 linux 下载版本更改为已编译好的版本了,我们可以直接下载解压后使用
wget https://nodejs.org/dist/v10.9.0/node-v10.9.0-linux-x64.tar.xz // 下载
tar xf node-v10.9.0-linux-x64.tar.xz // 解压
cd node-v10.9.0-linux-x64/ // 进入解压目录
./bin/node -v // 执行node命令 查看版本
v10.9.0
解压文件的 bin 目录底下包含了 node、npm 等命令,我们可以使用 ln 命令来设置软连接:
ln -s /usr/software/nodejs/bin/npm /usr/local/bin/
ln -s /usr/software/nodejs/bin/node /usr/local/bin/
windows安装node.js
下载网址:https://nodejs.org/zh-cn/download/
安装node.js详情
https://www.cnblogs.com/liuqiyun/p/8133904.html
composer环境安装
1、下载composer
[root@localhost ~]# curl -sS https://getcomposer.org/installer | php
All settings correct for using Composer
Downloading...
Composer (version 1.10.9) successfully installed to: /root/composer.phar
Use it: php composer.phar
[root@localhost ~]# mv composer.phar /usr/local/bin/composer
[root@localhost ~]# composer config -g repo.packagist composer https://packagist.phpcomposer.com
验证安装:
4. 授权登录流程
2.1 获取测试公众账号及其相关配置
微信公众平台开发者文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
微信公众号测试号获取地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
5.公众测试账号获取
访问上面的链接,通过微信客户端扫码登录即可登录。登录完即可获取到一个测试公众账号的信息。主要有appId和appsecret两个参数,这将唯一标示一个公众号,并且需要将他们作为参数获取用户的信息。
关注公众号
用户只有关注了这个公众号了,才能通过打开有公众号信息的链接去授权第三方登录,并获取用户信息的操作。故我们还需要用我们的微信关注微信号,操作如下: 还是刚刚那个登录成功后跳转的页面,我们可以看到,该页面有一个二维码,我们可以通过扫描该二维码进行关注,关注成功在右边的“用户列表”会多一个用户的信息。如下图所示:
配置回调函数
我们在微信客户端访问第三方网页(即我们自己的网页)的时候,我们可以通过微信网页授权机制,我们不仅要有前面获取到的appid和appsecret还需要有当用户授权之后,回调的域名设置,即用户授权后,页面会跳转到哪里。具体的配置如下: 还是在刚刚的页面,有一个“网页授权获取用户基本信息”,点击后面的修改
二、 实现微信授权登录
网页授权:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
具体而言,网页授权流程分为四步:
1、引导用户进入授权页面同意授权,获取code
参数:
通过PHP artisan 命令创建微信授权登录控制器
php artisan make:controller WeChateController
// WeChateController
<?php
public function wxcode()
{
//微信授权登录相关信息
$params = http_build_query([
'appid' => 'wx849ea16e0f42f232', //微信公众平台提供的appid
'redirect_uri' => 'http://blog-shop.com/wxtoken', //你想要回调的地址
'response_type' => 'code',
'scope' => 'snsapi_userinfo',
]);
//第一步:用户同意授权,获取code
$url = 'https://open.weixin.qq.com/connect/oauth2/authorize?' . $params . '#wechat_redirect';//获取用户code接口
return redirect($url);
}
?>
注意:
1.手册第一个参数
2.
3.访问
Route::get('wxCode','WeChateController@wxcode');
2、通过code换取网页授权access_token(与基础支持中的access_token不同)
<?php
public function wxtoken(Request $resquest)
{
#根据拿到的code值去访问用户的access_token令牌
$params = http_build_query([
'appid' => 'wx849ea16e0f42f232',
'secret' => '0864a3720d5972c8bbb49e029cbd033f',
'code' => $resquest->input('code'),
'grant_type' => 'authorization_code'
]);
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?' . $params;
$result = file_get_contents($url);
$access_token = json_decode($result);
dd($access_token);
}
?>
3、刷新网页授权access_token,避免过期(这里只需要根据上面的接口一样进行数据获取即可)
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
<?php
public function wxtoken(Request $resquest)
{
#根据拿到的code值去访问用户的access_token令牌
$params = http_build_query([
'appid' => 'wx849ea16e0f42f232',
'secret' => '0864a3720d5972c8bbb49e029cbd033f',
'code' => $resquest->input('code'),
'grant_type' => 'authorization_code'
]);
$url = 'https://api.weixin.qq.com/sns/oauth2/access_token?' . $params;
$result = file_get_contents($url);
$access_token = json_decode($result);
$params = http_build_query([
'access_token' => $access_token->access_token,
'openid' => $access_token->openid,
'lang' => 'zh_CN'
]);
$url = "https://api.weixin.qq.com/sns/userinfo?".$params;
$UserInfo = json_decode(file_get_contents($url));
dd($UserInfo);
}
?>
根据路由访问:
Route::get('wxcode','WeChateController@wxcode');
Route::get('wxtoken','WeChateController@wxtoken');
三 、运用esaywechat配合中间件实现
第一步:去微信公众号中设置和获取信息
注意:公众号必须已经认证,且必须拥有网页授权获取用户基本信息的权限。
开发-基本配置-公众号开发信息,获取 app_id 和 app_secret 这两个参数。
开发-基本配置-公众号开发信息,IP白名单中设置你的服务器公网IP。
设置-公众号设置-功能设置,业务域名中添加你的域名(主要用于防止微信中访问网页时进行转码和风险提示)。
设置-公众号设置-功能设置,网页授权域名中添加你的域名。
第二步:安装 EasyWeChat 的 Laravel 拓展包
EasyWeChat 的 Laravel 拓展包:https://packagist.org/packages/overtrue/laravel-wechat
EasyWeChat是一个开源的微信非官方SDK。EasyWeChat 的安装非常简单,因为它是一个标准的 Composer 包,这意味着任何满足下列安装条件的 PHP 项目支持 Composer 都可以使用它
PHP >= 7.0
PHP cURL 扩展
PHP OpenSSL 扩展
PHP SimpleXML 扩展
PHP fileinfo 拓展
安装前请切换到项目的根目录下。
composer require "overtrue/laravel-wechat:~5.0"
注意:安装完成后 Laravel 默认已经把 EasyWeChat 做为服务嵌入到了框架中,所以在开发中使用的代码和 EasyWeChat 官方帮助文档中稍微有不同,当然如果你不使用 Laravel 的服务特性或是原生方式,可以直接按官网的来,更具体可以查看 EasyWeChat 和 EasyWeChat Laravel 5 拓展包的使用文档。
第三步创建配置文件
php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
这里使用的是微信中登陆功能,因此需要将 app_id 和 secret 修改为你的公众号参数,其他默认就好,可以在 /config/wechat.php 中修改,或者也可以在 .evn 中添加并赋值,两个方式选其一,具体区别请阅读官方文档。
在 /config/wechat.php 中的 official_account 节点中修改:
/*
* 公众号
*/
'official_account' => [
'default' => [
'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', 'your-appid'), // AppID
'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', 'your-secret'), // AppSecret
'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', ''), // Token
'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', ''), // EncodingAESKey
/*
* OAuth 配置
*
* scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
* callback:OAuth授权完成后的回调页地址(如果使用中间件,则随便填写。。。)
*/
'oauth' => [
'scopes' => array_map('trim', explode(',', env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_SCOPES', 'snsapi_userinfo'))),
'callback' => env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_CALLBACK', '/products'),
],
],
],
第四步:在.evn中添加并赋值
WECHAT_OFFICIAL_ACCOUNT_APPID = your-app-id
WECHAT_OFFICIAL_ACCOUNT_SECRET = your-app-secret
第五步:注册中间件
/app/Http/Kernel.php 中的 protected $routeMiddleware 节点添加
'Auth.WeChat' => \Overtrue\LaravelWeChat\Middleware\OAuthAuthenticate::class,
/config/app.php 中的 providers与 节点中添加
'providers' => [
...
\Overtrue\LaravelWeChat\ServiceProvider::class,
]
'aliases' => [
...
'EasyWeChat' => \Overtrue\LaravelWeChat\Facade::class,
]
第六步:创建测试路由,添加中间件
在路由文件web.php中添加:
Route::get('wechat/auth', function(){
$wechat = session('wechat.oauth_user.default'); //拿到授权用户资料
dd($wechat); //打印出授权用户资料
})->middleware('Auth.WeChat');
此时,打开微信,在微信中访 http://你的域名/wechat/auth 试试,点击同意授权后,就会打印出你当前微信的用户资料。
如果在本地安装组件上传并配置之后 ,这里还会出现找不到服务的情况,请参考https://blog.csdn.net/qq_38941567/article/details/107907855
注意:必须在微信中访问,因为在浏览器中访问是需要微信开放平台的接口
这里可能会出现error
这个错误是因为我们并没授权登录,在esaywechat拉取授权登录信息的时候重定向头信息验证出现异常。
解决:可以通过修改中间件代码去解决问题
修改 \Overtrue\LaravelWeChat\Middleware\OAuthAuthenticate 中的handle方法代码,如下:
<?php
session([$sessionKey => $officialAccount->oauth->userFromCode($request->get('code')) ?? []]);
修改为:
session([$sessionKey => $officialAccount->oauth->user() ?? []]);
return redirect()->to($officialAccount->oauth->scopes($scope)->redirect($request->fullUrl()));
修改为:
return r$officialAccount->oauth->scopes($scope)->redirect($request->fullUrl());
?>
修改好了之后访问:
第七步:完善编写授权代码
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use App\Models\User;
use EasyWeChat\Factory;
class WeChatController extends Controller
{
//微信授权登录代码
public function auth(Request $request)
{
//通过session获取用户授权信息
$Auth = session('wechat.oauth_user.default');
//查询并判断微信用户是否已在并平台进行注册
$user = User::where('openid',$Auth['id'])->first();
//用户的密码需要他在第一次登录的时候进行设置
//手机号码需要进行绑定,需要根据用户id来进行异构索引表分表
if (!$user) {
// code...
$result = User::create([
'id' => $this->uuid(),
'Openid' => $Auth['id'],
'username' => $Auth['name'],
'role_id' => 1,//角色默认1位普通用户
'vender_type' => 2,
'status' => 0,
'login_ip' => $request->getClientIp()
]);
}else {
$result = $user;
}
//注册或者是验证完毕之后进行登录
Auth::login($result,true);
//重定向到商城首页地址
return redirect('/products');
}
public function uuid($prefix='')
{
$str = md5(uniqid(mt_rand(), true));
$uuid = substr($str,0,8) . '-';
$uuid .= substr($str,8,4) . '-';
$uuid .= substr($str,12,4) . '-';
$uuid .= substr($str,16,4) . '-';
$uuid .= substr($str,20,12);
return $prefix . $uuid;
}
}
?>
//app/User.php
protected $fillable = [
'id','username', 'Openid','password','role_id','vender_type',
'status','mobile','login_ip'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
第八步:创建正式路由,添加中间件
此时可以注释或者删除掉刚才创建的路由信息,并添加正式的路由:
//esaywechat配合中间件登录
Route::get('WeChat','WeChatController@auth')->middleware('Auth.WeChat')->name('Login.WeChat');
第九步:创建商品首页控制器
通过PHP artisan 命令创建商品首页控制器
php artisan make:controller ProductController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProductController extends Controller
{
//
public function index()
{
return '商品首页';
}
}
四、信公众号菜单处理
自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。开启自定义菜单后,公众号界面如图所示:
请注意: 自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“…”代替。
创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
自定义菜单接口可实现多种类型按钮,如下:
菜单类型名称 | 菜单类型描述 |
---|---|
click | 点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互 |
view | 跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息 |
scancode_push | 扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息 |
scancode_waitmsg | 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息 |
pic_sysphoto | 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息 |
pic_photo_or_album | 弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程 |
pic_weixin | 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息 |
location_select | 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息 |
media_id | 下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id |
view_limited | 跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id |
请注意,3到8的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。9和10,是专门给第三方平台旗下未微信认证(具体而言,是资质认证未通过)的订阅号准备的事件类型,它们是没有事件推送的,能力相对受限,其他类型的公众号不必使用。
{
"button": [
{
"type": "view",
"name": "进入商城",
"url": "http://lms-shops.com/WeChat"
},
{
"name": "菜单",
"sub_button": [
{
"type": "view",
"name": "我的订单",
"url": "http://lms-shops.com/order"
},
{
"type": "view",
"name": "购物车",
"url": "http://lms-shops.com/cart"
},
{
"type": "view",
"name": "个人中心",
"url": "http://lms-shops.com/member"
}
]
}
]
}
对于不同参数类型可以参考:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
设置成功之后哦,在微信中可以查看自定义好的微信公众号菜单: