微信公眾號測試賬號-訊息管理/事件推送
記錄一下微信公眾號開發的時候的一些過程。。。
首先註冊一個微信公眾測試賬號,雖然個人註冊的訂閱號也有此功能,但是卻沒有使用者管理功能,所以這裡就先拿測試賬號開發微信公眾號。。。
申請微信測試號在這裡http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
成功申請之後會有自己的APPID和appsecret。。。
微信開發者文件在這裡 。。。 http://mp.weixin.qq.com/wiki/home/index.html
開發人員可以根據該文件對微信公眾號進行介面的開發。。。
簡單的申請完之後。。。嘗試配置介面配置資訊需要填寫公網可以訪問的連結地址以及TOKEN,以確定微信可以訪問你的程式。。。
公網能訪問的連結地址不一定是特意去申請的域名或者買伺服器,可以用國內已有的一些網路對映工具,這裡我用的是Sunny-Ngrok啟動工具,也可以用花生殼。。。
根據這些對映工具,可以在公網上訪問該網址。。。這樣微信也可以訪問我的程式來呼叫相應的服務。。。
package org.ssm.maven.test1.controller;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/wechat")
public class WechatValidToken {
public static final String TOKEN = "ivy";
private static char[] hexDigits = { '0', '1', '2', '3', '4', '5' , '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
'f' };
@RequestMapping(value="/valid", method = RequestMethod.GET)
@ResponseBody
public String validToken( HttpServletRequest request) {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
String[] paramStr = new String[] { TOKEN, timestamp, nonce };
Arrays.sort(paramStr);
String str="";
for(String s : paramStr){
str += s;
}
String afterSha1 = sha1(str);
if (afterSha1.equals(signature))
return echostr;
else
return "null";
}
private static String sha1(String source) {
if ((source == null) || source.isEmpty()) {
return source;
}
try {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
byte[] sha1Bytes = sha1.digest(source.getBytes());
return toHexArray(sha1Bytes);
} catch (Exception e) {
// do nothing
}
return source;
}
private static String toHexArray(byte[] array) {
char[] resultCharArray = new char[array.length * 2];
int index = 0;
for (byte b : array) {
resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
return new String(resultCharArray);
}
}
該程式碼用於微信校驗是否接收到資訊的功能。。。
我的微信公眾號的後臺是基於ssm的java企業級的程式,關於ssm的配置檔案在網上隨便百度都可以找得到。。。
對於訂閱號的訊息管理,微信公眾平臺提供了簡單的對於訊息管理的功能。。。對於不是開發人員來說該功能已經能滿足普通微信公眾號的需求。。。
但是對於需求不僅滿足於普通的資訊管理的系統而言,這只是冰山一角。。。
對於訊息資訊管理分為以下幾類:
1 文字訊息
2 圖片訊息
3 語音訊息
4 視訊訊息
5 小視訊訊息
6 地理位置訊息
7 連結訊息
當普通微信使用者向公眾賬號發訊息時,微信伺服器將POST訊息的XML資料包到開發者填寫的URL上。。。
文字訊息
package org.ssm.maven.test1.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.ssm.maven.test1.model.TextMessage;
import org.ssm.maven.test1.util.MessageType;
import org.ssm.maven.test1.util.MessageUtil;
@Controller
@RequestMapping("/wechat")
public class WechatController {
@RequestMapping(value = "/valid", method = RequestMethod.POST)
@ResponseBody
public String accpetMessage(HttpServletRequest request) throws IOException {
request.setCharacterEncoding("utf-8");
Map<String, String> param = MessageUtil.xmlToMap(request);
String fromUserName = param.get("FromUserName");
String toUserName = param.get("ToUserName");
String msgType = param.get("MsgType");
String content = param.get("Content");
Long createTime = Long.valueOf(param.get("CreateTime"));
Long msgId = Long.valueOf(param.get("MsgId") );
System.out.println("--------->" + param);
String message = null;
if (MessageType.TEXT.equals(msgType)) {
if ("1".equals(content)) {
message = MessageUtil.initText(MessageUtil.firstMenu(), createTime, fromUserName, toUserName, msgId);
} else if ("2".equals(content)) {
message = MessageUtil.initNewsMessage(toUserName, fromUserName);
} else if ("?".equals(content)) {
message = MessageUtil.initText(MessageUtil.menuText(), createTime, fromUserName, toUserName, msgId);
} else {
TextMessage text = new TextMessage();
text.setContent("the message is:" + content);
text.setCreateTime(createTime);
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setMsgType("text");
message = MessageUtil.textMessageToXml(text);
System.out.println("message--------->" + message);
}
// StringBuffer sb = new StringBuffer();
// sb.append("<xml>");
// sb.append("<ToUserName><![CDATA[" + fromUserName +
// "]]></ToUserName>");
// sb.append("<FromUserName><![CDATA[" + toUserName +
// "]]></FromUserName>");
// sb.append("<CreateTime>" + new Date().getTime() +
// "</CreateTime>");
// sb.append("<MsgType><![CDATA[text]]></MsgType>");
// sb.append("<Content><![CDATA[this is a test]]></Content>");
// sb.append("<MsgId>1234567890123456</MsgId>");
// sb.append("</xml>");
// response.getWriter().write(message);
} else if (MessageType.EVENT.equals(msgType)) {
String event = param.get("Event");
if (MessageType.SUBSCRIBE.equals(event)) {
message = MessageUtil.initText(MessageUtil.menuText(), createTime, fromUserName, toUserName, msgId);
} else if (MessageType.CLICK.equals(event)) {
message = MessageUtil.initText(MessageUtil.menuText(), createTime, fromUserName, toUserName, msgId);
} else if (MessageType.VIEW.equals(event)) {
message = MessageUtil.initText(param.get("EventKey"), createTime, fromUserName, toUserName, msgId);
} else if (MessageType.SCANCODE.equals(event)) {
message = MessageUtil.initText(param.get("EventKey"), createTime, fromUserName, toUserName, msgId);
}
} else if (MessageType.LOCATION.equals(msgType)) {
message = MessageUtil.initText(param.get("Label"), createTime, fromUserName, toUserName, msgId);
}
return message;
}
}
訊息型別主要分為
package org.ssm.maven.test1.util;
public class MessageType {
public static final String TEXT = "text";
public static final String NEWS = "news";
public static final String IMAGE = "image";
public static final String VOICE = "voice";
public static final String VIDEO = "video";
public static final String SHORTVIDEO = "shortvideo";
public static final String LINK = "link";
public static final String LOCATION = "location";
public static final String EVENT = "event";
public static final String SUBSCRIBE = "subscribe";//event
public static final String UNSUBSCRIBE = "unsubscribe";//event
public static final String CLICK = "CLICK";//event
public static final String VIEW = "VIEW";//event
public static final String SCANCODE = "scancode_push";//event
}
大致用到的分為這幾類,subscribe,unsubscribe,CLICK,VIEW,scancode_push為event下
程式入口沿用了之間接收訊息介面的名稱。。。
這裡附上轉化成xml的程式碼以及初始化訊息返回的程式碼。。。
package org.ssm.maven.test1.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.charset.Charset;
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 org.ssm.maven.test1.controller.WechatController;
import org.ssm.maven.test1.model.TextMessage;
import org.ssm.maven.test1.model.WechatNews;
import org.ssm.maven.test1.model.WechatNewsMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
public class MessageUtil {
protected static String PREFIX_CDATA = "<![CDATA[";
protected static String SUFFIX_CDATA = "]]>";
/**
* xml to map����
* @param request
* @return
*/
public static Map<String, String> xmlToMap(HttpServletRequest request){
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
try {
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element element : list) {
map.put(element.getName(), element.getText());
}
ins.close();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
return map;
}
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
public static String newsMessageToXml(WechatNewsMessage wechatNewsMessage){
XStream xstream = new XStream();
xstream.alias("xml", wechatNewsMessage.getClass());
xstream.alias("item", new WechatNews().getClass());
return xstream.toXML(wechatNewsMessage);
}
/*初始化文字訊息*/
public static String initText(String content, Long createTime, String fromUserName, String toUserName, Long msgId){
String message = "";
TextMessage text = new TextMessage();
text.setContent("the message is:"+content);
text.setCreateTime(createTime);
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setMsgType(MessageType.TEXT);
text.setMsgId(msgId);
message = MessageUtil.textMessageToXml(text);
System.out.println("message--------->" + message);
return message;
}
/*初始化圖文訊息*/
public static String initNewsMessage(String toUserName, String fromUserName){
String message = "";
WechatNewsMessage wechatNewsMessage = new WechatNewsMessage();
WechatNews wechatNews = new WechatNews();
WechatNews wechatNews1 = new WechatNews();
List<WechatNews> wechatNewss = new ArrayList<WechatNews>();
wechatNews.setTitle("ivy's description");
wechatNews.setPicUrl("http://ivytest.ngrok.cc/org.ssm.maven.test1/images/IMG_0151.JPG");
wechatNews.setUrl("http://ivytest.ngrok.cc/org.ssm.maven.test1/images/IMG_0151.JPG");
wechatNews.setDescription("i am ivy");
wechatNews1.setTitle("haha's description");
wechatNews1.setPicUrl("http://ivytest.ngrok.cc/org.ssm.maven.test1/images/IMG_0152.JPG");
wechatNews1.setUrl("http://ivytest.ngrok.cc/org.ssm.maven.test1/images/IMG_0152.JPG");
wechatNews1.setDescription("i am gaga");
wechatNewss.add(wechatNews);
wechatNewss.add(wechatNews1);
wechatNewsMessage.setArticleCount(wechatNewss.size());
wechatNewsMessage.setArticles(wechatNewss);
wechatNewsMessage.setFromUserName(toUserName);
wechatNewsMessage.setToUserName(fromUserName);
wechatNewsMessage.setCreateTime(new Date().getTime());
wechatNewsMessage.setMsgType(MessageType.NEWS);
message = newsMessageToXml(wechatNewsMessage);
return message;
}
public static String menuText(){
StringBuffer sb = new StringBuffer();
sb.append("Welcome here\n");
sb.append("1.text field\n");
sb.append("2.news field\n");
sb.append("enter ? for help\n");
return sb.toString();
}
public static String firstMenu(){
return "Hi,i am ivy";
}
public static String secondMenu(){
return "Bye,i am ivy";
}
}