微信公众号开发者原生态的servlet

如果想要成功成为微信公众号开发者,那么首先就是要服务器与微信公众号接入

查询公众号开发文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319

  1. 根据微信的API来编写servlet,请求获取四个字段(signature、timestamp、nonce、echostr)这些参数的表示什么意义自己查询公众号的API。
  2. 对这三个字段进行list排序处理,通过SHA1加密算法返回密文,与第一个参数signature进行比较,hashcode如果一致,接入成功,原样返回echostr参数内容,则接入生效,成为开发者成功。
  3. 这个工程部署到Linux上。
  4. 微信公众号上的url写,部署工程的action请求地址。

值得注意的是上述接入公众号是servlet的doGet( )请求 ,直接上代码

编写JoinChatServlet.java文件的get请求方法:

package com.eastrobot.robotdev.wechat;import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.eastrobot.robotdev.Constants;
import com.eastrobot.robotdev.util.HttpUtils;
import com.eastrobot.robotdev.wechat.entity.AccessToken;
import com.eastrobot.robotdev.wechat.util.SHA1Utils;/*** 接入微信公众号平台* * @author han.sun* */
public class JoinChatServlet extends HttpServlet {private static final long serialVersionUID = 1L;private static Logger log = LoggerFactory.getLogger(JoinChatServlet.class);// private static ReceiveXmlUtils receiveXmlUtils;// 微信上填写的Token数据private static String Token = "sunhan";public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding(Constants.CHARSET);response.setCharacterEncoding(Constants.CHARSET);log.debug("GEt请求成功");// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。String signature = request.getParameter("signature");// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");// 随机字符串String echostr = request.getParameter("echostr");List<String> params = new ArrayList<String>();params.add(Token);params.add(timestamp);params.add(nonce);// 1. 将token、timestamp、nonce三个参数进行字典排序Collections.sort(params, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}});// 2. 将三个参数拼接成一个字符串进行SHA1进行加密String temp = SHA1Utils.encode(params.get(0) + params.get(1)+ params.get(2));// 3. 加密后的字符串与signature比较,标识该请求是来自微信if (temp.equals(signature)) {// 原样返回echostr参数内容,则接入成功response.getWriter().write(echostr);log.debug("echostr传回微信后台成功...");} else {log.debug("echostr传回微信后台失败...");}}
}

SHA1Utils.java

package com.eastrobot.robotdev.wechat.util;import java.security.MessageDigest;/*** SHA1算法* @author han.sun**/
public class SHA1Utils {private SHA1Utils() {}private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };public static String getFormattedText(byte[] bytes) {int len = bytes.length;StringBuffer buffer = new StringBuffer(len * 2);// 把密文转换成十六进制的字符串形式for (int i = 0; i < bytes.length; i++) {buffer.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);buffer.append(HEX_DIGITS[bytes[i] & 0x0f]);}return buffer.toString();}public static String encode(String str){if (str==null) {return null;}try {MessageDigest messageDigest = MessageDigest.getInstance("SHA1");messageDigest.update(str.getBytes());return getFormattedText(messageDigest.digest());} catch (Exception e) {throw new RuntimeException(e);}}
}

此时如果微信公众号后台的URL、秘钥、token等填写无误,用微信公众号调试接口:https://mp.weixin.qq.com/debug?token=233128916&lang=zh_CN进行测试服务器是否已经接入,会返回json数据状态为200 OK那么恭喜你已经成功接入开发者模式

二、实现公众号被动回复消息

可以回复文本、图片、语音、图文等等众多多谋体文件。创建这些文件消息实体。发送与回复消息都是通过Xml格式进行传输

创建一个消息实体基类,供它的子类继承,不论是文本还是图片都有4个共有的属性,ToUserName、FromUserName、CreateTime、MsgType,分别是接收方、来自方、会话创建时间、会话类型。

BaseMessage.java

