1. 申請公衆號
首先我們必須先申請號所需要開發的微信公衆號,這裏傳送門:https://mp.weixin.qq.com/,申請的流程我就不介紹了。
2. 創建工程
創建web工程,首先創建WeChatServlet類,重寫它的doGet方法:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
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);
}
}
這是CheckUtil工具類:
public class CheckUtil {
private static final String token = "doomthr";
public static boolean checkSignature(String signature, String timestamp,
String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// 排序
Arrays.sort(arr);
// 生成字符串
StringBuffer content = new StringBuffer();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
// sha1加密
String temp = getSha1(content.toString());
return temp.equals(signature);
}
/**
* sha1加密
*
* @param str
* @return
*/
public static String getSha1(String str) {
if (null == str || 0 == str.length())
return null;
char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
try {
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
mdTemp.update(str.getBytes("UTF-8"));
byte[] md = mdTemp.digest();
int j = md.length;
char[] buf = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
buf[k++] = hexDigits[byte0 & 0xf];
}
return new String(buf);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
}
這個工具類主要驗證了我們開發環境和微信後臺環境的對接。
3. 內網映射到外網
完成上述操作後在瀏覽器通過本地打開我們的WeChatServlet,看是否成功。成功後,就需要將我們內網映射到外網了。
這裏我們使用的是ngrok工具,它的使用方法也很簡單。先從命令提示行裏切換到我們ngrok的安裝路徑,然後執行以下語句:
ngrok -config ngrok.cfg -subdomain wechat 8080
其中wechat是我們起的名字,8080是我們使用的端口。
執行完畢後,它會生成一個外網的http地址,我們用這個地址替換我們本地的地址,看是否映射成功,成功後就可以提交我們的開發者服務器配置了。
URL(服務器地址)就填寫我們外網的地址,Token填寫我們工具類中定義的token,點擊生成EncodingAESKey,然後提交就可以了。
這裏有可能會出現token驗證失敗、或者驗證超時,檢查下我們的代碼,多提交幾次就成功了
提交成功後,點擊啓用開發模式。
這裏注意:開發模式和編輯模式是互相排斥的,二者只能使用一個。
4. 實現消息的接收和響應
返回我們的工程,創建MessageText實體類:
public class TextMessage {
private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
private String Content;
private String MsgId;
}
生成每一個屬性的set和get方法。
這裏注意,每一個屬性的大小寫和全名都要和幫助文檔上的一致。
然後編寫MessageUtil工具類,用來執行Stirng和Map還有xml之間的轉換:
/**
* xml轉換爲map集合
*
* @param request
* @return
* @throws IOException
* @throws DocumentException
*/
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 doc = reader.read(in);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
in.close();
return map;
}
/**
* 將文本消息轉換爲xml
*
* @param textMeesage
* @return
*/
public static String texMessageToXml(TextMessage textMeesage) {
XStream xStream = new XStream();
xStream.alias("xml", textMeesage.getClass());
return xStream.toXML(textMeesage);
}
這裏還需要兩個jar包,沒有的需要下載一下,一個是解析xml的dom4j的jar包,一個是轉換xml的xstream的jar包。
完成後,再重寫我們的WeChatServlet裏面的doPost方法:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try {
Map<String, String> map = MessageUtil.xmlToMap(request);
String fromUserName = map.get("FromUserName");
String toUserName = map.get("ToUserName");
String msgType = map.get("MsgType");
String content = map.get("Content");
String message = null;
if ("text".equals(msgType)) {
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType("text");
text.setCreateTime(new Date().getTime());
text.setContent("您發送的消息是:" + content);
message = MessageUtil.texMessageToXml(text);
}
System.out.println(message);
out.print(message);
} catch (DocumentException e) {
e.printStackTrace();
} finally {
out.close();
}
}
然後測試向公衆號發送消息,它已經可以根據你發的消息做自動回覆了!5. 添加其他的自動回覆等操作
繼續完善我們的工程,使它和我們用編輯器編輯的效果一致。
添加幾種消息類型的常量:
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";
添加生成消息的方法:
/**
* 主菜單
*
* @return
*/
public static String menuText() {
StringBuffer sb = new StringBuffer();
sb.append("歡迎你的關注,請按照菜單提示操作:\n\n");
sb.append("1、近期好看的電影\n");
sb.append("2、87屆奧斯卡獲獎電影\n");
sb.append("回覆?調出幫助菜單");
return sb.toString();
}
/**
* 回覆1的菜單
* @return
*/
public static String firstMenu() {
StringBuffer sb = new StringBuffer();
sb.append("近期口碑不錯的電影推薦——《大聖歸來》,很不錯,建議體驗一下哦~");
return sb.toString();
}
/**
* 回覆2的菜單
* @return
*/
public static String secondMenu() {
StringBuffer sb = new StringBuffer();
sb.append("《消失的愛人》——87屆奧斯卡最佳女主角獲獎電影,愛情懸疑類型電影迷的最愛。");
return sb.toString();
}
修改WeChatServlet類,根據不同消息做出不同的回覆:
if (MessageUtil.MESSAGE_TEXT.equals(msgType)) {
if ("1".equals(content)) {
message = MessageUtil.initText(toUserName, fromUserName,
MessageUtil.firstMenu());
} else if ("2".equals(content)) {
message = MessageUtil.initText(toUserName, fromUserName,
MessageUtil.secondMenu());
} else if ("?".equals(content) || "?".equals(content)) {
message = MessageUtil.initText(toUserName, fromUserName,
MessageUtil.menuText());
}
// TextMessage text = new TextMessage();
// text.setFromUserName(toUserName);
// text.setToUserName(fromUserName);
// text.setMsgType("text");
// text.setCreateTime(new Date().getTime());
// text.setContent("您發送的消息是:" + content);
// message = MessageUtil.texMessageToXml(text);
} else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) {
String eventType = map.get("Event");
if (MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)) {
message = MessageUtil.initText(toUserName, fromUserName,
MessageUtil.menuText());
}
}
OK~