如何使用PHP实现公众号的群发消息功能
《如何使用PHP实现公众号的群发消息功能》
在微信公众号开发中,群发消息功能是运营者与用户互动的重要手段。通过PHP实现该功能,可以自动化推送图文、文本、视频等内容,提升运营效率。本文将详细介绍从基础环境搭建到完整功能实现的完整流程,涵盖微信官方API调用、消息类型处理、错误排查等关键环节。
一、开发前准备
1.1 微信公众号类型选择
微信公众平台提供订阅号和服务号两种类型,群发消息功能存在差异:
订阅号:每日可群发1条消息(图文/文本/视频等)
服务号:每月可群发4条消息,但支持更高级的接口权限
开发前需确认账号类型,服务号更适合需要高频推送的场景。
1.2 服务器配置要求
PHP环境需满足以下条件:
{
"PHP版本": ">=7.0",
"扩展要求": [
"openssl",
"curl",
"json"
],
"服务器类型": "支持HTTPS的公网服务器"
}
建议使用Linux+Nginx+PHP-FPM架构,Windows服务器可能存在定时任务执行不稳定的问题。
1.3 微信开发者资质认证
获取API权限需完成:
公众号认证(300元/年)
开发者ID(AppID)和密钥(AppSecret)获取
服务器配置验证(需实现URL验证接口)
二、核心实现步骤
2.1 获取Access Token
所有微信API调用都需要有效的Access Token,其获取流程如下:
/**
* 获取微信Access Token
* @param string $appId 开发者ID
* @param string $appSecret 开发者密钥
* @return string|false 返回token或false
*/
function getWechatAccessToken($appId, $appSecret) {
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if (isset($data['access_token'])) {
// 建议将token存入缓存(Redis/Memcached),有效期7200秒
return $data['access_token'];
} else {
// 记录错误日志
error_log("获取AccessToken失败: ".json_encode($data));
return false;
}
}
注意事项:
Token有效期为2小时,需实现自动刷新机制
同一AppID的Token获取频率限制为200次/天
2.2 群发消息接口调用
微信提供两种群发方式:
2.2.1 根据分组群发
/**
* 按分组群发文本消息
* @param string $accessToken 接口凭证
* @param int $groupId 分组ID(0表示所有用户)
* @param string $content 消息内容
* @return array 接口返回结果
*/
function sendGroupMessage($accessToken, $groupId, $content) {
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token={$accessToken}";
$data = [
"filter" => [
"is_to_all" => ($groupId == 0),
"group_id" => ($groupId != 0 ? $groupId : "")
],
"text" => [
"content" => $content
],
"msgtype" => "text"
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
2.2.2 根据OpenID列表群发
/**
* 按OpenID列表群发图文消息
* @param string $accessToken 接口凭证
* @param array $openIds 用户OpenID数组(最多10000个)
* @param string $mediaId 图文媒体ID
* @return array 接口返回结果
*/
function sendOpenIdMessage($accessToken, $openIds, $mediaId) {
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token={$accessToken}";
$data = [
"touser" => $openIds,
"mpnews" => [
"media_id" => $mediaId
],
"msgtype" => "mpnews",
"send_ignore_reprint" => 0 // 是否过滤已发送用户
];
// 实际开发中需处理大数组的分批发送
$chunks = array_chunk($openIds, 100); // 微信限制每次最多100个OpenID
$results = [];
foreach ($chunks as $chunk) {
$data['touser'] = $chunk;
$ch = curl_init();
// ...(同上配置curl)
$response = curl_exec($ch);
$results[] = json_decode($response, true);
curl_close($ch);
}
return $results;
}
三、高级功能实现
3.1 图文消息素材管理
群发图文前需先上传永久素材:
/**
* 上传永久图文素材
* @param string $accessToken 接口凭证
* @param array $articles 图文数组(包含title/author/digest等)
* @return string|false 返回media_id或false
*/
function uploadNewsMaterial($accessToken, $articles) {
$url = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token={$accessToken}";
$data = [
"articles" => $articles
];
$ch = curl_init();
// ...(同上配置curl)
$response = curl_exec($ch);
$result = json_decode($response, true);
if (isset($result['media_id'])) {
return $result['media_id'];
}
return false;
}
3.2 定时群发实现
通过Linux crontab实现每日定时推送:
# 编辑crontab
crontab -e
# 添加以下内容(每天上午10点执行)
0 10 * * * /usr/bin/php /path/to/send_daily_news.php >> /var/log/wechat_send.log
脚本示例(send_daily_news.php):
"每日资讯",
"thumb_media_id" => "媒体ID",
"author" => "编辑部",
"digest" => "今日精选内容摘要...",
"content" => "完整HTML内容",
"content_source_url" => "原文链接"
]
];
$mediaId = uploadNewsMaterial($token, $dailyNews);
if (!$mediaId) {
exit('上传素材失败');
}
$result = sendGroupMessage($token, $groupId, $mediaId, 'mpnews');
if ($result['errcode'] != 0) {
error_log("群发失败: ".json_encode($result));
exit('群发失败');
}
echo "群发成功,消息ID: ".$result['msg_id'];
?>
四、常见问题解决方案
4.1 45015错误(请求次数超限)
原因:
同一Access Token调用频率过高
未实现Token缓存导致重复获取
解决方案:
// 使用Redis缓存Token示例
function getCachedAccessToken($appId, $appSecret) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cacheKey = "wechat_token_{$appId}";
$tokenData = $redis->get($cacheKey);
if ($tokenData) {
$tokenData = json_decode($tokenData, true);
// 检查是否过期(预留600秒缓冲)
if ($tokenData['expire_time'] > time() + 600) {
return $tokenData['token'];
}
}
$newToken = getWechatAccessToken($appId, $appSecret);
if ($newToken) {
$redis->setEx($cacheKey, 7000, json_encode([
'token' => $newToken,
'expire_time' => time() + 7200
]));
return $newToken;
}
return false;
}
4.2 40001错误(Access Token失效)
处理流程:
清除本地缓存的Token
重新获取新Token
重试失败的操作
4.3 群发消息未送达
排查步骤:
检查用户是否在48小时内有过互动(微信限制)
确认消息类型是否符合要求(视频消息需先上传素材)
通过
https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token=XXX
查询发送状态
五、性能优化建议
5.1 异步处理机制
对于大规模群发(>10万用户),建议使用队列处理:
// 使用Redis队列示例
function addToSendQueue($openIds, $mediaId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
foreach ($openIds as $openId) {
$redis->rPush('wechat_send_queue', json_encode([
'open_id' => $openId,
'media_id' => $mediaId,
'add_time' => time()
]));
}
}
// 消费者进程(需单独运行)
while (true) {
$data = $redis->lPop('wechat_send_queue');
if ($data) {
$task = json_decode($data, true);
$token = getCachedAccessToken();
sendSingleMessage($token, $task['open_id'], $task['media_id']);
sleep(1); // 控制频率
} else {
sleep(5);
}
}
5.2 消息去重策略
实现72小时内不重复发送相同内容:
function isMessageDuplicate($openId, $mediaId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "sent_message_{$openId}";
$sentMediaIds = $redis->sMembers($key);
return in_array($mediaId, $sentMediaIds);
}
// 发送后记录
$redis->sAdd("sent_message_{$openId}", $mediaId);
$redis->expire("sent_message_{$openId}", 86400 * 3); // 3天有效期
六、安全注意事项
6.1 接口验证
所有微信服务器配置的URL必须实现签名验证:
function checkWechatSignature() {
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = "你的验证Token"; // 与公众号后台配置一致
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
6.2 敏感操作保护
群发接口调用需记录操作日志
重要操作(如切换群发模式)需二次验证
限制IP访问频率(可通过Nginx配置)
关键词:PHP开发、微信公众号、群发消息、Access Token、图文素材、定时任务、接口安全、性能优化
简介:本文详细介绍了使用PHP实现微信公众号群发消息功能的完整流程,包括开发环境准备、核心接口调用、高级功能实现、常见问题解决和性能优化方案。内容涵盖从基础的消息发送到大规模用户群发的完整技术实现,适合PHP开发者快速掌握微信公众平台的高级接口开发。