这里的“模板”不是指 PHP 的模板引擎(如 Smarty、Twig),而是指微信官方提供的一种标准化的消息格式,用于向用户发送重要的、通知类的内容。

什么是微信模板消息?
微信模板消息是微信公众平台提供给开发者的一种消息推送能力,它允许开发者按照固定的模板格式,向关注公众号的用户发送服务通知。
核心特点:
- 格式固定由微信预先定义好的模板决定,开发者只能填充模板中的变量(如
{name},{amount}),而不能随意修改整体结构和样式。 - 用户授权:用户必须在与公众号的交互中(点击菜单、提交表单等)同意接收服务通知,才能被发送模板消息。
- 触发式:通常用于通知用户某个事件的结果,
- 订单支付成功
- 快递发货通知
- 预约成功提醒
- 账户余额变动
- 非营销性:微信严格禁止使用模板消息进行营销推广,如发送广告、优惠券等。
PHP 开发模板消息的完整流程
使用 PHP 发送模板消息主要分为以下几个步骤:
步骤 1:获取模板 ID
- 登录 微信公众平台。
- 进入
设置与开发->模板消息。 - 在模板库中,根据你的业务场景(如“服务提醒”、“物流通知”等)选择合适的模板。
- 点击“添加”,将模板添加到你的账号中,添加成功后,你会得到一个唯一的 模板 ID(
OPENTM2005151234567890),这个 ID 在后续的 API 调试和代码中至关重要。
步骤 2:获取用户的 OpenID
模板消息是精准推送给某个用户的,所以你必须知道这个用户的 OpenID,OpenID 是用户在当前公众号下的唯一标识符。

- 如何获取 OpenID?
- 用户关注公众号时,可以通过
关注事件推送获取。 - 用户在网页授权后,可以获取到
openid(详见微信网页授权文档)。 - 用户在公众号内进行交互时,可以通过事件推送或客服消息获取。
- 用户关注公众号时,可以通过
重要提示:在发送模板消息前,必须确保用户已经同意接收,通常的做法是在需要发送通知的场景(如下单成功后),让用户点击一个“同意接收服务通知”的按钮,此时后台记录下用户的 openid 和授权状态。
步骤 3:后端 PHP 代码实现
这是核心部分,我们使用 PHP 的 cURL 函数来调用微信的 API。
准备工作:获取 Access Token
调用任何微信 API 都需要一个有效的 access_token,它是一个全局唯一的票据,有效期 2 小时。

