이 기사에서는 WeChat에서 개발한 메시징 인터페이스를 살펴보겠습니다.
WeChat 개발은 WeChat 인터페이스를 호출하는 것이라고 생각하므로 읽고 호출해 보겠습니다. 예정된 작업이 없을 때 WeChat 인터페이스를 호출하려면 http get 및 post 요청을 보내야 하므로 get 및 post 요청을 구체적으로 보내려면 먼저 httputil 클래스를 작성하는 것이 가장 좋습니다. Java 네트워크 프로그래밍에서는 일부 코드를 Baidu하고 일부를 직접 캡슐화하면 정상적으로 사용할 수 있습니다.
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Iterator; import java.util.Map; import javax.activation.MimetypesFileTypeMap; /** * * @author luolei * */ public class HttpUtil { public static String httpGet(String httpUrl){ StringBuffer buffer = null; try{ URL url = new URL(httpUrl); HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); httpUrlConn.setDoInput(true); httpUrlConn.setRequestMethod("GET"); // 获取输入流 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); // 读取返回结果 buffer = new StringBuffer(); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } // 释放资源 bufferedReader.close(); inputStreamReader.close(); inputStream.close(); httpUrlConn.disconnect(); }catch(Exception e){ e.printStackTrace(); } return buffer.toString(); } /** * * 发 post 请求, */ public static String httpPost(String httpUrl,String data){ PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(httpUrl); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(data); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally{ try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } /** * 上传图片 * * @param urlStr * @param textMap * @param fileMap * @return */ public static String formUpload(String urlStr, Map<String, String> textMap, Map<String, String> fileMap) { String res = ""; HttpURLConnection conn = null; String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符 try { URL url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); // System.out.println(conn); conn.setConnectTimeout(5000); conn.setReadTimeout(30000); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn .setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); OutputStream out = new DataOutputStream(conn.getOutputStream()); // text if (textMap != null) { StringBuffer strBuf = new StringBuffer(); Iterator iter = textMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String inputName = (String) entry.getKey(); String inputValue = (String) entry.getValue(); if (inputValue == null) { continue; } strBuf.append("\r\n").append("--").append(BOUNDARY).append( "\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n"); strBuf.append(inputValue); } out.write(strBuf.toString().getBytes()); } // file if (fileMap != null) { Iterator iter = fileMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String inputName = (String) entry.getKey(); String inputValue = (String) entry.getValue(); if (inputValue == null) { continue; } File file = new File(inputValue); String filename = file.getName(); String contentType = new MimetypesFileTypeMap() .getContentType(file); if (filename.endsWith(".png")) { contentType = "image/png"; } if (contentType == null || contentType.equals("")) { contentType = "application/octet-stream"; } StringBuffer strBuf = new StringBuffer(); strBuf.append("\r\n").append("--").append(BOUNDARY).append( "\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"; filename=\"" + filename + "\"\r\n"); strBuf.append("Content-Type:" + contentType + "\r\n\r\n"); out.write(strBuf.toString().getBytes()); DataInputStream in = new DataInputStream( new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); } } byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes(); out.write(endData); out.flush(); out.close(); // 读取返回数据 StringBuffer strBuf = new StringBuffer(); BufferedReader reader = new BufferedReader(new InputStreamReader( conn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { strBuf.append(line).append("\n"); } res = strBuf.toString(); reader.close(); reader = null; } catch (Exception e) { System.out.println("发送POST请求出错。" + urlStr); e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); conn = null; } } return res; } }
그 중 httpGet과 httpPost가 사용됩니다. get 및 post 요청 보내기 WeChat 개발에서 메시지 인터페이스는 일반적으로 xml 형식이고, 기타 인터페이스에서 업로드하고 반환하는 데이터는 일반적으로 json이므로 json을 구문 분석하는 패키지가 필요합니다. gson을 사용할 수도 있습니다.
이제 메시지 인터페이스 테스트를 시작하겠습니다. 먼저 요청 프로세스를 이해해야 합니다.
WeChat 서버가 get 요청을 보냅니다. 입력된 URL을 기반으로 확인합니다. 확인이 성공하면 해당 URL을 기반으로 게시물 요청이 전송됩니다. 메시지 형식은 xml 형식입니다.
메시지 유형 개발 문서 네, 주로 다음과 같은 메시지가 있습니다. 텍스트, 사진, 음성뿐만 아니라 주의, 클릭, 점프와 같은 일부 이벤트도 포함됩니다.
이러한 메시지와 이벤트는 xml 형식이므로 xml 형식의 메시지를 파싱해야 합니다. dom4j를 사용하여 파싱합니다.
연결된 서블릿의 doPost 메서드는 이전에 확인되었습니다. 메시지를 파싱하기 위해
Liu Feng의 블로그에 작성된 방법을 따라 XML을 파싱하는 방법을 캡슐화하고 파싱된 결과를 map3b196469fdc8cfa403b3383d58a116c6에 넣는 MessageUtil을 작성했습니다. 다음과 같습니다:
public static Map18fed3eaa375b9cabd6da695ec776cac parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map18fed3eaa375b9cabd6da695ec776cac map = new HashMap18fed3eaa375b9cabd6da695ec776cac(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List558dc77cf99fee6757323747f07fa144 elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) map.put(e.getName(), e.getText()); // 释放资源 inputStream.close(); inputStream = null; return map; }
파싱된 xml은 태그 이름(컨텐츠)에 따라 맵에 저장됩니다.
그런 다음 메시지 유형 msgType
String msgType = requestMap.get("MsgType") ;
그런 다음 메시지 유형을 결정합니다.
// 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { request.getRequestDispatcher("TextMessage").forward(request, response); } // 图片消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) { request.getRequestDispatcher("ImageServlet").forward(request, response); } // 地理位置消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { request.getRequestDispatcher("LocationServlet").forward(request, response); } // 链接消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { request.getRequestDispatcher("LinkServlet").forward(request, response); } // 音频消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) { request.getRequestDispatcher("VedioServlet").forward(request, response); } // 事件推送 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) { // 事件类型 String eventType = requestMap.get("Event"); // 订阅 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { request.getRequestDispatcher("SubServlet").forward(request, response); } // 取消订阅 else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { // TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息 } // 自定义菜单点击事件 else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) { // TODO 自定义菜单权没有开放,暂不处理该类消息 request.getRequestDispatcher("ClickServlet").forward(request, response); } }서블릿마다 서로 다른 메시지를 처리하고 필요에 따라 서로 다른 메시지를 반환할 수 있습니다. 반환된 메시지의 형식도 xml 형식입니다. 반환 메시지 유형은 수락과 동일합니다. 메시지 유형은 기본적으로 유사합니다. 각 xml 태그는 필드 이름에 해당하고 내용은 필드의 내용입니다.
public class BaseMessageResp { // 接收方帐号(收到的OpenID) private String ToUserName; // 开发者微信号 private String FromUserName; // 消息创建时间 (整型) private long CreateTime; // 消息类型(text/music/news) private String MsgType; // 位0x0001被标志时,星标刚收到的消息 private int FuncFlag;set 및 get 메소드는 생략됩니다
public class TextMessage extends BaseMessageResp { // 回复的消息内容 private String Content; public String getContent() { return Content; } public void setContent(String content) { Content = content; } }다른 메시지에는 동일한 필드에는 공통 기본 클래스가 작성됩니다. 이제 사용자에게 메시지를 반환하는 단계가 한 단계 남았습니다. 이 기술은 이러한 pojo 클래스를 xml 문자열로 변환합니다xstream
/** * 文本消息对象转换成xml * * @param textMessage 文本消息对象 * @return xml */ public static String textMessageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); }여기에 간단한 설명이 있습니다. 링크를 잊어버렸으니 마지막으로 얻은 문자열을 반환하세요. WeChat 서버가 사용자에게 응답합니다. 이러한 메시지 인터페이스만 사용하면 간단한 구독 계정을 작성할 수 있습니다. 일반 회사의 공개 계정은 보기 유형 버튼을 통해 자체 웹 사이트로 이동하는 것처럼 보입니다. 이제 위의 인터페이스를 사용하여 사용자가 보낸 다양한 메시지를 수락한 다음 메시지를 미리 처리하거나 날씨, 농담, 기사 등과 같은 일부 API를 호출하여 결과를 얻을 수 있습니다. 분석 후 팔로우 사용자에게 원하는 형식으로 돌려드릴 수 있고, 생활도우미 등 구독 계정을 실습할 수 있습니다. 다만, 신청하신 구독 계정은 권한이 제한되어 있어 가능한지 모르겠습니다. 그것.
위 내용은 WeChat에서 개발한 메시지 인터페이스의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!