本文介绍微信公众号消息自动回复功能的开发,开发语言 java话不多说,直接上代码

1.控制器代码
package webapp.controller;import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import webapp.ext.WechatSignUtil;
import webapp.ext.wechat.AuthProcess;
import webapp.ext.wechat.MessageUtil;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@Scope("prototype")
@RestControllerpublic class NotifyController {@RequestMapping(value = "notify",method = { RequestMethod.GET, RequestMethod.POST })@ResponseBodypublic String wechatNotify(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp,String nonce, String echostr) throws IOException {boolean isGet = request.getMethod().toLowerCase().equals("get");if (isGet) {boolean isOk = WechatSignUtil.checkSignature(signature, timestamp, nonce);if (isOk)return echostr;elsereturn null;} else {String resp = "";request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");try {Map<String,String> map = MessageUtil.xmlToMap(request);String xml = "<xml><ToUserName>"+map.get("ToUserName")+"</ToUserName><Encrypt>" +map.get("Encrypt")+"</Encrypt></xml>";String result = AuthProcess.decryptMsg(request, xml);Map<String, Object> req = MessageUtil.xmlStr2Map(result);boolean hasEvent = req.containsKey("Event");String respXml = "";if (hasEvent) {String event = req.get("Event").toString();if ("subscribe".equals(event)) {//用户订阅公众号行为HashMap<String, Object> mapXml = new HashMap<>();mapXml.put("ToUserName",req.get("FromUserName"));mapXml.put("FromUserName",req.get("ToUserName"));mapXml.put("CreateTime",req.get("CreateTime"));mapXml.put("MsgType","text");mapXml.put("Content","感谢关注");respXml = MessageUtil.map2Xmlstring(mapXml);}} else {String msgType = req.get("MsgType").toString();String receive = "";if ("text".equals(msgType)){//普通文字消息receive = req.get("Content").toString();} else if ("voice".equals(msgType)){//语音消息//注意:这里Recognition拿到的直接就是语音消息转化之后的文字内容!!!直接用就好了receive = req.get("Recognition").toString();}respXml = sendMsg(req,receive);}resp = AuthProcess.encryptMsg(request, respXml.trim());return resp;} catch (Exception e) {e.printStackTrace();}return resp;}}private String sendMsg(Map<String, Object> req,String receive) {HashMap<String, Object> mapXml = new HashMap<>();mapXml.put("ToUserName",req.get("FromUserName"));mapXml.put("FromUserName",req.get("ToUserName"));mapXml.put("CreateTime",req.get("CreateTime"));mapXml.put("MsgType","text");//根据receive组装回复的内容mapXml.put("Content","回复的消息内容");return MessageUtil.map2Xmlstring(mapXml);}
}

2.杂七杂八的一些类,上面控制器用到的

package webapp.ext.wechat;@SuppressWarnings("serial")
public class AesException extends Exception {public final static int OK = 0;public final static int ValidateSignatureError = -40001;public final static int ParseXmlError = -40002;public final static int ComputeSignatureError = -40003;public final static int IllegalAesKey = -40004;public final static int ValidateAppidError = -40005;public final static int EncryptAESError = -40006;public final static int DecryptAESError = -40007;public final static int IllegalBuffer = -40008;//public final static int EncodeBase64Error = -40009;//public final static int DecodeBase64Error = -40010;//public final static int GenReturnXmlError = -40011;private int code;private static String getMessage(int code) {switch (code) {case ValidateSignatureError:return "签名验证错误";case ParseXmlError:return "xml解析失败";case ComputeSignatureError:return "sha加密生成签名失败";case IllegalAesKey:return "SymmetricKey非法";case ValidateAppidError:return "appid校验失败";case EncryptAESError:return "aes加密失败";case DecryptAESError:return "aes解密失败";case IllegalBuffer:return "解密后得到的buffer非法";
//        case EncodeBase64Error:
//            return "base64加密错误";
//        case DecodeBase64Error:
//            return "base64解密错误";
//        case GenReturnXmlError:
//            return "xml生成失败";default:return null; // cannot be
        }}public int getCode() {return code;}AesException(int code) {super(getMessage(code));this.code = code;}}

