- 后端
- 即时通讯
【免费下载链接】easywechat
📦 一个 PHP 微信 SDK
本篇基于 EasyWeChat 6.x(PHP 微信 SDK)的开放平台第三方平台模块,围绕其官方示例文档整理出一套可直接落地的实战方案:从 Laravel / Laravel Octane / webman 框架中接收开放平台推送消息、处理授权事件,到 6.3.0+ 新增的 PC 版预授权流程,以及基于 refresh_token / access_token 代公众号、代小程序调用 API,甚至代公众号响应回调消息。读完你可以直接在现有 PHP 框架中复刻整套第三方平台接入流程。
前置准备:实例化开放平台对象
示例中所有代码都基于一个已实例化的$app对象(即EasyWeChat\OpenPlatform\Application)。它需要开放平台账号的app_id、secret、token、aes_key四项核心配置,具体实例化方式可参考 开放平台模块总览。需要注意:不要把公众号/小程序的配置信息用来初始化开放平台对象。
在 Laravel / webman 等框架项目中,常见的做法是把配置放入config/wechatv6.php(如wechatv6.open_platform键),再通过new Application($config)创建实例:
use EasyWeChat\OpenPlatform\Application; $config = config('wechatv6.open_platform'); $app = new Application($config);从源码结构看,Application是一个工厂类,所有模块(服务端、客户端、ComponentAccessToken、VerifyTicket、账户信息等)都从$app上按需访问(见 src/OpenPlatform/Application.php)。
一、Laravel:接收开放平台推送消息并处理授权事件
开放平台第三方平台的所有事件推送(授权成功、授权更新、授权取消、VerifyTicket)都会推送到你设置的「授权事件接收 URL」。假设该 URL 为https://easywechat.com/open-platform,在 Laravel 中只需在routes/web.php注册一个 POST 路由,把请求直接交给$app->server->serve():
// routes/web.php Route::post('open-platform', function () { // $app 为你实例化的开放平台对象,此处省略实例化步骤 return $app->server->serve(); // Done! });⚠️ 注意:该路由需要排除 CSRF 校验(在 Laravel 的
VerifyCsrfToken中间件白名单中排除该 URI)。
如果要处理具体事件,例如「授权成功」,可以注册handleAuthorized监听器,$message为微信推送的通知内容(EasyWeChat\OpenPlatform\Message实例),不同事件内容字段不同:
// 处理授权事件 Route::post('open-platform', function () { $server = $app->getServer(); // 处理授权成功事件,其他事件同理 $server->handleAuthorized(function ($message) { // $message 为微信推送的通知内容,不同事件不同内容,详看微信官方文档 // 获取授权公众号 AppId: $message['AuthorizerAppid'] // 获取 AuthCode:$message['AuthorizationCode'] // 然后进行业务处理,如存数据库等... }); return $server->serve(); });这里有几个值得注意的源码细节(可印证 src/OpenPlatform/Server.php):
handleAuthorized()、handleUnauthorized()、handleAuthorizeUpdated()分别对应InfoType为authorized、unauthorized、updateauthorized三个事件,实现上通过中间件按InfoType分流(见 src/OpenPlatform/Server.php);- 官方示例中回调函数接收
$message并直接使用$message['AuthorizerAppid']、$message['AuthorizationCode']取字段,Message类继承自EasyWeChat\Kernel\Message,支持数组式属性访问(见 src/OpenPlatform/Message.php); serve()内部会先处理echostr服务端验证,再解密推送消息,并按中间件链处理事件,最终返回success或加工后的响应(见 src/OpenPlatform/Server.php)。
此外,component_verify_ticket事件已被 SDK 默认处理:getServer()每次被调用时会自动注入默认的 VerifyTicket 处理器,把推送中的ComponentVerifyTicket写入缓存(见 src/OpenPlatform/Application.php),因此即使你不注册任何监听器,直接serve()也能正常工作。
二、Laravel Octane(Swoole):长驻进程下的兼容写法
Laravel Octane(常配合 Swoole)下请求对象与常规 FPM 生命周期不同,需要把当前请求显式注入Application,再交给服务端处理:
// routes/web.php use EasyWeChat\OpenPlatform\Application; // 授权事件回调地址:http://easywechat.com/open-platform/server Route::post('open-platform/server', function () { $config = config('wechatv6.open_platform'); $app = new Application($config); // 兼容octane $app->setRequestFromSymfonyRequest(request()); $server = $app->getServer(); return $server->serve(); });关键点在于setRequestFromSymfonyRequest(request()):Application内部通过InteractWithServerRequestTrait 持有 PSR-7 风格的请求对象(见 src/OpenPlatform/Application.php),getServer()构造的Server会从该请求中读取echostr、signature、timestamp、nonce、msg_signature等查询参数以及推送的 XML 消息体,因此在 Swoole/Octane 这类「请求对象需手动绑定」的场景下,显式注入当前请求是保证消息验签与解密正确的必要步骤。
三、webman:手动构造 Symfony Request 接收推送
webman 同样需要把原生请求转换为Symfony\Component\HttpFoundation\Request后注入Application。示例中通过手动组装参数、Cookie、原始 Body 与 Header 实现:
namespace app\controller; use EasyWeChat\OpenPlatform\Application; use support\Request; use Symfony\Component\HttpFoundation\HeaderBag; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; // 授权事件回调地址:http://easywechat.com/openPlatform/server class OpenPlatform { public function server(Request $request) { $config = config('wechatv6.open_platform'); $app = new Application($config); $symfony_request = new SymfonyRequest($request->get(), $request->post(), [], $request->cookie(), [], [], $request->rawBody()); $symfony_request->headers = new HeaderBag($request->header()); $app->setRequestFromSymfonyRequest($symfony_request); $server = $app->getServer(); $response = $server->serve(); return $response->getBody()->getContents(); } }这段代码把 webman 的support\Request中的 GET、POST、Cookie、原始请求体(rawBody(),推送的 XML 就在这里)以及请求头完整搬运到 Symfony Request 上,再通过setRequestFromSymfonyRequest()注入。返回时取$response->getBody()->getContents(),以适配 webman 的响应格式。验签所需的signature等参数来自查询字符串,头部则用于框架层面兼容,二者缺一不可。
四、开放平台 PC 版预授权流程(6.3.0+)
从 6.3.0 版本开始,SDK 提供了createPreAuthorizationUrl()与createPreAuthorizationCode(),可以一键生成预授权码并拼装授权页地址(旧版本需要手动调微信接口拿预授权码,再自行拼 URL)。
一个完整的 Laravel 预授权用例包含「授权落地页」与「授权跳转页」两个路由:
// routes/web.php // 授权落地页 Route::any('open-platform/auth', function(){ $auth_code = request()->get('auth_code'); // 完成授权写入数据库的逻辑省略。。。 })->name('open_platform.auth'); // 授权跳转页 Route::any('open-platform/preauth', function(){ // $app 为你实例化的开放平台对象,此处省略实例化步骤 $options=[ //1 表示手机端仅展示公众号;2 表示仅展示小程序,3 表示公众号和小程序都展示。如果为未指定,则默认小程序和公众号都展示。 // 'auth_type' => '', // 指定的权限集id列表,如果不指定,则默认拉取当前第三方账号已经全网发布的权限集列表。 // 'category_id_list' => '', ]; $url = $app->createPreAuthorizationUrl(route('open_platform.auth'), $options); return response("<script>window.location.href='$url';</script>")->header('Content-Type', 'text/html'); });参数说明:
| 参数 | 说明 |
|---|---|
auth_type | 展示类型:1手机端仅展示公众号;2仅展示小程序;3公众号和小程序都展示。不传则默认小程序和公众号都展示 |
category_id_list | 指定的权限集 id 列表;不指定则默认拉取当前第三方账号已全网发布的权限集列表 |
从源码看,createPreAuthorizationUrl(string $callbackUrl, array|string $optional = [])的实现逻辑是(见 src/OpenPlatform/Application.php):
- 若
$optional是字符串,则兼容旧版 API,把它当作pre_auth_code使用; - 若传入数组,则自动调用
createPreAuthorizationCode()获取pre_auth_code填充; - 最终把
pre_auth_code、component_appid、redirect_uri等参数拼装到https://mp.weixin.qq.com/cgi-bin/componentloginpage?...上。
所以上面的示例即使不显式传pre_auth_code,方法内部也会自动完成「创建预授权码 → 拼授权页地址」的全过程。授权完成后,微信会携带auth_code与expires_in跳回落地页(如https://easywechat.com/callback?auth_code=xxx&expires_in=600),你可以用$app->getAuthorization($auth_code)换取授权方信息(见 获取授权信息)。
五、代公众号 / 代小程序调用 API(6.3.0+)
第三方平台最常见的业务是代替已授权的公众号、小程序调用其接口。6.3.0+ 提供了两条便捷入口:
getOfficialAccountWithRefreshToken($appId, $refreshToken):传入公众号appid与授权时拿到的authorizer_refresh_token,返回EasyWeChat\OfficialAccount\Application实例;getMiniAppWithRefreshToken($appId, $refreshToken):同上,返回EasyWeChat\MiniApp\Application实例。
这两个方法内部都会先调用getAuthorizerAccessToken(),其实现会对 token 做按 appid + refresh_token 维度缓存,缓存键为open-platform.authorizer_access_token.{appid}.{md5(refresh_token)},并以expires_in - 500秒的余量写入缓存,未命中时才回源refreshAuthorizerToken()刷新(见 src/OpenPlatform/Application.php),因此高并发场景下不必担心频繁触发刷新接口的每日限额。
一个同时演示「代小程序」和「代公众号」的 Laravel 控制器示例如下。首先配置路由:
// routes/web.php // 例如:https://easywechat.com/open-platform/miniapp/get-phone-number/wx123212312313abc Route::any('open-platform/miniapp/get-phone-number/{appid}', 'OpenPlatformController@getPhoneNumber'); Route::any('open-platform/officialAccount/get-user-list/{appid}', 'OpenPlatformController@getUsers');对应控制器app/Http/Controllers/OpenPlatformController:
use App\Http\Controllers\Controller; class OpenPlatformController extends Controller { public function mini(string $appid): \EasyWeChat\MiniApp\Application { $refreshToken = '授权后在缓存或数据库获取'; // $app 为你实例化的开放平台对象,此处省略实例化步骤 return $app->getMiniAppWithRefreshToken($appid, $refreshToken); } public function officialAccount(string $appid): \EasyWeChat\OfficialAccount\Application { $refreshToken = '授权后在缓存或数据库获取'; // $app 为你实例化的开放平台对象,此处省略实例化步骤 return $app->getOfficialAccountWithRefreshToken($appid, $refreshToken); } public function getUsers(string $appid) { return $this->officialAccount($appid) ->getClient() ->get('cgi-bin/users/list') ->toArray(); } public function getPhoneNumber(string $appid) { $data = [ 'code' => (string) request()->get('code'), ]; return $this->mini($appid) ->getClient() ->postJson('wxa/business/getuserphonenumber', $data) ->toArray(); } }核心要点:
- 返回的
Application实例可直接用->getClient()调用该公众号/小程序任意 API,SDK 会自动携带代调用所需的authorizer_access_token; - 代调用的小程序、公众号对象实际是
EasyWeChat\MiniApp\Application与EasyWeChat\OfficialAccount\Application,其 Client 的 token 来自AuthorizerAccessToken(见 src/OpenPlatform/AuthorizerAccessToken.php),并通过setAccessToken()注入(见 src/OpenPlatform/Application.php); authorizer_access_token有效期仅 2 小时,SDK 内部通过缓存 + 自动刷新机制管理,你只需持久化authorizer_refresh_token即可。
除了 refresh_token 方式,6.3.0+ 还支持直接使用authorizer_access_token的getOfficialAccountWithAccessToken()/getMiniAppWithAccessToken(),适用于「独立中央授权服务单独维护授权信息」的架构;旧版通过new AuthorizerAccessToken($appId, $token)+getOfficialAccount()/getMiniApp()的方式官方示例中已标注不推荐使用。更多细节见 开放平台模块总览。
六、代公众号处理回调事件
第三方平台还可以代替公众号接收并响应用户发来的消息。示例中在同一个回调路由里,根据 URL 中的{appid}取出对应授权方的 refresh_token,构造公众号对象并注册消息监听器:
// 代公众号处理回调事件 Route::any('callback/{appid}', function ($appId) { // $app 为你实例化的开放平台对象,此处省略实例化步骤 // $refreshToken 为授权后你缓存或数据库中的 authorizer_refresh_token,此处省略获取步骤 $refreshToken = '你已缓存或数据库中的 authorizer_refresh_token'; $server = $app->getOfficialAccountWithRefreshToken($appId, $refreshToken)->getServer(); $server->addMessageListener('text', function ($message) { return sprintf("你对 overtrue 说:“%s”", $message->Content); }); return $server->serve(); });这里getOfficialAccountWithRefreshToken()返回的公众号对象自带getServer()服务端,其加密参数(token、aes_key、Encryptor)会复用开放平台的配置(见 src/OpenPlatform/Application.php),因此代公众号回调同样走「验签 → 解密 → 消息监听器 → 加密回复」的完整链路。addMessageListener('text', ...)注册的是文本消息处理器,$message->Content即用户发送的文本内容,返回字符串即自动回复。更多服务端用法(handleAuthorized/handleUnauthorized/handleAuthorizeUpdated/ 自定义中间件 /getDecryptedMessage等)可参考 服务端使用文档。
七、周边模块衔接与注意事项
- CSRF 排除:开放平台事件推送与回调路由必须从 Laravel CSRF 白名单中排除,否则会收到 419 响应;
- VerifyTicket 默认处理:
component_verify_ticket事件由 SDK 默认写入缓存(缓存键open_platform.verify_ticket.{app_id},见 src/OpenPlatform/VerifyTicket.php),ComponentAccessToken的获取与刷新都依赖它(见 src/OpenPlatform/ComponentAccessToken.php)。若你自行接管 VerifyTicket 推送,必须同时注入自定义ComponentAccessToken,否则会因缺少 ticket 而无法换取component_access_token; - token 缓存策略:
ComponentAccessToken以expires_in - 100秒写入缓存,authorizer_access_token以expires_in - 500秒写入缓存,均预留了时钟偏差余量,请勿再手动缩短或重复刷新; - 代调用入口:公众号代调用详见 公众号模块,小程序代调用详见 小程序模块,普通 API 调用方式见 API Client 文档;
- 网页授权:第三方应用/网站的网页授权通过
$app->getOAuth()获取,逻辑与公众号网页授权基本一致,详见 网页授权; - 授权码换授权信息:
$app->getAuthorization($authCode)返回的Authorization对象可依次取得getAppId()、getAccessToken()(AuthorizerAccessToken实例)、getRefreshToken(),并支持toArray()/toJson()序列化,便于落库(对应实现见 src/OpenPlatform/Authorization.php)。
附:如何验证与继续深入
仓库中 tests/OpenPlatform/ApplicationTest.php 提供了上述能力的单元测试佐证:test_get_authorization验证了换取授权信息时 POST 到cgi-bin/component/api_query_auth且请求体包含component_appid与authorization_code;test_refresh_authorizer_token验证了刷新令牌接口cgi-bin/component/api_authorizer_token的请求参数拼装;test_get_official_account/test_get_mini_app验证了代调用返回的实例类型。接入时若遇到验签失败、消息解密异常或 token 类问题,可对照这些测试与上述源码路径定位。想要继续完善本文示例,欢迎按 贡献指南 向 EasyWeChat 文档仓库补充更多框架的接入用例。
- 后端
- 即时通讯
【免费下载链接】easywechat
📦 一个 PHP 微信 SDK
相关推荐
EasyWeChat 开放平台第三方平台:代授权方(公众号/小程序)实现业务完整指南
EasyWeChat 开放平台第三方平台:代授权方(公众号/小程序)实现业务完整指南 授权方(公众号、小程序)把自己的账号授权给你的开放平台第三方平台之后,你就
后端即时通讯EasyWeChat 开放平台第三方平台代授权方开发指南:一行代码获取公众号/小程序实例并代其执行业务
EasyWeChat 开放平台第三方平台代授权方开发指南:一行代码获取公众号/小程序实例并代其执行业务 本篇指南聚焦 EasyWeChat 开放平台第三方平台的
后端即时通讯EasyWeChat 微信开放平台(第三方平台)开发指南:事件推送监听、授权管理与 API 调用实战
EasyWeChat 微信开放平台(第三方平台)开发指南:事件推送监听、授权管理与 API 调用实战 本指南围绕 EasyWeChat 官方文档中的「微信开放平
后端即时通讯
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考