package com.eastrobot.robotdev.wechat.entity;import java.io.Serializable;import com.thoughtworks.xstream.annotations.XStreamAlias;/*** 请求消息基类* @author han.sun**/
public class BaseMessage implements Serializable{private static final long serialVersionUID = 1L;@XStreamAlias("ToUserName")public String ToUserName;@XStreamAlias("FromUserName")public String FromUserName;@XStreamAlias("CreateTime")public Long CreateTime;@XStreamAlias("MsgType")public String MsgType;public String getToUserName() {return ToUserName;}public void setToUserName(String toUserName) {ToUserName = toUserName;}public String getFromUserName() {return FromUserName;}public void setFromUserName(String fromUserName) {FromUserName = fromUserName;}public Long getCreateTime() {return CreateTime;}public void setCreateTime(Long createTime) {CreateTime = createTime;}public String getMsgType() {return MsgType;}public void setMsgType(String msgType) {MsgType = msgType;}}

文本消息类

package com.eastrobot.robotdev.wechat.entity;/*** 文本消息类* @author han.sun**/
public class TextMessage extends BaseMessage {private static final long serialVersionUID = 1L;private String Content;private String MsgId;public String getContent() {return Content;}public void setContent(String content) {Content = content;}public String getMsgId() {return MsgId;}public void setMsgId(String msgId) {MsgId = msgId;}}

图片消息类

package com.eastrobot.robotdev.wechat.entity;import com.thoughtworks.xstream.annotations.XStreamAlias;/*** 图片消息类* @author han.sun**/
@XStreamAlias("xml")
public class ImageMessage extends BaseMessage {private static final long serialVersionUID = 1L;@XStreamAlias("Image")private Image Image;public Image getImage() {return Image;}public void setImage(Image image) {Image = image;}}

ImageMessage的图片消息类下的子属性Image类

package com.eastrobot.robotdev.wechat.entity;/*** 图片消息类的Image* @author han.sun**/
public class Image {/*** 图片的临时文件Id*/private String MediaId;public String getMediaId() {return MediaId;}public void setMediaId(String mediaId) {MediaId = mediaId;}}

我还实现了很多的类型,图文消息实体就不附加上来了

下面就是消息回复所用到的工具类啦,Message消息处理工具类(最重要的工具类)

  1. 此工具类是为了,把请求的Xml格式数据转换成Map集合类型,这样才好处理,用到消息实体时候,我们使用map.get()方法就可以获取出想要的xml标签中的数据
  2. 在servlet处理好数据准备回复的时候,也要把数据进行输出xml形式返回给微信后台
