Spring RestTemplate 进行微信公众号请求的代码笔记

多的不说直接上代码:

 

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));
	}
}

 

转载于:https://my.oschina.net/vity/blog/1580886

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值