package com.wood.util; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; import org.apache.commons.httpclient.methods.multipart.StringPart; import org.apache.log4j.Logger; import com.wood.model.Token; import net.sf.json.JSONException; import net.sf.json.JSONObject; /** * * @title :WeChatApiUtil * @description :微信公众接口API * @update :2014-10-23 上午11:38:02 * @author :wang_ll * @version :1.0.0 * @since :2014-10-23 */ public class WeChatApiUtil { private static Logger logger = Logger.getLogger(WeChatApiUtil.class.getName()); //文件上传使用到的对象 private static HttpClient httpClient = null; // token 接口 private static final String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; // 创建菜单 private static final String MENU_CREATE = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s"; // 删除菜单 private static final String MENU_DELETE = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s"; // 获取账号粉丝信息 private static final String GET_FANS_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s"; // 生成二维码 private static final String GET_QCODE = " https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s"; // 生成二维码 private static final String SHOW_QCODE = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; // 素材上传 private static final String UPLOAD_MEDIA = "http://file.api.weixin.qq.com/cgi-bin/media/upload"; // 素材下载:不支持视频文件的下载 private static final String DOWNLOAD_MEDIA = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s"; public static String getTokenUrl(String appId, String appSecret) { return String.format(ACCESS_TOKEN, appId, appSecret); } public static String getMenuCreateUrl(String token) { return String.format(MENU_CREATE, token); } public static String getMenuDeleteUrl(String token) { return String.format(MENU_DELETE, token); } public static String getFansInfoUrl(String token, String openid) { return String.format(GET_FANS_INFO, token, openid); } public static String getUploadUrl() { return UPLOAD_MEDIA; } public static String getDownloadUrl(String token, String mediaId) { return String.format(DOWNLOAD_MEDIA, token, mediaId); } public static String getQCodeUrl(String token) { return String.format(GET_QCODE, token); } public static String getShowQCodeUrl(String ticket) { return String.format(SHOW_QCODE, ticket); } /** * 通用接口获取Token凭证 * @param appId * @param appSecret * @return */ public static Token getToken(String appId, String appSecret) { Token token = null; String tockenUrl = WeChatApiUtil.getTokenUrl(appId, appSecret); String response = httpsRequestToString(tockenUrl, "GET", null); JSONObject jsonObject = JSONObject.fromObject(response); 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失败 logger.error(e); } } return token; } /** * 发送请求以https方式发送请求并将请求响应内容以String方式返回 * @param path 请求路径 * @param method 请求方法 * @param body 请求数据体 * @return 请求响应内容转换成字符串信息 */ public static String httpsRequestToString(String path, String method, String body) { if(path==null||method==null){ return null; } String response = null; InputStream inputStream = null; InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null; HttpsURLConnection conn = null; try { TrustManager[] tm = { new JEEWeiXinX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(path); conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(ssf); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod(method); if (null != body) { OutputStream outputStream = conn.getOutputStream(); outputStream.write(body.getBytes("UTF-8")); outputStream.close(); } inputStream = conn.getInputStream(); inputStreamReader = new InputStreamReader(inputStream, "UTF-8"); bufferedReader = new BufferedReader(inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } response = buffer.toString(); } catch (Exception e) { logger.error(e); }finally{ if(conn!=null){ conn.disconnect(); } try { bufferedReader.close(); inputStreamReader.close(); inputStream.close(); } catch (IOException execption) { logger.error(execption); } } return response; } /** * 发送请求已https方式发送请求并将请求响应内容以String方式返回 * @param fileName 保存文件名称 * @param path 请求路径 * @param method 请求方式 * @param body 请求数据体 * @return 请求响应内容输出到文件 */ public static File httpsRequestToFile(String fileName,String path, String method, String body) { if(fileName==null||path==null||method==null){ return null; } InputStream inputStream = null; HttpsURLConnection conn = null; File file = null; try { TrustManager[] tm = { new JEEWeiXinX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(path); conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(ssf); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod(method); if (null != body) { OutputStream outputStream = conn.getOutputStream(); outputStream.write(body.getBytes("UTF-8")); outputStream.close(); } inputStream = conn.getInputStream(); if(inputStream!=null){ file = new File(fileName); }else{ return file; } //写入到文件 FileOutputStream fileOut = new FileOutputStream(file); if(fileOut!=null){ int c = inputStream.read(); while(c!=-1){ fileOut.write(c); c = inputStream.read(); } } } catch (Exception e) { logger.error(e); }finally{ if(conn!=null){ conn.disconnect(); } try { inputStream.close(); } catch (IOException execption) { logger.error(execption); } } return file ; } /** * 以http方式发送请求,并将请求响应内容以String格式返回 * @param path 请求路径 * @param method 请求方法 * @param body 请求数据 * @return 返回响应的字符串 */ public static String httpRequestToString(String path, String method, String body) { String response = null; HttpURLConnection conn = null; InputStream inputStream = null; InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null; try { URL url = new URL(path); conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod(method); if (null != body) { OutputStream outputStream = conn.getOutputStream(); outputStream.write(body.getBytes("UTF-8")); outputStream.close(); } inputStream = conn.getInputStream(); inputStreamReader = new InputStreamReader( inputStream, "UTF-8"); bufferedReader = new BufferedReader( inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } response = buffer.toString(); } catch (Exception e) { logger.error(e); }finally{ if(conn!=null){ conn.disconnect(); } try { bufferedReader.close(); inputStreamReader.close(); inputStream.close(); } catch (IOException execption) { logger.error(execption); } } return response; } /** * 以http方式发送请求,并将请求响应内容输出到文件 * @param path 请求路径 * @param method 请求方法 * @param body 请求数据 * @return 返回响应的存储到文件 */ public static File httpRequestToFile(String fileName,String path, String method, String body) { if(fileName==null||path==null||method==null){ return null; } File file = null; HttpURLConnection conn = null; InputStream inputStream = null; try { URL url = new URL(path); conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod(method); if (null != body) { OutputStream outputStream = conn.getOutputStream(); outputStream.write(body.getBytes("UTF-8")); outputStream.close(); } inputStream = conn.getInputStream(); if(inputStream!=null){ file = new File(fileName); }else{ return file; } //写入到文件 FileOutputStream fileOut = new FileOutputStream(file); if(fileOut!=null){ int c = inputStream.read(); while(c!=-1){ fileOut.write(c); c = inputStream.read(); } } } catch (Exception e) { logger.error(e); }finally{ if(conn!=null){ conn.disconnect(); } } return file; } /** * 微信服务器素材上传 * @param file 表单名称media * @param token access_token * @param type type只支持四种类型素材(video/image/voice/thumb) */ public static JSONObject uploadMedia(File file, String token, String type) { if(file==null||token==null||type==null){ return null; } if(!file.exists()){ logger.info("上传文件不存在,请检查!"); return null; } String url = getUploadUrl(); JSONObject jsonObject = null; PostMethod post = new PostMethod(url); post.setRequestHeader("Connection", "Keep-Alive"); post.setRequestHeader("Cache-Control", "no-cache"); FilePart media = null; try { media = new FilePart("media", file); Part[] parts = new Part[] { new StringPart("access_token", token), new StringPart("type", type), media }; MultipartRequestEntity entity = new MultipartRequestEntity(parts, post.getParams()); post.setRequestEntity(entity); int status = getHttpClient().executeMethod(post); if (status == HttpStatus.SC_OK) { String text = post.getResponseBodyAsString(); jsonObject = JSONObject.fromObject(text); } else { logger.info("upload Media failure status is:" + status); } } catch (FileNotFoundException execption) { logger.error(execption); } catch (HttpException execption) { logger.error(execption); } catch (IOException execption) { logger.error(execption); } return jsonObject; } /** * 多媒体下载接口 * @comment 不支持视频文件的下载 * @param fileName 素材存储文件路径 * @param token 认证token * @param mediaId 素材ID(对应上传后获取到的ID) * @return 素材文件 */ public static File downloadMedia(String fileName, String token, String mediaId) { String url = getDownloadUrl(token, mediaId); return httpRequestToFile(fileName, url, "GET", null); } /** * 获取httpClient对象 * @return */ public synchronized static HttpClient getHttpClient() { if(httpClient==null){ httpClient = new HttpClient(); } return httpClient; } } class JEEWeiXinX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }
今日工作是调研微信开发者接口,实现了基本接口的代码,贴出代码如上。微信开发者API大多数是https方法访问的,少部分(如素材上传下载是http方式)。微信服务器主动推送给开发者服务器的数据都是以XML格式传输的,而开发者服务器主动请求微信服务器时数据则是json格式。
微信的客服消息,只能给最近24小时跟公众号有过互动的用户发送客服消息,否则会遭遇"response out of time limit"错误。