1、controller代码
@Controller
@RequestMapping("/wechat/platform")
public class WechatController extends AbstractController {
@ResponseBody
@GetMapping("test")
public String test(String signature, String timestamp, String nonce, String echostr) {
boolean bool = WechatUtils.checkSign(signature, timestamp, nonce);
return bool ? echostr : null;
}
@ResponseBody
@PostMapping("test")
public String test(HttpServletRequest request) throws Exception {
Map<String, String> map = WechatUtils.decryptWxMsg2Map(request);
String openid = request.getParameter("openid"), msgType = map.get("MsgType");
if ("text".equals(msgType)) {
} else if ("event".equals(msgType)) {
String event = map.get("Event"), key = map.get("EventKey");
if ("SCAN".equalsIgnoreCase(event)) {
} else if ("CLICK".equalsIgnoreCase(event)) {
}
}
return WechatUtils.encryptWxMsg2Xml(openid, platformId, "xxxxxx");
return "success";
}
@ResponseBody
@RequestMapping(value = "makeCode")
public R makeCode(HttpServletRequest request) throws Exception {
String state = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
BusinessDelayQueue instance = BusinessDelayQueue.getInstance();
PublicTask task = new PublicTask("wx_" + state, "false");
long expire = System.currentTimeMillis() + 300000;
DelayTask<?> delay = new DelayTask<>(expire, task);
instance.put(delay);
return R.ok().put("url", String.format(wxConfig.getWxQrcode(), state)).put("state", state);
}
@ResponseBody
@PostMapping(value = "checkState")
public R checkState(String state) {
PublicTask task = new PublicTask("wx_" + state, null);
String value = task.getValue(String.class, false);
if (value == null) {
return R.error(-1, "二维码已失效").put(SysLogUtils.SYSLOG_NOT_SAVE, true);
}
if ("false".equals(value)) {
return R.error(-2, "未扫码登录").put(SysLogUtils.SYSLOG_NOT_SAVE, true);
}
String info = task.getValue(String.class, true);
return r;
}
@RequestMapping(value = "openid")
public String openid(String code, String state, Model model, HttpServletRequest request) throws IOException {
String resp = HttpTookit.doGet(String.format(wxConfig.getWxOpenid(), code), null);
String openid = JSON.parseObject(resp).getString("openid");
JSONObject user = WechatUtils.userInfo(openid);
return "xxx";
}
public void pushMessage(String str, Integer type, String ext) {
Map<String, Object> data = new HashMap<>(), map = new HashMap<>(), first = new HashMap<>(),
k1 = new HashMap<>(), k2 = new HashMap<>(), k3 = new HashMap<>(), k4 = new HashMap<>(),
remark = new HashMap<>();
data.put("touser", openid);
map.put("first", first);
map.put("keyword1", k1);
map.put("keyword2", k2);
map.put("keyword3", k3);
map.put("keyword4", k4);
map.put("remark", remark);
first.put("color", "#159815");
k1.put("color", "#003AFF");
k2.put("color", "#FF0066");
k3.put("color", "#003AFF");
k4.put("color", "#003AFF");
remark.put("color", "#159815");
data.put("template_id", "模板ID");
data.put("data", map);
WechatUtils.pushMessage(data);
}
}
2、WechatUtils工具类
public class WechatUtils {
public static String access_token = null;
private static WXBizMsgCrypt crypt = null;
static {
try {
crypt = new WXBizMsgCrypt(wxConfig.getToken(), wxConfig.getAesKey(), wxConfig.getAppid());
} catch (AesException e) {
}
}
public static void getAccessToken() {
String format = String.format(wxConfig.getAccessToken(), access_token);
access_token = HttpTookit.doGet(format, null);
}
public static void userInfo(String openid) {
String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s";
String info = HttpTookit.doGet(String.format(url, access_token, openid), null);
}
public static boolean checkSign(String signature, String timestamp, String nonce) {
String arrs[] = { "微信公众号的token", timestamp, nonce };
Arrays.sort(arrs);
StringBuffer sb = new StringBuffer();
for (String str : arrs) {
sb.append(str);
}
String s= Sha1Util.encode(sb.toString());
return s.equals(signature);
}
public static void pushMessage(Map<String, Object> data) throws Exception {
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
String resp = HttpTookit.sendHttpPost(String.format(url, access_token), JSON.toJSONString(data));
}
public static String encryptWxMsg2Xml(String toOpenid, String fromOpenid, String content) throws Exception {
String xml = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName>"
+ "<CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>";
String createTime = Long.toString(System.currentTimeMillis() / 1000), nonce = SerialNumUtil.randam(10);
return crypt.encryptMsg(String.format(xml, toOpenid, fromOpenid, createTime, content), createTime, nonce);
}
public static Map<String, String> decryptWxMsg2Map(HttpServletRequest request) throws Exception {
request.setCharacterEncoding("UTF-8");
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream(), "utf-8"))) {
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
}
String s= request.getParameter("msg_signature"), timeStamp = request.getParameter("timestamp"),
nonce = request.getParameter("nonce");
System.out.println("用户发送过来信息解密前:" + sb);
String decryptMsg = crypt.decryptMsg(s, timeStamp, nonce, sb.toString());
System.out.println("用户发送过来信息解密后:" + decryptMsg);
return xmlToMap(decryptMsg);
}
public static Map<String, String> xmlToMap(String strXML) throws Exception {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
try (InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"))) {
Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
}
return data;
}
public static String mapToXml(String toOpenid, String fromOpenid, String timestamp, String content) {
String xml = "<xml>" + "<ToUserName><![CDATA[%s]]></ToUserName>"
+ "<FromUserName><![CDATA[%s}]]></FromUserName>" + "<CreateTime>%s</CreateTime>"
+ "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[%s]]></Content>"
+ "<MsgId>1234567890123456</MsgId> " + "</xml>";
return String.format(xml, toOpenid, fromOpenid, timestamp, content);
}
}
3、Java延时队列相关类
public class BusinessDelayQueue {
private final static int DEFAULT_THREAD_NUM = 10;
private ExecutorService executor;
public DelayQueue<DelayTask<?>> delayQueue;
private Thread daemonThread;
private static BusinessDelayQueue instance = new BusinessDelayQueue();
private BusinessDelayQueue() {
executor = Executors.newFixedThreadPool(DEFAULT_THREAD_NUM);
delayQueue = new DelayQueue<>();
init();
}
public static BusinessDelayQueue getInstance() {
return instance;
}
public void init() {
daemonThread = new Thread(() -> {
execute();
});
daemonThread.setName("DelayQueueMonitor");
daemonThread.start();
}
private void execute() {
while (true) {
try {
DelayTask<?> delayTask = delayQueue.take();
if (delayTask != null) {
Callable<Integer> task = delayTask.getTask();
if (null == task) {
continue;
}
executor.submit(task);
}
} catch (Exception e) {
}
}
}
public void put(DelayTask<?> delay) {
if(delayQueue.contains(delay)) {
delayQueue.remove(delay);
}
delayQueue.put(delay);
}
public boolean removeTask(DelayTask<?> delay) {
return delayQueue.remove(delay);
}
}
public class DelayTask<T extends Callable<Integer>> implements Delayed {
private final long expire;
private T task;
public DelayTask(long expire, T task) {
this.expire = expire;
this.task = task;
}
@Override
public int compareTo(Delayed o) {
long self = this.getDelay(TimeUnit.MILLISECONDS), other = o.getDelay(TimeUnit.MILLISECONDS);
return self <= other ? -1 : 1;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public T getTask() {
return task;
}
}
public class PublicTask implements Callable<Integer> {
private String key;
private Object value;
public PublicTask(String key, Object value) {
this.key = key;
this.value = value;
}
@Override
public Integer call() throws Exception {
return null;
}
}