之前的消息发送与接收都是用户给微信发一条,之后微信回复给用户,也就是API上面所说的被动回复消息,那么微信是否支持主动给关注用户发消息吗,答案是肯定的,但是却有一些限制。看下微信开发文档上怎么说就明白了:
当用户主动发消息给公众号的时候(包括发送信息、点击自定义菜单、订阅事件、扫描二维码事件、支付成功事件、用户维权),微信将会把消息数据推送给开发者,开发者在一段时间内(目前修改为48小时)可以调用客服消息接口,通过POST一个JSON数据包来发送消息给普通用户,在48小时内不限制发送次数。此接口主要用于客服等有人工消息处理环节的功能,方便开发者为用户提供更加优质的服务。
这次就针对客服消息分享下我的心得和体会
1 客服接口-发消息接口使用说明
接口调用请求说明
http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
各消息类型所需的JSON数据包如下:
发送文本消息
{ "touser":"OPENID", "msgtype":"text", "text": { "content":"Hello World" } }
发送图片消息
{ "touser":"OPENID", "msgtype":"image", "image": { "media_id":"MEDIA_ID" } }
发送语音消息
{ "touser":"OPENID", "msgtype":"voice", "voice": { "media_id":"MEDIA_ID" } }
......,基本上来说常用的消息类型,客服接口都是支持的
2 封装客服消息接口
public static String makeTextCustomMessage(String openId,String content){
content.replace("\"", "\\\"");
String jsonMsg="{\"touser\":\"%s\",\"msgtype\":\"text\",\"text\":{\"content\":\"%s\"}}";
return String.format(jsonMsg, openId,content);
}
/**
* 组装图片客服消息
*
* @param openId 消息发送对象
* @param mediaId 媒体文件id
* @return
*/
public static String makeImageCustomMessage(String openId, String mediaId) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"%s\"}}";
return String.format(jsonMsg, openId, mediaId);
}
/**
* 组装语音客服消息
*
* @param openId 消息发送对象
* @param mediaId 媒体文件id
* @return
*/
public static String makeVoiceCustomMessage(String openId, String mediaId) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"%s\"}}";
return String.format(jsonMsg, openId, mediaId);
}
/**
* 组装视频客服消息
*
* @param openId 消息发送对象
* @param mediaId 媒体文件id
* @param thumbMediaId 视频消息缩略图的媒体id
* @return
*/
public static String makeVideoCustomMessage(String openId, String mediaId, String thumbMediaId) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"video\",\"video\":{\"media_id\":\"%s\",\"thumb_media_id\":\"%s\"}}";
return String.format(jsonMsg, openId, mediaId, thumbMediaId);
}
/**
* 组装音乐客服消息
*
* @param openId 消息发送对象
* @param music 音乐对象
* @return
*/
public static String makeMusicCustomMessage(String openId, Music music) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"music\",\"music\":%s}";
jsonMsg = String.format(jsonMsg, openId, JSONObject.fromObject(music).toString());
// 参数名称替换 @20140125
jsonMsg = jsonMsg.replace("musicUrl", "musicurl");
jsonMsg = jsonMsg.replace("HQMusicUrl", "hqmusicurl");
jsonMsg = jsonMsg.replace("thumbMediaId", "thumb_media_id");
return jsonMsg;
}
/**
* 组装图文客服消息
*
* @param openId 消息发送对象
* @param articleList 图文消息列表
* @return
*/
public static String makeNewsCustomMessage(String openId, List articleList) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"news\",\"news\":{\"articles\":%s}}";
jsonMsg = String.format(jsonMsg, openId, JSONArray.fromObject(articleList).toString().replaceAll("\"", "\\\""));
// 将jsonMsg中的picUrl替换为picurl
jsonMsg = jsonMsg.replace("picUrl", "picurl");
return jsonMsg;
}
public static boolean sendCustomMessage(String token,String jsonMsg){
boolean flag=false;
//String accessToken=getAccessToken("xxxx","xxxx").getToken();
String requestUrl="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
requestUrl=requestUrl.replace("ACCESS_TOKEN", token);
JSONObject jsonResult=CommonUtil.httpsRequest(requestUrl, "POST", jsonMsg);
if(jsonResult!=null){
int errorCode=jsonResult.getInt("errcode");
String errorMessage=jsonResult.getString("errmsg");
if(errorCode==0){
flag=true;
}else{
System.out.println("客服消息发送失败:"+errorCode+","+errorMessage);
flag=false;
}
}
return flag;
}
List all=new ArrayList();
Article a2=new Article();
a2.setDescription("最崇拜的明星Justin Timberlake");
a2.setPicUrl("http://img3.douban.com/view/photo/photo/public/p1408738004.jpg");
a2.setTitle("贾斯汀·汀布莱克(Justin Timberlake),1981年1月31日出生于美国田纳西州孟菲斯市,美国男歌手、演员、音乐制作人、主持人,前男子演唱组合超级男孩成员。");
a2.setUrl("http://baike.haosou.com/doc/3382630-3560934.html?from=1358&sid=3560934&redirect=search");
all.add(a2);
String articleMsg=makeNewsCustomMessage("xxx", all);
boolean res=sendCustomMessage(token,articleMsg);
if(res){
System.out.println("客服消息发送成功");
}else{
System.out.println("客服消息发送失败");
}
4 多客服的使用
多客服功能主要用于处理需人工操作、耗时较长的场景,我们都知道如果微信服务器在5秒钟没给用户返回消息则会出现“公众号暂时无法提供服务”。这样用户体验会很差,有这种情况不妨考虑下多客服。
下面是API:http://mp.weixin.qq.com/wiki/5/ae230189c9bd07a6b221f48619aeef35.html
个人建议是可以把多客服看成是一种比较特别的消息类型,这样的话只需修改一下MessageUtil就OK了,加入如下代码:
/**
* 客服消息对象转换成xml
*
* @return xml
*/
public static String customMessageToXml(CustomServiceMessage customServiceMessage) {
xstream.alias("xml", customServiceMessage.getClass());
return xstream.toXML(customServiceMessage);
}
/**
* 多客服消息
*/
public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
String content=requestMap.get("Content");
if(content.startsWith("人工客服")){
CustomServiceMessage cus=new CustomServiceMessage();
cus.setToUserName(fromUserName);
cus.setFromUserName(toUserName);
cus.setCreateTime(new Date().getTime());
cus.setMsgType(MessageUtil.TRANSFER_CUSTOMER_SERVICE);
TransInfo t=new TransInfo();
t.setKfAccount("你的客服账号");
cus.setTransInfo(t);
respMessage=MessageUtil.customMessageToXml(cus);
}else{
respContent = "您发送的是文本消息!";
}
}
package com.debug.weixin.message.res;
import com.debug.weixin.pojo.TransInfo;
public class CustomServiceMessage extends BaseMessage {
private TransInfo TransInfo;
public TransInfo getTransInfo() {
return TransInfo;
}
public void setTransInfo(TransInfo transInfo) {
TransInfo = transInfo;
}
}
package com.debug.weixin.pojo;
public class TransInfo {
private String KfAccount;
public String getKfAccount() {
return KfAccount;
}
public void setKfAccount(String kfAccount) {
KfAccount = kfAccount;
}
}
http://dkf.qq.com/
这里在贴2个我的运行截图:
下面是windows的客户端,就类似QQ的界面
差不多就这样子了