3. 被动回复与客服消息:消息响应的两种姿势
做公众号开发,最核心的事情就是「消息处理」。用户发一条消息过来,你得想办法回应他。但这里有个关键问题——你什么时候能回?怎么回?能回几条?
嗯,这就要说到我们今天的主角:被动回复和客服消息。这两个概念,我当年刚接触时也绕了好一阵子。说白了,它们就是公众号响应用户消息的两种不同姿势。
3.1 被动回复机制:5秒内的生死时速
先说说被动回复。这个名字其实挺形象的——你「被动」地响应,用户发什么,你回什么。
用户给公众号发了一条消息,微信服务器会把这条消息推送到你的后台。你的后台必须在5秒内返回一个XML格式的响应。超过5秒,微信就当你没反应,直接给用户弹一句「该公众号暂时无法提供服务」。
为什么会这样?我猜微信团队的设计思路是:既然用户主动找你,你就得及时回应。5秒,够你查个数据库、做个简单判断了。
核心要点:
- 用户触发 → 微信推送 → 你处理 → 你返回XML
- 5秒超时限制,超时即失败
- 只能回复一次,不能连续回复
- 回复内容有格式限制(文本、图片、图文等)
我在项目中遇到过一个问题:有个客户说他们的公众号偶尔会回复失败。排查了半天,发现是他们的服务器响应太慢——数据库查询用了3秒,再加上业务逻辑处理,刚好卡在5秒边缘。网络一波动就超时。
我的建议:被动回复的代码一定要轻量。复杂的业务逻辑,别放在这里做。实在要处理,先返回一个「正在处理中」的提示,然后用客服消息异步推送结果。
被动回复的XML格式长这样:
<xml>
<ToUserName><![CDATA[用户OpenID]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好,欢迎关注!]]></Content>
</xml>
注意那个CDATA,很多新手会忘。XML里有些字符需要转义,CDATA就是告诉解析器「这里面是纯文本,别转义」。我曾经因为这个踩过坑——用户发了个「&」符号,我的回复直接炸了。
3.2 客服消息接口:48小时内的自由发挥
被动回复有5秒限制,那如果我想在用户发消息后的任意时间点回复呢?比如用户下单后,我想在10分钟后通知他订单状态。
这时候就需要客服消息接口了。
客服消息的规则是这样的:用户主动给公众号发消息后的48小时内,你可以主动给他发消息。不限制条数,不限制时间点。
你想想看,这给了我们多大的操作空间。用户发了一条「我要查订单」,你可以先回复「正在查询中」,然后后台慢慢查数据库,查完了再用客服消息把结果推过去。
客服消息 vs 被动回复:
| 对比项 | 被动回复 | 客服消息 |
|---|---|---|
| 触发条件 | 用户发消息时 | 用户发消息后48小时内 |
| 响应时间 | 5秒内 | 任意时间 |
| 回复次数 | 1次 | 不限次数 |
| 调用方式 | 返回XML | 调用API接口 |
调用客服消息接口的代码示例:
// 发送客服文本消息
POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
{
"touser": "用户OpenID",
"msgtype": "text",
"text": {
"content": "您好,您的订单已处理完成。"
}
}
嗯,这里要注意:客服消息的access_token和被动回复不是同一个东西。access_token有有效期(7200秒),你得自己维护刷新逻辑。我习惯用一个定时任务每1小时刷新一次,存到Redis里。
3.3 多客服系统:人工介入的正确姿势
有些场景,机器搞不定。比如用户投诉、复杂咨询、售后问题。这时候就需要把消息转给真人客服。
微信提供了多客服系统,说白了就是你可以把消息转发给指定的客服人员。每个客服有一个工号,比如kf1001、kf1002。
转发的方式有两种:
- 被动回复转发:在5秒内返回一个转发到多客服的XML
- 客服消息转发:调用API把消息分配给指定客服
被动回复转发到多客服的XML:
<xml>
<ToUserName><![CDATA[用户OpenID]]></ToUserName>
<FromUserName><![CDATA[开发者微信号]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>
如果你想指定某个客服,可以加一个KfAccount字段:
<xml>
...
<TransInfo>
<KfAccount><![CDATA[kf1001@你的微信号]]></KfAccount>
</TransInfo>
</xml>
避坑指南:我曾经犯过一个错——把所有消息都转给多客服。结果客服根本忙不过来,用户等半天没人理。后来我加了一层判断:只有包含「人工」「投诉」「转客服」等关键词的消息才转发。其他常规问题,让机器人先挡一挡。
3.4 消息转发:让消息流动起来
消息转发,其实是个更宽泛的概念。它不只是转给客服,还可以转给其他系统、其他公众号、甚至第三方平台。
常见的消息转发场景:
- 转给第三方平台:比如你用了某个SaaS服务,把消息转发过去处理
- 转给其他公众号:多公众号体系下,把消息路由到对应的公众号
- 转给内部系统:比如CRM系统、工单系统
消息转发的实现方式,其实就是在你的后台做一层路由。收到消息后,根据消息类型、用户标签、关键词等条件,决定把消息转发到哪里。
我做过一个项目,客户有3个公众号,分别对应售前、售后、投诉。用户在任何一个公众号发消息,后台会根据消息内容自动路由到对应的客服组。比如用户说「我要退货」,消息就被转发到售后公众号的客服。
我的经验:消息转发一定要做好日志。每条消息从哪来、到哪去、处理结果是什么,都得记录下来。不然出了问题,你根本不知道消息丢在哪一步了。
3.5 实战中的选择策略
讲了这么多,你可能会问:实际开发中,到底用哪种方式?
我的建议是这样的:
- 简单问答(查天气、查快递):用被动回复,5秒内搞定
- 复杂查询(查订单、查积分):被动回复返回「正在查询」,然后用客服消息推送结果
- 需要人工介入:转发到多客服系统
- 跨系统协作:用消息转发机制路由到对应系统
说白了,没有银弹。每种方式都有自己的适用场景。你得多想想用户的实际体验,而不是一味追求技术上的「优雅」。
嗯,这一章的内容就到这。下一章我们聊聊菜单——那个用户天天点、但你得小心伺候的自定义菜单。