View Code

package webapp.ext.wechat;import javax.servlet.http.HttpServletRequest;public class AuthProcess {/*** 将加密后的原文进行解密重新封装* @param request* @param originalXml 原xml* @return    重新解密后的xml*/public static String  decryptMsg(HttpServletRequest request,String originalXml) {// 微信加密签名//String sVerifyMsgSig = request.getParameter("signature");String msgSignature = request.getParameter("msg_signature");// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");try {WXBizMsgCrypt pc = new WXBizMsgCrypt("your token", "your EncodingAESKey", "your appid");return pc.decryptMsg(msgSignature, timestamp, nonce, originalXml);} catch (AesException e) {// TODO Auto-generated catch block
            e.printStackTrace();}return null;}/*** 对需要回复的原文进行加密重新封装* @param request* @param replyXml 需要回复的xml* @return    重新加密后的xml*/public static String  encryptMsg(HttpServletRequest request, String replyXml) {// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");try {WXBizMsgCrypt pc = new WXBizMsgCrypt("your token", "your EncodingAESKey", "your appid");return pc.encryptMsg(replyXml, timestamp, nonce);} catch (AesException e) {// TODO Auto-generated catch block
            e.printStackTrace();}return null;}}

View Code

package webapp.ext.wechat;import java.util.ArrayList;class ByteGroup {ArrayList<Byte> byteContainer = new ArrayList<Byte>();public byte[] toBytes() {byte[] bytes = new byte[byteContainer.size()];for (int i = 0; i < byteContainer.size(); i++) {bytes[i] = byteContainer.get(i);}return bytes;}public ByteGroup addBytes(byte[] bytes) {for (byte b : bytes) {byteContainer.add(b);}return this;}public int size() {return byteContainer.size();}
}

View Code

package webapp.ext.wechat;import com.thoughtworks.xstream.XStream;
import org.apache.http.util.TextUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;public class MessageUtil {public static final String MESSAGE_TEXT = "text";public static final String MESSAGE_IMAGE = "image";public static final String MESSAGE_VOICE = "voice";public static final String MESSAGE_VIDEO = "video";public static final String MESSAGE_LINK = "link";public static final String MESSAGE_LOCATION = "location";public static final String MESSAGE_EVENT = "event";public static final String EVENT_SUB = "subscribe";public static final String EVENT_UNSUB = "unsubscribe";public static final String EVENT_CLICK = "CLICK";public static final String EVENT_VIEW = "VIEW";/*** xml转为map* @param request* @return* @throws DocumentException* @throws IOException*/public static Map<String, String> xmlToMap(HttpServletRequest request ) throws DocumentException, IOException{Map<String,String> map = new HashMap<String, String>();SAXReader reader = new SAXReader();InputStream ins = request.getInputStream();Document doc = reader.read(ins);Element root = doc.getRootElement();List<Element> list = root.elements();for (Element e : list) {map.put(e.getName(), e.getText());}ins.close();return map;}public static String textMessageToXml(TextMessage textMessage){XStream xstream = new XStream();xstream.alias("xml", textMessage.getClass());return xstream.toXML(textMessage);}public static Map<String,Object> xmlStr2Map(String xmlStr){Map<String,Object> map = new HashMap<String,Object>();Document doc;try {doc = DocumentHelper.parseText(xmlStr);Element root = doc.getRootElement();List children = root.elements();if(children != null && children.size() > 0) {for(int i = 0; i < children.size(); i++) {Element child = (Element)children.get(i);map.put(child.getName(), child.getTextTrim());}}} catch (DocumentException e) {e.printStackTrace();}return map;}public static String map2Xmlstring(Map<String,Object> map){StringBuffer sb = new StringBuffer("");sb.append("<xml>");Set<String> set = map.keySet();for(Iterator<String> it = set.iterator(); it.hasNext();){String key = it.next();Object value = map.get(key);sb.append("<").append(key).append(">");sb.append(value);sb.append("</").append(key).append(">");}sb.append("</xml>");return sb.toString();}public static String map2XmlstringWithHead(Map<String,Object> map,String head){StringBuffer sb = new StringBuffer("");if (!TextUtils.isEmpty(head)) {sb.append("<"+head+">");}Set<String> set = map.keySet();for(Iterator<String> it = set.iterator(); it.hasNext();){String key = it.next();Object value = map.get(key);sb.append("<").append(key).append(">");sb.append(value);sb.append("</").append(key).append(">");}if (!TextUtils.isEmpty(head)) {sb.append("</"+head+">");}return sb.toString();}}