package com.eastrobot.robotdev.wechat.util;import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import com.eastrobot.robotdev.wechat.entity.ArticlesItem;
import com.eastrobot.robotdev.wechat.entity.ArticlesMessage;
import com.eastrobot.robotdev.wechat.entity.Image;
import com.eastrobot.robotdev.wechat.entity.ImageMessage;
import com.eastrobot.robotdev.wechat.entity.TextMessage;
import com.thoughtworks.xstream.XStream;/*** 处理Xml消息工具类* @author han.sun**/
public class MessageUtils {public static final String MESSAGE_SCAN = "SCAN";// 未关注公众号扫描二维码public static final String MESSAGE_TEXT = "text";// 文本public static final String MESSAGE_IMAGE = "image";// 图片public static final String MESSAGE_VOICE = "voice";// 语音public static final String MESSAGE_VIDEO = "video";// 视频public static final String MESSAGE_LINK = "link";// 连接public static final String MESSAGE_LOCATION = "location";// 地理位置事件public static final String MESSAGE_EVENT = "event";// 事件public static final String MESSAGE_SUBSCRIBE = "subscribe";// 关注public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";// 取消关注public static final String MESSAGE_CLICK = "CLICK";// 点击public static final String MESSAGE_VIEW = "VIEW";// t跳转链接urlpublic static final String MESSAGE_NEWS = "news";private MessageUtils() {}/*** 将接受到的xml转换成Map集合* @param request* @return Map集合*/public static Map<String, String> xmlToMap(HttpServletRequest request)throws IOException, DocumentException {Map<String, String> map = new HashMap<String, String>();SAXReader reader = new SAXReader();InputStream in = request.getInputStream();Document document = reader.read(in);Element root = document.getRootElement();@SuppressWarnings("unchecked")List<Element> list = root.elements();for (Element e : list) {map.put(e.getName(), e.getText());}in.close();return map;}/*** 将文本信息转换成Xml* @param textMessage   文本消息实体* @return    准备返回的xml字符串*/private static String textMessageToXml(TextMessage textMessage) {XStream stream = new XStream();stream.alias("xml", textMessage.getClass());return stream.toXML(textMessage);}/*** 将图片消息转换成xml* @param imageMessage    图片消息实体* @return    准备返回的xml字符串*/private static String imageMessageToXml(ImageMessage imageMessage) {XStream stream = new XStream();stream.alias("xml", imageMessage.getClass());return stream.toXML(imageMessage);}/*** 图文消息转为xml* @param newsMessage* @return*/public static String articlesMessageToXml(ArticlesMessage articlesMessage){XStream xstream = new XStream();xstream.alias("xml", articlesMessage.getClass());xstream.alias("item", new ArticlesItem().getClass());return xstream.toXML(articlesMessage);}/*** 图文消息的组装(类型为news)* @param toUserName* @param fromUserName* @return*/public static String initArticlesMessage(String toUserName,String fromUserName){String message = null;List<ArticlesItem> newsList = new ArrayList<ArticlesItem>();ArticlesMessage newsMessage = new ArticlesMessage();ArticlesItem article = new ArticlesItem();article.setTitle("图文消息");article.setDescription("你,在或者不在;这些年风里,雨里;无论,快乐还是哀愁;我都将终点,等你 。");article.setPicUrl("http://ctr.demo.xiaoi.com/robot-dev/image/028.jpg");article.setUrl("https://www.baidu.com");newsList.add(article);newsMessage.setToUserName(fromUserName);newsMessage.setFromUserName(toUserName);newsMessage.setCreateTime(new Date().getTime());newsMessage.setMsgType(MESSAGE_NEWS);newsMessage.setArticles(newsList);newsMessage.setArticleCount(newsList.size());message = articlesMessageToXml(newsMessage);return message;}/*** 文本消息的组装* @param content* @param toUserName* @param fromUserName* @return  发送给客户端*/public static String initTextMessage(String content, String toUserName,String fromUserName) {String message = null;TextMessage textMessage = new TextMessage();textMessage.setContent(content);textMessage.setCreateTime(new Date().getTime());textMessage.setFromUserName(toUserName);textMessage.setToUserName(fromUserName);textMessage.setMsgType(MESSAGE_TEXT);message = textMessageToXml(textMessage);return message;}/*** 图片消息的组装* @param mediaId* @param toUserName* @param fromUsername* @return    发送给客户端*/public static String initImageMessage(String mediaId, String toUserName,String fromUserName) {String message = null;ImageMessage imageMessage = new ImageMessage();Image image = new Image();image.setMediaId(mediaId);imageMessage.setImage(image);imageMessage.setFromUserName(toUserName);imageMessage.setToUserName(fromUserName);imageMessage.setCreateTime(new Date().getTime());imageMessage.setMsgType(MESSAGE_IMAGE);message = imageMessageToXml(imageMessage);return message;}public static String initMuenMessage() {StringBuffer bf = new StringBuffer();bf.append("你,在或者不在\n");bf.append("这些年风里,雨里\n");bf.append("无论是快乐,哀愁\n");bf.append("我都将终点,等你\n");return bf.toString();}
}

