欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JAVA實現(xiàn) SpringMVC方式的微信接入、實現(xiàn)簡單的自動回復功能

 更新時間:2016年11月07日 13:52:28   作者:helijun  
這篇文章主要介紹了JAVA實現(xiàn) SpringMVC方式的微信接入、實現(xiàn)簡單的自動回復功能的相關資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下

前端時間小忙了一陣,微信公眾號的開發(fā),從零開始看文檔,踩了不少坑,也算是熬過來了,最近考慮做一些總結,方便以后再開發(fā)的時候回顧,也給正在做相關項目的同學做個參考。

其實做過一遍之后會發(fā)現(xiàn)也不難,大致思路:用戶消息和開發(fā)者需要的事件推送都會通過微信方服務器發(fā)起一個請求,轉發(fā)到你在公眾平臺配置的服務器url地址,微信方將帶上signature,timestamp,nonce,echostr四個參數(shù),我們自己服務器通過拼接公眾平臺配置的token,以及傳上來的timestamp,nonce進行SHA1加密后匹配signature,返回ture說明接入成功。

1.公眾平臺配置

2.Controller

@Controller
@RequestMapping("/wechat")
publicclass WechatController {
@Value("${DNBX_TOKEN}")
private String DNBX_TOKEN;
private static final Logger LOGGER = LoggerFactory.getLogger(WechatController.class);
@Resource
WechatService wechatService;
/**
* 微信接入
* @param wc
* @return
* @throws IOException 
*/
@RequestMapping(value="/connect",method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
publicvoid connectWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException{
// 將請求、響應的編碼均設置為UTF-8(防止中文亂碼) 
request.setCharacterEncoding("UTF-8"); //微信服務器POST消息時用的是UTF-8編碼,在接收時也要用同樣的編碼,否則中文會亂碼;
response.setCharacterEncoding("UTF-8"); //在響應消息(回復消息給用戶)時,也將編碼方式設置為UTF-8,原理同上;boolean isGet = request.getMethod().toLowerCase().equals("get"); 
PrintWriter out = response.getWriter();
try {
if (isGet) {
String signature = request.getParameter("signature");// 微信加密簽名 
String timestamp = request.getParameter("timestamp");// 時間戳 
String nonce = request.getParameter("nonce");// 隨機數(shù) 
String echostr = request.getParameter("echostr");//隨機字符串 
// 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗 if (SignUtil.checkSignature(DNBX_TOKEN, signature, timestamp, nonce)) { 
LOGGER.info("Connect the weixin server is successful.");
response.getWriter().write(echostr); 
} else { 
LOGGER.error("Failed to verify the signature!"); 
}
}else{
String respMessage = "異常消息!";
try {
respMessage = wechatService.weixinPost(request);
out.write(respMessage);
LOGGER.info("The request completed successfully");
LOGGER.info("to weixin server "+respMessage);
} catch (Exception e) {
LOGGER.error("Failed to convert the message from weixin!"); 
}
}
} catch (Exception e) {
LOGGER.error("Connect the weixin server is error.");
}finally{
out.close();
}
}
}

 3.簽名驗證 checkSignature

   從上面的controller我們可以看到,我封裝了一個工具類SignUtil,調用了里面的一個叫checkSignature,傳入了四個值,DNBX_TOKEN, signature, timestamp, nonce。這個過程非常重要,其實我們可以理解為將微信傳過來的值進行一個加解密的過程,很多大型的項目所有的接口為保證安全性都會有這樣一個驗證的過程。DNBX_TOKEN我們在微信公眾平臺配置的一個token字符串,主意保密哦!其他三個都是微信服務器發(fā)送get請求傳過來的參數(shù),我們進行一層sha1加密:

public class SignUtil { 
/** 
* 驗證簽名 
* 
* @param token 微信服務器token,在env.properties文件中配置的和在開發(fā)者中心配置的必須一致 
* @param signature 微信服務器傳過來sha1加密的證書簽名
* @param timestamp 時間戳
* @param nonce 隨機數(shù) 
* @return 
*/ 
public static boolean checkSignature(String token,String signature, String timestamp, String nonce) { 
String[] arr = new String[] { token, timestamp, nonce }; 
// 將token、timestamp、nonce三個參數(shù)進行字典序排序 
Arrays.sort(arr); 
// 將三個參數(shù)字符串拼接成一個字符串進行sha1加密 
String tmpStr = SHA1.encode(arr[0] + arr[1] + arr[2]); 
// 將sha1加密后的字符串可與signature對比,標識該請求來源于微信 
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; 
} 
}