View Code

/*** 对公众平台发送给公众账号的消息加解密示例代码.* * @copyright Copyright (c) 1998-2014 Tencent Inc.*/// ------------------------------------------------------------------------package webapp.ext.wechat;import java.nio.charset.Charset;
import java.util.Arrays;/*** 提供基于PKCS7算法的加解密接口.*/
class PKCS7Encoder {static Charset CHARSET = Charset.forName("utf-8");static int BLOCK_SIZE = 32;/*** 获得对明文进行补位填充的字节.* * @param count 需要进行填充补位操作的明文字节个数* @return 补齐用的字节数组*/static byte[] encode(int count) {// 计算需要填充的位数int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);if (amountToPad == 0) {amountToPad = BLOCK_SIZE;}// 获得补位所用的字符char padChr = chr(amountToPad);String tmp = new String();for (int index = 0; index < amountToPad; index++) {tmp += padChr;}return tmp.getBytes(CHARSET);}/*** 删除解密后明文的补位字符* * @param decrypted 解密后的明文* @return 删除补位字符后的明文*/static byte[] decode(byte[] decrypted) {int pad = (int) decrypted[decrypted.length - 1];if (pad < 1 || pad > 32) {pad = 0;}return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);}/*** 将数字转化成ASCII码对应的字符,用于对明文进行补码* * @param a 需要转化的数字* @return 转化得到的字符*/static char chr(int a) {byte target = (byte) (a & 0xFF);return (char) target;}}

View Code

/*** 对公众平台发送给公众账号的消息加解密示例代码.* * @copyright Copyright (c) 1998-2014 Tencent Inc.*/// ------------------------------------------------------------------------package webapp.ext.wechat;import java.security.MessageDigest;
import java.util.Arrays;/*** SHA1 class** 计算公众平台的消息签名接口.*/
class SHA1 {/*** 用SHA1算法生成安全签名* @param token 票据* @param timestamp 时间戳* @param nonce 随机字符串* @param encrypt 密文* @return 安全签名* @throws com.qq.weixin.mp.aes.AesException*/public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException{try {String[] array = new String[] { token, timestamp, nonce, encrypt };StringBuffer sb = new StringBuffer();// 字符串排序
            Arrays.sort(array);for (int i = 0; i < 4; i++) {sb.append(array[i]);}String str = sb.toString();// SHA1签名生成MessageDigest md = MessageDigest.getInstance("SHA-1");md.update(str.getBytes());byte[] digest = md.digest();StringBuffer hexstr = new StringBuffer();String shaHex = "";for (int i = 0; i < digest.length; i++) {shaHex = Integer.toHexString(digest[i] & 0xFF);if (shaHex.length() < 2) {hexstr.append(0);}hexstr.append(shaHex);}return hexstr.toString();} catch (Exception e) {e.printStackTrace();throw new AesException(AesException.ComputeSignatureError);}}
}

View Code

package webapp.ext.wechat;public class TextMessage {public String ToUserName;public String FromUserName;public int CreateTime;public String MsgType;public String Content;public String getToUserName() {return ToUserName;}public void setToUserName(String toUserName) {ToUserName = toUserName;}public String getFromUserName() {return FromUserName;}public void setFromUserName(String fromUserName) {FromUserName = fromUserName;}public int getCreateTime() {return CreateTime;}public void setCreateTime(int createTime) {CreateTime = createTime;}public String getMsgType() {return MsgType;}public void setMsgType(String msgType) {MsgType = msgType;}public String getContent() {return Content;}public void setContent(String content) {Content = content;}
}

View Code

/*** 对公众平台发送给公众账号的消息加解密示例代码.* * @copyright Copyright (c) 1998-2014 Tencent Inc.*/// ------------------------------------------------------------------------/*** 针对org.apache.commons.codec.binary.Base64,* 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)* 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi*/
package webapp.ext.wechat;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Random;/*** 提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).* <ol>*     <li>第三方回复加密消息给公众平台</li>*     <li>第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。</li>* </ol>* 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案* <ol>*     <li>在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:*      http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li>*     <li>下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt</li>*     <li>如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件</li>*     <li>如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件</li>* </ol>*/
public class WXBizMsgCrypt {static Charset CHARSET = Charset.forName("utf-8");Base64 base64 = new Base64();byte[] aesKey;String token;String appId;/*** 构造函数* @param token 公众平台上,开发者设置的token* @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey* @param appId 公众平台appid* * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息*/public WXBizMsgCrypt(String token, String encodingAesKey, String appId) throws AesException {if (encodingAesKey.length() != 43) {throw new AesException(AesException.IllegalAesKey);}this.token = token;this.appId = appId;aesKey = Base64.decodeBase64(encodingAesKey + "=");}// 生成4个字节的网络字节序byte[] getNetworkBytesOrder(int sourceNumber) {byte[] orderBytes = new byte[4];orderBytes[3] = (byte) (sourceNumber & 0xFF);orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);return orderBytes;}// 还原4个字节的网络字节序int recoverNetworkBytesOrder(byte[] orderBytes) {int sourceNumber = 0;for (int i = 0; i < 4; i++) {sourceNumber <<= 8;sourceNumber |= orderBytes[i] & 0xff;}return sourceNumber;}// 随机生成16位字符串
    String getRandomStr() {String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < 16; i++) {int number = random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}/*** 对明文进行加密.* * @param text 需要加密的明文* @return 加密后base64编码的字符串* @throws AesException aes加密失败*/String encrypt(String randomStr, String text) throws AesException {ByteGroup byteCollector = new ByteGroup();byte[] randomStrBytes = randomStr.getBytes(CHARSET);byte[] textBytes = text.getBytes(CHARSET);byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);byte[] appidBytes = appId.getBytes(CHARSET);// randomStr + networkBytesOrder + text + appid
        byteCollector.addBytes(randomStrBytes);byteCollector.addBytes(networkBytesOrder);byteCollector.addBytes(textBytes);byteCollector.addBytes(appidBytes);// ... + pad: 使用自定义的填充方式对明文进行补位填充byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());byteCollector.addBytes(padBytes);// 获得最终的字节流, 未加密byte[] unencrypted = byteCollector.toBytes();try {// 设置加密模式为AES的CBC模式Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);// 加密byte[] encrypted = cipher.doFinal(unencrypted);// 使用BASE64对加密后的字符串进行编码String base64Encrypted = base64.encodeToString(encrypted);return base64Encrypted;} catch (Exception e) {e.printStackTrace();throw new AesException(AesException.EncryptAESError);}}/*** 对密文进行解密.* * @param text 需要解密的密文* @return 解密得到的明文* @throws AesException aes解密失败*/String decrypt(String text) throws AesException {byte[] original;try {// 设置解密模式为AES的CBC模式Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);// 使用BASE64对密文进行解码byte[] encrypted = Base64.decodeBase64(text);// 解密original = cipher.doFinal(encrypted);} catch (Exception e) {e.printStackTrace();throw new AesException(AesException.DecryptAESError);}String xmlContent, from_appid;try {// 去除补位字符byte[] bytes = PKCS7Encoder.decode(original);// 分离16位随机字符串,网络字节序和AppIdbyte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);int xmlLength = recoverNetworkBytesOrder(networkOrder);xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),CHARSET);} catch (Exception e) {e.printStackTrace();throw new AesException(AesException.IllegalBuffer);}// appid不相同的情况if (!from_appid.equals(appId)) {throw new AesException(AesException.ValidateAppidError);}return xmlContent;}/*** 将公众平台回复用户的消息加密打包.* <ol>*     <li>对要发送的消息进行AES-CBC加密</li>*     <li>生成安全签名</li>*     <li>将消息密文和安全签名打包成xml格式</li>* </ol>* * @param replyMsg 公众平台待回复用户的消息,xml格式的字符串* @param timeStamp 时间戳,可以自己生成,也可以用URL参数的timestamp* @param nonce 随机串,可以自己生成,也可以用URL参数的nonce* * @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串* @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息*/public String encryptMsg(String replyMsg, String timeStamp, String nonce) throws AesException {// 加密String encrypt = encrypt(getRandomStr(), replyMsg);// 生成安全签名if (timeStamp == "") {timeStamp = Long.toString(System.currentTimeMillis());}String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt);// System.out.println("发送给平台的签名是: " + signature[1].toString());// 生成发送的xmlString result = XMLParse.generate(encrypt, signature, timeStamp, nonce);return result;}/*** 检验消息的真实性,并且获取解密后的明文.* <ol>*     <li>利用收到的密文生成安全签名,进行签名验证</li>*     <li>若验证通过,则提取xml中的加密消息</li>*     <li>对消息进行解密</li>* </ol>* * @param msgSignature 签名串,对应URL参数的msg_signature* @param timeStamp 时间戳,对应URL参数的timestamp* @param nonce 随机串,对应URL参数的nonce* @param postData 密文,对应POST请求的数据* * @return 解密后的原文* @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息*/public String decryptMsg(String msgSignature, String timeStamp, String nonce, String postData)throws AesException {// 密钥,公众账号的app secret// 提取密文Object[] encrypt = XMLParse.extract(postData);// 验证安全签名String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());// 和URL中的签名比较是否相等// System.out.println("第三方收到URL中的签名:" + msg_sign);// System.out.println("第三方校验签名:" + signature);if (!signature.equals(msgSignature)) {throw new AesException(AesException.ValidateSignatureError);}// 解密String result = decrypt(encrypt[1].toString());return result;}/*** 验证URL* @param msgSignature 签名串,对应URL参数的msg_signature* @param timeStamp 时间戳,对应URL参数的timestamp* @param nonce 随机串,对应URL参数的nonce* @param echoStr 随机串,对应URL参数的echostr* * @return 解密之后的echostr* @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息*/public String verifyUrl(String msgSignature, String timeStamp, String nonce, String echoStr)throws AesException {String signature = SHA1.getSHA1(token, timeStamp, nonce, echoStr);if (!signature.equals(msgSignature)) {throw new AesException(AesException.ValidateSignatureError);}String result = decrypt(echoStr);return result;}}

View Code

/*** 对公众平台发送给公众账号的消息加解密示例代码.* * @copyright Copyright (c) 1998-2014 Tencent Inc.*/// ------------------------------------------------------------------------package webapp.ext.wechat;import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;/*** XMLParse class** 提供提取消息格式中的密文及生成回复消息格式的接口.*/
class XMLParse {/*** 提取出xml数据包中的加密消息* @param xmltext 待提取的xml字符串* @return 提取出的加密消息字符串* @throws com.qq.weixin.mp.aes.AesException*/public static Object[] extract(String xmltext) throws AesException {Object[] result = new Object[3];try {DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);dbf.setXIncludeAware(false);dbf.setExpandEntityReferences(false);DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(xmltext);InputSource is = new InputSource(sr);Document document = db.parse(is);Element root = document.getDocumentElement();NodeList nodelist1 = root.getElementsByTagName("Encrypt");NodeList nodelist2 = root.getElementsByTagName("ToUserName");result[0] = 0;result[1] = nodelist1.item(0).getTextContent();result[2] = nodelist2.item(0).getTextContent();return result;} catch (Exception e) {e.printStackTrace();throw new AesException(AesException.ParseXmlError);}}/*** 生成xml消息* @param encrypt 加密后的消息密文* @param signature 安全签名* @param timestamp 时间戳* @param nonce 随机字符串* @return 生成的xml字符串*/public static String generate(String encrypt, String signature, String timestamp, String nonce) {String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"+ "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"+ "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n" + "</xml>";return String.format(format, encrypt, signature, timestamp, nonce);}
}

View Code

package webapp.ext;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;/*** @Author:Fei.chu* @Date:Created in 21:52 2018/08/17* @Description:微信签名校验*/
public class WechatSignUtil {/*** 校验签名* @param signature 微信加密签名.* @param timestamp 时间戳.* @param nonce 随机数.* @return*/public static boolean checkSignature(String signature, String timestamp, String nonce) {// 对token、timestamp、和nonce按字典排序.String[] paramArr = new String[] {"your token", timestamp, nonce};Arrays.sort(paramArr);// 将排序后的结果拼接成一个字符串.String content  = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);String ciphertext = null;try {MessageDigest md = MessageDigest.getInstance("SHA-1");// 对拼接后的字符串进行sha1加密.byte[] digest = md.digest(content.toString().getBytes());ciphertext = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}// 将sha1加密后的字符串与signature进行对比.return ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;}/*** 将字节数组转换为十六进制字符串.* @param byteArray* @return*/private static String byteToStr(byte[] byteArray) {String strDigest = "";for (int i = 0; i < byteArray.length; i++) {strDigest += byteToHexStr(byteArray[i]);}return strDigest;}/*** 将字节转换为十六进制字符串.* @param mByte* @return*/private static String byteToHexStr(byte mByte) {char[] Digit = { '0', '1' , '2', '3', '4' , '5', '6', '7' , '8', '9', 'A' , 'B', 'C', 'D' , 'E', 'F'};char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}//    //获取token
//    public static String getToken() throws Exception{
//        String token = DbGhostApi.tokenIsValid();
//        if (token != null) {
//            return token;
//        } else {
//            Date now = new Date();
//            String rsp = HttpUtil.getString("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + Config.appid + "&secret=" + Config.secret);
//            JSONObject obj = JSONObject.parseObject(rsp);
//            String access_token = obj.getString("access_token");
//            int expires_in = obj.getIntValue("expires_in");
//            DbGhostApi.updateToken(access_token, DateUtil.dateAddSecond(now,expires_in));
//            return access_token;
//        }
//    }
}

View Code

注意:语音消息识别需要在公众号后台开启相应功能

转载于:https://www.cnblogs.com/vicF/p/11230837.html

微信公众号开发java版-消息回复(普通文字消息和语音消息)相关推荐