实现图片回复的功能,因为图片不是在微信后台的,所以必要我们提供的服务器来进行预上传到公众号的临时素材库中(失效是三天吧)。公众号的API中提供的接口中要求必须有一个MediaId,这就是此类的作用

package com.eastrobot.robotdev.wechat.util;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.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;import net.sf.json.JSONObject;import com.eastrobot.robotdev.Constants;
import com.eastrobot.robotdev.util.HttpUtils;
import com.eastrobot.robotdev.wechat.entity.AccessToken;/*** 上传图片到临时素材库类* @author han.sun**/
public class WechatUtils {private static final String APPID = "wx7eea4228e2073fb8";private static final String APPSECRET = "13f608d28a4d2cefedb790fa321766fb";private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";private static final String UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";private WechatUtils(){}/*** doGet形式的HttpClient请求* @param url   接口地址* @return  返回Json对象*/public static JSONObject doGetStr(String url) {JSONObject jsonObject = null;String result = HttpUtils.get(url, Constants.CHARSET);jsonObject = JSONObject.fromObject(result);return jsonObject;}/*** 获取AccessToken* @return AccessToken* @author han.sun*/public static AccessToken getAccessToken() {AccessToken token = new AccessToken();String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);JSONObject jsonObject = doGetStr(url);if (jsonObject != null) {token.setToken(jsonObject.getString("access_token"));token.setExpiresIn(jsonObject.getInt("expires_in"));}return token;}/*** 上传本地文件到微信获取mediaId* @param filePath   文件路径* @param accessToken   令牌* @param type    消息类型* @return 返回mediaId*/public static String upload(String filePath, String accessToken, String type)throws IOException, NoSuchAlgorithmException,NoSuchProviderException, KeyManagementException {System.out.println("filePath:" + filePath);File file = new File(filePath);if (!file.exists() || !file.isFile()) {throw new IOException("文件不存在");}String url = UPLOAD_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type);URL urlObj = new URL(url);// 连接HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();con.setRequestMethod("POST");con.setDoInput(true);con.setDoOutput(true);con.setUseCaches(false);// 设置请求头信息con.setRequestProperty("Connection", "Keep-Alive");con.setRequestProperty("Charset", "UTF-8");// 设置边界String BOUNDARY = "----------" + System.currentTimeMillis();con.setRequestProperty("Content-Type", "multipart/form-data; boundary="+ BOUNDARY);StringBuilder sb = new StringBuilder();sb.append("--");sb.append(BOUNDARY);sb.append("\r\n");sb.append("Content-Disposition: form-data;name=\"file\";filename=\""+ file.getName() + "\"\r\n");sb.append("Content-Type:application/octet-stream\r\n\r\n");byte[] head = sb.toString().getBytes("utf-8");// 获得输出流OutputStream out = new DataOutputStream(con.getOutputStream());// 输出表头out.write(head);// 文件正文部分// 把文件已流文件的方式 推入到url中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[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线out.write(foot);out.flush();out.close();StringBuffer buffer = new StringBuffer();BufferedReader reader = null;String result = null;try {// 定义BufferedReader输入流来读取URL的响应reader = new BufferedReader(new InputStreamReader(con.getInputStream()));String line = null;while ((line = reader.readLine()) != null) {buffer.append(line);}if (result == null) {result = buffer.toString();}} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {reader.close();}}JSONObject jsonObj = JSONObject.fromObject(result);System.out.println(jsonObj);String typeName = "media_id";if (!"image".equals(type)) {typeName = type + "_media_id";}String mediaId = jsonObj.getString(typeName);return mediaId;}}

三、实现查询天气的功能

根据天气的接口,来定义查询出来的天气实体类。进行查询天气并且处理我们场景实用的信息

