微信公众号开发
1.登录微信公众平台:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
登录测试账号。
2.对微信公众号测试账号进行相关配置:
url指向项目的controller或者servlet,例如:http://www.test.qer/demo/test.do,其中www.test.qer是映射地址,先把本地映射到外网,否则微信公众号发送消息进入不了本地项目中。映射工具使用ngrok。
3.代码:
web.xml中配置:
<servlet> <servlet-name>WeixinServlet</servlet-name> <servlet-class>com.test.www.servlet.WeixinServlet1</servlet-class> </servlet> <servlet-mapping> <servlet-name>WeixinServlet</servlet-name> <url-pattern>/wx.do</url-pattern> </servlet-mapping>
WeixinServlet1.java:
package com.test.www.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.dom4j.DocumentException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.support.SpringBeanAutowiringSupport; import com.fasterxml.jackson.databind.ObjectMapper; import com.test.www.entity.XmlParam; import com.test.www.enums.KeyEnum; import com.test.www.utils.CheckUtil; import com.test.www.utils.MessageUtil; import com.test.www.utils.encrypt.cus.AuthProcess; import com.test.www.web.controller.entity.Article; import com.test.www.web.controller.entity.ArticleMeaasge; import com.test.www.web.controller.entity.Image; import com.test.www.web.controller.entity.ImgMeaasge; import com.test.www.web.controller.entity.Music; import com.test.www.web.controller.entity.MusicMeaasge; import com.test.www.web.controller.entity.TextMeaasge; import com.test.www.web.controller.entity.Video; import com.test.www.web.controller.entity.VideoMeaasge; import com.test.www.web.controller.entity.Voice; import com.test.www.web.controller.entity.VoiceMeaasge; import com.test.www.web.service.GoodService; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; /** * 微信公众号开发者模式开发 * @className WeixinServlet1 * @author liuyachao * @date 2018-5-7 */ public class WeixinServlet1 extends HttpServlet { /*@Resource GoodService goodService;*/ @Autowired private GoodService goodService; /** * 注入service需要执行此方法 */ @Override public void init(ServletConfig config) throws ServletException { SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); } /*@Resource private GoodService goodService;*/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 接收微信服务器以Get请求发送的4个参数 String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); PrintWriter out = response.getWriter(); if (CheckUtil.checkSignature(signature, timestamp, nonce)) { out.print(echostr); // 校验通过,原样返回echostr参数内容 } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //doGet(request, response); request.setCharacterEncoding("utf-8"); response.setContentType("text/xml;charset=utf-8"); PrintWriter out = response.getWriter(); try { Map<String, String> map; try { map = MessageUtil.xmlToMap(request); String toUserName = map.get("ToUserName"); String fromUserName = map.get("FromUserName"); String msgType = map.get("MsgType"); String content = map.get("Content"); String key = map.get("EventKey"); //消息处理 String message = messageProcessing(toUserName,fromUserName,msgType,content,key); //消息加解密 /*String message = ""; ObjectMapper objectMapper = new ObjectMapper(); //加密消息处理 String encrypt_type =request.getParameter("encrypt_type"); if (StringUtils.isBlank(encrypt_type) || encrypt_type.equals("raw")) {//不用加密 map = MessageUtil.xmlToMap(request); String toUserName = map.get("ToUserName"); String fromUserName = map.get("FromUserName"); String msgType = map.get("MsgType"); String content = map.get("Content"); String key = map.get("EventKey"); //消息处理 message = messageProcessing(toUserName,fromUserName,msgType,content,key); } else {//需走加解密流程 //先转map再转xml map = MessageUtil.xmlToMap(request); XmlParam xmlParam = new XmlParam(); xmlParam.setToUserName(map.get("ToUserName")); xmlParam.setEncrypt(map.get("Encrypt")); String xml = MessageUtil.messageToXML(xmlParam); //String xml = MessageUtil.xmlToMap3(request); //解密请求消息体 String nXmlString = AuthProcess.decryptMsg(request, xml); map = MessageUtil.xmlToMap2(nXmlString); //map = objectMapper.readValue(nXmlString, Map.class); String toUserName = map.get("ToUserName"); String fromUserName = map.get("FromUserName"); String msgType = map.get("MsgType"); String content = map.get("Content"); String key = map.get("EventKey"); //消息处理 message = messageProcessing(toUserName,fromUserName,msgType,content,key); //加密回复消息体 message = AuthProcess.encryptMsg(request, message); }*/ System.out.println(message); out.print(message); } catch (com.itextpdf.text.DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 将回应发送给微信服务器 } catch (DocumentException e) { e.printStackTrace(); }finally{ out.close(); } } private String messageProcessing(String toUserName, String fromUserName, String msgType, String content, String key) { String message = null; if ("text".equals(msgType)) { // 对文本消息进行处理 /*TextMeaasge text = new TextMeaasge(); text.setFromUserName(toUserName); // 发送和回·复是反向的 text.setToUserName(fromUserName); text.setMsgType("text"); text.setCreateTime(new Date().getTime()); text.setContent("你发送的消息是:" + content);*/ TextMeaasge text = new TextMeaasge(); text = Handle(toUserName,fromUserName,msgType,content,text,key); message = MessageUtil.messageToXML(text); }else if("event".equals(msgType)){ if(KeyEnum.V1001_TODAY_MUSIC.getCode().equals(key)){ //url /*UrlMeaasge urlMeaasge = new UrlMeaasge(); urlMeaasge.setFromUserName(toUserName); urlMeaasge.setToUserName(fromUserName); urlMeaasge.setMsgType("link"); urlMeaasge.setUrl("http://www.baidu.com/link?url=rzDPtXKQB42V4aTkeM_09D5sEI9bVW5tQ9la8uaJH0tfSZ1rinLD2ppcPdMa-9V7ka3EJFIA4rBYoFde_EVTLq"); urlMeaasge.setTitle("女儿国-女儿情"); urlMeaasge.setCreateTime(new Date().getTime()); urlMeaasge.setDescription("女儿情"); message = MessageUtil.urlMessageToXML(urlMeaasge); System.out.println(message); */ //音乐 MusicMeaasge musicMeaasge = new MusicMeaasge(); musicMeaasge.setCreateTime(new Date().getTime()); musicMeaasge.setFromUserName(toUserName); musicMeaasge.setToUserName(fromUserName); musicMeaasge.setMsgType("music"); Music music = new Music(); music.setTitle("女儿情"); music.setHQMusicUrl("http://localhost:80/weixin/img/4214239130.mp3"); music.setMusicUrl("http://localhost:80/weixin/img/4214239130.mp3"); music.setThumbMediaId("eJT2a5F5fYl2FtSrhxWRRt4Qsjq-N8YTcOOZK8ntZpSxHaPR_Ui6rr9EsmWbGRxD"); music.setDescription("西游记插曲"); musicMeaasge.setMusic(music); message = MessageUtil.messageToXML(musicMeaasge); } if(KeyEnum.V1001_GOOD.getCode().equals(key)){ Map<String,Object> result = goodService.insert(); TextMeaasge textMeaasge = new TextMeaasge(); textMeaasge.setFromUserName(toUserName); // 发送和回复是反向的 textMeaasge.setToUserName(fromUserName); textMeaasge.setMsgType("text"); textMeaasge.setCreateTime(new Date().getTime()); textMeaasge.setContent("谢谢您的支持!您是第"+result.get("count")+"个点赞的人"); //textMeaasge.setContent("谢谢您的支持!您是第500个点赞的人"); message = MessageUtil.messageToXML(textMeaasge); } if(KeyEnum.V1001_text.getCode().equals(key)){ TextMeaasge text = new TextMeaasge(); text = Handle(toUserName,fromUserName,msgType,content,text,key); message = MessageUtil.messageToXML(text); } if(KeyEnum.V1001_image.getCode().equals(key)){ //图片 ImgMeaasge imgMeaasge = new ImgMeaasge(); imgMeaasge.setCreateTime(new Date().getTime()); imgMeaasge.setFromUserName(toUserName); Image image = new Image(); image.setMediaId("8UwRYzG6BE719fckUQb0C3tdnh11cToA_Kw0PflEcNMWXAqi975zkcCKZfHvu9d_"); imgMeaasge.setImage(image); //imgMeaasge.getsetMediaId("NngcTJ3Ch4in6Vb5lHFBmhI8RCH1l9fBP_1zi0XoZejcGqfVApw4l1A75ztkD61T"); imgMeaasge.setMsgType("image"); imgMeaasge.setToUserName(fromUserName); message = MessageUtil.imgMessageToXML(imgMeaasge); } if(KeyEnum.V1001_video.getCode().equals(key)){ //视频 VideoMeaasge videoMeaasge = new VideoMeaasge(); videoMeaasge.setFromUserName(toUserName); videoMeaasge.setToUserName(fromUserName); videoMeaasge.setCreateTime(new Date().getTime()); videoMeaasge.setMsgType("video"); Video video = new Video(); video.setTitle("环保小视频"); video.setDescription("希望大家保护环境,节约用水"); //video.setMediaId("UyiC8gAXlJIfwdPEB8-VDLfoKeaGYWy9761yWgYMpSnRTjqtFpLzmG9MLuzzMhya"); //video.setMediaId("TFFzdu0HVViNeg3HvrbakpgTqvoC8zHkEgRcAs8OyowiKACqzkvBdGaVhyo-eVzt"); video.setMediaId("5bYQTWcEVMaMIGOKACDfshkt7cyXmGJKGv0HzFenoxQIYV_2JSC7dULSUPxLBbqL"); videoMeaasge.setVideo(video); message = MessageUtil.messageToXML(videoMeaasge); } if(KeyEnum.V1001_music.getCode().equals(key)){ //音乐 MusicMeaasge musicMeaasge = new MusicMeaasge(); musicMeaasge.setCreateTime(new Date().getTime()); musicMeaasge.setFromUserName(toUserName); musicMeaasge.setToUserName(fromUserName); musicMeaasge.setMsgType("music"); Music music = new Music(); music.setTitle("女儿情"); music.setHQMusicUrl("http://localhost:80/weixin/img/4214239130.mp3"); music.setMusicUrl("http://localhost:80/weixin/img/4214239130.mp3"); music.setThumbMediaId("eJT2a5F5fYl2FtSrhxWRRt4Qsjq-N8YTcOOZK8ntZpSxHaPR_Ui6rr9EsmWbGRxD"); music.setDescription("西游记插曲"); musicMeaasge.setMusic(music); message = MessageUtil.messageToXML(musicMeaasge); } if(KeyEnum.V1001_voice.getCode().equals(key)){ //语音消息 VoiceMeaasge voiceMeaasge = new VoiceMeaasge(); Voice voice = new Voice(); voice.setMediaId("L9GPORex_dJr-AwWiZHvv-gSf5MrwoztqK20qzA9ooKtwQ3_07tiSxhNCB2ZfgMc"); voiceMeaasge.setFromUserName(toUserName); // 发送和回复是反向的 voiceMeaasge.setToUserName(fromUserName); voiceMeaasge.setMsgType("voice"); voiceMeaasge.setCreateTime(new Date().getTime()); voiceMeaasge.setVoice(voice); message = MessageUtil.messageToXML(voiceMeaasge); } if(KeyEnum.V1001_article.getCode().equals(key)){ //图文消息 ArticleMeaasge articleMeaasge = new ArticleMeaasge(); Article article = new Article(); List<Article> list = new ArrayList<Article>(); article.setDescription("图文testtesttesttesttesttesttesttesttest"); article.setPicUrl("http://liuyachao110.tunnel.qydev.com/weixin/img/wang.jpg"); article.setTitle("test"); article.setUrl("http://www.bybo.com.cn"); list.add(article); articleMeaasge.setFromUserName(toUserName); articleMeaasge.setToUserName(fromUserName); articleMeaasge.setCreateTime(new Date().getTime()); articleMeaasge.setMsgType("news"); articleMeaasge.setArticleCount(list.size()); articleMeaasge.setArticles(list); message = MessageUtil.newsMessageToXml(articleMeaasge); } } return message; } /** * 文本消息处理 * @param toUserName * @param fromUserName * @param msgType * @param content * @param text * @param key * @return */ private TextMeaasge Handle(String toUserName, String fromUserName, String msgType, String content, TextMeaasge text, String key) { StringBuffer sb = new StringBuffer(); if("电影".equals(content)){ sb.append("<a href='http://www.baidu.com/link?url=N756uq7MPY-JWLok6hvcU_VgbzksWEWLcJgOIehxw1dy7Pfaavr6pZljeHKFR0qv&wd=&eqid=bdf02a660001b4de000000035ae02acc'>女儿国</a>\n\n"); sb.append("<a href='http://www.baidu.com/link?url=ykNZi2TClLyY6zuKfP-gbLnht9kJsnrVnNeksRm6gKBweWTbPHiBTw0WVXC1KNOa3ra937Um07Ux2gRZYxzmMK'>红海行动</a>\n\n"); sb.append("<a href='http://www.baidu.com/link?url=6-9h3UA9CZ8owwaekZK2UhyM_-ghzi9G_y0Jkkdy0pXBkOXw9Z4SfowNrEv4Z6yJoC2PQTPyDRSk-dZqIHRk4zNtLt97mNrugmKPoCWg6XNnmO-JYpSn6MpbFoI1Mw04'>缝纫机乐队</a>"); content = sb.toString(); msgType = "text"; text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(msgType); text.setContent(content); } if(KeyEnum.V1001_text.getCode().equals(key)){ sb.append("<a href='http://www.baidu.com/link?url=N756uq7MPY-JWLok6hvcU_VgbzksWEWLcJgOIehxw1dy7Pfaavr6pZljeHKFR0qv&wd=&eqid=bdf02a660001b4de000000035ae02acc'>女儿国</a>\n\n"); sb.append("<a href='http://www.baidu.com/link?url=ykNZi2TClLyY6zuKfP-gbLnht9kJsnrVnNeksRm6gKBweWTbPHiBTw0WVXC1KNOa3ra937Um07Ux2gRZYxzmMK'>红海行动</a>\n\n"); sb.append("<a href='http://www.baidu.com/link?url=6-9h3UA9CZ8owwaekZK2UhyM_-ghzi9G_y0Jkkdy0pXBkOXw9Z4SfowNrEv4Z6yJoC2PQTPyDRSk-dZqIHRk4zNtLt97mNrugmKPoCWg6XNnmO-JYpSn6MpbFoI1Mw04'>缝纫机乐队</a>"); content = sb.toString(); msgType = "text"; text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(msgType); text.setContent(content); } return text; } }
CheckUtil.java:
package com.test.www.utils; import java.util.Arrays; import org.apache.commons.codec.digest.DigestUtils; public class CheckUtil { private static final String token = "weixinTest"; public static boolean checkSignature(String signature,String timestamp,String nonce){ String[] arr = new String[] { token, timestamp, nonce }; // 排序 Arrays.sort(arr); // 生成字符串 StringBuilder content = new StringBuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); } // sha1加密 String temp = getSHA1String(content.toString()); return temp.equals(signature); // 与微信传递过来的签名进行比较 } private static String getSHA1String(String data){ return DigestUtils.sha1Hex(data); // 使用commons codec生成sha1字符串 } }
MessageUtil.java:
package com.test.www.utils; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.itextpdf.text.DocumentException; import com.test.www.web.controller.entity.Article; import com.test.www.web.controller.entity.ArticleMeaasge; import com.test.www.web.controller.entity.ImgMeaasge; import com.test.www.web.controller.entity.TextMeaasge; import com.test.www.web.controller.entity.UrlMeaasge; import com.test.www.web.controller.entity.VideoMeaasge; import com.thoughtworks.xstream.XStream; public class MessageUtil { /** * 将XML转换成Map集合 * @throws org.dom4j.DocumentException */ public static Map<String, String>xmlToMap(HttpServletRequest request) throws IOException, DocumentException, org.dom4j.DocumentException{ Map<String, String> map = new HashMap<String, String>(); SAXReader reader = new SAXReader(); // 使用dom4j解析xml InputStream ins = request.getInputStream(); // 从request中获取输入流 Document doc = reader.read(ins); Element root = doc.getRootElement(); // 获取根元素 List<Element> list = root.elements(); // 获取所有节点 for (Element e : list) { map.put(e.getName(), e.getText()); System.out.println(e.getName() + "--->" + e.getText()); } ins.close(); return map; } /** * xml字符串转换为map集合 * @throws org.dom4j.DocumentException */ public static Map<String, String>xmlToMap2(String xml) throws IOException, DocumentException, org.dom4j.DocumentException{ Map<String, String> map = new HashMap<String, String>(); SAXReader reader = new SAXReader(); // 使用dom4j解析xml Document doc = DocumentHelper.parseText(xml); Element root = doc.getRootElement(); // 获取根元素 List<Element> list = root.elements(); // 获取所有节点 for (Element e : list) { map.put(e.getName(), e.getText()); System.out.println(e.getName() + "--->" + e.getText()); } return map; } /** * document转换为xml字符串 * @throws org.dom4j.DocumentException */ public static String xmlToMap3(HttpServletRequest request) throws IOException, DocumentException, org.dom4j.DocumentException{ Map<String, String> map = new HashMap<String, String>(); SAXReader reader = new SAXReader(); // 使用dom4j解析xml InputStream ins = request.getInputStream(); // 从request中获取输入流 Document doc = reader.read(ins); String xml = doc.asXML(); ins.close(); return xml; } /** * 将文本消息对象转换成XML */ public static String textMessageToXML(TextMeaasge textMessage){ XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式 xstream.alias("xml", textMessage.getClass()); // 将xml的默认根节点替换成“xml” return xstream.toXML(textMessage); } /** * 将文本消息对象转换成XML * @param urlMessage * @return */ public static String urlMessageToXML(UrlMeaasge urlMessage){ XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式 xstream.alias("xml", urlMessage.getClass()); // 将xml的默认根节点替换成“xml” return xstream.toXML(urlMessage); } /** * 将图片消息对象转换成XML * @param imgMeaasge * @return */ public static String imgMessageToXML(ImgMeaasge imgMeaasge) { XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式 xstream.alias("xml", imgMeaasge.getClass()); // 将xml的默认根节点替换成“xml” return xstream.toXML(imgMeaasge); } /** * 将视频消息对象转换成XML * @param videoMeaasge * @return */ public static String videoMessageToXML(VideoMeaasge videoMeaasge) { XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式 xstream.alias("xml", videoMeaasge.getClass()); // 将xml的默认根节点替换成“xml” return xstream.toXML(videoMeaasge); } /** * 将消息对象转换成XML 泛型 * @param t * @return */ public static <T> String messageToXML(T t) { XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式 xstream.alias("xml", t.getClass()); // 将xml的默认根节点替换成“xml” return xstream.toXML(t); } /** * 图文消息 * @param articleMeaasge * @return */ public static String newsMessageToXml(ArticleMeaasge articleMeaasge) { XStream xstream = new XStream(); xstream.alias("xml", articleMeaasge.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(articleMeaasge); } }
UploadUtils.java:
package com.test.www.utils; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import net.sf.json.JSONObject; import com.test.www.constant.Constant; import com.test.www.web.controller.entity.WeixinMedia; public class UploadUtils { /** * 上传媒体文件 * @param accessToken 接口访问凭证 * @param type 媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file) * @param media form-data中媒体文件标识,有filename、filelength、content-type等信息 * @param mediaFileUrl 媒体文件的url * 上传的媒体文件限制 * 图片(image):1MB,支持JPG格式 * 语音(voice):2MB,播放长度不超过60s,支持AMR格式 * 视频(video):10MB,支持MP4格式 * 普通文件(file):10MB * */ /*public static WeixinMedia uploadMedia(String accessToken, String type, String mediaFileUrl) { WeixinMedia weixinMedia = null; // 拼装请求地址 //String uploadMediaUrl = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; String uploadMediaUrl = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; uploadMediaUrl = uploadMediaUrl.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type); // 定义数据分隔符 String boundary = "------------7da2e536604c8"; try { URL uploadUrl = new URL(uploadMediaUrl); HttpURLConnection uploadConn = (HttpURLConnection) uploadUrl.openConnection(); uploadConn.setDoOutput(true); uploadConn.setDoInput(true); uploadConn.setRequestMethod("POST"); // 设置请求头Content-Type uploadConn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); // 获取媒体文件上传的输出流(往微信服务器写数据) OutputStream outputStream = uploadConn.getOutputStream(); URL mediaUrl = new URL(mediaFileUrl); HttpURLConnection meidaConn = (HttpURLConnection) mediaUrl.openConnection(); meidaConn.setDoOutput(true); meidaConn.setRequestMethod("GET"); System.out.println(meidaConn.getContent()); // 从请求头中获取内容类型 String contentType = meidaConn.getHeaderField("Content-Type"); // 根据内容类型判断文件扩展名 String fileExt = getFileEndWitsh(contentType); // 请求体开始 outputStream.write(("--" + boundary + "\r\n").getBytes()); outputStream.write(String.format("Content-Disposition: form-data; name=\"media\"; filename=\"file1%s\"\r\n", fileExt).getBytes()); outputStream.write(String.format("Content-Type: %s\r\n\r\n", contentType).getBytes()); // 获取媒体文件的输入流(读取文件) BufferedInputStream bis = new BufferedInputStream(meidaConn.getInputStream()); byte[] buf = new byte[8096]; int size = 0; while ((size = bis.read(buf)) != -1) { // 将媒体文件写到输出流(往微信服务器写数据) outputStream.write(buf, 0, size); } // 请求体结束 outputStream.write(("\r\n--" + boundary + "--\r\n").getBytes()); outputStream.close(); bis.close(); meidaConn.disconnect(); // 获取媒体文件上传的输入流(从微信服务器读数据) InputStream inputStream = uploadConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); StringBuffer buffer = new StringBuffer(); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; uploadConn.disconnect(); // 使用JSON-lib解析返回结果 JSONObject jsonObject = JSONObject.fromObject(buffer.toString()); // 测试打印结果 System.out.println("打印测试结果"+jsonObject); weixinMedia = new WeixinMedia(); weixinMedia.setType(jsonObject.getString("type")); // type等于 缩略图(thumb) 时的返回结果和其它类型不一样 if ("thumb".equals(type)) weixinMedia.setMediaId(jsonObject.getString("thumb_media_id")); else weixinMedia.setMediaId(jsonObject.getString("media_id")); weixinMedia.setCreatedAt(jsonObject.getInt("created_at")); } catch (Exception e) { weixinMedia = null; String error = String.format("上传媒体文件失败:%s", e); System.out.println(error); } return weixinMedia; }*/ /** * 根据内容类型判断文件扩展名 * * @param contentType 内容类型 * @return */ public static String getFileEndWitsh(String contentType) { String fileEndWitsh = ""; //text/html if ("image/jpeg;charset=UTF-8".equals(contentType) || "image/jpeg".equals(contentType)) fileEndWitsh = ".jpg"; else if ("audio/mpeg".equals(contentType) || "audio/mpeg;charset=UTF-8".equals(contentType)) fileEndWitsh = ".mp3"; else if ("audio/amr".equals(contentType)) fileEndWitsh = ".amr"; else if ("video/mp4".equals(contentType) || "video/mp4;charset=UTF-8".equals(contentType)) fileEndWitsh = ".mp4"; else if ("video/mpeg4".equals(contentType)) fileEndWitsh = ".mp4"; else if ("audio/x-wav;charset=UTF-8".equals(contentType)) fileEndWitsh = ".wav"; return fileEndWitsh; } /** * 获取媒体文件 * @param accessToken 接口访问凭证 * @param media_id 媒体文件id * @param savePath 文件在服务器上的存储路径 * */ public static String downloadMedia(String accessToken, String mediaId, String savePath) { String filePath = null; // 拼接请求地址 //String requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"; String requestUrl = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"; requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId); System.out.println(requestUrl); try { URL url = new URL(requestUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); conn.setRequestMethod("GET"); if (!savePath.endsWith("/")) { savePath += "/"; } // 根据内容类型获取扩展名 String fileExt = getFileEndWitsh(conn.getHeaderField("Content-Type")); // 将mediaId作为文件名 filePath = savePath + mediaId + fileExt; BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); FileOutputStream fos = new FileOutputStream(new File(filePath)); byte[] buf = new byte[8096]; int size = 0; while ((size = bis.read(buf)) != -1) fos.write(buf, 0, size); fos.close(); bis.close(); conn.disconnect(); String info = String.format("下载媒体文件成功,filePath=" + filePath); System.out.println(info); } catch (Exception e) { filePath = null; String error = String.format("下载媒体文件失败:%s", e); System.out.println(error); } return filePath; } /** * 上传多媒体文件 * @param access_token 接口访问凭证 * @param mediaType 媒体文件类型,分别有图片(image)、语音(voice)、视频(video) * @param mediaUrl * 媒体文件的url ,本地路径和网络路径的文件都能上传 * * 图片大小不超过2M,支持bmp/png/jpeg/jpg/gif格式, * 语音大小不超过5M,长度不超过60秒,支持mp3/wma/wav/amr格式 * @return */ public static WeixinMedia uploadMedia(String access_token, String mediaType , String mediaUrl) { //返回数据 String result = ""; // 拼接上传地址uploadUrl String uploadUrl = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; uploadUrl = uploadUrl.replace("ACCESS_TOKEN", access_token).replace( "TYPE", mediaType); try { // 创建一个https连接 URL requstUrl = new URL(uploadUrl); HttpsURLConnection conn = (HttpsURLConnection) requstUrl.openConnection(); conn.setRequestMethod("POST");//设置请求方式 conn.setUseCaches(false); conn.setDoInput(true); conn.setDoOutput(true); //设置请求消息头 conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Charset", "UTF-8"); String boundary = "----" + System.currentTimeMillis();//分隔字符串 conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); //拼接请求消息体的格式头 StringBuilder sb1 = new StringBuilder(); sb1.append("--"); sb1.append(boundary); sb1.append("\r\n"); //回车 sb1.append("Content-Disposition:form-data;name=\"file\";filename=\""+mediaUrl+"\"\r\n");//回车 sb1.append("Content-Type:application/octet-stream\r\n");//回车 sb1.append("\r\n");//回车 - 空行 byte[] head = sb1.toString().getBytes("UTF-8"); //获得连接的写入流out DataOutputStream out = new DataOutputStream(conn.getOutputStream()); //将请求消息体的格式头写入conn的写入流out中 out.write(head); //读数据要用的 int len = 0; byte[] buf = new byte[1024]; //>>>>>>>>>>判断mediaUrl是本地路径还是网络路径 if(mediaUrl.startsWith("http")){ URL url2 = new URL(mediaUrl); HttpURLConnection conn2 = (HttpURLConnection) url2.openConnection(); conn2.setDoInput(true); conn2.setRequestMethod("GET"); System.out.println("内容类型ContentType:"+conn2.getContentType()); BufferedInputStream bis = new BufferedInputStream(conn2.getInputStream()); while((len = bis.read(buf))>0){ out.write(buf, 0, len); } bis.close(); conn2.disconnect(); }else{ //将请求消息体的正文写入conn的写入流out中 DataInputStream in = new DataInputStream(new FileInputStream(mediaUrl)); while((len = in.read(buf))>0){ out.write(buf,0,len); } in.close();//关闭流 } System.out.println("文件写入完成 ..."); //拼接请求消息体的格式尾 StringBuilder sb2 = new StringBuilder(); sb2.append("\r\n");//回车 - 请求消息体的正文和格式头、格式尾分别隔着一个空行 sb2.append("--"); sb2.append(boundary); sb2.append("--"); sb2.append("\r\n");//回车 byte[] foot = sb2.toString().getBytes("UTF-8"); //System.out.println(foot); //将请求消息体的格式尾写入out流 out.write(foot); out.flush(); out.close(); System.out.println("上传多媒体请求消息发出 ..."); //读取服务器响应的消息 StringBuffer temp = new StringBuffer(); InputStream respIn = conn.getInputStream(); len = 0; while((len = respIn.read(buf))>0){ temp.append(new String(buf,0,len)); } respIn.close(); conn.disconnect(); result = temp.toString(); } catch (IOException e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } System.out.println("微信服务器回复的消息:" + result); JSONObject json = JSONObject.fromObject(result); //组装WeiXinMedia WeixinMedia wxMedia = new WeixinMedia(); wxMedia.setType(json.getString("type")); wxMedia.setMediaId(json.getString("media_id")); wxMedia.setCreatedAt(json.getInt("created_at")); return wxMedia; } //示例 public static void main(String[] args) throws IOException { /** * 上传多媒体文件 */ //String access_token = WeixinUtil.getAccessToken(ParamesAPI.corpId, ParamesAPI.secret).getToken(); //String access_token = "9_wOiuJvO4pMIT23CuxXxcQwHLru3BUqV5CyDMYf1q3bzox3d96igJsIVMiRw7cMxbZVY_1MiVcltBrMc-VEzHcKsOZBUavOMUi0eqwp2UcMlDIUUZCUEE3nTCySJ__I7hL_LMuygZFCdI06tnRUDdABAGJS"; String accessToken = Constant.AccessToken; //地址 //WeixinMedia weixinMedia = uploadMedia(access_token, "video", "http://liuyachao110.tunnel.qydev.com/weixin/img/test.mp4"); //WeixinMedia weixinMedia = uploadMedia(access_token, "video", "http://liuyachao110.tunnel.qydev.com/weixin/img/test.mp4"); //WeixinMedia weixinMedia = uploadMedia(access_token, "video", "http://localhost:80/weixin/img/test.mp4"); WeixinMedia weixinMedia = uploadMedia(accessToken, "thumb", "http://localhost:80/weixin/img/wang.jpg"); //WeixinMedia weixinMedia = uploadMedia(accessToken, "voice", "http://localhost:80/weixin/img/msg_3023510223182f97dc8843a105.amr"); //WeixinMedia weixinMedia = uploadMedia(accessToken, "video", "http://liuyachao110.tunnel.qydev.com/weixin/img/test.mp4"); //media_id System.out.println("media_id:"+weixinMedia.getMediaId()); //类型 System.out.println("类型:"+weixinMedia.getType()); //时间戳 System.out.println("时间戳:"+weixinMedia.getCreatedAt()); //打印结果 if(null!=weixinMedia){ System.out.println("上传成功!"); }else{ System.out.println("上传失败!"); } System.out.println("分割线*******************************************************************************************"); /** * 下载多媒体文件 */ //String accessToken = "9_wOiuJvO4pMIT23CuxXxcQwHLru3BUqV5CyDMYf1q3bzox3d96igJsIVMiRw7cMxbZVY_1MiVcltBrMc-VEzHcKsOZBUavOMUi0eqwp2UcMlDIUUZCUEE3nTCySJ__I7hL_LMuygZFCdI06tnRUDdABAGJS"; /*String mediaId = "L9GPORex_dJr-AwWiZHvv-gSf5MrwoztqK20qzA9ooKtwQ3_07tiSxhNCB2ZfgMc"; String savePath = downloadMedia(accessToken, mediaId, "E:/download"); System.out.println("下载成功之后保存在本地的地址为:"+savePath);*/ } }
测试公众号号发送信息就会进入本地进行相应处理返回相应结果,至此微信公众号开发demo已完成。