![](https://img.haomeiwen.com/i3239635/01da0f9f72de2c0b.png)
微信服务接入
微信服务器传递signature、timestamp、nonce、echostr这四个参数。定义时需要根据{token, timestamp, nonce}此顺序进行校验,经过SHA编码后是否与signature相等。
- 接口提供
@GetMapping("/wx")
public String wxAuthentication(String signature, Long timestamp, String nonce, String echostr) {
logger.info(" signature: " + signature + " timestamp: " + timestamp + " nonce: " + nonce + " echostr: " + echostr);
if (!StringUtils.isEmpty(signature) && !StringUtils.isEmpty(timestamp)
&& !StringUtils.isEmpty(nonce) && !StringUtils.isEmpty(echostr)) {
if (wxServerVerifyService.checkSignature(signature, timestamp.toString(), nonce)) {
return echostr;
}
} else {
logger.error("params is null");
}
return null;
}
- 校验服务
public class WxServerVerifyService {
@Value("${wx.token}")
private String token;
public boolean checkSignature(String signature, String timestamp, String nonce) {
String[] str = new String[]{token, timestamp, nonce};
Arrays.sort(str);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < str.length; i++) {
buffer.append(str[i]);
}
String temp = SHAUtil.encode(buffer.toString());
return signature.equals(temp);
}
}
- SHAUtil
public class SHAUtil {
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);
}
}
}
- 注意服务必须是以80端口向外暴露(或者由nginx等工具80映射到此服务)
- 接入方法为GET请求,POST为接收微信服务端消息接口。
微信消息接收
- 接口提供
@PostMapping("/wx")
public void handleWxEvent(HttpServletRequest request, HttpServletResponse response) {
PrintWriter out = null;
String responseMessage = null;
try {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
out = response.getWriter();
responseMessage = wxMessageProcessService.responseMessage(request);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
if (responseMessage != null) {
out.print(responseMessage);
} else {
out.print("");
}
out.flush();
out.close();
}
}
}
- 定义消息处理 wxMessageProcessService
public String responseMessage(HttpServletRequest request) {
String replyMessage = "";
try {
String content = MessageUtil.requestToXml(request);
logger.info(content);
Map<String, String> requestMap = MessageUtil.parseXml(content);
if (requestMap.containsKey("MsgType")) {
if ("event".equals(requestMap.get("MsgType"))) {
replyMessage = processEventMessage(requestMap, content);
} else {
replyMessage = processCommonMessage(requestMap, content);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return replyMessage;
}
- 普通消息
private String processCommonMessage(Map<String, String> requestMap, String content) {
String msgType = requestMap.get("MsgType");
String replyMessage = "";
MsgType type = MsgType.valueOf(msgType);
switch (type) {
case text:
break;
case link:
break;
case image:
break;
case video:
break;
case voice:
break;
case location:
break;
case shortvideo:
break;
default:
replyMessage = "";
}
return replyMessage;
}
- 事件消息
private String processEventMessage(Map<String, String> requestMap, String reciveContent) {
String eventName = requestMap.get("Event");
String replyMessage = "";
EventMessage.Event event = EventMessage.Event.valueOf(eventName);
TextMessage replyTextMessage = new TextMessage();
switch (event) {
case unsubscribe:
break;
case CLICK:
break;
case LOCATION:
break;
case SCAN:
break;
case VIEW:
break;
case subscribe:
break;
default:
}
return replyMessage;
}
- 默认请回复""或者"success",否则用户一段时间接收不到正确的消息格式,就会出现服务异常信息。
网友评论