package com.eastrobot.robotdev.wechat.weather;import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.eastrobot.robotdev.Constants;
import com.eastrobot.robotdev.util.HttpUtils;
import com.google.gson.Gson;/*** 拼接查询天气接口所需的URL,查询天气* @author han.sun**/
public class BaiduWeather {public static final Logger log = LoggerFactory.getLogger(BaiduWeather.class);private static final String API = "http://api.map.baidu.com/telematics/v3/weather?";private static final String AK = "81218080E79C9685b35e757566d8cbe5";private static final String OUTPUT = "json";/*** 获取天气的结果* @param location    地点* @return    该地点的天气信息*/public static String getResult(String location) {try {URLEncoder.encode(location, Constants.CHARSET);} catch (UnsupportedEncodingException e) {e.printStackTrace();}// 拼接urlStringBuffer sb = new StringBuffer();sb.append("location=");sb.append(location);sb.append("&output=");sb.append(OUTPUT);sb.append("&ak=");sb.append(AK);String url = API + sb.toString();// 百度天气返回的内容String result = "";result = HttpUtils.get(url, Constants.CHARSET);// 去解析查询回来的json字符串String message = handleResult(result);// 如果返回的不是Json那么还需要进行处理....return message;}/*** 处理查询出来的天气结果* @param result   原始的Json字符串* @return    真正返回给用户的字符串*/private static String handleResult(String result){Gson gson = new Gson();Status status = gson.fromJson(result, Status.class);List<Results> list = status.getResults();StringBuffer buffer = new StringBuffer();for (int i = 0; i < list.size(); i++) {Results results = list.get(i);List<Weather> weather_data = results.getWeather_data();for (int j = 0; j < weather_data.size(); j++) {Weather weather = weather_data.get(j);String date = weather.getDate();String weath= weather.getWeather();String temperature = weather.getTemperature();buffer.append(date+" ");buffer.append(weath+" ");buffer.append(temperature+" ");buffer.append("\n");}}return buffer.toString();} }

最后编写我们最核心的大脑系统servlet,编写JoinChatServlet中doPost()方法,接入公众号是get请求,粉丝与公众号之间进行消息回复是Post请求

最终的servlet程序代码:

package com.eastrobot.robotdev.wechat;import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Random;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.eastrobot.robotdev.Constants;
import com.eastrobot.robotdev.util.HttpUtils;
import com.eastrobot.robotdev.wechat.entity.AccessToken;
import com.eastrobot.robotdev.wechat.util.MessageUtils;
import com.eastrobot.robotdev.wechat.util.SHA1Utils;
import com.eastrobot.robotdev.wechat.util.WechatUtils;/*** 接入微信公众号平台* * @author han.sun* */
public class JoinChatServlet extends HttpServlet {private static final long serialVersionUID = 1L;private static Logger log = LoggerFactory.getLogger(JoinChatServlet.class);// private static ReceiveXmlUtils receiveXmlUtils;// 微信上填写的Token数据private static String Token = "sunhan";public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding(Constants.CHARSET);response.setCharacterEncoding(Constants.CHARSET);log.debug("GEt请求成功");// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。String signature = request.getParameter("signature");// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");// 随机字符串String echostr = request.getParameter("echostr");List<String> params = new ArrayList<String>();params.add(Token);params.add(timestamp);params.add(nonce);// 1. 将token、timestamp、nonce三个参数进行字典排序Collections.sort(params, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}});// 2. 将三个参数拼接成一个字符串进行SHA1进行加密String temp = SHA1Utils.encode(params.get(0) + params.get(1)+ params.get(2));// 3. 加密后的字符串与signature比较,标识该请求是来自微信if (temp.equals(signature)) {// 原样返回echostr参数内容,则接入成功response.getWriter().write(echostr);log.debug("echostr传回微信后台成功...");} else {log.debug("echostr传回微信后台失败...");}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding(Constants.CHARSET);response.setCharacterEncoding(Constants.CHARSET);PrintWriter out = response.getWriter();String result = null;Map<String, String> map = null;try {map = MessageUtils.xmlToMap(request);} catch (DocumentException e1) {e1.printStackTrace();}String toUserName = map.get("ToUserName");String fromUserName = map.get("FromUserName");String msgType = map.get("MsgType");String content = map.get("Content");String echostr = request.getParameter("echostr");// 判断是否是微信接入激活验证,只有首次接入验证时才会收到echostr参数,此时需要把它直接返回if (echostr != null && echostr.length() > 1) {result = echostr;} else {// 判断请求是是否是文本类型 textif (MessageUtils.MESSAGE_TEXT.equals(msgType)) {if ("文艺".equals(content)) {result = imageProcess(toUserName, fromUserName);// String mediaId =// "7u19uWKlh-Nfpm8dAEpkhgxr0u5y0H5hxARQKsqtv3FjcMOV9dtFGxpYU4RvaV4t";// result = MessageUtils.initImageMessage(mediaId,// toUserName,fromUserName);} else if ("图文".equals(content)) {result = MessageUtils.initArticlesMessage(toUserName,fromUserName);} else {String api = "http://ctr.demo.xiaoi.com/robot/ask.action?";try {URLEncoder.encode(content, Constants.CHARSET);} catch (UnsupportedEncodingException e) {e.printStackTrace();}// 拼接urlStringBuffer bf = new StringBuffer();bf.append("question=");bf.append(content);bf.append("&paltform=weixin");String url = api + bf.toString();String message = HttpUtils.get(url, Constants.CHARSET);message = message.substring(message.indexOf("<Content>") + 9,message.indexOf("</Content>"));result = MessageUtils.initTextMessage(message, toUserName,fromUserName);}}}out.write(result);out.close();}private String imageProcess(String toUserName, String fromUserName) {String message = null;AccessToken token = WechatUtils.getAccessToken();String mediaId = null;Random ran = new Random();int i = ran.nextInt(28);String filePath = "/app/ibot-odin-robot-8005/webapps/robot-dev/image/0" + (i+1) + ".jpg";try {mediaId = WechatUtils.upload(filePath, token.getToken(),MessageUtils.MESSAGE_IMAGE);// mediaId =// "7u19uWKlh-Nfpm8dAEpkhgxr0u5y0H5hxARQKsqtv3FjcMOV9dtFGxpYU4RvaV4t";} catch (Exception e) {e.printStackTrace();}message = MessageUtils.initImageMessage(mediaId, toUserName,fromUserName);return message;}
}

当然了还有一个常用类HttpUtils工具类,进行各种接口的调用。但凡遇见Constant.CHARSET全部改成UTF-8就行啦。

微信公众号开发者原生态的servlet相关推荐

