1. 程式人生 > >微信公眾號開發--接收與回覆訊息(Java)

微信公眾號開發--接收與回覆訊息(Java)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

第一步:配置微信公眾號

進入微信公眾平臺地址

這裡寫圖片描述

進入基本配置

這裡寫圖片描述

這裡需要填寫的有伺服器的URL、Token兩個地方

URL

是一個公網地址,只能接收80埠的(http預設埠)

http://公網地址/專案名稱/請求路徑

Token

在校驗的時候需要用到,隨便輸入一個字串就可以了

開發者提交資訊後,微信伺服器將傳送GET請求到填寫的伺服器地址URL上,GET請求攜帶四個引數 
引數 描述 
signature 微信加密簽名,signature結合了開發者填寫的token引數和請求中的timestamp引數、nonce引數。 
timestamp 時間戳 
nonce 隨機數 
echostr 隨機字串

所以需要編寫相應的Controller(採用spring MVC)

    /**     * 驗證微信伺服器     *      *
@param response     * @param signature     * @param timestamp     * @param nonce     * @param echostr     */
    @RequestMapping(value = "/wechat", method = RequestMethod.GET)    public
void wechatService(PrintWriter out, HttpServletResponse response,            @RequestParam(value = "signature", required = false) String signature, @RequestParam String timestamp,            @RequestParam String nonce, @RequestParam String echostr) {        if (CheckUtil.checkSignature(signature, timestamp, nonce)) {            out.print(echostr);        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

CheckUtil.Java

package com.wechat.utils;import java.util.Arrays;/** *  * 校驗工具類 * 開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信伺服器,請原樣返回echostr引數內容,則接入生效, * 成為開發者成功,否則接入失敗。 *  * @author GWCheng * */public class CheckUtil {    //配置微信公眾號時填寫的Token    private static final String token = "chenggaowei";    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 tmp = DecriptUtil.SHA1(content.toString());        return tmp.equals(signature);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

DecriptUtil.java

import java.io.UnsupportedEncodingException;import java.security.InvalidKeyException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.KeyGenerator;import javax.crypto.NoSuchPaddingException;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;/** * 各種加密解密 * */public class DecriptUtil {    public static String SHA1(String decript) {        try {            MessageDigest digest = java.security.MessageDigest                    .getInstance("SHA-1");            digest.update(decript.getBytes());            byte messageDigest[] = digest.digest();            // Create Hex String            StringBuffer hexString = new StringBuffer();            // 位元組陣列轉換為 十六進位制 數            for (int i = 0; i < messageDigest.length; i++) {                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);                if (shaHex.length() < 2) {                    hexString.append(0);                }                hexString.append(shaHex);            }            return hexString.toString();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        return "";    }    public static String SHA(String decript) {        try {            MessageDigest digest = java.security.MessageDigest                    .getInstance("SHA");            digest.update(decript.getBytes());            byte messageDigest[] = digest.digest();            // Create Hex String            StringBuffer hexString = new StringBuffer();            // 位元組陣列轉換為 十六進位制 數            for (int i = 0; i < messageDigest.length; i++) {                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);                if (shaHex.length() < 2) {                    hexString.append(0);                }                hexString.append(shaHex);            }            return hexString.toString();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        return "";    }    public static String MD5(String input) {        try {            // 獲得MD5摘要演算法的 MessageDigest 物件            MessageDigest mdInst = MessageDigest.getInstance("MD5");            // 使用指定的位元組更新摘要            mdInst.update(input.getBytes());            // 獲得密文            byte[] md = mdInst.digest();            // 把密文轉換成十六進位制的字串形式            StringBuffer hexString = new StringBuffer();            // 位元組陣列轉換為 十六進位制 數            for (int i = 0; i < md.length; i++) {                String shaHex = Integer.toHexString(md[i] & 0xFF);                if (shaHex.length() < 2) {                    hexString.append(0);                }                hexString.append(shaHex);            }            return hexString.toString();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        return "";    }    /**     * 加密     *     * @param content     *            需要加密的內容     * @param password     *            加密密碼     * @return     */    public static byte[] encryptAES(String content, String password) {        try {            KeyGenerator kgen = KeyGenerator.getInstance("AES");            kgen.init(128, new SecureRandom(password.getBytes()));            SecretKey secretKey = kgen.generateKey();            byte[] enCodeFormat = secretKey.getEncoded();            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");            Cipher cipher = Cipher.getInstance("AES");// 建立密碼器            byte[] byteContent = content.getBytes("utf-8");            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化            byte[] result = cipher.doFinal(byteContent);            return result; // 加密        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        }        return null;    }    /**     * 解密     *     * @param content     *            待解密內容     * @param password     *            解密金鑰     * @return     */    public static byte[] decryptAES(byte[] content, String password) {        try {            KeyGenerator kgen = KeyGenerator.getInstance("AES");            kgen.init(128, new SecureRandom(password.getBytes()));            SecretKey secretKey = kgen.generateKey();            byte[] enCodeFormat = secretKey.getEncoded();            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");            Cipher cipher = Cipher.getInstance("AES");// 建立密碼器            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化            byte[] result = cipher.doFinal(content);            return result; // 加密        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        }        return null;    }    /**     * BASE64解密     *     * @param key     * @return     * @throws Exception     */    public static String decryptBASE64(String key) {        return "";    }    /**     * BASE64加密     *     * @param key     * @return     * @throws Exception     */    public static String encryptBASE64(String key) {        return "";    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187

驗證寫好了就可以點選提交了

配置成功之後會有如下的提示資訊

這裡寫圖片描述

下面是微信發過來的四個引數,以及給微信回覆的echostr

這裡寫圖片描述

至此開發環境已經配置好了!

第二步:接收訊息

環境配置好之後就可以開發了

微信會將發往公眾賬號的訊息發到我們配置的URL中,以POST的方式

​當普通微信使用者向公眾賬號發訊息時,微信伺服器將POST訊息的XML資料包到開發者填寫的URL上。

以下是debug的資訊

這裡寫圖片描述

微信已經將發往公眾賬號的訊息發到了我們配置的伺服器地址

xml訊息不太利於編寫程式,所以需要對xml訊息進行相應的轉換,這裡將其轉會為map

將xml轉換為map

    /**     * 將xml轉化為Map集合     *      * @param request     * @return     */    public static Map<String, String> xmlToMap(HttpServletRequest request) {        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);        } catch (DocumentException e1) {            e1.printStackTrace();        }        Element root = doc.getRootElement();        @SuppressWarnings("unchecked")        List<Element> list = root.elements();        for (Element e : list) {            map.put(e.getName(), e.getText());        }        try {            ins.close();        } catch (IOException e1) {            e1.printStackTrace();        }        return map;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

用到的jar包

dom4j.jar

這個方法寫好之後就可以呼叫了:

Controller如下,微信發過來的訊息用POST接收

    /**     * 接收來自微信發來的訊息     *      * @param out     * @param request     * @param response     */    @ResponseBody    @RequestMapping(value = "/wechat", method = RequestMethod.POST)    public void wechatServicePost(PrintWriter out, HttpServletRequest request, HttpServletResponse response) {        String responseMessage = wechatService.processRequest(request);        out.print(responseMessage);        out.flush();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Controller呼叫Service的方法(給使用者返回訊息,也是一個xml格式的字串)

Service關鍵程式碼如下

@Servicepublic class WechatService {    private static Logger log = Logger.getLogger(WechatService.class);    public String processRequest(HttpServletRequest request) {        Map<String, String> map = WechatMessageUtil.xmlToMap(request);        log.info(map);        // 傳送方帳號(一個OpenID)        String fromUserName = map.get("FromUserName");        // 開發者微訊號        String toUserName = map.get("ToUserName");        // 訊息型別        String msgType = map.get("MsgType");        // 預設回覆一個"success"        String responseMessage = "success";        // 對訊息進行處理        if (WechatMessageUtil.MESSAGE_TEXT.equals(msgType)) {// 文字訊息            TextMessage textMessage = new TextMessage();            textMessage.setMsgType(WechatMessageUtil.MESSAGE_TEXT);            textMessage.setToUserName(fromUserName);            textMessage.setFromUserName(toUserName);            textMessage.setCreateTime(System.currentTimeMillis());            textMessage.setContent("我已經受到你發來的訊息了");            responseMessage = WechatMessageUtil.textMessageToXml(textMessage);        }        log.info(responseMessage);        return responseMessage;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Servie呼叫WechatMessageUtil將reques中的xml轉換為map

WechatMessageUtil.java如下

import java.io.IOException;import java.io.InputStream;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 com.thoughtworks.xstream.XStream;import com.wechat.entity.vo.wechat.message.TextMessage;public class WechatMessageUtil {    // 各種訊息型別,除了掃帶二維碼事件    /**     * 文字訊息     */    public static final String MESSAGE_TEXT = "text";    /**     * 圖片訊息     */    public static final String MESSAtGE_IMAGE = "image";    /**     * 圖文訊息     */    public static final String MESSAGE_NEWS = "news";    /**     * 語音訊息     */    public static final String MESSAGE_VOICE = "voice";    /**     * 視訊訊息     */    public static final String MESSAGE_VIDEO = "video";    /**     * 小視訊訊息     */    public static final String MESSAGE_SHORTVIDEO = "shortvideo";    /**     * 地理位置訊息     */    public static final String MESSAGE_LOCATION = "location";    /**     * 連結訊息     */    public static final String MESSAGE_LINK = "link";    /**     * 事件推送訊息     */    public static final String MESSAGE_EVENT = "event";    /**     * 事件推送訊息中,事件型別,subscribe(訂閱)     */    public static final String MESSAGE_EVENT_SUBSCRIBE = "subscribe";    /**     * 事件推送訊息中,事件型別,unsubscribe(取消訂閱)     */    public static final String MESSAGE_EVENT_UNSUBSCRIBE = "unsubscribe";    /**     * 事件推送訊息中,上報地理位置事件     */    public static final String MESSAGE_EVENT_LOCATION_UP = "LOCATION";    /** &nb