  1. 微信公众号开发-Java版学习笔记

    微信公众号开发整体不难,主要是熟悉微信公众号常用的一些接口文档,然后会一门后端语言(比如java)即可. 罗召勇老师教程:微信公众号开发-Java版(蓝桥罗召勇) 微信公众号文档:微信公众号官方文档 ...

  2. 微信公众号开发-java版 腾讯课堂(开发接入)

    微信公众号开发-java版 腾讯课堂 微信测试号申请地址: 微信二维码直接扫描登录 1.新建web项目 2.内网穿透映射公网ip  (免费隧道需要支付宝实名认证) 3.微信接入验证签名 TOKEN自己 ...

  3. 微信公众号开发Java版

    源码地址: https://github.com/ishuaige/myWxMp https://gitee.com/niumazlb/myWxMp 一.申请微信开发者账号 注册账号 申请测试号 这里 ...

  4. 微信公众号开发Java版的学习笔记和操作demo!

    基本原理: 会用到微信服务器,调用自己的服务器,自己服务器的访问可以基于spring boot的部署,当然也可以基于其他,其本质就是类似于远程的接口调用: 为社么需要:比如第三方,银行或者独立公司的服 ...

  5. C#微信公众号开发系列教程五(接收事件推送与消息排重)

    C#微信公众号开发系列教程五(接收事件推送与消息排重) 原文:C#微信公众号开发系列教程五(接收事件推送与消息排重) 微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续 ...