  1. 微信公众号云服务器年服务费_微信公众号开发者接口费用高吗

    微信公众号开发者接口费用高吗 很多企业都想开发自己公司的微信公众号,不过大家最关心的还是微信公众号开发价格问题.今天,微速云小编就为大家带来微信公众号开发者接口费用高吗,一起来了解一下吧. 微信公众号 ...

  2. 公众号自动回复不生效php,php,微信公众平台开发者_微信公众号开发者自动回复设置没反应,php,微信公众平台开发者 - phpStudy...

    微信公众号开发者自动回复设置没反应 在新浪sea平台设置了微信公众号应用,设置关注自动回复功能,接口设置成功,,代码写好,url也修改代码的页面,但是测试后没反应. //define your tok ...

  3. 微信公众号基本设置服务器设置教程,最新最全的微信公众号开发者模式配置

    微信公众号的开发分为编辑模式和开发者模式,那么最新最全的微信公众号开发者模式配置是什么呢,下面是学习啦小编收集整理的最新最全的微信公众号开发者模式配置,希望对大家有帮助~~ 最新最全的微信公众号开发者 ...

  4. android 微信公众号开发教程,微信公众号-开发者-自定义菜单,公众开发者

    微信公众号-开发者-自定义菜单,公众开发者 我是个初学者,网上找了看了好多,都是第三方实现的,考虑到安全问题,不敢用! 今天终于摸索出了实现方法. 官方api:http://mp.weixin.qq. ...

