Hi ~ 小老弟开始转公众号啦,欢迎大家来指点迷津呀
接入校验
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
/**
* 验证消息的确来自微信服务器,一般由微信服务器响应
*
* @param signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
* @param timestamp 时间戳
* @param nonce 随机数
* @param echoStr 随机字符串
* @return 成功则返回【echoStr:随机字符串】,否者返回""
*/
@ApiOperation(value = "GET介入校验")
@GetMapping(value = "/verify")
public String getVerify(@RequestParam(name = "signature") String signature,
@RequestParam(name = "timestamp") String timestamp,
@RequestParam(name = "nonce") String nonce,
@RequestParam(name = "echostr") String echoStr) {
// 1)将token、timestamp、nonce三个参数进行字典序排序
String token = "公众号设置的token";
String[] stringArray = {token, timestamp, nonce};
Arrays.sort(stringArray);
// 2)将三个参数字符串拼接成一个字符串进行sha1加密
String param = StringUtils.join(stringArray);
String sha1HexParam = DigestUtils.sha1Hex(param);
// 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
return signature.equal(sha1HexParam) ? echoStr : "";
}
/**
* 介入校验,一般由微信服务器响应
*
* @param xmlData 事件类型参数
* @return 成功则返回【事件类型参数xml】,否者返回""
*/
@ApiOperation(value = "POST介入校验")
@PostMapping(value = "/verify", produces = "text/xml;charset=UTF-8")
public String postVerify(@RequestBody String xmlData) {
String result = xmlData;
JSONObject jsonObject = (JSONObject) XML.toJSONObject(xmlData).get("xml");
String toUserName = jsonObject.getString("ToUserName");
String fromUserName = jsonObject.getString("FromUserName");
String msgType = jsonObject.getString("MsgType");
String eventKey = jsonObject.getString("EventKey");
// 事件推送
if ("event".equalsIgnoreCase(msgType)) {
String event = jsonObject.getString("Event");
// 订阅(关注),回复文本消息
if ("subscribe".equalsIgnoreCase(event)) {
// 响应信息
TextMsgDto textMsg = new TextMsgDto();
textMsg.setFromUserName(toUserName);
textMsg.setToUserName(fromUserName);
textMsg.setMsgType("text");
textMsg.setCreateTime(Instant.now().toEpochMilli());
textMsg.setContent("您好,欢迎关注!体验生活,从这里开始!");
result = XStreamUtils.beanToXmlWithCdata(textMsg);
}
// TODO 其他响应类型
}
// TODO 其他响应类型
return result;
}
TextMsg
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.io.Serializable;
/**
* 文本消息
* https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html#0
*
* @author alya
*/
@Data
public class TextMsgDto implements Serializable {
private static final long serialVersionUID = -6178549945796262821L;
/**
* 开发者微信号 / 接收方帐号(收到的OpenID)
*/
@XStreamAlias(value = "ToUserName")
private String toUserName;
/**
* 发送方帐号(一个OpenID) / 开发者微信号
*/
@XStreamAlias(value = "FromUserName")
private String fromUserName;
/**
* 消息创建时间 (整型)
*/
@XStreamAlias(value = "CreateTime")
private Long createTime;
/**
* 消息类型
*/
@XStreamAlias(value = "MsgType")
private String msgType;
/**
* 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)
*/
@XStreamAlias(value = "Content")
private String content;
/**
* 消息id,64位整型
*/
@XStreamAlias(value = "MsgId")
private Integer msgId;
}
XStreamUtils
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import java.io.Writer;
/**
* @author alya
*/
public class XStreamUtils {
private XStreamUtils() {
}
/**
* 扩展XStream使其支持CDATA, 对所有xml节点的转换都增加CDATA标记
*/
private static XStream xStream = new XStream(new XppDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
@Override
protected void writeText(QuickWriter writer, String text) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
}
};
}
});
/**
* 转换
*
* @param object 转换对象
* @return String
*/
public static String beanToXmlWithCdata(Object object) {
xStream.processAnnotations(object.getClass());
xStream.alias("xml", object.getClass());
return xStream.toXML(object);
}
}