123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- package com.iamberry.wechat.utils;
- import java.io.BufferedReader;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.UnsupportedEncodingException;
- import java.net.ConnectException;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.util.Date;
- import java.util.logging.Logger;
- import javax.net.ssl.HttpsURLConnection;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.SSLSocketFactory;
- import javax.net.ssl.TrustManager;
- import net.sf.json.JSONObject;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import com.iamberry.app.tool.log.RatFWLogger;
- import com.iamberry.wechat.core.entity.wx.AccessToken;
- import com.iamberry.wechat.core.entity.wx.ITTempLate;
- import com.iamberry.wechat.core.entity.wx.Menu;
- import com.iamberry.wechat.core.entity.wx.QRCJson;
- import com.iamberry.wechat.core.entity.wx.Ticket;
- import com.iamberry.wechat.core.entity.wx.Token;
- import com.iamberry.wechat.face.wechat.TokenService;
- import com.iamberry.wechat.tools.MyX509TrustManager;
- import com.iamberry.wechat.tools.NameUtils;
- /**
- * @company 深圳爱贝源科技有限公司
- * @website www.iamberry.com
- * @author 献
- * @tel 18271840547
- * @date 2016年11月3日
- * @explain 微信公众平台通用接口工具类
- */
- @Component
- public class WeixinUtil {
-
-
- @Autowired
- private RatFWLogger logger;
-
- @Autowired
- private TokenService tokenService;
-
- private static String sendTemplate = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";
-
- /**
- * 网页授权获取access_token
- *
- * @param code
- * @return
- */
- public JSONObject getParamByOauth2(String code) {
- JSONObject jsonObject = null;
- // 得到access_token和openid
- jsonObject = httpRequest(NameUtils.oauth2_getToken_url.replaceAll("CODE", code).replaceAll("APPID", NameUtils.appId).replaceAll("SECRET", NameUtils.appSecret), "GET", null);
- if (null != jsonObject) {
- return jsonObject;
- }
- // 获取token失败
- return null;
- }
- /**
- * 发起https请求并获取结果
- *
- * @param requestUrl
- * 请求地址
- * @param requestMethod
- * 请求方式(GET/POST)
- * @param outputStr
- * 提交的数据
- * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
- * java.lang.ClassCastException:
- * sun.net.www.protocol.http.HttpURLConnection cannot be cast to
- * javax.net.ssl.HttpsURLConnection
- */
- public 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) {
- Logger.getAnonymousLogger().info("Weixin server connection timed out.");
- } catch (Exception e) {
- Logger.getAnonymousLogger().info("信任管理器请求时..." + e);
- Logger.getAnonymousLogger().info("jsonObject..." + jsonObject);
- }
- return jsonObject;
- }
- /**
- * 获取access_token
- * @param appid 凭证
- * @param appsecret 密钥
- * @return
- */
- public AccessToken getAccessToken(String appid, String appsecret) {
-
- // 查询缓存,如果是第一次,绝对为空
- Token accessTokenMemory = StaticCacheMemory.getAccessToken();
- if (accessTokenMemory != null) {
- if (new Date().getTime() < accessTokenMemory.getEndDate().getTime()) {
- AccessToken accessToken = new AccessToken();
- accessToken.setExpiresIn(7200);
- accessToken.setToken(accessTokenMemory.getToken());
- return accessToken;
- }
- }
-
- // 根据public No查询access_token
- Token token = tokenService.selectOne(NameUtils.pubNo);
-
- // 查询到了植入环境中
- StaticCacheMemory.setAccessToken(token);
- AccessToken accessToken = null;
- //判断数据库中是否存在token
- if (token != null) {
- //判断token是否失效
- Date date = new Date();
- if (date.getTime() < token.getEndDate().getTime()) {
- accessToken = new AccessToken();
- accessToken.setExpiresIn(7200);
- accessToken.setToken(token.getToken());
- return accessToken;
- } else {
- String requestUrl = NameUtils.access_token_url.replace("APPID", NameUtils.appId).replace("APPSECRET", NameUtils.appSecret);
- 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"));
- token.setToken(accessToken.getToken());
- token.setEndDate(new Date(date.getTime() + 6500000));
- token.setAppid(NameUtils.pubNo);
- try {
- tokenService.updateToken(token);
- StaticCacheMemory.setAccessToken(token);
- } catch (Exception e) {
- System.out.println("更新token失败:" + e.getMessage());
- }
- return accessToken;
- } catch (Exception e) {
- e.printStackTrace();
- accessToken = null;
- // 获取token失败
- Logger.getAnonymousLogger().info("获取token失败 errcode:{} errmsg:{}" + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
- }
- }
- }
- } else {
- String requestUrl = NameUtils.access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
- 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"));
-
- token = new Token();
- token.setToken(accessToken.getToken());
- token.setEndDate(new Date(new Date().getTime() + 6500000));
- token.setAppid(NameUtils.pubNo);
-
- try {
- tokenService.updateToken(token);
- StaticCacheMemory.setAccessToken(token);
- } catch (Exception e) {
- // 更新失败
- }
- return accessToken;
- } catch (Exception e) {
- accessToken = null;
- // 获取token失败
- Logger.getAnonymousLogger().info("获取token失败 errcode:{} errmsg:{}" + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
- }
- }
- }
- return accessToken;
- }
-
- /**
- * 获取jsapi_ticket(jsapi_ticket的有效期为7200秒)
- * @param token
- * @return
- */
- public Ticket getTicket(String token) {
- Ticket ticket = null;
- String requestUrl = NameUtils.jsapi_ticket_url.replace("ACCESS_TOKEN", token);
- JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
- if (null == jsonObject) {
- // 网络异常
- return null;
- }
- try {
- ticket = new Ticket();
- ticket.setTicket(jsonObject.getString("ticket"));
- ticket.setExpiresIn(jsonObject.getInt("expires_in"));
- } catch (Exception e) {
- // 获取token失败
- Logger.getAnonymousLogger().info("获取ticket失败 errcode:{} errmsg:{}" + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
-
- // 判断错误信息是否为 access_token 失效的问题,只有access失效,我们才重新获取,否则每次获取可能导致access_token资源耗尽
- if (jsonObject.getInt("errcode") != 40001)
- return null;
-
- // 强制刷新access_token,存在多线程安全隐患!
- requestUrl = NameUtils.access_token_url.replace("APPID", NameUtils.appId).replace("APPSECRET", NameUtils.appSecret);
- JSONObject accessTokenJsonObject = httpRequest(requestUrl, "GET", null);
-
- // 报错access_token信息,不管报错与否
- Token wechatToken = new Token();
- wechatToken.setEndDate(new Date(new Date().getTime() + 6500000));
- wechatToken.setAppid(NameUtils.pubNo);
- wechatToken.setToken(accessTokenJsonObject.getString("access_token"));
- tokenService.updateToken(wechatToken);
- StaticCacheMemory.setAccessToken(wechatToken);
-
- // 重新获取一次
- requestUrl = NameUtils.jsapi_ticket_url.replace("ACCESS_TOKEN", wechatToken.getToken());
- jsonObject = httpRequest(requestUrl, "GET", null);
- ticket = new Ticket();
- ticket.setTicket(jsonObject.getString("ticket"));
- ticket.setExpiresIn(jsonObject.getInt("expires_in"));
- }
-
- return ticket;
- }
- /**
- * 创建菜单
- * @param menu 菜单实例
- * @param accessToken 有效的access_token
- * @return 0表示成功,其他值表示失败
- */
- public int createMenu(Menu menu, String accessToken) {
- int result = 0;
- // 拼装创建菜单的url
- String url = NameUtils.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");
- Logger.getAnonymousLogger().info("创建菜单失败 errcode:{} errmsg:{}" + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
- }
- }
- return result;
- }
- /**
- * 创建菜单
- * @param jsonMenu
- * @param accessToken
- */
- public int createMenu(String jsonMenu, String accessToken) {
- int result = 0;
- // 拼装创建菜单的url
- String url = NameUtils.menu_create_url.replace("ACCESS_TOKEN", accessToken);
- // 调用接口创建菜单
- JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
- if (null != jsonObject) {
- if (0 != jsonObject.getInt("errcode")) {
- result = jsonObject.getInt("errcode");
- Logger.getAnonymousLogger().info("创建菜单失败 errcode:{} errmsg:{} " + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
- }
- }
- return result;
- }
- /**
- * 创建二维码
- * @param qrCode
- * @return
- */
- public QRCJson createQrcode(String json) {
- AccessToken at = this.getAccessToken(NameUtils.appId, NameUtils.appSecret);
- if (at == null) {
- return null;
- }
- String token = at.getToken();
- JSONObject jsonObject = httpRequest(NameUtils.get_token_url.replaceAll("TOKEN", token), "POST", json);
- if (jsonObject == null) {
- return null;
- }
- QRCJson qrcJson = new QRCJson();
- String ticket = null;
- try {
- ticket = URLEncoder.encode(jsonObject.getString("ticket"), "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- qrcJson.setTicket(ticket);
- qrcJson.setUrl(NameUtils.show_qrcode_url + ticket);
- if (json.contains("expire_seconds")) {// 临时二维码才有过期时间
- qrcJson.setExpire_seconds(jsonObject.getString("expire_seconds"));
- }
- return qrcJson;
- }
- /**
- * 生成网页授权链接
- *
- * @param type
- * @param redirectURI
- */
- public String getOauth2Url(String type, String redirectURI) {
- String url = "";
- try {
- redirectURI = URLEncoder.encode(redirectURI, "utf-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- if ("snsapi_base".equals(type)) {
- url = NameUtils.oauth2_url.replace("SCOPE", "snsapi_base").replace("APPID", NameUtils.appId).replace("REDIRECT_URI", redirectURI);
- } else {
- url = NameUtils.oauth2_url.replace("SCOPE", "snsapi_userinfo").replace("APPID", NameUtils.appId).replace("REDIRECT_URI", redirectURI);
- }
- return url;
- }
- /**
- * (网页授权)拉取用户信息
- *
- * @param code
- * @param type
- * @return
- */
- public JSONObject getUserInfoByOauth2(String code, String type) {
- JSONObject jsonObject = null;
- String openid = "", access_token = "";
- // 得到access_token和openid
- jsonObject = httpRequest(NameUtils.oauth2_getToken_url.replaceAll("CODE", code).replaceAll("APPID", NameUtils.appId).replaceAll("SECRET", NameUtils.appSecret), "GET", null);
- if (null == jsonObject) {
- return null;
- }
- openid = jsonObject.getString("openid");
- access_token = jsonObject.getString("access_token");
- // 获取用户信息
- if ("info".equals(type) && !"".equals(openid) && !"".equals(access_token)) {
- jsonObject = null;
- jsonObject = httpRequest(NameUtils.oauth2_getUserInfo_url.replaceAll("ACCESS_TOKEN", access_token).replaceAll("OPENID", openid), "GET", null);
- if (jsonObject != null)
- return jsonObject;
- }
- return jsonObject;
- }
- /**
- * 拉取用户信息
- *
- * @param code
- * @param appid
- * @param secret
- */
- public String[] getOpenId(String code, String appid, String secret) {
- String[] strs = new String[2];
- String url = "", openid = "", access_token = "";
- Logger.getAnonymousLogger().info("code = " + code + ", appid = " + appid + ", secret = " + secret);
- // 得到access_token和openid
- url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
- JSONObject jsonObject = httpRequest(url.replaceAll("CODE", code).replaceAll("APPID", appid).replaceAll("SECRET", secret), "GET", null);
- if (null == jsonObject) {
- return null;
- }
- openid = jsonObject.getString("openid");
- access_token = jsonObject.getString("access_token");
- strs[0] = openid;
- strs[1] = access_token;
- return strs;
- }
- /**
- * 根据openid拉取用户信息
- * @param openid
- * @return
- */
- public JSONObject getUserInfo(String openid) {
- AccessToken token = this.getAccessToken(NameUtils.appId, NameUtils.appSecret);
- if (token == null) {
- // 此处如果出错,只能说明程序逻辑改变,存在多线程安全隐患
- return null;
- }
- // 获取信息
- JSONObject jsonObject = httpRequest(NameUtils.userinfo_url.replaceAll("ACCESS_TOKEN", token.getToken()).replaceAll("OPENID", openid), "GET", null);
- if (null == jsonObject) {
- // 网络错误
- return null;
- }
- // 对数据进行get(防止出现问题,能够让程序及时补救), 如果抛出异常,表示access_token可能失效,强制获取一次。
- try {
- jsonObject.getString("sex");
- } catch (Exception e) {
-
- // 记录日志
- logger.error(this, "getUserInfo method throw exception:" + e.getMessage() + "[" + jsonObject + "]");
-
- // 判断错误信息是否为 access_token 失效的问题,只有access失效,我们才重新获取,否则每次获取可能导致access_token资源耗尽
- if (jsonObject.getInt("errcode") != 40001)
- return jsonObject;
-
- // 强制刷新access_token,存在多线程安全隐患!
- String requestUrl = NameUtils.access_token_url.replace("APPID", NameUtils.appId).replace("APPSECRET", NameUtils.appSecret);
- JSONObject accessTokenJsonObject = httpRequest(requestUrl, "GET", null);
-
- // 报错access_token信息,不管报错与否
- Token wechatToken = new Token();
- wechatToken.setEndDate(new Date(new Date().getTime() + 6500000));
- wechatToken.setAppid(NameUtils.pubNo);
- wechatToken.setToken(accessTokenJsonObject.getString("access_token"));
- tokenService.updateToken(wechatToken);
- StaticCacheMemory.setAccessToken(wechatToken);
-
- // 再次获取用户信息
- return httpRequest(NameUtils.userinfo_url.replaceAll("ACCESS_TOKEN", wechatToken.getToken()).replaceAll("OPENID", openid), "GET", null);
- }
- return jsonObject;
- }
- /**
- * 发送模板消息 appId 公众账号的唯一标识 appSecret 公众账号的密钥 openId 用户标识
- */
- public boolean sendTemplateMessage(String appId, String appSecret,
- String openId, String template_id, Object data, String redirectUrl) {
- // 准备数据
- AccessToken token = this.getAccessToken(appId, appSecret);
- String access_token = token.getToken();
-
- String url = sendTemplate + access_token;
- //json格式转换
- String jsonObj = JSONObject.fromObject(data).toString();
- data = "="+jsonObj.toString()+"=";
-
- // 准备模版
- ITTempLate temp = new ITTempLate();
- temp.setTouser(openId);
- temp.setTemplate_id(template_id);
- temp.setUrl(redirectUrl);
- temp.setData(data);
- // format
- String jsonString = JSONObject.fromObject(temp).toString();
-
- jsonString = jsonString.replace("\"=", "").replace("=\"", "").replaceAll("\\\\", "");
-
- // send
- JSONObject jsonObject = httpRequest(url, "POST", jsonString);
- if (null == jsonObject) {
- return false;
- }
- if (0 != jsonObject.getInt("errcode")) {
- logger.info("错误 errcode:{} errmsg:{}" + jsonObject.getInt("errcode") + jsonObject.getString("errmsg"));
- return false;
- }
- return true;
- }
- }
|