上篇文章介绍了开启回调模式,开始回调模式后我们就要实现聊天功能了。平时使用微信聊天可以发送文本消息、语音、图片、视频等,这里只实现了其中的一些功能和大家分享。
一、与微信企业号建立连接
1、企业应用调用企业号提供的接口,管理或查询企业号后台所管理的资源、或给成员发送消息等,以下称主动调用模式。
2、企业号把用户发送的消息或用户触发的事件推送给企业应用,由企业应用处理,以下称回调模式。
3、用户在微信中阅读企业应用下发的H5页面,该页面可以调用微信提供的原生接口,使用微信开放的终端能力,以下称JSAPI模式。
这是微信企业号的开发文档中写的,但是我们一般使用前两种方式。其实主动调用和回调都是相对的,这是站在微信服务器的角度,微信服务器通过企业号给微信客户端发送消息是主动调用,微信客户端主动发送消息去调用微信服务器相对服务器来说就是被动调用(回调)。
二、主被动调用微信服务器处理的数据格式
1.主调:服务器向微信客户端发送json格式的数据,数据不需要加密
2.回调:微信客户端发送的消息需要AES加密,服务器接受的消息是xml格式
这两条用一张图表示如下:
三、聊天原理图
首先微信客户端发送消息到服务器处理,数据以xml格式传输到第三方服务器后,第三方服务器再将数据转为json格式,传送给微信服务器,发送给客户端。
三、代码实现
有了上面的原理基础,下面是代码部分
1.servlet
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String msg_signature = request.getParameter("msg_signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
InputStream inputStream = request.getInputStream();
String postData = IOUtils.toString(inputStream, "UTF-8");
System.out.println(postData);
String msg = "";
WXBizMsgCrypt wxcpt = null;
try {
wxcpt = new WXBizMsgCrypt(sToken , sEncodingAESKey , sCorpID );
msg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);
} catch (AesException e) {
e.printStackTrace();
}
System.out.println("msg=" + msg);
//获取接口访问凭证
String accessToken = CommonUtil.getToken("wxe510946434680dab", "eWTaho766INvp4e1MCsz1mHYuT2DAleb62REQ3vsFizhY4vtmwZpKweuxUVh33G0").getAccessToken();
try {
@SuppressWarnings("unused")
boolean flag = ChatService1.sendMessage(accessToken,msg);
} catch (Exception e) {
e.printStackTrace();
}
}
public class ChatService1 {
public static boolean sendMessage(String accessToken,String msg) throws Exception{
boolean flag = false;
Map requestMap = MessageUtil.parseXml(msg);
// 发送者
String fromUserName = requestMap.get("FromUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)){//如果是文本客服消息
String Content = requestMap.get("Content");//文本消息的消息内容
//组装文本客服消息,参数1:用户id;参数2:发送的内容
jsonMsg = AdvancedUtil.makeTextCustomMessage("lishehe|zhisheng|zhangwenyuan|lixinjiang", Content);
}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)){//发送的是图片
String mediaId = requestMap.get("MediaId");
jsonMsg = AdvancedUtil.makeImageCustomMessage("lishehe|zhisheng|zhangwenyuan|lixinjiang", mediaId);
}else if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)){
String mediaId = requestMap.get("MediaId");
jsonMsg= AdvancedUtil.makeVoiceCustomMessage("lishehe|zhisheng|zhangwenyuan|lixinjiang", mediaId);
}
flag = AdvancedUtil.sendCustomMessage(accessToken, jsonMsg);
return flag;
}
}
3.工具类
public class AdvancedUtil {
private static Logger log = LoggerFactory.getLogger(AdvancedUtil.class);
/**
* 组装发送文本消息
* @return
*/
public static String makeTextCustomMessage(String openId, String content) {
content = content.replace("\"", "\\\"");
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"text\",\"agentid\":\"%s\",\"text\":{\"content\":\"%s\"}}";
return String.format(jsonMsg, openId, 14,content);
}
/**
* 组装发送图片消息
*
* @return
*/
public static String makeImageCustomMessage(String openId, String mediaId) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"image\",\"agentid\":\"%s\",\"image\":{\"media_id\":\"%s\"}}";
return String.format(jsonMsg, openId,14, mediaId);
}
/**
* 组装发送语音消息
*
* @return
*/
public static String makeVoiceCustomMessage(String openId, String mediaId) {
String jsonMsg = "{\"touser\":\"%s\",\"msgtype\":\"voice\",\"agentid\":\"%s\",\"voice\":{\"media_id\":\"%s\"}}";
return String.format(jsonMsg, openId,14, mediaId);
}
这样就实现了消息的接收和推送,第三方服务器将接受的xml数据先解密解析,从中获取消息类型,然后将要发送的消息封装后转为json格式,并传送给微信服务器在发送到客户端。