多的不说直接上代码:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.WritableResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
* 微信端通信相关操作
*
* @author Vity
*/
@Service
public class WechatService {
@Autowired
RestTemplate rest;
@Autowired
SettingService settingService;
@Autowired
WechatUserService userService;
@Autowired
WechatReplyService replyService;
@Autowired
WechatMaterialService materialService;
@Autowired
WechatNewsService newsService;
// 内存Token过期时间
long accessTokenExpireTime = 0L;
// 内存Token
String accessToken = null;
/**
* 效验签名,微信端消息
*
* @return
*/
public boolean checkSignature(String signature, String timestamp, String nonce) {
String arr[] = new String[] { settingService.findSetting().get("wx_token"), timestamp, nonce };
Arrays.sort(arr);
return signature.equals(DigestUtils.sha1Hex(arr[0] + arr[1] + arr[2]));
}
/**
* 处理微信服务端发起的请求
*
* @param xmlSource
* @return
* @throws DocumentException
*/
public String handleWechatRequest(String xmlSource) throws DocumentException {
Element root = DocumentHelper.parseText(xmlSource).getRootElement();
Element node = null;
Map<String, String> map = new LinkedHashMap<>();
for (int i = 0; i < root.elements().size(); i++) {
node = (Element) root.elements().get(i);
map.put(node.getName(), node.getStringValue());
}
if (map.containsKey("MsgType") && map.get("MsgType").equalsIgnoreCase("Event")) {
return handleEvent(map);
} else {
return handleMessage(map);
}
}
/**
* 处理事件请求
*
* @param req
* @return
*/
private String handleEvent(Map<String, String> req) {
WechatReply reply = null;
if ("subscribe".equals(req.get("Event"))) {
// 关注事件
userService.syncUserInfo(req.get("FromUserName"));
reply = replyService.findReply(WxReplyType.Subscribe);
} else if ("CLICK".equalsIgnoreCase(req.get("Event"))) {
// 菜单点击
reply = replyService.findMenuReply(req.get("EventKey"));
}
return getWechatResponse(reply, req.get("FromUserName"), req.get("ToUserName"));
}
/**
* 处理消息请求
*
* @param req
* @return
*/
private String handleMessage(Map<String, String> req) {
WechatReply reply = null;
if ("text".equals(req.get("MsgType"))) {
// 文本消息
reply = replyService.findKeywordReply(req.get("Content"));
}
if (reply == null) {
// 存储消息
}
return getWechatResponse(reply, req.get("FromUserName"), req.get("ToUserName"));
}
/**
* 获取微信响应格式,xml
*
* @return
*/
private String getWechatResponse(WechatReply reply, String to, String from) {
String resp = "";
if (reply == null) {
reply = replyService.findReply(WxReplyType.Default);
}
if (reply == null) {
resp = "success";
} else {
WechatMaterial material = materialService.getMaterialRepository().findOne(reply.getMaterialId());
Document document = DocumentHelper.createDocument();
Element xml = document.addElement("xml");
Element toUserName = xml.addElement("ToUserName");
toUserName.addCDATA(to);
Element fromUserName = xml.addElement("ToUserName");
fromUserName.addCDATA(from);
Element createTime = xml.addElement("CreateTime");
createTime.addText(System.currentTimeMillis() / 1000L + "");
Element msgType = xml.addElement("MsgType");
msgType.addCDATA(material.getType().name().toLowerCase());
switch (material.getType()) {
case Text: {
Element content = xml.addElement("Content");
content.addCDATA(material.getContent());
break;
}
case Image:
case Thumb: {
Element image = xml.addElement("Image");
Element mediaId = image.addElement("MediaId");
mediaId.addCDATA(material.getMediaId());
break;
}
case News: {
List<WechatNews> news = new ArrayList<>();
for (String id : material.getNewsIds().split(",")) {
news.add(newsService.getRepository().findOne(id));
}
Element count = xml.addElement("ArticleCount");
count.addText(news.size() + "");
Element articles = xml.addElement("Articles");
for (WechatNews wn : news) {
articles.add(wn.getWechatResponse());
}
break;
}
case Video: {
Element video = xml.addElement("Video");
Element mediaId = video.addElement("MediaId");
mediaId.addCDATA(material.getMediaId());
Element title = video.addElement("Title");
title.addCDATA(material.getTitle());
Element desc = video.addElement("Description");
desc.addCDATA(material.getContent());
break;
}
case Voice: {
Element voice = xml.addElement("Voice");
Element mediaId = voice.addElement("MediaId");
mediaId.addCDATA(material.getMediaId());
break;
}
}
resp = xml.asXML();
}
return resp;
}
/**
* 获取AccessToken
*
* @return
*/
public String getAccessToken() {
if (accessTokenExpireTime > System.currentTimeMillis() && StringUtils.isNotBlank(accessToken)) {
return accessToken;
}
String uri = String.format(
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
settingService.findSetting().get("wx_appid"), settingService.findSetting().get("wx_appsecret"));
int count = 0;
do {
count++;
JSONObject resp = new JSONObject(rest.getForObject(uri, String.class));
if (resp.has("access_token") && resp.has("expires_in")) {
accessToken = resp.getString("access_token");
accessTokenExpireTime = System.currentTimeMillis() + (resp.getInt("expires_in") - 10) * 1000L;
break;
}
} while (count < 10);
return accessToken;
}
/**
* 获取关注用户列表
*
* @param nextOpenId
* @return
*/
public JSONObject getUsers(String nextOpenid) {
String uri = String.format("https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s",
getAccessToken(), StringUtils.defaultIfBlank(nextOpenid, ""));
return new JSONObject(rest.getForObject(uri, String.class));
}
/**
* 获取指定OpenID用户的基本信息
*
* @param openid
* @return
*/
public JSONObject getUserInfo(String openid) {
String uri = String.format("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN",
getAccessToken(), openid);
return new JSONObject(rest.getForObject(uri, String.class));
}
/**
* 设置用户备注
*
* @param openid
* @param remark
* @return
*/
public JSONObject setUserRemark(String openid, String remark) {
JSONObject param = new JSONObject();
param.put("openid", openid);
param.put("remark", remark);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 获取黑名单用户列表
*
* @param nextOpenId
* @return
*/
public JSONObject getBlackUsers(String nextOpenid) {
JSONObject param = new JSONObject();
param.put("begin_openid", StringUtils.defaultIfBlank(nextOpenid, ""));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/members/getblacklist?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 拉黑一批用户
*
* @param openids
* @return
*/
public JSONObject blackUsers(List<String> openids) {
JSONObject param = new JSONObject();
param.put("openid_list", openids);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/members/batchblacklist?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 取消拉黑用户
*
* @param openids
* @return
*/
public JSONObject unblackUsers(List<String> openids) {
JSONObject param = new JSONObject();
param.put("openid_list", openids);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/members/batchunblacklist?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 创建用户标签
*
* @param tagName
* @return
*/
public JSONObject createUserTag(String tagName) {
Map<String, Object> map = new HashMap<>();
map.put("name", tagName);
JSONObject param = new JSONObject();
param.put("tag", map);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/create?access_token=%s", getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 获取用户标签列表
*
* @return
*/
public JSONObject getUserTags() {
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/get?access_token=%s", getAccessToken());
return new JSONObject(rest.getForObject(uri, String.class));
}
/**
* 修改用户标签
*
* @param tagid
* @param tagName
* @return
*/
public JSONObject updateUserTag(int tagid, String tagName) {
Map<String, Object> map = new HashMap<>();
map.put("name", tagName);
map.put("id", tagid);
JSONObject param = new JSONObject();
param.put("tag", map);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/update?access_token=%s", getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 删除用户标签
*
* @param tagid
* @return
*/
public JSONObject deleteUserTag(int tagid) {
Map<String, Object> map = new HashMap<>();
map.put("id", tagid);
JSONObject param = new JSONObject();
param.put("tag", map);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/delete?access_token=%s", getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 对用户打标签
*
* @param tagid
* @return
*/
public JSONObject tagUsers(int tagid, List<String> openids) {
JSONObject param = new JSONObject();
param.put("tagid", tagid);
param.put("openid_list", openids);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 对用户取消标签
*
* @param tagid
* @return
*/
public JSONObject untagUsers(int tagid, List<String> openids) {
JSONObject param = new JSONObject();
param.put("tagid", tagid);
param.put("openid_list", openids);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/members/batchuntagging?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 获取用户标签列表
*
* @return
*/
public JSONObject getUserTagsByOpenid(String openid) {
JSONObject param = new JSONObject();
param.put("openid", openid);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/tags/getidlist?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 创建普通菜单
*
* @param menus
* @return
*/
public JSONObject createMenu(JSONObject menus) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(menus.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s", getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 创建个性化菜单
*
* @param menus
* @return
*/
public JSONObject createConditionalMenu(JSONObject menus) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(menus.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 删除个性化菜单
*
* @return
*/
public JSONObject deleteConditionalMenu(String menuid) {
JSONObject param = new JSONObject();
param.put("menuid", menuid);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 删除菜单
*
* @param menus
* @return
*/
public JSONObject deleteAllMenu() {
String uri = String.format("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s", getAccessToken());
return new JSONObject(rest.getForObject(uri, String.class));
}
/**
* 上传图文消息内图片
*
* @param imageFile
* @return
*/
public JSONObject uploadNewsImage(File imageFile) {
WritableResource resource = new FileSystemResource(imageFile);
MultiValueMap<String, Object> data = new LinkedMultiValueMap<String, Object>();
data.add("media", resource);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, data, String.class));
}
/**
* 添加永久图文素材
*
* @param news
* @return
*/
public JSONObject addNews(JSONObject news) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(news.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 修改永久图文素材
*
* @param news
* @return
*/
public JSONObject editNews(JSONObject news) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(news.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/update_news?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 添加音频、图片永久素材
*
* @param type
* @param file
* @return
*/
public JSONObject addMaterial(WxMessageType type, File file) {
WritableResource resource = new FileSystemResource(file);
MultiValueMap<String, Object> data = new LinkedMultiValueMap<String, Object>();
data.add("media", resource);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s&type=%s",
getAccessToken(), type.name().toLowerCase());
return new JSONObject(rest.postForObject(uri, data, String.class));
}
/**
* 添加视频永久素材
*
* @param type
* @param file
* @param title
* @param introduction
* @return
*/
public JSONObject addMaterial(WxMessageType type, File file, String title, String introduction) {
WritableResource resource = new FileSystemResource(file);
MultiValueMap<String, Object> data = new LinkedMultiValueMap<String, Object>();
data.add("media", resource);
if (type == WxMessageType.Video) {
JSONObject p = new JSONObject();
p.put("title", title);
p.put("introduction", introduction);
data.add("description", p.toString());
}
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s&type=%s",
getAccessToken(), type.name().toLowerCase());
return new JSONObject(rest.postForObject(uri, data, String.class));
}
/**
* 获取音频、图片素材
*
* @param mediaId
* @return
* @throws IOException
*/
public File getMaterialFile(String mediaId) throws IOException {
JSONObject param = new JSONObject();
param.put("media_id", mediaId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=%s",
getAccessToken());
ResponseEntity<byte[]> response = rest.exchange(uri, HttpMethod.GET, entity, byte[].class);
File file = File.createTempFile("tmp-", "." + response.getHeaders().getContentType().getSubtype());
FileOutputStream fos = new FileOutputStream(file);
fos.write(response.getBody());
fos.flush();
fos.close();
return file;
}
/**
* 获取图文、视频素材
*
* @param mediaId
* @return
*/
public JSONObject getMaterial(String mediaId) {
JSONObject param = new JSONObject();
param.put("media_id", mediaId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 删除素材
*
* @param mediaId
* @return
*/
public JSONObject deleteMaterial(String mediaId) {
JSONObject param = new JSONObject();
param.put("media_id", mediaId);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
/**
* 获取素材总数
*
* @return
*/
public JSONObject getMaterialCount() {
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=%s",
getAccessToken());
return new JSONObject(rest.getForObject(uri, String.class));
}
/**
* 获取素材总数
*
* @return
*/
public JSONObject getMaterialList(WxMessageType type, int offset) {
JSONObject param = new JSONObject();
param.put("type", type.name().toLowerCase());
param.put("offset", offset);
param.put("count", 20);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(param.toString(), headers);
String uri = String.format("https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=%s",
getAccessToken());
return new JSONObject(rest.postForObject(uri, entity, String.class));
}
}