☰
EasyWeChat 6.x 微信公众号模块实战指南:Application 工厂、配置、AccessToken 与消息服务端
2026/9/25 17:40:24 网站建设 项目流程
  • 后端
  • 即时通讯

【免费下载链接】easywechat

📦 一个 PHP 微信 SDK

项目地址:https://gitcode.com/gh_mirrors/ea/easywechat
点击查看免费下载

本文基于 EasyWeChat 6.x 官方文档 公众号模块索引 编写。公众号(Official Account)模块是 EasyWeChat 中最常用的模块之一,用于对接微信公众号的消息推送、服务端验证、网页授权、素材与客服消息等能力。读完本文,你将掌握:如何初始化Application工厂并配置核心参数、如何通过getServer()/getClient()/getAccessToken()等入口调用各子模块、如何理解服务端验证与消息加解密的签名校验逻辑,以及如何结合仓库源码(Application.php、AccessToken.php、Server.php)排查配置问题。

使用前建议先熟读微信官方《公众号》文档(Overview 章节),本文所有配置项与接口行为均以当前仓库 6.x 源码为准。

一、最小可用的初始化配置

公众号模块的常用配置参数其实很少——除非你有特别的定制需求(例如自定义 OAuth 回调、自定义 HTTP 重试策略、使用 Stable Access Token),否则大部分参数使用默认值即可。以下是最小可用配置:

use EasyWeChat\OfficialAccount\Application; $config = [ 'app_id' => 'wx3cf0f39249eb0exx', 'secret' => 'f1c242f4f28f735d4687abb469072axx', 'token' => 'easywechat', 'aes_key' => '', // 明文模式请勿填写 EncodingAESKey /** * OAuth 配置 * * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login * redirect_url:OAuth授权完成后的回调页地址 */ 'oauth' => [ 'scopes' => ['snsapi_userinfo'], 'redirect_url' => '/examples/oauth_callback.php', ], /** * 接口请求相关配置,超时时间等 */ 'http' => [ 'timeout' => 5.0, // 'base_uri' => 'https://api.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用 'retry' => true, // 使用默认重试配置 // 'retry' => [ // // 仅以下状态码重试 // 'status_codes' => [429, 500], // // 最大重试次数 // 'max_retries' => 3, // // 请求间隔 (毫秒) // 'delay' => 1000, // // 如果设置,每次重试的等待时间都会增加这个系数 // // (例如. 首次:1000ms; 第二次: 3 * 1000ms; etc.) // 'multiplier' => 3 // ], ], ]; $app = new Application($config);
  • app_id:公众号 AppID,必填。Config类将app_id声明为唯一必填键(见 src/OfficialAccount/Config.php 的requiredKeys),缺失会直接报错。
  • secret:AppSecret,用于换取access_token。
  • token:服务端消息推送的签名校验依赖它,必须填写。
  • aes_key:EncodingAESKey。明文模式请留空;兼容模式与安全模式下一定要填写。
  • oauth:网页授权配置,scopes可选snsapi_userinfo/snsapi_base(公众平台)或snsapi_login(开放平台)。
  • http:HTTP 请求配置,支持timeout、base_uri、retry等。

完整配置样例(含require_encryption、use_stable_access_token等进阶项)见 配置文档。文档明确建议"用到啥就配置啥",大部分默认值即可。

二、Application:统一工厂与子模块入口

Application是一个工厂类,所有子模块都从$app访问,并且几乎每个模块都提供了 getter 和 setter 可自定义替换。它的完整接口定义在 src/OfficialAccount/Contracts/Application.php,实现位于 src/OfficialAccount/Application.php。

1. 服务端:$app->getServer()

服务端模块封装了消息推送接收、服务端验证(echostr校验)与消息加解密,基于中间件模式处理推送:

$server = $app->getServer();

从源码看(Application.php),getServer()会基于当前请求、Encryptor、token 与require_encryption配置惰性创建Server实例;只有配置了aes_key时才会注入加密器。

$response = $server->serve();

serve()内部依次处理echostr验证、请求签名校验、密文解密与中间件链,最终返回一个Psr\Http\Message\ResponseInterface实例。关于中间件注册、消息监听与完整示例,详见 服务端使用文档。

2. API Client:$app->getClient()

封装了多种模式的 API 调用类,默认自动处理access_token注入、过期自动刷新等逻辑:

$client = $app->getClient();

从源码看(Application.php),createClient()会:

  • 先基于http配置构建底层 HttpClient,默认base_uri为https://api.weixin.qq.com/;
  • 若http.retry为 true,则包装为RetryableHttpClient并绑定AccessTokenExpiredRetryStrategy;
  • 再包装为AccessTokenAwareClient,并将errcode != 0视为失败判定,实现 access_token 过期(错误码 42001)时的自动刷新重试。

更完整的用法(GET/POST、上传、下载、异步请求等)见 API 调用文档。

3. 配置:$app->getConfig()

$config = $app->getConfig();

你可以用$config->get($key, $default)读取配置,或在调用前用$config->set($key, $value)修改配置项。例如运行时临时改 OAuth 回调地址:

$app->getConfig()->set('oauth.redirect_url', '/my-callback.php');

4. AccessToken:$app->getAccessToken()

access_token是调用公众号 API 的必备凭证。手动获取:

$accessToken = $app->getAccessToken(); $accessToken->getToken(); // string

也可以注入自定义 AccessToken 类:

$accessToken = new MyCustomAccessToken(); $app->setAccessToken($accessToken);

5. 网页授权:$app->getOAuth()

$oauth = $app->getOAuth();

getOAuth()基于oauth.scopes与oauth.redirect_url配置创建 Overtrue Socialite 的 WeChat Provider(Application.php)。详情参考 网页授权文档。

6. 公众号账户:$app->getAccount()

公众号账户类提供一系列 getter 获取基本信息:

$account = $app->getAccount(); $account->getAppId(); $account->getSecret(); $account->getToken(); $account->getAesKey();

对应实现见 src/OfficialAccount/Account.php:getSecret()在未配置时会抛出RuntimeException;getToken()/getAesKey()允许为 null(明文模式)。

7. 其他内置模块

  • $app->getEncryptor():消息加解密器,基于token+aes_key构建(Application.php)。
  • $app->getTicket():JsApiTicket,用于 JSSDK 签名。
  • $app->getUtils():工具类,例如buildJsSdkConfig()一键生成 JSSDK 配置(Utils.php)。
  • $app->getCache()/$app->getHttpClient():缓存与底层 HTTP 客户端,默认分别为 Symfony FilesystemAdapter 与 HttpClient::create。

上述 getter/setter 的行为均有对应的单元测试验证,见 tests/OfficialAccount/ApplicationTest.php(test_get_and_set_account、test_get_and_set_server、test_get_and_set_access_token、test_get_and_set_ticket等)。

三、进阶配置项深入解析

以下配置项来自 配置文档,默认值已标注。

配置项默认值说明
app_id无(必填)AppID,缺失时 Config 直接抛错
secret无AppSecret
token无消息推送签名校验 Token,必填
aes_key空字符串EncodingAESKey,兼容/安全模式必填
require_encryptionfalse设为 true 时,服务端拒绝一切明文推送
use_stable_access_tokenfalse是否使用 Stable Access Token 接口
oauth.scopes['snsapi_userinfo']授权范围
oauth.redirect_url无OAuth 回调地址
http.timeout5.0请求超时(秒)
http.base_urihttps://api.weixin.qq.com/接口基地址,海外部署时可覆盖
http.retryfalse是否启用重试;可为布尔值或数组
http.max_retries2重试次数上限
http.throwtrue请求失败是否抛异常

1.require_encryption:只接受加密推送

公众号后台设为「安全模式」时,建议将require_encryption设为true。开启后,服务端将拒绝一切明文推送的消息(即使其 signature 校验通过),从而在 token 泄露时也能防止攻击者伪造明文消息。实现见 Server.php:加密请求走decryptRequestMessage()解密,非加密请求若requireEncryption为 true 则抛出BadRequestException。

2.use_stable_access_token:使用 Stable Access Token

默认false。设为true后,AccessToken::refresh()会调用getStableAccessToken(),请求https://api.weixin.qq.com/cgi-bin/stable_token接口(AccessToken.php);否则走传统cgi-bin/token接口(AccessToken.php)。Stable Access Token 适用于需要更稳定凭证、希望减少主动刷新次数的场景。

3.http.retry:重试策略

retry支持布尔值或数组两种形态:

  • true:使用默认重试配置;
  • 数组:可精确控制status_codes(仅对哪些状态码重试,如[429, 500])、max_retries(最大重试次数)、delay(请求间隔,毫秒)、multiplier(指数退避系数,每次重试等待时间乘以该系数)。

重试策略由getRetryStrategy()构建(Application.php),并额外判断响应内容中是否出现错误码42001+access_token expired——即 access_token 过期时也会触发自动刷新并重试,这是 SDK 处理 token 失效的底层机制。

四、服务端:验证、加解密与中间件(核心实操)

服务端是公众号模块最核心的入口。完整参考 服务端使用文档,以下提炼关键点。

1. 服务端验证

SDK 内置了echostr验证逻辑,你不需要关心如何拼签名、返回echostr:

$server = $app->getServer(); return $server->serve();

serve()会校验请求的signature(token、timestamp、nonce三者排序后 sha1),校验通过则原样返回echostr。

$response是Psr\Http\Message\ResponseInterface实现,请自行适配你的框架。若使用 ThinkPHP、Workerman 等框架,需先把框架请求转换成 Symfony 请求,再通过$app->setRequestFromSymfonyRequest($symfonyRequest)替换 request 对象,然后再调用getServer()。

2. 消息校验与加解密(6.20.0+)

serve()与getDecryptedMessage()会强制校验每一个请求的签名,校验不通过时抛出EasyWeChat\Kernel\Exceptions\BadRequestException:

推送形态校验方式
带密文(encrypt_type=aes或消息体含Encrypt节点)且配置了aes_key校验msg_signature并解密,缺失或不匹配即拒绝
纯明文校验signature(token、timestamp、nonce 三者排序后 sha1)
纯明文,且配置了require_encryption => true直接拒绝

因此token必须正确配置,否则抛出InvalidConfigException。手动实例化Server而非通过$app->getServer()时,请记得显式传入 token:

use EasyWeChat\OfficialAccount\Server; $server = new Server( request: $request, encryptor: $encryptor, // 明文模式下可为 null token: 'your-token', requireEncryption: false, );

如果公众号后台设置为「安全模式」,强烈建议同时配置'require_encryption' => true,这样即使 token 泄露,攻击者也无法通过明文推送伪造消息。

加密请求的识别逻辑见 Server.php:当 query 中encrypt_type === 'aes'或消息体含Encrypt/encrypt节点时判定为密文请求,进而校验msg_signature并解密。

3. 自助处理推送消息

不要在返回$server->serve()前输出任何内容。获取原始推送消息:

$message = $server->getRequestMessage(); // 原始消息

获取解密后的消息(6.5.0+):

$message = $server->getDecryptedMessage();

$message为EasyWeChat\OfficialAccount\Message实例(定义见 src/OfficialAccount/Message.php,提供MsgType、Event等属性)。

4. 中间件模式

服务端使用中间件链依次调用开发者注册的中间件,处理完逻辑后可以回复消息或交给下一个中间件:

$server->with(function($message, \Closure $next) { // 你的自定义逻辑 return $next($message); }); $response = $server->serve();

可链式注册多个中间件:

$server ->with(function($message, \Closure $next) { // 你的自定义逻辑1 return $next($message); }) ->with(function($message, \Closure $next) { // 你的自定义逻辑2 return $next($message); }) ->with(function($message, \Closure $next) { // 你的自定义逻辑3 return $next($message); }); $response = $server->serve();

回复消息:当中间件不回复消息时,调用$next($message)传递给下一个中间件;若需返回消息给用户,直接返回字符串或数组即可:

function($message, \Closure $next) { return '感谢你使用 EasyWeChat'; }

注意:回复消息后,后续未执行的中间件将不再执行,所以请将全局都需要执行的中间件优先提前注册。

回复图片等多媒体消息:参考微信官方「被动回复消息」的 XML 结构,以数组形式返回,需省略ToUserName、FromUserName、CreateTime:

function($message, \Closure $next) { return [ 'MsgType' => 'image', 'Image' => [ 'MediaId' => 'media_id', ], ]; }

多条消息:服务端只能被动回复一条消息,若需发送多条,请调用微信客服消息接口(对应 JSON 结构见下文"消息结构"一节)。

使用独立中间件类:中间件支持可调用对象与类名:

class MyCustomHandler { public function __invoke($message, \Closure $next) { if ($message->MsgType === 'text') { //... } return $next($message); } } $server->with(MyCustomHandler::class); // 或者 $server->with(new MyCustomHandler());

使用 callable 类型中间件:支持函数名、[$class, $method]、'ClassName::method'等 callable 形式:

$server->with([$object, 'method']); $server->with('ClassName::method');

5. 便捷监听:按消息类型 / 事件类型注册

addMessageListener:匹配MsgType字段,例如文本消息:

$server->addMessageListener('text', function() { ... });

addEventListener:匹配Event字段,例如关注事件:

$server->addEventListener('subscribe', function() { ... });

对应实现见 Server.php,它们本质上是帮你包了一层按字段匹配的中间件。

6. 完整示例

use EasyWeChat\OfficialAccount\Application; $config = [...]; $app = new Application($config); $server = $app->getServer(); $server->addEventListener('subscribe', function($message, \Closure $next) { return '感谢您关注 EasyWeChat!'; }); $response = $server->serve(); return $response;

五、消息结构速查:服务端 XML vs 客服消息 JSON

公众号消息分为服务端被动回复消息(XML)与客服消息(JSON)两个场景,结构类似但命名有差异,使用时请勿混淆(详见 消息文档)。

1. 服务端请求消息(XML)基本属性

所有消息均包含:

- `ToUserName` 接收方帐号(该公众号 ID) - `FromUserName` 发送方帐号(OpenID,代表用户的唯一标识) - `CreateTime` 消息创建时间(时间戳) - `MsgId` 消息 ID(64位整型)

按MsgType细分:

  • 文本:Content(文本消息内容)
  • 图片:MediaId(媒体id)、PicUrl(图片链接)
  • 语音:MediaId、Format(如 amr、speex)、Recognition(开通语音识别后才有)
  • 视频:MediaId、ThumbMediaId(缩略图媒体id)
  • 小视频:MsgType = shortvideo、MediaId、ThumbMediaId
  • 事件:MsgType = event、Event(如 subscribe、unsubscribe、CLICK 等)
    • 扫描带参数二维码:EventKey(如qrscene_123123)、Ticket
    • 上报地理位置:Latitude、Longitude、Precision
    • 自定义菜单:EventKey(对应菜单 KEY 值或 URL)
  • 地理位置:Location_X、Location_Y、Scale、Label
  • 链接:Title、Description、Url
  • 文件:Title、Description、FileKey、FileMd5、FileTotalLen(字节)

2. 客服消息(JSON)结构

客服消息通过 API 主动发送给用户,常用的几种:

// 文本 { "touser": "OPENID", "msgtype": "text", "text": { "content": "Hello World" } } // 图片 { "touser": "OPENID", "msgtype": "image", "image": { "media_id": "MEDIA_ID" } } // 语音 { "touser": "OPENID", "msgtype": "voice", "voice": { "media_id": "MEDIA_ID" } } // 视频 { "touser": "OPENID", "msgtype": "video", "video": { "media_id": "MEDIA_ID", "thumb_media_id": "MEDIA_ID", "title": "TITLE", "description": "DESCRIPTION" } } // 音乐 { "touser": "OPENID", "msgtype": "music", "music": { "title": "MUSIC_TITLE", "description": "MUSIC_DESCRIPTION", "musicurl": "MUSIC_URL", "hqmusicurl": "HQ_MUSIC_URL", "thumb_media_id": "THUMB_MEDIA_ID" } } // 图文(跳转外链) { "touser": "OPENID", "msgtype": "news", "news": { "articles": [ { "title": "Happy Day", "description": "Is Really A Happy Day", "url": "URL", "picurl": "PIC_URL" } ]} } // 图文(跳转图文消息页面) { "touser": "OPENID", "msgtype": "mpnews", "mpnews": { "media_id": "MEDIA_ID" } } // 菜单消息 { "touser": "OPENID", "msgtype": "msgmenu", "msgmenu": { "head_content": "您对本次服务是否满意呢? ", "list": [ { "id": "101", "content": "满意" }, { "id": "102", "content": "不满意" } ], "tail_content": "欢迎再次光临" } } // 卡券消息 { "touser": "OPENID", "msgtype": "wxcard", "wxcard": { "card_id": "123dsdajkasd231jhksad" } }

客服消息的具体发送方式(通过getClient()调用message/custom/send接口)请结合 API 调用文档 使用;消息结构以微信官方文档为准。

六、源码级验证:这些行为如何被测试保障

当前仓库对上述模块行为提供了完整的单元测试,可作为配置与调用的"活文档":

  • tests/OfficialAccount/ApplicationTest.php:验证getAccount()/getServer()/getAccessToken()/getTicket()等 getter 的惰性创建与 setter 替换行为,并验证无http配置时getClient()不会抛异常(对应 issue #2743 回归测试)。
  • tests/OfficialAccount/ServerTest.php:验证服务端验证、消息解密与中间件链路。
  • tests/OfficialAccount/AccessTokenTest.php:验证 access_token 的缓存读写与刷新逻辑。
  • tests/OfficialAccount/ConfigTest.php:验证app_id必填等配置约束。

七、常见问题排查建议

  • "The token is required to validate the request signature":token未配置。确保config['token']已填写,且与公众号后台「服务器配置」中的 Token 一致。
  • 服务端验证返回 401/校验失败:检查签名校验所需的token、timestamp、nonce是否来自微信推送原样传递;若框架改写了 query 参数,请先通过setRequestFromSymfonyRequest()注入原始请求。
  • 安全模式下收到明文推送被拒:这是require_encryption => true的预期行为;请确认公众号后台已切换为「安全模式」并正确配置aes_key。
  • access_token 获取失败:检查app_id/secret是否正确;启用use_stable_access_token => true时需确认接口权限。
  • 海外部署请求超时:可通过http.base_uri覆盖默认的https://api.weixin.qq.com/,并结合http.timeout、http.retry调整网络策略。

更多框架集成(Laravel、Symfony 等)与缓存、自定义替换服务的说明,请参考 安装文档、缓存配置 与 替换服务文档。

  • 后端
  • 即时通讯

【免费下载链接】easywechat

📦 一个 PHP 微信 SDK

项目地址:https://gitcode.com/gh_mirrors/ea/easywechat
点击查看免费下载

相关推荐

上一篇:Renovate helm-requirements 管理器全指南:自动更新 Helm v2 requirements.yaml 中的 Chart 依赖
下一篇:Megatron-LM 首次训练实战指南:从最小分布式循环到 LLaMA-3 FP8 训练与数据预处理

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询