  6. 微信公众号开发——Java

    微信公众号开发--Java 步骤一:需要先进入公众号平台进行JS接口安全域名的设置. 步骤二:引入微信jssdk.js文件 生成JS-SDK权限验证签名 步骤三:通过config接口注入权限验证配置 ...

  7. 使用Python进行微信公众号开发(三)回复消息

    写在前面 <使用Python进行微信公众号开发>系列文章将与大家分享如何使用Python一步步搭建微信公众号后台服务器. 效果体验 扫码"是雯子吖"公众号进行体验 配置 ...

  8. 微信公众号开发java流程_微信公众号开发教程java 编程语言的特点及选择

    微信公众号开发教程java 编程语言的特点及选择 微信公众号为用户提供了相关的工具,来对微信公众号进行一个简单的开发.但是如果想实现一些复杂的功能,其实还是要借助于一些编程语言的使用.所以要了解,在微 ...

  9. 微信公众号开发(JAVA)-环境搭建与开发接入

    使用JAVA开发微信公众平台(一)--环境搭建与开发接入 一. 初始微信公众平台 微信公众平台,即我们平时所说的"公众号",曾用名"官方平台"."媒体 ...

最新文章

  1. php 派生类 数据库连接 单例模式 xhprof实测 高效连接
  2. SAP freelancer接SAP项目的几种方法
  3. Java的List排序
  4. 多面体体积 matlab,matlab计算多面体体积实现代码
  5. DB2 格式化输出 Date
  6. 群星巨型计算机事件,群星 三种特殊事件介绍 特殊事件有几种
  7. Mac 开发中如何设置 关闭 以及最小化 最大化按钮事件处理
  8. 深度有趣 | 01 前言
  9. 小白也能懂的 Nacos 服务模型介绍
  10. x86_64 arm制linux-gcc,arm-linux-gcc 制作
  11. 【2016年第1期】山东省农业大数据发展刍议
  12. 两个八进制小数怎么相加_两个十六进制怎么相加的
  13. CCProgressTimer进度条效果
  14. python语言程序设计实践教程实验八答案_Python程序设计实验报告: 实验八 文件...
  15. 北方民族大学计算机考研专业课,2021北方民族大学专业课考研真题资料汇总!!...
  16. 王道计算机考研图书勘误表公布!
  17. java rsa密钥转pkcs8_openssl RSA密钥格式PKCS1和PKCS8相互转换
  18. mega linux教程,MegaRAID工具使用详解
  19. 新站快速排名的seo优化流程
  20. vatic标注工具安装步骤(非docker安装)以及错误解决办法

热门文章

  1. 课程设计_solidworks_机械狗玩具建模,机械原理连杆机构运动
  2. Python中的十六进制数
  3. ListView控件绑定数据
  4. 超详细的Nginx入门教程
  5. linux scp拷贝软连接,scp 拷贝 针对软连接的问题
  6. <微机原理>[汇编语言]-[实验五] 定时器实验
  7. 核电池:一切电池的终极形态
  8. matlab 贝叶斯网络
  9. validate如何使用
  10. 计算两个点之间的距离