在微信生态里,直播预约如果只靠运营人员群发图文,很容易石沉大海。把预约动作放到公众号自定义菜单上,用户点一下就完成预约,再由系统在开播前发消息提醒,是性价比很高的做法。这种方式依赖微信的事件推送机制,开发者需要在公众号后台配置菜单,并在自己的服务器接收微信发来的XML消息,解析出用户点击行为后再做业务处理。

自定义菜单的配置与事件类型选择
要实现点击菜单弹出直播预约,首先得明确菜单的类型。微信公众号自定义菜单支持多种类型,其中click类型会在用户点击时给开发者服务器推送带EventKey的事件;而view类型直接跳转网页,不适合做带业务状态的预约。对于直播预约场景,通常使用click菜单,或者微信后来支持的view_limited类型(跳转到公众号图文消息)。最稳妥的方案是用click,因为我们可以完全掌控后端逻辑。
配置菜单需要通过微信的自定义菜单创建接口,使用access_token调用。下面是一段用Python requests库创建菜单的示例,菜单中包含一个key为LIVE_RESERVE的点击型按钮。注意菜单结构必须是微信要求的JSON格式,并且按钮名称不能超长。创建成功后,用户在公众号对话界面点这个菜单,微信就会向我们配置的服务器地址发送事件推送。
import requests
import json
token = "YOUR_ACCESS_TOKEN"
url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + token
menu_data = {
"button": [
{
"type": "click",
"name": "直播预约",
"key": "LIVE_RESERVE"
},
{
"type": "view",
"name": "往期回放",
"url": "https://ipipp.com/replay"
}
]
}
resp = requests.post(url, data=json.dumps(menu_data, ensure_ascii=False).encode("utf-8"))
print(resp.json())
当菜单创建好之后,必须保证公众号后台的服务器配置地址能够正确接收微信的POST请求。微信会以XML格式推送事件,其中包含ToUserName、FromUserName、Event和EventKey等字段。只有正确响应微信的校验和消息体,后续的预约和提醒流程才能跑通。很多新手在这一步失败,是因为服务器没有返回success字符串,导致微信重试或菜单点击无反应。
接收点击事件并落地预约记录
用户点击菜单后,微信服务器会向我们填写的回调地址发送一条事件消息。我们需要在后端写一个接口来接收并解析这条XML。以Java Spring Boot为例,可以用HttpServletRequest读取输入流,再用工具把XML转成Map。判断Event等于CLICK且EventKey等于LIVE_RESERVE时,就说明用户发起了直播预约。此时要拿到用户的openid,也就是FromUserName的值。
拿到openid之后,下一步是把预约关系存起来。一般设计两张表:一张是直播场次表,记录开播时间、标题、推流地址;另一张是预约表,记录openid、live_id、reserve_time和notify_status。这样后续定时任务就能扫出即将开播且未提醒的预约记录。下面的代码演示了接收事件并写入预约的核心逻辑,这里用伪代码简化数据库操作,重点看事件判断与落库时机。
public String handleEvent(HttpServletRequest request) throws Exception {
Map<String, String> xml = parseXml(request.getInputStream());
String event = xml.get("Event");
String eventKey = xml.get("EventKey");
String openid = xml.get("FromUserName");
if ("CLICK".equals(event) && "LIVE_RESERVE".equals(eventKey)) {
Long liveId = getCurrentLiveId();
if (liveId != null && !reserveDao.exists(openid, liveId)) {
reserveDao.insert(openid, liveId, System.currentTimeMillis(), 0);
}
return "success";
}
return "success";
}
这里有一个细节:微信要求五秒内返回响应,所以不要在处理事件时做太重的任务,比如调用模板消息接口可以放到异步队列。如果当场就发模板消息告知预约成功,要确保接口稳定且快速。更推荐的做法是返回success后,通过消息队列异步发送一条文本或模板消息,告诉用户“预约成功,开播会提醒您”。这样既满足微信的响应要求,也提升了用户体验。
开播前提醒用户的消息推送方案
预约记录落库后,真正的价值体现在开播前的提醒。微信公众号给用户主动发消息受限于接口权限,常用的是模板消息或订阅消息。模板消息需要用户曾在小程序或公众号内产生交互,而我们的菜单点击正好构成了交互前提,因此可以用模板消息推送开播提醒。定时任务每分钟或每五分钟跑一次,找出十分钟后开播且notify_status为0的记录,逐条发送。
发送模板消息要调用微信的模板消息接口,并带上提前申请好的模板ID。消息内容里可以写直播标题、开播时间和进入链接。下面是一段Node.js的发送示例,使用了axios。注意模板消息的data字段格式必须和后台申请的模板一致,否则会报错。发送成功后把notify_status更新为1,避免重复提醒。如果用户量很大,建议做批量发送和失败重试。
const axios = require('axios');
async function sendNotify(openid, liveTitle, startTime, token) {
const url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' + token;
const data = {
touser: openid,
template_id: 'YOUR_TEMPLATE_ID',
data: {
title: { value: liveTitle },
time: { value: startTime },
remark: { value: '点击公众号菜单可进入直播' }
}
};
try {
await axios.post(url, data);
return true;
} catch (e) {
return false;
}
}
除了模板消息,如果直播是在微信小程序或视频号进行,也可以结合订阅消息,让用户授权一次性订阅,开播时推送。但菜单点击场景里,模板消息的链路最短。实践中要注意用户取关后openid失效,发送会返回错误码,此时要把本地预约标记为无效。另外提醒时间不要过早或过晚,提前十五分钟到半小时是比较合适的区间,既能唤醒用户又不至于造成骚扰。通过自定义菜单事件把预约和提醒串起来,整体开发量不大,却能明显提高直播观看转化。