package com.ann.wechat.controller;
import com.ann.wechat.domain.ImageMsgEntity;
import com.ann.wechat.domain.InMsgEntity;
import com.ann.wechat.domain.OutMsgEntity;
import com.ann.wechat.util.EncryptionUtil;
import com.ann.wechat.util.WechatUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Arrays;
/**
* @author code
* 微信公众号测试
*/
@Controller
public class WechatController {
/**
* 校验URL的连接
*
* @param signature 微信加密签名
* @param timestamp 时间戳
* @param nonce 随机数
* @param echostr 随机字符串
* @return echostr
*/
@RequestMapping(value = "/weChat", method = RequestMethod.GET)
@ResponseBody
public String validate(String signature, String timestamp, String nonce, String echostr) {
String[] arr = {WechatUtil.WECHAT_TOKEN, timestamp, nonce};
//排序后加密 保证和微信的(signature)一致
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
for (String s : arr) {
sb.append(s);
}
String mySignature = EncryptionUtil.sha1(sb.toString());
//校验加密参数是否一致,一致返回随机字符串 表示没有问题
if (signature.equals(mySignature)) {
return echostr;
}
return "";
}
/**
* 消息处理
*
* @param inMsg
* @return
*/
@RequestMapping(value = "/weChat", method = RequestMethod.POST, produces = "application/xml;charset=UTF-8")
@ResponseBody
public OutMsgEntity handleMsg(@RequestBody InMsgEntity inMsg) {
String msgType = inMsg.getMsgType();
OutMsgEntity outMsg = new OutMsgEntity();
outMsg.setFromUserName(inMsg.getToUserName());
outMsg.setToUserName(inMsg.getFromUserName());
outMsg.setCreateTime(System.currentTimeMillis());
if ("text".equals(msgType)) {
outMsg.setMsgType(msgType);
//文本类型
outMsg.setContent(inMsg.getContent());
} else if ("image".equals(msgType)) {
outMsg.setMsgType(msgType);
outMsg.setMediaId(new String[]{inMsg.getMediaId()});
}
//时间类型
else if ("event".equals(msgType)) {
//关注
if ("subscribe".equals(inMsg.getEvent())) {
outMsg.setMsgType("text");
outMsg.setContent("欢迎关注[微笑]");
} else if ("CLICK".equals(inMsg.getEvent())) {
String eventKey = inMsg.getEventKey();
//地址
if ("address".equals(eventKey)) {
//图文回复
outMsg.setMsgType("news");
outMsg.setArticleCount(1);
ImageMsgEntity imageMsgEntity = new ImageMsgEntity();
imageMsgEntity.setDescription("图文内容,描述");
imageMsgEntity.setPicUrl("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2203568591,1160230704&fm=11&gp=0.jpg");
imageMsgEntity.setTitle("这是标题");
imageMsgEntity.setUrl("https://www.baidu.com");
ImageMsgEntity[] item = {imageMsgEntity};
outMsg.setItem(item);
}
//联系我
else if ("call".equals(eventKey)) {
outMsg.setMsgType("image");
outMsg.setMediaId(new String[]{"L-xiSP_6t044sM48MSfmKO0zG8BNsQ8efbFCmcyXhzMiDNVGi-C-tBVWlVZxadHz"});
}
}
} else {
outMsg.setMsgType("text");
outMsg.setContent("未识别");
}
return outMsg;
}
}
package com.ann.wechat.domain;
import lombok.Getter;
import lombok.Setter;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@Getter
@Setter
@XmlAccessorType(value = XmlAccessType.FIELD)
public class ImageMsgEntity {
/**
* 图文消息标题
*/
private String Title;
/**
* 图文消息描述
*/
private String Description;
/**
* 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
*/
private String PicUrl;
/**
* 点击图文消息跳转链接
*/
private String Url;
}
package com.ann.wechat.domain;
import lombok.Getter;
import lombok.Setter;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 接收消息
* @author code
*/
@Getter
@Setter
@XmlRootElement(name="xml")
@XmlAccessorType(value = XmlAccessType.FIELD)
public class InMsgEntity {
/**开发者微信号*/
private String ToUserName;
/**发送方帐号*/
private String FromUserName;
/**消息创建时间*/
private Long CreateTime;
/**消息类型 ->text/*/
private String MsgType;
/**消息id64位整型*/
private Long MsgId;
/**文本消息内容*/
private String Content;
/**图片内容*/
private String MediaId;
/**事件*/
private String Event;
/**菜单值*/
private String EventKey;
}
package com.ann.wechat.domain;
import lombok.Getter;
import lombok.Setter;
import javax.xml.bind.annotation.*;
/**
* 接收消息
*
* @author code
*/
@Getter
@Setter
//解析xml 表示根路径是 "xml"
@XmlRootElement(name = "xml")
//表示映射节点映射到 字段上,如果字段不一致 需要 @XmlElement映射
@XmlAccessorType(value = XmlAccessType.FIELD)
public class OutMsgEntity {
/**
* 发送方帐号
*/
private String ToUserName;
/**
* 开发者微信号
*/
private String FromUserName;
/**
* 消息创建时间
*/
private Long CreateTime;
/**
* 消息类型 ->text/
*/
private String MsgType;
/**
* 文本消息内容
*/
private String Content;
//添加父节点"Image" 仅允许出现在集合属性上
@XmlElementWrapper(name="Image")
private String[] MediaId;
/**图文消息个数*/
private Integer ArticleCount;
/**图文信息*/
@XmlElementWrapper(name="Articles")
private ImageMsgEntity[] item;
}
package com.ann.wechat.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class EncryptionUtil {
public static String sha1(String str) {
try {
//指定sha1算法
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(str.getBytes());
//获取字节数组
byte[] messageDigest = digest.digest();
StringBuilder hexString = new StringBuilder();
// 字节数组转换为十六进制数
for (byte b : messageDigest) {
String shaHex = Integer.toHexString(b & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
return "";
}
}
}
package com.ann.wechat.util;
import com.sun.deploy.net.HttpResponse;
import com.sun.xml.internal.ws.util.UtilException;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.http.HttpEntity;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.security.KeyStore;
@SuppressWarnings("deprecation")
public class HttpUtil {
private static final String UTF8 = "utf-8";
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String get(String url, String param) {
return get(url + "?" + param);
}
public static String get(String url) {
BufferedReader in = null;
try {
// 打开和URL之间的连接
URLConnection connection = new URL(url).openConnection();
// 设置通用的请求属性
setURLConnection(connection);
// 建立实际的连接
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.defaultCharset()));
StringBuilder sb = new StringBuilder();
for (String line; (line = in.readLine()) != null; ) {
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
throw new UtilException( e);
} finally {
IOUtils.closeQuietly(in);
}
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String post(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
try {
URLConnection connection = new URL(url).openConnection();
// 设置通用的请求属性
setURLConnection(connection);
// 发送POST请求必须设置如下两行
connection.setDoOutput(true);
connection.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), UTF8));
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), UTF8));
StringBuilder sb = new StringBuilder();
for (String line; (line = in.readLine()) != null; ) {
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
throw new UtilException( e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(in);
}
}
private static void setURLConnection(URLConnection connection) {
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
}
}
package com.ann.wechat.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class WechatUtil {
/**TOKEN*/
public static final String WECHAT_TOKEN = "**************";
/**appID*/
private static final String APP_ID= "***********";
/**appsecret*/
private static final String APP_SECRET = "*****************";
/**获取微信token*/
private static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/**创建菜单 */
private static final String CRATE_MENU = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
private static String accessToken;
/**accessToken的过期时间*/
private static Long expiresIn;
private static String getWechatToken() {
if (accessToken == null || expiresIn < System.currentTimeMillis()) {
String result = HttpUtil.get(GET_TOKEN_URL.replace("APPID", APP_ID).replace("APPSECRET", APP_SECRET));
JSONObject obj= JSON.parseObject(result);
accessToken = obj.getString("access_token");
//过期时间
expiresIn = obj.getLong("expires_in") + (7140);
}
return accessToken;
}
public static void main(String[] args) {
createMenu(CRATE_MENU.replace("ACCESS_TOKEN", getWechatToken()));
}
public static void createMenu(String url){
String menu ="{\"button\":[{\"type\":\"click\",\"name\":\"地址\",\"key\":\"address\"},{\"type\":\"click\",\"name\":\"联系我\",\"key\":\"call\"},{\"name\":\"精选栏目\",\"sub_button\":[{\"type\":\"view\",\"name\":\"搜索\",\"url\":\"http://www.baidu.com/\"},{\"type\":\"scancode_waitmsg\",\"name\":\"扫一扫\",\"key\":\"scan\"}]}]}\n";
String result = HttpUtil.post(url, menu);
System.out.println(result);
}
}