-
获取方式:通过 GET 请求以下地址:
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=YOUR_APPID&secret=YOUR_APPSECRET -
PHP 封装获取 Token 的函数:
<?php
// 你的公众号配置
define('APPID', '你的AppID');
define('APPSECRET', '你的AppSecret');
/**
* 获取 access_token
* @return string|false 成功返回token,失败返回false
*/
function getAccessToken() {
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . APPID . "&secret=" . APPSECRET;
// 使用 cURL 请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过SSL证书验证
$output = curl_exec($ch);
curl_close($ch);
$json = json_decode($output, true);
if (isset($json['access_token'])) {
return $json['access_token'];
} else {
// 可以在这里记录错误日志
error_log("获取AccessToken失败: " . $output);
return false;
}
}
?>
发送模板消息的核心函数
现在我们编写一个函数来发送模板消息。
<?php
// ... (包含上面的 getAccessToken 函数) ...
/**
* 发送模板消息
* @param string $openid 用户的openid
* @param string $templateId 模板ID
* @param array $data 模板数据,格式为 ['key' => 'value']
* @param string $url 点击模板消息后跳转的URL (可选)
* @param string $topcolor 顶部颜色 (可选)
* @return array|false 返回微信API的响应结果,失败返回false
*/
function sendTemplateMessage($openid, $templateId, $data, $url = '', $topcolor = '#FF0000') {
$accessToken = getAccessToken();
if (!$accessToken) {
return false;
}
$apiUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $accessToken;
// 构建请求体
$requestBody = [
'touser' => $openid,
'template_id' => $templateId,
'url' => $url, // 点击后跳转的链接
'topcolor' => $topcolor,
'data' => $data
];
// 将数组转换为JSON字符串
$jsonBody = json_encode($requestBody, JSON_UNESCAPED_UNICODE); // JSON_UNESCAPED_UNICODE保证中文正常显示
// 使用 cURL 发送POST请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonBody);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($jsonBody)
]);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 解析响应
$response = json_decode($output, true);
// 检查HTTP状态码和微信返回的errcode
if ($httpCode == 200 && isset($response['errcode']) && $response['errcode'] == 0) {
return $response;
} else {
// 记录详细错误信息
error_log("发送模板消息失败: HTTP_CODE={$httpCode}, RESPONSE={$output}");
return false;
}
}
?>
步骤 4:调用发送函数
假设你的订单处理逻辑如下,你可以在订单创建成功后调用发送函数。
<?php
// ... (包含上面的所有函数) ...
// --- 模拟业务场景 ---
$userId = 'o6_bmjrPTlm6_2sgVt7hMZopifF0'; // 用户的openid
$orderNo = '20251027123456';
$totalAmount = 99.50;
$templateId = 'OPENTM2005151234567890'; // 你自己的模板ID
// 1. 根据你的模板,定义要填充的数据
// 假设你的模板字段是:{{first}} (订单号)、{{keyword1}} (金额)、{{keyword2}} (状态)、{{remark}} (备注)
$templateData = [
'first' => ['value' => '您的订单已支付成功', 'color' => '#173177'],
'keyword1' => ['value' => $orderNo, 'color' => '#173177'],
'keyword2' => ['value' => '¥' . $totalAmount, 'color' => '#173177'],
'remark' => ['value' => '感谢您的惠顾,商品将尽快为您发出。', 'color' => '#173177']
];
// 2. 定义点击消息后跳转的URL
$jumpUrl = 'https://www.yourwebsite.com/order/detail?no=' . $orderNo;
// 3. 调用发送函数
$result = sendTemplateMessage($userId, $templateId, $templateData, $jumpUrl);
// 4. 处理结果
if ($result) {
echo "模板消息发送成功!";
// 可以在这里更新订单状态,记录发送日志等
} else {
echo "模板消息发送失败!";
}
?>
模板数据格式详解
在调用 sendTemplateMessage 函数时,$data 参数的格式是固定的。
格式:
{
"data": {
"字段名": {
"value": "显示的文本内容",
"color": "文本颜色 (可选,如 #FF0000)"
},
"字段名": {
"value": "显示的文本内容",
"color": "文本颜色"
}
}
}
如何确定“字段名”?
这个“字段名”不是你在模板库中看到的中文名称(如“订单金额”),而是微信后台模板中定义的 key。
- 在微信公众平台,找到你添加的模板。
- 点击模板右侧的“详情”。
- 你会看到模板的结构,每个可编辑的字段都有一个
key,通常是keyword1,keyword2,first,remark等。
first 和 remark 是特殊字段:
first:模板消息的开头部分。remark:模板消息的底部备注部分。
颜色格式:
必须是十六进制颜色代码,如 #FF0000(红色)、#173177(深蓝色)。
常见错误排查
发送模板消息失败时,微信 API 会返回一个 JSON 对象,包含 errcode 和 errmsg。
常见错误码及解决方案:
| 错误码 | 错误信息 | 原因及解决方案 |
|---|---|---|
| 40003 | invalid openid | touser 字段的 OpenID 不正确或为空,请检查 OpenID 是否有效。 |
| 40037 | invalid template id | template_id 不正确或模板已被公众号删除,请检查模板 ID。 |
| 43101 | user refuse to receive the message | 用户拒绝接收,这是最常见的问题,用户之前没有授权,或在设置中关闭了接收权限,需要引导用户重新授权。 |
| 47003 | template message data incomplete | data 字段缺少必要的 key,或者 value 为空,请严格按照你模板的 key 来构建数据数组。 |
| 41030 | invalid pagepath | url 字段中的页面路径不正确,请确保跳转链接是合法的 URL。 |
| 45009 | api frequency limit exceeded | API 调用频率超限,模板消息的发送有频率限制,通常是每个用户每月最多发送 4 条(具体以官方文档为准),请勿频繁发送。 |
| 0 | ok | 发送成功。 |
调试技巧:
- 打印日志:在
sendTemplateMessage函数中,打印出$jsonBody(发送给微信的数据)和$output(微信的响应),可以快速定位是数据格式问题还是 API 问题。 - 使用在线工具:可以使用 Postman 等工具,手动构造 JSON 请求体并发送到微信 API,来验证你的数据和逻辑是否正确。
重要注意事项
-
模板消息的替代方案:微信官方已经逐步弱化模板消息,并推出了更强大的 “统一服务消息” 和 “订阅消息”。
- 订阅消息:是目前推荐的替代方案,它允许用户主动订阅,开发者可以在用户授权后,在特定场景下(如订单状态变更)向用户推送一次性的通知,权限更灵活,用户体验更好。
- 如果是新项目,强烈建议优先研究和使用 订阅消息。
-
测试环境:在公众号设置中,可以配置一个测试微信号(微信号或 OpenID),在开发阶段,将模板消息发送给这个测试号,可以避免对真实用户造成打扰,并且不会受到每月发送次数的限制。
-
内容合规:发送的内容必须符合微信平台规范,不能包含敏感词汇或违法信息。
希望这份详细的指南能帮助你完全理解和使用 PHP 在微信公众平台开发中发送模板消息!