  5. 微信开发者模式php,php 开启微信公众号开发者模式

    php 开启微信公众号开发者模式 /** * wechat php test */ header('Content-type:text'); //define your token //定义TOKEN ...

  6. 微信开发者模式php,PHP实现模拟微信公众号开发者模式

    本文主要和大家分享PHP实现模拟微信公众号开发者模式,主要以代码的形式和大家分享,希望能帮助到大家.$url = 'http://xxxx.com/test/aaaa/index.php';//开发者 ...

  7. 开启微信公众号服务器后面的开发,微信公众号开发者权限 开通接口与配置服务器...

    微信公众号开发者权限 开通接口与配置服务器 作为微信公众平台的开发者,是可以修改自定义菜单的.每个公众号下端都会有三个或者是四个菜单.关于菜单的内容以及显示的方式都是可以通过后台的开发者权限更改的.如 ...

  8. 用spring搭建微信公众号开发者模式下服务器处理用户消息的加密传输构架(java)

    要搭建加密传输的微信公众号消息传输,首先要在开发这平台下载一下微信加密的相关jar包,并做一些准备.准备的步骤如下: 1.打开开发者文档,找到消息加减密--->接入指引,如下图所示: 2.在页面 ...

  9. java调用微信加密_用spring搭建微信公众号开发者模式下服务器处理用户消息的加密传输构架(java)...

    要搭建加密传输的微信公众号消息传输,首先要在开发这平台下载一下微信加密的相关jar包,并做一些准备.准备的步骤如下: 1.打开开发者文档,找到消息加减密--->接入指引,如下图所示: 2.在页面 ...

最新文章

  1. Android控件系统(三)——Window与WindowMananger
  2. 如果重走职场,一定会送自己 8 个锦囊
  3. #51CTO学院四周年# 成长路上的我和你
  4. 过半网友支持马斯克卖掉特斯拉10%股票,马斯克:会遵守投票结果
  5. 用 Flask 来写个轻博客 (35) — 使用 Flask-RESTful 来构建 RESTful API 之四
  6. python编程基础是什么-编程学习第一步,让你20天搞定Python编程
  7. MPAndroidChart的具体属性方法
  8. Android activity 参数传递
  9. TF之DD:利用Inception模型+GD算法生成带背景的大尺寸、高质量的Deep Dream图片——五个架构设计思维导图
  10. #define宏定义中的#,##,@#,\
  11. 通过豆瓣电影的多方法解析,带你学会爬虫的所有解析方法
  12. C++实现计数排序(附完整源码)
  13. Linux nano编辑txt文件,Linux 文本编辑器 nano 的简单使用
  14. 数据库SQL语言从入门到精通--Part 4--SQL语言中的模式、基本表、视图
  15. Debian安装autoconf
  16. jzoj 6301. 普及组
  17. BT没死!305个国外BT资源聚合站点大全
  18. 推挽电路原理及应用-上N下P以及下N上P
  19. java接口和抽象函数_Java接口和抽象类区别
  20. Android:自定义View实现绚丽的圆形进度条

热门文章

  1. 马云:阿里巴巴的最高机密是我们的组织架构图
  2. 无线移动通信技术快速发展历程和趋向
  3. wsl 2 中安装docker
  4. 权限和归属关系解析与新手小白操作教程
  5. Pandas GroupBy 深度总结
  6. 三十岁,真的是人生的分水岭吗
  7. JSON树转换成线性列表(python)
  8. zabbix_agentd_window端运行报错cannot connect to Service Manager: [0x00000005]
  9. Mimikatz各模块基本用法
  10. 中望3D 2021 “基准面”之“动态基准面”模式