微信二次開發
第一步:
已認證的微信公衆號, 或者用測試賬號。只要有一個就行
http://mp.weixin.qq.com/wiki/16/992df48524118c3e89945856694b30cc.html (測試賬號申請地址)
、域名一個。
URL地址說明:該url是你自己的服務端地址,是微信請求你的服務器對應的地址。微信通過該地址與你服務端進行數據交互。
第二步:開發服務端
private String Token = "52weixin"; //
@RequestMapping(value = "firstTest")
@ResponseBody
public void firstTest(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {
log.info("進入請求");
boolean isGet = request.getMethod().toLowerCase().equals("get");
if (isGet) {
//首次接入驗證
access(request, response);
} else {
// 進入POST聊天處理
log.info("enter post");
try {
// 接收消息並返回消息
acceptMessage(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 首次接入驗證URL真實性
*
* @author morning
* @date 2015年2月17日 上午10:53:07
* @param request
* @param response
* @return String
*/
private String access(HttpServletRequest request, HttpServletResponse response) {
String retString = null;
// 驗證URL真實性
log.info("進入驗證access");
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>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
// 2. 將三個參數字符串拼接成一個字符串進行sha1加密
String temp = WxSha1.encode(params.get(0) + params.get(1) + params.get(2));
log.info(temp+ " 對比 " + signature);
if (temp.equals(signature)) {
try {
response.getWriter().write(echostr);
retString="接入成功返回 echostr:" + echostr;
log.info(retString);
return echostr;
} catch (IOException e) {
e.printStackTrace();
}
}
retString="失敗 認證";
log.info(retString);
return retString;
}
/**
* 回覆測試
* @param request
* @param response
* @throws Exception
*/
private void acceptMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, String> map = new HashMap<String, String>();
// 從request中取得輸入流
InputStream inputStream = request.getInputStream();
// 讀取輸入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子節點
List<Element> elementList = root.elements();
System.out.println("xml是:"+elementList.toString());
// 遍歷所有子節點
for (Element e : elementList)
map.put(e.getName(), e.getText());
// 釋放資源
inputStream.close();
inputStream = null;
PrintWriter out= response.getWriter();
if(map.get("MsgType").equals("event")){//首次關注回覆。
if(map.get("Event").equals("subscribe")){//訂閱
StringBuffer firstReturn= new StringBuffer();
firstReturn.append("歡迎你關注xx公衆平臺 \n");
out.print(new dom2Xml().getBackXMLTypeText(map.get("FromUserName"), map.get("ToUserName"), firstReturn.toString()));
}
}else {
//微信端回覆 “圖文測試”
if(map.get("Content").equals("圖文測試")){
out.print(new dom2Xml().getBackXMLTypeTextPicUrl(map.get("FromUserName"), map.get("ToUserName"), "這是標題",
"簡單描述", "http://img1.moko.cc/users/15/4670/1401096/post/89/img1_cover_6639195.jpg", "http://www.baidu.com"));
log.info("發送圖文消息");
}
out.print(new dom2Xml().getBackXMLTypeText(map.get("FromUserName"), map.get("ToUserName"), "程序員努力開發中。。。"));
}
if(out!=null){
out.flush();
out.close();
}
}
------------------------------------------------------------------
public class dom2Xml {
/**
* 純文本回復
* @param toName
* @param fromName
* @param content
* @return
*/
public String getBackXMLTypeText(String toName, String fromName,
String content) {
String returnStr = "";
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String times = format.format(new Date());
Element rootXML = new Element("xml");
rootXML.addContent(new Element("ToUserName").setText(toName));
rootXML.addContent(new Element("FromUserName").setText(fromName));
rootXML.addContent(new Element("CreateTime").setText(times));
rootXML.addContent(new Element("MsgType").setText("text"));
rootXML.addContent(new Element("Content").setText(content));
Document doc = new Document(rootXML);
XMLOutputter XMLOut = new XMLOutputter();
returnStr = XMLOut.outputString(doc);
return returnStr;
}
/**
* 回覆一個圖文、跳轉鏈接
* @param toName
* @param fromName
* @param content
* @return
*/
public String getBackXMLTypeTextPicUrl(String toName, String fromName,
String title,String description,String picUrl,String url) {
String returnStr = "";
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String times = format.format(new Date());
Element rootXML = new Element("xml");
rootXML.addContent(new Element("ToUserName").setText(toName));
rootXML.addContent(new Element("FromUserName").setText(fromName));
rootXML.addContent(new Element("CreateTime").setText(times));
rootXML.addContent(new Element("MsgType").setText("news"));
rootXML.addContent(new Element("ArticleCount").setText("1"));
Element articles = new Element("Articles");
Element item = new Element("item");
item.addContent(new Element("Title").setText(title));
item.addContent(new Element("Description").setText(description));
item.addContent(new Element("PicUrl").setText(picUrl));
item.addContent(new Element("Url").setText(url));
articles.addContent(item);
rootXML.addContent(articles);
Document doc = new Document(rootXML);
XMLOutputter XMLOut = new XMLOutputter();
returnStr = XMLOut.outputString(doc);
return returnStr;
}
加密工具
/**
* <p>
* Title: SHA1算法
* </p>
*
*/
public final class WxSha1 {
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* Takes the raw bytes from the digest and formats them correct.
*
* @param bytes
* the raw bytes from the digest.
* @return the formatted bytes.
*/
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
// 把密文轉換成十六進制的字符串形式
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.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);
}
}
}
第三步:配置
域名解析 項目放上去
測試賬號只需配這個就行 Token 就是上面代碼紅色部分
正式賬號配下面這個
點擊提交! 看反應。。。
一個app後臺框架介紹:http://blog.csdn.net/jialiuyang/article/details/46842477