为丰富小程序的服务能力,提高服务质量,微信为小程序提供客服消息的功能。小程序用户可以使用客服消息与小程序服务提供方进行沟通。
客服消息会话入口
- 小程序内:开发者在小程序内添加客服消息按钮组件,用户可在小程序内唤起客服会话页面,给小程序发消息;
- 已使用过的小程序客服消息的用户会在微信中看到一个微信会话:“小程序客服消息”,进入“小程序客服消息”会话可查看历史客服消息,以及发送客服消息。
客服消息类型
目前支持文本及图片类型消息
客服消息的接收
- 若小程序没有启用消息推送,则用户发送的消息将会被转发至网页版和移动端小程序客服工具,客服人员可在网页版与移动端小程序客服工具中接入并回复用户。
- 如小程序启用了消息推送,则所有的客服消息将推送到开发者填写的URL对应的服务器,不再推送到网页版客服工具和移动端小程序客服工具。
发送客服消息
小程序可通过以下两种方式下发客服消息:
- 调用发送客服消息接口下发客服消息。
- 使用公众平台网页版客服工具下发客服消息。
下发条件说明
当用户和小程序客服产生特定动作(如用户向小程序客服发送消息、或者进入会话等情况)的交互时,微信将会把消息数据推送给开发者,开发者可以在一段时间内(目前为 48 小时)调用客服接口,给用户发送客服消息。
8.1消息推送的设置
登录小程序管理后台后,在【开发管理】->【开发设置】->【消息推送】中,管理员扫码启用消息服务,填写服务器地址(URL)、令牌(Token) 和消息加密密钥(EncodingAESKey)等信息。
- URL: 开发者用来接收微信消息和事件的服务器URL地址。开发者所填写的URL 必须以 http:// 或 https:// 开头,分别支持 80 端口和 443 端口。
- Token: 可由开发者可以任意填写,用于生成签名(该Token会和接口 URL中包含的Token进行比对,从而验证安全性)。
- EncodingAESKey: 由开发者手动填写或随机生成,将用作消息体加解密密钥。
开发者提交信息后,微信服务器将给填写的服务器URL地址发送GET请求,GET请求携带参数如下所示: - signature:微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
- timestamp:时间戳
- nonce:随机数
- echostr:随机字符串
开发者通过 signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验逻辑如下: - 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行sha1加密
- 开发者把加密后的字符串与signature对比,验证该请求是否来源于微信
验证URL有效性成功后即接入生效,成为开发者。消息推送参数验证的相关代码如下所示:
func str2sha1(data string)string{
t:=sha1.New()
io.WriteString(t,data)
return fmt.Sprintf("%x",t.Sum(nil))
}
//验证消息推送参数
func HandlerWxSignCheck(w http.ResponseWriter, r *http.Request) {
signature := r.FormValue("signature")
timestamp := r.FormValue("timestamp")
nonce := r.FormValue("nonce")
echostr := r.FormValue("echostr")
var token string="demo_token"
tmps:=[]string{
token,timestamp,nonce}
sort.Strings(tmps)
tmpStr:=tmps[0]+tmps[1]+tmps[2]
tmp:=str2sha1(tmpStr)
if signature != tmp {
echostr = ""
}
w.Write([]byte(echostr))
}
8.2接收客服消息
当某些特定的用户操作(如用户向小程序客服发送消息、或者进入会话等情况)引发事件推送时,微信服务器会将消息(或事件)的数据包以POST请求发送到开发者配置的URL,开发者可以依据自身业务逻辑进行响应。
微信服务器在将用户的消息发给开发者服务器地址后,微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。服务器收到请求后必须做出下述回复,这样微信服务器才不会发起重试,否则,将出现严重的错误提示。详见下面说明:
- 直接回复success(推荐方式)
- 直接回复空串(指字节长度为0的空字符串,而不是结构体中content字段的内容为空)
对于客服消息,一旦遇到以下情况,微信会在小程序会话中向用户下发系统提示“该小程序客服暂时无法提供服务,请稍后再试”: - 开发者在5秒内未回复任何内容
- 开发者回复了异常数据
文本消息的结构
用户在客服会话中发送文本消息时将产生如下数据包:
{
"ToUserName": "toUser",
"FromUserName": "fromUser",
"CreateTime": 1482048670,
"MsgType": "text",
"Content": "this is a test",
"MsgId": 1234567890123456
}
参数说明
- ToUserName:小程序的原始ID
- FromUserName:发送者的openid
- Content:文本消息内容
图片消息的结构
用户在客服会话中发送图片消息时将产生如下数据包:
{
"ToUserName": "toUser",
"FromUserName": "fromUser",
"CreateTime": 1482048670,
"MsgType": "image",
"PicUrl": "this is a url",
"MediaId": "media_id",
"MsgId": 1234567890123456
}
参数说明
- ToUserName:小程序的原始ID
- FromUserName:发送者的openid
- MsgType:image
- PicUrl:图片链接(由系统生成)
- MediaId:图片消息媒体id,可以调用【获取临时素材】((getTempMedia)接口拉取数据。
接收客服消息的示例代码:
//微信用户消息
type WxMsgRecive struct {
ToUserName string `json:"ToUserName"`
FromUserName string `json:"FromUserName"`
CreateTime int64 `json:"CreateTime"`
MsgType string `json:"MsgType"`
MsgId int64 `json:"MsgId"`
Content string `json:"Content"`
PicUrl string `json:"PicUrl"`
MediaId string `json:"MediaId"`
}
//接收微信发送的消息
func HandlerReciveWxMsg(w http.ResponseWriter, r *http.Request) {
bdata, _ := ioutil.ReadAll(r.Body)
var ent wxpay.WxMsgRecive
err := json.Unmarshal(bdata, &ent)
if err != nil {
fmt.Println(err)
}
//接受到消息后的业务流程
//.......
w.Write([]byte("success"))
}
说明:
- 上述代码只能用于明文消息的接收,若消息推送培配置中将消息设置为安全模式,则需要对发送的数据进行解密。
- 由于接收前不能获取消息的类型,因此需要定义一个包含所有字段的结构来解析消息数据:WxMsgRecive。