Java微信公众号开发(附源码!!!)
筆者最近在為一個藝考服務(wù)團隊開發(fā)手機端的服務(wù),由于開發(fā)app需要的時間較長,所以選擇開發(fā)微信公眾號。本人比較擅長Java開發(fā),所以本文是基于Java語言的公眾號開發(fā)。話不多說,直接進入正題。
準備工作:
一、在微信公眾平臺申請賬號。
百度搜索微信公眾平臺,點擊注冊,通過郵箱注冊成功后會看到如下畫面。
在這里,選擇類型時要注意下。如果你是個人開發(fā)的話只能選擇訂閱號,訂閱號沒有自定義菜單等接口,具體接口權(quán)限你可以登錄公眾平臺后在開發(fā)--->接口權(quán)限中看到。如果你想擁有自定義菜單等接口,需要注冊服務(wù)號,但是服務(wù)號只能企業(yè)、組織等注冊。本人想做的公眾號是要求有自定義菜單的,并且委托我開發(fā)的團隊是一家公司,所以注冊的服務(wù)號。無論你是訂閱號還是服務(wù)號都不影響本文的閱讀。
注冊完登錄進入公眾平臺,微信會給你分配屬于你的AppID和AppSecret,在開發(fā)--->基本配置中可以看到。有了這兩個ID和密鑰你就可以開發(fā)你的公眾號了。以上為準備工作。
代碼編寫
一、創(chuàng)建自定義菜單(不需要自定義菜單的讀者可以跳過該節(jié))
本文中沒有使用Java框架,采用的是原生jdbc和servlet,這樣可以確保在云服務(wù)器配置有限的情況下提升公眾號的響應(yīng)速度。
新建CreateMenuServlet,該servlet用于創(chuàng)建自定義菜單。doGet方法中的代碼如下:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 第三方用戶唯一憑證 ?
? ? ? ? String appId = "你的APPID"; ?
? ? ? ? // 第三方用戶唯一憑證密鑰 ?
? ? ? ? String appSecret = "你的appSecret"; ?
??
? ? ? ? // 調(diào)用接口獲取access_token ?
? ? ? ? AccessToken at = WeixinUtil.getAccessToken(appId, appSecret); ?
??
? ? ? ? if (null != at) { ?
? ? ? ? ? ? // 調(diào)用接口創(chuàng)建菜單 ?
? ? ? ? ? ? int result = WeixinUtil.createMenu(getMenu(), at.getToken()); ?
??
? ? ? ? ? ? // 判斷菜單創(chuàng)建結(jié)果 ?
? ? ? ? ? ? if (0 == result){
? ? ? ? ? ? response.setContentType("text/html;charset=UTF-8"); ?
? ? ? ? ? ? PrintWriter pw = response.getWriter(); ?
? ? ? ? ? ?pw.println("菜單創(chuàng)建成功!"); ?
? ? ? ? ? ?pw.flush(); ? ??
? ? ? ? ? ? }else{
? ? ? ? ? ? response.setContentType("text/html;charset=UTF-8"); ?
? ? ? ? ? ? PrintWriter pw = response.getWriter(); ?
? ? ? ? ? ?pw.println("菜單創(chuàng)建失敗,錯誤碼:" + result); ?
? ? ? ? ? ?pw.flush(); ? ??
? ? ? ? ? ? } ??
? ? ? ? }
}
AccessToken類代碼如下:
public class AccessToken {
// 獲取到的憑證 ?
? ? private String token; ?
? ? // 憑證有效時間,單位:秒 ?
? ? private int expiresIn; ?
??
? ? public String getToken() { ?
? ? ? ? return token; ?
? ? } ?
??
? ? public void setToken(String token) { ?
? ? ? ? this.token = token; ?
? ? } ?
??
? ? public int getExpiresIn() { ?
? ? ? ? return expiresIn; ?
? ? } ?
??
? ? public void setExpiresIn(int expiresIn) { ?
? ? ? ? this.expiresIn = expiresIn; ?
? ? } ?
}
WeixinUtil類主要功能是用于調(diào)用微信提供的接口來創(chuàng)建菜單,因全部代碼過長,不便貼出,會在后面的源碼中給出。
getMenu方法代碼如下,其中Menu、CommonButton等是我自定義的類,它可以實現(xiàn)一級菜單、二級菜單等效果。每一個按鈕都有它自己的Type和key,type用于說明該按鈕的類型,即點擊之后回復消息還是跳轉(zhuǎn)網(wǎng)頁;key用于唯一定義該按鈕,后面會通過這個key來判斷哪個按鈕被點擊了。
private static Menu getMenu() { ?
? ? ? ? CommonButton btn11 = new CommonButton(); ?
? ? ? ? btn11.setName("個人信息查看"); ?
? ? ? ? btn11.setType("click"); ?
? ? ? ? btn11.setKey("stuInfoView"); ?
??
? ? ? ? CommonButton btn12 = new CommonButton(); ?
? ? ? ? btn12.setName("個人信息修改"); ?
? ? ? ? btn12.setType("click"); ?
? ? ? ? btn12.setKey("stuInfoEdit");?
??
? ? ? ? CommonButton btn21 = new CommonButton(); ?
? ? ? ? btn21.setName("行程查看"); ?
? ? ? ? btn21.setType("click"); ?
? ? ? ? btn21.setKey("stuTravelView"); ?
??
? ? ? ? CommonButton btn22 = new CommonButton(); ?
? ? ? ? btn22.setName("行程添加"); ?
? ? ? ? btn22.setType("click"); ?
? ? ? ? btn22.setKey("stuTravelAdd"); ?
??
? ? ? ? CommonButton btn23 = new CommonButton(); ?
? ? ? ? btn23.setName("行程修改"); ?
? ? ? ? btn23.setType("click"); ?
? ? ? ? btn23.setKey("stuTravelEdit"); ?
??
? ? ? ? ComplexButton mainBtn1 = new ComplexButton(); ?
? ? ? ? mainBtn1.setName("個人信息"); ?
? ? ? ? mainBtn1.setSub_button(new Button[] { btn11, btn12}); ?
??
? ? ? ? Menu menu = new Menu(); ?
? ? ? ? menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 }); ?
??
? ? ? ? return menu; ?
? ? }?
在瀏覽器中運行l(wèi)ocalhost:8080/WechatDemo/CreateMenuServlet,如果頁面顯示“菜單創(chuàng)建成功!"說明菜單已創(chuàng)建,在公眾號中效果如下圖:
二、接收消息并作出響應(yīng)
新建EastnetServlet,該Servlet用于公眾號接收用戶的消息并作出響應(yīng)返回給用戶。
doGet方法代碼如下:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("接口測試開始!!!");
//微信加密簽名
String signature = request.getParameter("signature");
//時間戳
String timestamp = request.getParameter("timestamp");
//隨機數(shù)
String nonce = request.getParameter("nonce");
//隨機字符串
String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
//通過校驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗
if(SignUtil.checkSignature(signature,timestamp,nonce)){
out.print(echostr);
}
out.close();
out = null;
}
SignUtil類中checkSignature方法代碼如下:
private static String token ?= "你的token";
public static boolean checkSignature(String signature, String timestamp,
String nonce) {
String[] arra = new String[]{token,timestamp,nonce};
//將signature,timestamp,nonce組成數(shù)組進行字典排序
Arrays.sort(arra);
StringBuilder sb = new StringBuilder();
for(int i=0;i<arra.length;i++){
sb.append(arra[i]);
}
MessageDigest md = null;
String stnStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(sb.toString().getBytes());
stnStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//釋放內(nèi)存
sb = null;
//將sha1加密后的字符串與signature對比,標識該請求來源于微信
return stnStr!=null?stnStr.equals(signature.toUpperCase()):false;
}
token設(shè)置在開發(fā)--->基本配置中有Token(令牌),上面的token要和公眾號中設(shè)置的token一致。
以上doGet方法中的代碼是用于確認請求來源于微信服務(wù)器,滿足微信API。
doPost方法中代碼如下:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//消息的接受、處理、響應(yīng)
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//調(diào)用核心業(yè)務(wù)類型接受消息、處理消息
String respMessage = EastnetService.processRequest(request);
//響應(yīng)消息
PrintWriter out = response.getWriter();
out.print(respMessage);
out.close();
}
doPost中用于處理接收到的消息,其中EastnetService為業(yè)務(wù)層,專門用于處理消息并作出響應(yīng)。
EastnetService中processRequest方法部分代碼如下:
public static String processRequest(HttpServletRequest request) {
String respMessage = null;
//默認返回的文本消息類容
String respContent = "請求處理異常,請稍后嘗試!";
String fromUserName="";
String toUserName ="";
String msgType ="";
try {
//xml請求解析
Map<String,String> requestMap = MessageUtil.pareXml(request);
//發(fā)送方賬號(open_id)
fromUserName = requestMap.get("FromUserName");
//公眾賬號
toUserName = requestMap.get("ToUserName");
//消息類型
msgType = requestMap.get("MsgType");
// String eventType = requestMap.get("Event");
String fromContent=requestMap.get("Content");
String userName="";
if((MessageUtil.REQ_MESSSAGE_TYPE_EVENT).equals(msgType)){
// 事件類型
String eventType = requestMap.get("Event");
if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
// 事件KEY值,與創(chuàng)建自定義菜單時指定的KEY值對應(yīng)
String eventKey = requestMap.get("EventKey");
if ("stuInfoEdit".equals(eventKey)) {//個人信息修改
respContent=new OperatorUtil().editStuInfo(fromUserName);
}else if("stuInfoView".equals(eventKey)){
respContent=new OperatorUtil().viewStuInfo(fromUserName);
}else if("stuTravelView".equals(eventKey)){//行程查看
respContent=new OperatorUtil().viewTravel(fromUserName);
}else if("stuTravelAdd".equals(eventKey)){//行程添加
respContent=new OperatorUtil().addTravel(fromUserName);
}else if("stuTravelEdit".equals(eventKey)){//行程修改
respContent=new OperatorUtil().editTravel(fromUserName);
}else{
respContent="請求失敗";
}
}
}
//訂閱
String eventTypeSub = requestMap.get("Event");
if((MessageUtil.EVENT_TYPE_SUBSCRIBE).equals(eventTypeSub)){
respContent = "景程教育歡迎您的到來! \n 回復\"用戶名綁定\"+登錄用戶名 ?如:用戶名綁定fangw ?可完成賬號綁定!\n 只有綁定賬號后才可以實現(xiàn)接下來的操作";
}
//回復文本消息
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(toUserName);
textMessage.setFromUserName(fromUserName);
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(MessageUtil.RESP_MESSSAGE_TYPE_TEXT);
textMessage.setFuncFlag(0);
StringBuffer sb=new StringBuffer();
respMessage=("<xml><ToUserName><![CDATA["+requestMap.get("FromUserName")+
"]]></ToUserName>"+"<FromUserName><![CDATA["+requestMap.get("ToUserName")
+"]]></FromUserName><CreateTime>"+System.currentTimeMillis()+"</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA["+respContent+"]]></Content></xml>");
} catch (Exception e) {
respMessage=("<xml><ToUserName><![CDATA["+fromUserName+
"]]></ToUserName>"+"<FromUserName><![CDATA["+toUserName
+"]]></FromUserName><CreateTime>"+System.currentTimeMillis()+"</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA["+respContent+"]]></Content></xml>");
}
return respMessage;
}
上面代碼中MessageUtil.pareXml用于解析request中攜帶的內(nèi)容,將fromUserName、toUserName、msgType等內(nèi)容解析出來,用于公眾號對消息作出響應(yīng)。OperatorUtil類用于操作數(shù)據(jù)庫,暫且不用管。respMessage是公眾號發(fā)送給用戶的響應(yīng)消息,要滿足微信api要求的xml格式。
以上就是基于Java的微信公眾號開發(fā)實例,具體效果如下:
源碼地址:http://download.csdn.net/detail/fanguoddd/9746510
沒有下載積分的童鞋看這里!!!掃描公眾號二維碼免費獲取。公眾號二維碼:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
歡迎在評論區(qū)留言,我會盡快回復~~~
最后,打波廣告。微信搜索公眾號"購即省",淘寶購物領(lǐng)券,購物即省錢。
?
總結(jié)
以上是生活随笔為你收集整理的Java微信公众号开发(附源码!!!)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最短公共超序列(最短公共父序列)
- 下一篇: 华为机试真题 Java实现【最短木板长度