SHA1:

/** 
* 微信公眾平臺(JAVA) SDK 
* 
* SHA1算法
* 
* @author helijun 2016/06/15 19:49
*/ 
public final class SHA1 { 
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); 
} 
} 
}

當你在公眾平臺提交保存,并且看到綠色的提示“接入成功”之后,恭喜你已經完成微信接入。這個過程需要細心一點,注意加密算法里的大小寫,如果接入不成功,大多數(shù)情況都是加密算法的問題,多檢查檢查。

4. 實現(xiàn)消息自動回復service

/**
* 處理微信發(fā)來的請求
* 
* @param request
* @return
*/
public String weixinPost(HttpServletRequest request) {
String respMessage = null;
try {
// xml請求解析
Map<String, String> requestMap = MessageUtil.xmlToMap(request);
// 發(fā)送方帳號(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公眾帳號
String toUserName = requestMap.get("ToUserName");
// 消息類型
String msgType = requestMap.get("MsgType");
// 消息內容
String content = requestMap.get("Content");
LOGGER.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType);
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
//這里根據(jù)關鍵字執(zhí)行相應的邏輯,只有你想不到的,沒有做不到的
if(content.equals("xxx")){
}
//自動回復
TextMessage text = new TextMessage();
text.setContent("the text is" + content);
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(msgType);
respMessage = MessageUtil.textMessageToXml(text);
} /*else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {// 事件推送
String eventType = requestMap.get("Event");// 事件類型
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {// 訂閱
respContent = "歡迎關注xxx公眾號!";
return MessageResponse.getTextMessage(fromUserName , toUserName , respContent);
} else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {// 自定義菜單點擊事件
String eventKey = requestMap.get("EventKey");// 事件KEY值,與創(chuàng)建自定義菜單時指定的KEY值對應
logger.info("eventKey is:" +eventKey);
return xxx;
}
}
//開啟微信聲音識別測試 2015-3-30
else if(msgType.equals("voice"))
{
String recvMessage = requestMap.get("Recognition");
//respContent = "收到的語音解析結果:"+recvMessage;
if(recvMessage!=null){
respContent = TulingApiProcess.getTulingResult(recvMessage);
}else{
respContent = "您說的太模糊了,能不能重新說下呢?";
}
return MessageResponse.getTextMessage(fromUserName , toUserName , respContent); 
}
//拍照功能
else if(msgType.equals("pic_sysphoto"))
{
}
else
{
return MessageResponse.getTextMessage(fromUserName , toUserName , "返回為空"); 
}*/
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
String eventType = requestMap.get("Event");// 事件類型
// 訂閱
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
TextMessage text = new TextMessage();
text.setContent("歡迎關注,xxx");
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
respMessage = MessageUtil.textMessageToXml(text);
} 
// TODO 取消訂閱后用戶再收不到公眾號發(fā)送的消息,因此不需要回復消息
else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {// 取消訂閱
} 
// 自定義菜單點擊事件
else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
String eventKey = requestMap.get("EventKey");// 事件KEY值,與創(chuàng)建自定義菜單時指定的KEY值對應
if (eventKey.equals("customer_telephone")) {
TextMessage text = new TextMessage();
text.setContent("0755-86671980");
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
respMessage = MessageUtil.textMessageToXml(text);
}
}
}
}
catch (Exception e) {
Logger.error("error......")
}
return respMessage;
}

先貼代碼如上,大多都有注釋,讀一遍基本語義也懂了不需要多解釋。

簡要思路:當用戶給公眾號發(fā)送消息時,微信服務器會將用戶消息以xml格式通過POST請求到我們配置好的服務器對應的接口,而我們要做的事情就是根據(jù)消息類型等做相應的邏輯處理,并將最后的返回結果也通過xml格式return給微信服務器,微信方再傳達給用戶的這樣一個過程。

有一個地方格外需要注意:

上面標紅的fromUserName和toUserName剛好相反,這也是坑之一,還記得我當時調了很久,明明都沒有問題就是不通,最后把這兩個一換消息就收到了!其實回過頭想也對,返回給微信服務器這時本身角色就變了,所以發(fā)送和接收方也肯定是相反的。

5.MessageUtil

