package com.duomikeji.weixin.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 信任管理器
*
* @author liufeng
* @date 2013-04-10
*/
public class MyX509TrustManager implements X509TrustManager {
// 检查客户端证书
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 检查服务器端证书
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509证书数组
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
package com.duomikeji.weixin.util;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.duomikeji.weixin.menu.Menu;
/**
* 自定义菜单工具类
*
* @author liufeng
* @date 2013-10-17
*/
public class MenuUtil {
private static Logger log = LoggerFactory.getLogger(MenuUtil.class);
// 菜单创建(POST)
public final static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
// 菜单查询(GET)
public final static String menu_get_url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
// 菜单删除(GET)
public final static String menu_delete_url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
/**
* 创建菜单
*
* @param menu 菜单实例
* @param accessToken 凭证
* @return true成功 false失败
*/
public static boolean createMenu(Menu menu, String accessToken) {
boolean result = false;
String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
// 将菜单对象转换成json字符串
String jsonMenu = JSONObject.fromObject(menu).toString();
// 发起POST请求创建菜单
String respJSON = CommonUtil.httpsRequest(url, "POST", jsonMenu);
JSONObject jsonObject = JSONObject.fromObject(respJSON);
if (null != jsonObject) {
int errorCode = jsonObject.getInt("errcode");
String errorMsg = jsonObject.getString("errmsg");
if (0 == errorCode) {
result = true;
} else {
result = false;
log.error("创建菜单失败 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return result;
}
/**
* 查询菜单
*
* @param accessToken 凭证
* @return
*/
public static String getMenu(String accessToken) {
String result = null;
String requestUrl = menu_get_url.replace("ACCESS_TOKEN", accessToken);
// 发起GET请求查询菜单
String respJSON = CommonUtil.httpsRequest(requestUrl, "GET", null);
JSONObject jsonObject = JSONObject.fromObject(respJSON);
if (null != jsonObject) {
result = jsonObject.toString();
}
return result;
}
/**
* 删除菜单
*
* @param accessToken 凭证
* @return true成功 false失败
*/
public static boolean deleteMenu(String accessToken) {
boolean result = false;
String requestUrl = menu_delete_url.replace("ACCESS_TOKEN", accessToken);
// 发起GET请求删除菜单
String respJSON = CommonUtil.httpsRequest(requestUrl, "GET", null);
JSONObject jsonObject = JSONObject.fromObject(respJSON);
if (null != jsonObject) {
int errorCode = jsonObject.getInt("errcode");
String errorMsg = jsonObject.getString("errmsg");
if (0 == errorCode) {
result = true;
} else {
result = false;
log.error("删除菜单失败 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return result;
}
}
/**
* 通用工具类
*
* @author liufeng
* @date 2013-10-17
*/
public class CommonUtil {
private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
// 凭证获取(GET)
public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/**
* 处理https GET/POST请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方法(GET/POST)
* @param outputStr 参数
* @return
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
StringBuffer buffer = null;
try {
// 创建SSLContext
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
TrustManager[] tm = { new MyX509TrustManager() };
// 初始化
sslContext.init(null, tm, new SecureRandom());
// 获取SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
// 设置当前实例使用的SSLSocketFactory
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
// 往服务器端写内容
if (null != outputStr) {
OutputStream os = conn.getOutputStream();
os.write(outputStr.getBytes("utf-8"));
os.close();
}
// 读取服务器端返回的内容
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
buffer = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
/**
* 获取接口访问凭证
*
* @param appid 凭证
* @param appsecret 密钥
* @return
*/
public static Token getToken(String appid, String appsecret) {
Token token = null;
String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
// 发起GET请求获取凭证
String respJSON = httpsRequest(requestUrl, "GET", null);
JSONObject jsonObject = JSONObject.fromObject(respJSON);
if (null != jsonObject) {
try {
token = new Token();
token.setAccessToken(jsonObject.getString("access_token"));
token.setExpiresIn(jsonObject.getInt("expires_in"));
} catch (JSONException e) {
token = null;
// 获取token失败
log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
}
}
return token;
}
/**
* URL编码(utf-8)
*
* @param source
* @return
*/
public static String urlEncodeUTF8(String source) {
String result = source;
try {
result = java.net.URLEncoder.encode(source, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
/**
* 根据内容类型判断文件扩展名
*
* @param contentType 内容类型
* @return
*/
public static String getFileExt(String contentType) {
String fileExt = "";
if ("image/jpeg".equals(contentType))
fileExt = ".jpg";
else if ("audio/mpeg".equals(contentType))
fileExt = ".mp3";
else if ("audio/amr".equals(contentType))
fileExt = ".amr";
else if ("video/mp4".equals(contentType))
fileExt = ".mp4";
else if ("video/mpeg4".equals(contentType))
fileExt = ".mp4";
return fileExt;
}
// /**
// * 处理https GET/POST请求(针对需要商户证书的API)
// *
// * @param requestUrl 请求地址
// * @param requestMethod 请求方法(GET/POST)
// * @param outputStr 参数
// * @return
// */
// public static String httpsForAPICert(String requestUrl, String requestMethod, String outputStr) {
// StringBuffer buffer = null;
// try {
// // 证书文件(微信商户平台-账户设置-API安全-API证书-下载证书)
// String keyStorePath = "D:/apiclient_cert.p12";
// // 证书密码(默认为商户ID)
// String password = DuoMiUtil.partner;
// // 实例化密钥库
// KeyStore ks = KeyStore.getInstance("PKCS12");
// // 获得密钥库文件流
// FileInputStream fis = new FileInputStream(keyStorePath);
// // 加载密钥库
// ks.load(fis, password.toCharArray());
// // 关闭密钥库文件流
// fis.close();
//
// // 实例化密钥库
// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// // 初始化密钥工厂
// kmf.init(ks, password.toCharArray());
//
// // 创建SSLContext
// SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
// sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
// // 获取SSLSocketFactory对象
// SSLSocketFactory ssf = sslContext.getSocketFactory();
//
// URL url = new URL(requestUrl);
// HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
// conn.setRequestMethod(requestMethod);
// // 设置当前实例使用的SSLSocketFactory
// conn.setSSLSocketFactory(ssf);
// conn.setDoOutput(true);
// conn.setDoInput(true);
// conn.connect();
//
// // 往服务器端写内容
// if (null != outputStr) {
// OutputStream os = conn.getOutputStream();
// os.write(outputStr.getBytes("utf-8"));
// os.close();
// }
//
// // 读取服务器端返回的内容
// InputStream is = conn.getInputStream();
// InputStreamReader isr = new InputStreamReader(is, "utf-8");
// BufferedReader br = new BufferedReader(isr);
//
// buffer = new StringBuffer();
// String line = null;
// while ((line = br.readLine()) != null) {
// buffer.append(line);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// return buffer.toString();
// }
/**
* 获取客户端ip
*
* @param request
* @return 客户端的IP地址
*/
public static String getClientIP(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknow".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
package com.duomikeji.weixin.util;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.jms.TextMessage;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
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;
/**
* 消息处理工具类
*
* @author liufeng
* @date 2013-09-15
*/
public class MessageUtil {
// 请求消息类型:文本
public static final String REQ_MESSAGE_TYPE_TEXT = "text";
// 请求消息类型:图片
public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
// 请求消息类型:语音
public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
// 请求消息类型:视频
public static final String REQ_MESSAGE_TYPE_VIDEO = "video";
// 请求消息类型:地理位置
public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
// 请求消息类型:链接
public static final String REQ_MESSAGE_TYPE_LINK = "link";
// 请求消息类型:事件推送
public static final String REQ_MESSAGE_TYPE_EVENT = "event";
// 事件类型:subscribe(订阅)
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
// 事件类型:unsubscribe(取消订阅)
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
// 事件类型:scan(用户已关注时的扫描带参数二维码)
public static final String EVENT_TYPE_SCAN = "scan";
// 事件类型:LOCATION(上报地理位置)
public static final String EVENT_TYPE_LOCATION = "LOCATION";
// 事件类型:CLICK(自定义菜单)
public static final String EVENT_TYPE_CLICK = "CLICK";
// 响应消息类型:文本
public static final String RESP_MESSAGE_TYPE_TEXT = "text";
// 响应消息类型:图片
public static final String RESP_MESSAGE_TYPE_IMAGE = "image";
// 响应消息类型:语音
public static final String RESP_MESSAGE_TYPE_VOICE = "voice";
// 响应消息类型:视频
public static final String RESP_MESSAGE_TYPE_VIDEO = "video";
// 响应消息类型:音乐
public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
// 响应消息类型:图文
public static final String RESP_MESSAGE_TYPE_NEWS = "news";
// 多客服
public static final String RESP_MESSAGE_CUSTOMER = "transfer_customer_service";
/**
* 解析微信发来的请求(XML)
*
* @param request
* @return Map<String, String>
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 从request中取得输入流
InputStream inputStream = request.getInputStream();
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList)
map.put(e.getName(), e.getText());
// 释放资源
inputStream.close();
inputStream = null;
return map;
}
/**
* 扩展xstream使其支持CDATA
*/
private static XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
@SuppressWarnings("unchecked")
public void startNode(String name, Class clazz) {
super.startNode(name, clazz);
}
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
/**
* 文本消息对象转换成xml
*
* @param textMessage 文本消息对象
* @return xml
*/
public static String messageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
// /**
// * 图片消息对象转换成xml
// *
// * @param imageMessage 图片消息对象
// * @return xml
// */
// public static String messageToXml(ImageMessage imageMessage) {
// xstream.alias("xml", imageMessage.getClass());
// return xstream.toXML(imageMessage);
// }
//
// /**
// * 语音消息对象转换成xml
// *
// * @param voiceMessage 语音消息对象
// * @return xml
// */
// public static String messageToXml(VoiceMessage voiceMessage) {
// xstream.alias("xml", voiceMessage.getClass());
// return xstream.toXML(voiceMessage);
// }
//
// /**
// * 视频消息对象转换成xml
// *
// * @param videoMessage 视频消息对象
// * @return xml
// */
// public static String messageToXml(VideoMessage videoMessage) {
// xstream.alias("xml", videoMessage.getClass());
// return xstream.toXML(videoMessage);
// }
//
// /**
// * 音乐消息对象转换成xml
// *
// * @param musicMessage 音乐消息对象
// * @return xml
// */
// public static String messageToXml(MusicMessage musicMessage) {
// xstream.alias("xml", musicMessage.getClass());
// return xstream.toXML(musicMessage);
// }
//
// /**
// * 图文消息对象转换成xml
// *
// * @param newsMessage 图文消息对象
// * @return xml
// */
// public static String messageToXml(NewsMessage newsMessage) {
// xstream.alias("xml", newsMessage.getClass());
// xstream.alias("item", new Article().getClass());
// return xstream.toXML(newsMessage);
// }
//
// /**
// * 多客服消息对象转换成xml
// *
// * @param customerMessage 多客服消息对象
// * @return xml
// */
// public static String messageToXml(CustomerMessage customerMessage) {
// xstream.alias("xml", customerMessage.getClass());
// return xstream.toXML(customerMessage);
// }
/**
* emoji表情转换(hex -> utf-16)
*
* @param hexEmoji
* @return
*/
public static String emoji(int hexEmoji) {
return String.valueOf(Character.toChars(hexEmoji));
}
/**
* 计算字符串所占字节数(采用utf-8编码)
*
* @param content
* @return
*/
public static int getByteSize(String content) {
int size = 0;
if (null != content) {
try {
// 汉字采用utf-8编码时占3个字节
size = content.getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return size;
}
/**
* 将微信消息中的CreateTime转换成标准格式的时间(yyyy-MM-dd HH:mm:ss)
*
* @param createTime 消息创建时间
* @return
*/
public static String formatTime(String createTime) {
// 将微信传入的CreateTime转换成long类型,再乘以1000
long msgCreateTime = Long.parseLong(createTime) * 1000L;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date(msgCreateTime));
}
/**
* URL编码(utf-8)
*
* @param source
* @return
*/
public static String urlEncodeUTF8(String source) {
String result = source;
try {
result = java.net.URLEncoder.encode(source, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}