package com.bcxin.survey.wechat.utils; import com.bcxin.survey.domain.wechat.AccessToken; import com.bcxin.survey.utils.FileUtils; import com.bcxin.survey.utils.StringUtil; import com.bcxin.survey.wechat.menuutils.Menu; import com.bcxin.survey.wechat.menuutils.MyX509TrustManager; import com.bcxin.survey.wechat.request.Oauth2AccessToken; import com.bcxin.survey.wechat.request.UserinfoRequest; import com.bcxin.survey.wechat.response.TemplateMsg; import com.bcxin.survey.wechat.response.UserinfoResponse; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import java.util.*; /** * 公众平台通用接口工具类 * * * @date 2014-11-24 */ @Slf4j public class WeixinUtil { /** * 发起https请求并获取结果 * * @param requestUrl 请求地址 * @param requestMethod 请求方式(GET、POST) * @param outputStr 提交的数据 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) */ public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); try { // 创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = {new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 设置请求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 当有数据需要提交时 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意编码格式,防止中文乱码 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (ConnectException ce) { //log.error("Weixin server connection timed out."); } catch (Exception e) { //log.error("https request error:{}", e); } return jsonObject; } // 获取access_token的接口地址(GET) 限200(次/天) public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; /** * 获取access_token * * @param appid 凭证 * @param appsecret 密钥 * @return */ public static AccessToken getAccessToken(String appid, String appsecret) { AccessToken accessToken = null; String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret); System.out.println("=========> 公众号鉴权地址:"+requestUrl); JSONObject jsonObject = httpRequest(requestUrl, "GET", null); // 如果请求成功 if (null != jsonObject) { try { accessToken = new AccessToken(); accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); accessToken.setCreateOn(new Date()); } catch (JSONException e) { accessToken = null; // 获取token失败 , jsonObject.getInt("errcode"), jsonObject.getString("errmsg") System.out.println(jsonObject.toString()); System.out.println("获取token失败 errcode:{} errmsg:{}"); } } return accessToken; } // 菜单创建(POST) 限100(次/天) public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; /** * 创建菜单 * * @param menu 菜单实例 * @param accessToken 有效的access_token * @return 0表示成功,其他值表示失败 */ public static int createMenu(Menu menu, String accessToken) { int result = 0; // 拼装创建菜单的url String url = menu_create_url.replace("ACCESS_TOKEN", accessToken); // 将菜单对象转换成json字符串 String jsonMenu = JSONObject.fromObject(menu).toString(); // 调用接口创建菜单 JSONObject jsonObject = httpRequest(url, "POST", jsonMenu); if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { result = jsonObject.getInt("errcode"); //创建菜单失败, jsonObject.getInt("errcode"), jsonObject.getString("errmsg") System.out.println("创建菜单失败 "); } } return result; } // 菜单查询(GET) 限100(次/天) public static String menu_get_url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN"; /** * 查询菜单 * * @param accessToken 有效的access_token * @return 0表示成功,其他值表示失败 */ public static String getMenu(String accessToken) { String result = null; // 拼装创建菜单的url String url = menu_get_url.replace("ACCESS_TOKEN", accessToken); // 调用接口创建菜单 JSONObject jsonObject = httpRequest(url, "GET", null); if (null != jsonObject) { result = jsonObject.getString("menu"); System.out.println("菜单 " + result); } return result; } // 菜单删除(GET) 限100(次/天) public static String menu_delete_url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; /** * 删除菜单 * * @param accessToken 有效的access_token * @return 0表示成功,其他值表示失败 */ public static int deleteMenu(String accessToken) { int result = 0; // 拼装创建菜单的url String url = menu_delete_url.replace("ACCESS_TOKEN", accessToken); // 调用接口创建菜单 JSONObject jsonObject = httpRequest(url, "GET", null); if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { result = jsonObject.getInt("errcode"); //创建菜单失败, jsonObject.getInt("errcode"), jsonObject.getString("errmsg") System.out.println("删除菜单失败 "); } } return result; } // 通过code换取网页授权access_token(GET) public static String OAuth_accessToken_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; /** * 通过code换取网页授权access_token * * @param appid 凭证 * @param scret 密钥 * @param code 菜单实例 * @return access_token */ public static Oauth2AccessToken getAccessToken(String appid, String scret, String code) { Oauth2AccessToken oat = null; // 换取网页授权的url String url = OAuth_accessToken_url.replace("APPID", appid).replace("SECRET", scret).replace("CODE", code); // 调用接口通过code换取网页授权access_token JSONObject jsonObject = httpRequest(url, "GET", null); if (null != jsonObject) { oat = new Oauth2AccessToken(); oat.setAccess_token(jsonObject.getString("access_token")); oat.setOpenid(jsonObject.getString("openid")); } return oat; } //拉取用户信息access_token(GET) public static String userinfo_get_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=LANG"; /** * 拉取用户信息(需scope为 snsapi_userinfo) * * @param userinfoResponse 凭证 */ public static UserinfoRequest getUserinfo(UserinfoResponse userinfoResponse) { UserinfoRequest userinfo = null; // 拉取用户信息的url String url = userinfo_get_url.replace("ACCESS_TOKEN", userinfoResponse.getAccess_token()) .replace("OPENID", userinfoResponse.getOpenid()).replace("LANG", userinfoResponse.getLang()); // 调用接口拉取用户信息 JSONObject jsonObject = httpRequest(url, "GET", null); if (null != jsonObject) { userinfo = new UserinfoRequest(); userinfo.setOpenid(jsonObject.getString("openid")); userinfo.setNickname(jsonObject.getString("nickname")); userinfo.setSex(jsonObject.getString("sex")); userinfo.setCity(jsonObject.getString("city")); userinfo.setCountry(jsonObject.getString("country")); userinfo.setHeadimgurl(jsonObject.getString("headimgurl")); //userinfo.setPrivilege(jsonObject.getString("privilege")); //userinfo.setUnionid(jsonObject.getString("unionid")); } return userinfo; } //用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi public static String getjsapi_ticket(String access_token){ String ticket = ""; String url= "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; url = url.replace("ACCESS_TOKEN", access_token); JSONObject jsonObject = httpRequest(url, "GET", null); if (null != jsonObject) { ticket = jsonObject.getString("ticket"); } return ticket; } public static AccessToken getjsapi_ticket(AccessToken accesstoken){ AccessToken jsapi_ticket = new AccessToken(); String url= "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; url = url.replace("ACCESS_TOKEN", accesstoken.getToken()); JSONObject jsonObject = httpRequest(url, "GET", null); if (null != jsonObject) { jsapi_ticket.setToken(jsonObject.getString("ticket")); jsapi_ticket.setExpiresIn(jsonObject.getInt("expires_in")); jsapi_ticket.setCreateOn(new Date()); } return jsapi_ticket; } //发送消息模版 public static String sendTemplateMsg = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN"; public static boolean sendTemplateMsg(TemplateMsg templateMsg,AccessToken accessToken) { String jsonMsg = JSONObject.fromObject(templateMsg).toString(); String url = sendTemplateMsg.replace("ACCESS_TOKEN", accessToken.getToken()); System.out.println(url); // 调用接口创建菜单 JSONObject jsonObject = httpRequest(url, "POST", jsonMsg); if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { System.out.println("发送失败 "); return false; } } return true; } //客服回复消息 public static String customMsg= "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN"; public static boolean sendCustomMsg(String jsonMsg,AccessToken accessToken){ String url = customMsg.replace("ACCESS_TOKEN", accessToken.getToken()); JSONObject jsonObject = httpRequest(url, "POST", jsonMsg); System.out.println(jsonMsg); System.out.println(jsonObject.toString()); if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { System.out.println("发送失败 "); return false; } } return true; } public static String getJSSDKSign(String jsapi_ticket, String noncestr, String timestamp,String url){ List signParams = Lists.newLinkedList(); signParams.add(new BasicNameValuePair("jsapi_ticket", jsapi_ticket)); signParams.add(new BasicNameValuePair("noncestr", noncestr)); signParams.add(new BasicNameValuePair("timestamp", timestamp)); signParams.add(new BasicNameValuePair("url", url)); return getJSSDKSign(signParams); } private static String getJSSDKSign(List params) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < params.size(); i++) { sb.append(params.get(i).getName()); sb.append('='); sb.append(params.get(i).getValue()); sb.append('&'); } String sign = sb.toString(); sign= sign.substring(0,sign.length()-1); String appSign = MD5.encode(sign,"SHA-1"); return appSign; } public static boolean sendTemplateMsg(String jsonMsg,AccessToken accessToken) { String url = sendTemplateMsg.replace("ACCESS_TOKEN", accessToken.getToken()); System.out.println(url); // 调用接口创建菜单 JSONObject jsonObject = httpRequest(url, "POST", jsonMsg); if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { System.out.println("发送失败 "); return false; } } return true; } /** * 下载多媒体文件 */ public static boolean downloadImg(AccessToken accessToken, String mediaId,String filename,String savePath){ String downloadMediaUrl = "https://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"; downloadMediaUrl = downloadMediaUrl.replace("ACCESS_TOKEN", accessToken.getToken()).replace("MEDIA_ID", mediaId); try { // 返回文件路径地址 String filePath=FileUtils.downloadForHttps(downloadMediaUrl, filename, savePath); if(StringUtil.isNotEmpty(filePath)){ return true; } return false; } catch (Exception e) { e.printStackTrace(); return false; } } }