ThinkPHP做微信公众号消息推送需稳住验签、消息接收、access_token三关键点:验签须字典序排序token/timestamp/nonce后SHA1;收消息须读php://input并禁用XML实体加载;模板消息需正确缓存access_token、规范data结构及校验域名与模板ID。

ThinkPHP 做微信公众号消息推送,核心不是写多少代码,而是踩准三个关键点:验签不翻车、消息能收全、access_token 不乱刷。只要这三处稳住,模板消息、客服消息、事件响应都能跑通。
验签失败?字典序+拼接+SHA1 必须严丝合缝
微信 GET 请求验证时传来的 signature,是用 token、timestamp、nonce 三个字符串按字典序排序后拼成一串,再 SHA1 得到的。常见错误有:
- 用
asort()或ksort()排序——必须用sort($arr, SORT_STRING),否则键名干扰顺序 - 数组里混入
echostr或空格/BOM/换行——只保留且仅限这三个值 - 用
hash('sha1', $str)却没加true参数——等效写法只有sha1($str) - 没并列打印比对:
var_dump($_GET['signature'], sha1(implode('', $arr))),光靠猜很难定位
收不到 POST 消息?别碰 $_POST,改读 php://input
微信所有用户行为(关注、点击菜单、发消息)都以原始 XML 形式 POST 过来,Content-Type 不是 application/x-www-form-urlencoded,所以 $_POST 一定为空——这不是 bug,是设计如此。
微信公众号推文写作与发布助手。支持深度文章撰写(1500+ 字)、智能配图搜索、API 配置引导、草稿箱上传、一键排版等全流程功能。 每篇文章默认 1500 字以上,配备 1 张相关配图(放在第一段后),包含清晰的分段标题结构。
- 唯一正确方式:
$raw = file_get_contents('php://input'); - 解析前务必关闭实体加载:
libxml_disable_entity_loader(true);,防 XXE 漏洞 - 字段名严格区分大小写:
FromUserName、MsgType、Event都是大驼峰 - 回复 XML 时,
Content-Type必须设为text/xml; charset=utf-8(注意分号和 utf-8 的连字符)
模板消息发送失败?重点查 access_token 和 data 结构
模板消息接口依赖全局 access_token,且对 JSON 字段格式极其敏感。高频问题集中在:
立即学习“PHP免费学习笔记(深入)”;
-
access_token 缓存失效:不能存在 session、文件未加锁、或每次请求都重拉。推荐 Redis:
$redis->setex('wx_access_token', 7200, $token) -
data 字段嵌套错误:每个 keyword 必须是
['value' => 'xxx', 'color' => '#xxx']形式,不能直接写字符串 - url 跳转限制:必须是已配置在公众号后台的业务域名下的 HTTPS 页面,且不能带参数 hash(#)
- 模板 ID 不匹配:确保用的是“我的模板库”里的真实 ID,不是模板标题或申请编号
客服消息能发但没反应?确认触发窗口和 media_id 合法性
客服消息只在用户 48 小时内主动交互(如支付、扫码、点击菜单)后有效。发图片/二维码等需额外处理:
- 图片必须先调用
/cgi-bin/media/upload上传为临时素材,拿到media_id才能发 - 上传时用
curl -F media=@qrcode.png "https://...&type=image",路径必须是服务器本地可读文件 - 客服消息 URL 中的
access_token和模板消息不同,不可混用 - 若发图文,
news类型需提前上传永久素材,临时图文不支持


