public class MessageUtil {
/** 
* 返回消息類型:文本 
*/ 
public static final String RESP_MESSAGE_TYPE_TEXT = "text"; 
/** 
* 返回消息類型:音樂 
*/ 
public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; 
/** 
* 返回消息類型:圖文 
*/ 
public static final String RESP_MESSAGE_TYPE_NEWS = "news"; 
/** 
* 請求消息類型:文本 
*/ 
public static final String REQ_MESSAGE_TYPE_TEXT = "text"; 
/** 
* 請求消息類型:圖片 
*/ 
public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; 
/** 
* 請求消息類型:鏈接 
*/ 
public static final String REQ_MESSAGE_TYPE_LINK = "link"; 
/** 
* 請求消息類型:地理位置 
*/ 
public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; 
/** 
* 請求消息類型:音頻 
*/ 
public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; 
/** 
* 請求消息類型:推送 
*/ 
public static final String REQ_MESSAGE_TYPE_EVENT = "event"; 
/** 
* 事件類型:subscribe(訂閱) 
*/ 
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; 
/** 
* 事件類型:unsubscribe(取消訂閱) 
*/ 
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; 
/** 
* 事件類型:CLICK(自定義菜單點擊事件) 
*/ 
public static final String EVENT_TYPE_CLICK = "CLICK"; 
}

這里為了程序可讀性、擴展性更好一點,我做了一些封裝,定義了幾個常量,以及將微信傳過來的一些參數(shù)封裝成java bean持久化對象,核心代碼如上。重點講下xml和map之間的轉換

其實這個問題要歸咎于微信是用xml通訊,而我們平時一般是用json,所以可能短時間內會有點不適應

1.引入jar包

<!-- 解析xml -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>

2.xml轉map集合對象

/**
* xml轉換為map
* @param request
* @return
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException{
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
InputStream ins = null;
try {
ins = request.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
Document doc = null;
try {
doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
return map;
} catch (DocumentException e1) {
e1.printStackTrace();
}finally{
ins.close();
}
return null;
}

3.文本消息對象轉換成xml

/** 
* 文本消息對象轉換成xml 
* 
* @param textMessage 文本消息對象 
* @return xml 
*/ 
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}

以上所述是小編給大家介紹的JAVA實現(xiàn) SpringMVC方式的微信接入、實現(xiàn)簡單的自動回復功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

相關文章

  • Spring Boot 深入分析AutoConfigurationImportFilter自動化條件配置源碼

    Spring Boot 深入分析AutoConfigurationImportFilter自動化條件

    這篇文章主要分析了Spring Boot AutoConfigurationImportFilter自動化條件配置源碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-07-07
  • Java開發(fā)中synchronized的定義及用法詳解

    Java開發(fā)中synchronized的定義及用法詳解

    這篇文章主要介紹了Java開發(fā)中synchronized的定義及用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Java多線程之線程的創(chuàng)建

    Java多線程之線程的創(chuàng)建

    這篇文章主要介紹了Java多線程之線程的創(chuàng)建,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Java錯誤問題:找不到或無法加載主類的解決

    Java錯誤問題:找不到或無法加載主類的解決

    這篇文章主要介紹了Java錯誤問題:找不到或無法加載主類的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java正則替換img標簽中src值的方法

    java正則替換img標簽中src值的方法

    今天小編就為大家分享一篇java正則替換img標簽中src值的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Java中統(tǒng)計字符個數(shù)以及反序非相同字符的方法詳解

    Java中統(tǒng)計字符個數(shù)以及反序非相同字符的方法詳解

    本篇文章是對Java中統(tǒng)計字符個數(shù)以及反序非相同字符的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • Intellij IDEA實現(xiàn)springboot熱部署過程解析

    Intellij IDEA實現(xiàn)springboot熱部署過程解析

    這篇文章主要介紹了Intellij IDEA實現(xiàn)springboot熱部署過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • 詳解java開發(fā)webservice的幾種方式

    詳解java開發(fā)webservice的幾種方式

    webservice的應用已經越來越廣泛了,下面介紹幾種在Java體系中開發(fā)webservice的方式,有興趣的可以了解一下。
    2016-11-11
  • Java堆空間爆滿導致宕機的問題分析及解決

    Java堆空間爆滿導致宕機的問題分析及解決

    團隊有一個服務,一直運行的好好的,突然訪問異常了,先是請求超時,然后直接無法訪問,本文將給大家介紹Java堆空間爆滿導致宕機的問題分析及解決,需要的朋友可以參考下
    2024-02-02
  • Java泛型中的通配符舉例詳解

    Java泛型中的通配符舉例詳解

    Java泛型中的通配符是指使用"?"來表示未知類型,可以用于定義泛型類、泛型方法和泛型接口,下面這篇文章主要給大家介紹了關于Java泛型中通配符的相關資料,需要的朋友可以參考下
    2023-06-06

最新評論