在微信平台配置
1、AppSecret需要管理员扫码生成,注意需要保存起来。
2、平台配置:
权限集-配置权限集;
开发资料-配置相关服务端Url(接口)、校验、解密token、调用IP白名单
在开发者资料中配置授权url:
服务端接口地址、三个ip前缀需一致、消息与事件中的Url
A
P
P
I
D
APPID
APPID在回调时是动态的,哪个公众号事件就是哪个APPID
3、服务端开发:
根据以上配置的授权事件配置中的URL进行开发:
1、 接收URL中的各项参数:signature、timestamp、nonce、encrypt_type、msg_signature
推送的包体为XML加密格式
接收XML包体:
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
StringBuilder requestBody = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
requestBody.append(line);
}
2、、校验msg_signature签名是否正确,以判断请求是否来自微信服务器:
1、将token、timestamp(URL参数中的)、nonce(URL参数中的)、Encrypt(包体内的字段)四个参数进行字典序排序;
2、将四个参数字符串拼接成一个字符串,然后进行sha1计算签名: 6c12a4205838198b8fa631b3220723bb07f1015c,与URL参数中的msg_signature参 数进行对比,相等说明请求来自微信服务器,合法。
获取包体的Encrypt:
validateMsgSignature(TOKEN, timestamp, nonce, getEncryptContent(requestBody.toString()), msgSignature);
与入参里的msgSignature一致即验证通过
public static String getEncryptContent(String xmlString) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xmlString));
Document doc = builder.parse(is);
Element root = doc.getDocumentElement();
String encryptContent = root.getElementsByTagName("Encrypt").item(0).getTextContent();
return encryptContent;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
进行验证的方法:
public static boolean validateMsgSignature(String token, String timestamp, String nonce, String encrypt, String msgSignature) {
try {
String[] arr = {timestamp, nonce, token, encrypt};
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
for (String s : arr) {
sb.append(s);
}
MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] signatureBytes = digest.digest(sb.toString().getBytes());
// Convert byte array to hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte b : signatureBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
String calculatedSignature = hexString.toString();
return calculatedSignature.equals(msgSignature);
}
}
3、解密消息体"Encrypt"密文:获取到包体中的Encrypt内容,使用微信示例接口中的方法直接解密处理:
使用该方法可获取到xml中的指定内容:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(requestBody.toString()));
Document doc = builder.parse(is);
NodeList nodeList = doc.getElementsByTagName("Encrypt");
4、使用微信接口解密:
(该接口方法是使用微信官方文档提供的接口,下载地址:https://wximg.gtimg.com/shake_tv/mpwiki/cryptoDemo.zip)
WXBizMsgCrypt pc = new WXBizMsgCrypt(TOKEN, AES_KEY, THIRD_APPID);
pc.decryptMsgNew(msgSignature, timestamp, nonce, nodeList.item(0).getTextContent())
4、拿到明文后将其中的ComponentVerifyTicket字段保存,并记录生成时间,有效时间为12小时,最后返回success。
//回包给微信
PrintWriter out = response.getWriter();
out.print("success");
out.flush();
写完代码更新后,如果平台上已经开启推送ticket,那么每隔十分钟微信就会推送到这个url接口上,获取存储到ticket即可,每个ticket有效期是12个小时,在测试时可以一直获取最新的,通过全网发布后再设置有效的保存更新逻辑。
5、随后前往开放平台进行全网发布,发布前它会进行检测,这里有个坑,就是他的普通文本\api失败不影响发布,如果这里显示失败,可以不理会继续发布。发布成功,则可以进行其他操作了!