package com.fr.plugin.utils; import com.fanruan.api.log.LogKit; import com.fanruan.api.net.http.HttpKit; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.plugin.dao.MyYiTuanDao; import com.fr.plugin.entitys.YTYiTuanEntity; import com.fr.plugin.yt.MyCoreDBAccess; import com.fr.report.stable.fun.Actor; import com.fr.stable.ActorConstants; import com.fr.stable.ActorFactory; import com.fr.stable.StringUtils; import com.fr.stable.db.action.DBAction; import com.fr.stable.db.dao.DAOContext; import com.fr.stable.query.QueryFactory; import com.fr.stable.query.restriction.RestrictionFactory; import com.fr.third.guava.cache.*; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.JsonNode; import com.mashape.unirest.http.Unirest; import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * xx码API调用工具类 * Created by Shinelon on 2017/12/13. */ public class YiTuanMaUtils { public final static String API_BASE_URL = "https://xxxx.cn/openapi/" ; public final static String APP_TOKEN_URL = API_BASE_URL + "oauth/token" ; public final static String APP_TICKET_URL = API_BASE_URL + "oauth/ticket" ; public final static String APP_AUTHCODE_URL = API_BASE_URL + "oauth/authorize" ; public final static String APP_AUTHUSERID_URL = API_BASE_URL + "user/get-user-ids?authCode=" ; public final static String GET_ALLUSER_URL = API_BASE_URL + "group/members/" ; public final static String APP_SENDMSG_URL = API_BASE_URL + "message/send-to-eapp" ; public final static String APP_SENDMSG_TO_USER = API_BASE_URL + "message/send-to-users" ; public final static String GROUP_SENDMSG_URL = API_BASE_URL + "message/send-to-group" ; public final static String ACCOUNT_URL = "https://xxxx.cn/esenaccount/openapi/account" ; public final static int SUCCESS_CODE = 200; public final static int EXPIRE_CODE = 400; public final static int ERROR_CODE = 401; public final static int SYS_ERROR_CODE = 500; public final static String APPLICATION_JSON_UTF8 = "application/json;charset=UTF-8" ; /** * token缓存,2小时有效期 */ private static LoadingCache tokenCache = CacheBuilder.newBuilder() .expireAfterWrite(2, TimeUnit.HOURS) .removalListener(new RemovalListener() { @Override public void onRemoval( RemovalNotification notification) { LogKit.debug(notification.getKey() + " was removed, cause is " + notification.getCause()); } }).build(new CacheLoader() { @Override public String load(String key) throws Exception { return getAccessTokenFromAPI(key); } }); /** * ticket缓存,10分钟有效期 */ private static LoadingCache ticketCache = CacheBuilder.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .removalListener(new RemovalListener() { @Override public void onRemoval( RemovalNotification notification) { LogKit.debug(notification.getKey() + " was removed, cause is " + notification.getCause()); } }).build(new CacheLoader() { @Override public String load(String key) throws Exception { return getTicketFromAPI(key); } }); private static LoadingCache testCache = CacheBuilder.newBuilder() .expireAfterWrite(5, TimeUnit.SECONDS) .removalListener(new RemovalListener() { @Override public void onRemoval(RemovalNotification notification) { LogKit.debug(notification.getKey() + " was removed, cause is " + notification.getCause()); } }).build(new CacheLoader() { @Override public String load(String key) throws Exception { return getTicketFromAPI(key); } }); /** * post请求 * * @param bodyJSON * @param url * @return * @throws Exception */ private static HttpResponse buildPostResponce(JSONObject bodyJSON, String url) throws Exception { HttpResponse jsonResponse = null; jsonResponse = Unirest .post(url) .header("Content-Type" , APPLICATION_JSON_UTF8) .body(bodyJSON.toString()).asJson(); return jsonResponse; } /** * post请求(header处理) * * @param bodyJSON * @param url * @param access_token * @return * @throws Exception */ private static HttpResponse buildPostResponceWithToken(JSONObject bodyJSON, String url, String access_token) throws Exception { HttpResponse jsonResponse = null; jsonResponse = Unirest .post(url) .header("Content-Type" , APPLICATION_JSON_UTF8) .header("Authorization" , getAuthorizationHeader(access_token)) .body(bodyJSON.toString()).asJson(); return jsonResponse; } /** * get请求 * * @param url * @param access_token * @return * @throws Exception */ private static HttpResponse buildGetResponceWithToken(String url, String access_token) throws Exception { HttpResponse jsonResponse = null; jsonResponse = Unirest .get(url) .header("Content-Type" , APPLICATION_JSON_UTF8) .header("Authorization" , getAuthorizationHeader(access_token)) .asJson(); return jsonResponse; } /** * 获取缓存中的token * * @return */ public static String getAccessToken(String clientId) { try { String token = tokenCache.get(clientId); if (StringUtils.isEmpty(token)) { token = getAccessTokenFromAPI(clientId); if (StringUtils.isNotBlank(token)) { tokenCache.put(clientId, token); } } return token; } catch (Exception e) { FineLoggerFactory.getLogger().debug("==================== 获取缓存access_token失败!"); } return "" ; } /** * 根据clientId以及clientSecret获取token * * @param clientId * @param clientSecret * @return * @throws Exception */ public static String getAccessTokenFromConfig(String clientId, String clientSecret) throws Exception { JSONObject jsonObject = new JSONObject(); jsonObject.put("clientId" , clientId); jsonObject.put("clientSecret" , clientSecret); HttpResponse jsonResponse = buildPostResponce(jsonObject, APP_TOKEN_URL); if (jsonResponse.getStatus() == SUCCESS_CODE) { JsonNode jsonNode = jsonResponse.getBody(); return jsonNode.getObject().getString("access_token"); } else { FineLoggerFactory.getLogger().debug("==================== 获取xx码access_token失败!"); FineLoggerFactory.getLogger().debug("==================== 获取xx码access_token失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); } return "" ; } /** * 缓存build时专用,获取token * todo 改成查询clientId * * @return * @throws Exception */ public static String getAccessTokenFromAPI(String clientId) throws Exception { // YiTuanMaManager manager = YiTuanMaManager.getInstance(); // return getAccessTokenFromConfig(manager.getClientId(), manager.getClientSecret()); YTYiTuanEntity entity = getYituanEntityByClientId(clientId); if (entity != null) { String secret = entity.getSecret(); return getAccessTokenFromConfig(clientId, secret); } return "" ; } public static YTYiTuanEntity getYituanEntityByClientId(String clientId) throws Exception { List ytYiTuanEntities = MyCoreDBAccess.getAccessor().runQueryAction(new DBAction>() { @Override public List run(DAOContext daoContext) throws Exception { return daoContext.getDAO(MyYiTuanDao.class).find(QueryFactory.create().addRestriction(RestrictionFactory.eq("clientId" , clientId))); } }); if (!ytYiTuanEntities.isEmpty()) { return ytYiTuanEntities.get(0); } return null; } /** * 获取缓存中的ticket * * @return */ public static String getTicket(String clientid) { try { String ticket = ticketCache.get(clientid); if (StringUtils.isEmpty(ticket)) { ticket = getTicketFromAPI(clientid); ticketCache.put(clientid, ticket); } return ticket; } catch (Exception e) { FineLoggerFactory.getLogger().debug("==================== 获取缓存ticket失败!"); } return "" ; } public static String refreshToken(String clientId) throws Exception { String access_token = getAccessTokenFromAPI(clientId); if (StringUtils.isNotBlank(access_token)) { tokenCache.put(clientId, access_token); } return access_token; } /** * 根据token获取ticket * * @param access_token * @return * @throws Exception */ public static String getTicketWithToken(String clientId, String access_token) throws Exception { LogKit.debug("==================== :获取ticket token=" + access_token); return getTicket4ThreeTimes(clientId, access_token, 0); } private static String getTicket4ThreeTimes(String clientId, String access_token, int count) throws Exception { if (count < 3) { JSONObject jsonObject = new JSONObject(); jsonObject.put("accessToken" , access_token); HttpResponse jsonResponse = buildPostResponceWithToken(jsonObject, APP_TICKET_URL, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { JsonNode jsonNode = jsonResponse.getBody(); return jsonNode.getObject().getString("ticket"); } else if (jsonResponse.getStatus() == EXPIRE_CODE || jsonResponse.getStatus() == ERROR_CODE) { LogKit.debug("==================== 获取xx码ticket失败! token失效,重新获取"); access_token = refreshToken(clientId); count++; return getTicket4ThreeTimes(clientId, access_token, count); } else { FineLoggerFactory.getLogger().debug("==================== 获取xx码ticket失败!"); FineLoggerFactory.getLogger().debug("==================== 获取xx码ticket失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); return "" ; } } else { FineLoggerFactory.getLogger().debug("==================== 3次获取xx码ticket失败!"); return "" ; } } /** * 缓存build时专用,获取ticket * * @return * @throws Exception */ public static String getTicketFromAPI(String clientId) throws Exception { String access_token = getAccessToken(clientId); if (StringUtils.isNotEmpty(access_token)) { return getTicketWithToken(clientId, access_token); } return "" ; } /** * 获取authCode,已弃 * * @param ticket * @param access_token * @return * @throws Exception */ public static String getAuthCode(String ticket, String access_token) throws Exception { LogKit.debug("==================== :获取authCode token=" + access_token); JSONObject jsonObject = new JSONObject(); jsonObject.put("ticket" , ticket); HttpResponse jsonResponse = buildPostResponceWithToken(jsonObject, APP_AUTHCODE_URL, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { JsonNode jsonNode = jsonResponse.getBody(); return jsonNode.getObject().getString("authCode"); } else { FineLoggerFactory.getLogger().debug("==================== 获取xx码authCode失败!"); FineLoggerFactory.getLogger().debug("==================== 获取xx码authCode失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); } return null; } /** * 获取当前xx码用户id * * @param authCode * @param access_token * @return * @throws Exception */ public static String getCurrentUserId(String clientId, String authCode, String access_token) throws Exception { LogKit.debug("==================== :获取当前xx码用户id token=" + access_token); return getCurrentUserId4ThreeTimes(clientId, authCode, access_token, 0); } private static String getCurrentUserId4ThreeTimes(String clientId, String authCode, String access_token, int count) throws Exception { if (count < 3) { HttpResponse jsonResponse = buildGetResponceWithToken(APP_AUTHUSERID_URL + authCode, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { JsonNode jsonNode = jsonResponse.getBody(); return jsonNode.getObject().getString("userId"); } else if (jsonResponse.getStatus() == EXPIRE_CODE || jsonResponse.getStatus() == ERROR_CODE) { LogKit.debug("==================== 获取xx码用户ID失败! token失效,重新获取"); access_token = refreshToken(clientId); count++; return getCurrentUserId4ThreeTimes(clientId, authCode, access_token, count); } else { FineLoggerFactory.getLogger().debug("==================== 获取xx码用户ID失败!"); FineLoggerFactory.getLogger().debug("==================== 获取xx码用户ID失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); return null; } } else { FineLoggerFactory.getLogger().debug("==================== 3次获取xx码用户ID失败!"); return null; } } /** * 获取团队id,已弃 * * @param authCode * @param access_token * @return * @throws Exception */ public static String getGroupId(String authCode, String access_token) throws Exception { LogKit.debug("==================== :获取团队id token=" + access_token); HttpResponse jsonResponse = buildGetResponceWithToken(APP_AUTHUSERID_URL + authCode, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { JsonNode jsonNode = jsonResponse.getBody(); return jsonNode.getObject().getString("tenantId"); } else { FineLoggerFactory.getLogger().debug("==================== 获取BI团队ID失败!"); FineLoggerFactory.getLogger().debug("==================== 获取BI团队ID失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); } return null; } /** * 获取团队下所有用户 * * @param access_token * @return * @throws Exception */ public static JSONArray getUserInfo(String clientId, String access_token) throws Exception { YTYiTuanEntity tuanEntity = getYituanEntityByClientId(clientId); if (tuanEntity != null) { String groupId = tuanEntity.getGroupId(); return getUserInfo4ThreeTimes(clientId, groupId, access_token, 0); } LogKit.error("同步 client ID : {} 无法获取到对应的配置" , clientId); return new JSONArray(); } private static JSONArray getUserInfo4ThreeTimes(String clientId, String groupId, String access_token, int count) throws Exception { if (count < 3) { HttpResponse jsonResponse = buildGetResponceWithToken(GET_ALLUSER_URL + groupId, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { JsonNode jsonNode = jsonResponse.getBody(); return jsonNode.getObject().getJSONArray("members"); } else if (jsonResponse.getStatus() == EXPIRE_CODE || jsonResponse.getStatus() == ERROR_CODE) { LogKit.debug("==================== 获取xx码团队所有用户失败! token失效,重新获取"); access_token = refreshToken(clientId); count++; return getUserInfo4ThreeTimes(clientId, groupId, access_token, count); } else { FineLoggerFactory.getLogger().debug("==================== 获取xx码团队所有用户失败!"); FineLoggerFactory.getLogger().debug("==================== 获取xx码团队所有用户失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); return null; } } else { FineLoggerFactory.getLogger().debug("==================== 3次获取xx码团队所有用户失败!"); return null; } } /** * build请求header * * @param access_token * @return */ private static String getAuthorizationHeader(String access_token) { String authorization = "Bearer " + access_token; return authorization; } /** * 兼容旧报表h5插件 * * @return */ public static String getCprOP() { //兼容老的h5插件 Actor newH5Actor = ActorFactory.getActor("h5"); if (newH5Actor == null || ComparatorUtils.equalsIgnoreCase(ActorFactory.getType(newH5Actor), ActorConstants.TYPE_PAGE)) { return "h5_page" ; } return "h5" ; } /** * 消息发送接口message实体拼接 * * @param title * @param content * @param linkUrl * @return * @throws Exception */ private static JSONObject buildMessage(String title, String content, String linkUrl, String image) throws Exception { JSONObject message = new JSONObject(); message.put("content" , content); if (StringUtils.isNotEmpty(linkUrl)) { message.put("linkUrl" , linkUrl); } message.put("msgType" , "TEXT"); message.put("appletName" , "BI平台"); YiTuanMaManager manager = YiTuanMaManager.getInstance(); String logourl = manager.getUrl() + "/url/ytlogo"; // String logourl = manager.getUrl() + "/resources?path=com/fr/plugin/web/images/log.jpg" ; message.put("appletLogoUrl" , logourl); message.put("avatar" , logourl); message.put("msgType" , "TEXT"); message.put("msgType" , "TEXT"); message.put("imageUrl" , image); message.put("title" , StringUtils.isNotEmpty(title) ? title : "BI消息推送"); return message; } /** * 发送应用消息 * * @param access_token * @param eappId * @param targetIds * @param title * @param content * @param linkUrl * @throws Exception */ public static void sendMsgToUserFromAppWithToken(String clientId, String access_token, String eappId, List targetIds, String title, String content, String linkUrl, String imageUrl) throws Exception { LogKit.debug("ASP ==================== :发送应用消息clientId:{} token={}" , clientId, access_token); JSONObject jsonObject = new JSONObject(); jsonObject.put("eappId" , eappId); jsonObject.put("appId" , eappId); jsonObject.put("targetIds" , targetIds); jsonObject.put("message" , buildMessage(title, content, linkUrl, imageUrl)); LogKit.debug("==================== 消息内容为:" + jsonObject.toString()); sendMsgToUserFromAppWithToken4ThreeTimes(clientId, jsonObject, access_token, 0); } private static void sendMsgToUserFromAppWithToken4ThreeTimes(String clientId, JSONObject jsonObject, String access_token, int count) throws Exception { if (count < 3) { HttpResponse jsonResponse = buildPostResponceWithToken(jsonObject, APP_SENDMSG_URL, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { LogKit.debug("==================== 发送应用消息成功!"); LogKit.debug("==================== 响应{}" , jsonResponse.getBody()); } else if (jsonResponse.getStatus() == EXPIRE_CODE || jsonResponse.getStatus() == ERROR_CODE) { LogKit.debug("==================== 发送应用消息失败! token失效,重新获取:{}",jsonResponse.getBody()); access_token = refreshToken(clientId); count++; sendMsgToUserFromAppWithToken4ThreeTimes(clientId, jsonObject, access_token, count); } else { FineLoggerFactory.getLogger().debug("==================== 发送应用消息失败!"); FineLoggerFactory.getLogger().debug("==================== 发送应用消息失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); } } else { FineLoggerFactory.getLogger().debug("==================== 3次发送应用消息失败!"); } } /** * 发送应用消息 * * @param targetIds * @param title * @param content * @param linkUrl * @throws Exception */ public static void sendMsgToUserFromApp(String clientId, List targetIds, String title, String content, String linkUrl, String imageUrl) throws Exception { YTYiTuanEntity entity = getYituanEntityByClientId(clientId); if (entity != null) { LogKit.debug("发送请求到clientId {} 团队ID:{}" , clientId, entity.getTeamId()); sendMsgToUserFromAppWithToken(clientId, getAccessToken(clientId), entity.getTeamId(), targetIds, title, content, linkUrl, imageUrl); } else { LogKit.debug("发送请求到clientId 未能找到?????" , clientId); } } /** * 发送用户信息 * * @param targetIds * @param title * @param content * @param linkUrl * @throws Exception */ public static void sendMSGtoUser(String clientId, String fromUserId, List targetIds, String title, String content, String linkUrl, String imageUrl) throws Exception { JSONObject params = new JSONObject(); params.put("fromUserId" , fromUserId); JSONObject message = buildMessage(title, content, linkUrl, imageUrl); params.put("message" , message); JSONArray targets = new JSONArray(); for (String targetId : targetIds) { targets.put(targetId); } params.put("targetIds" , targets); sendMSGtoUserWithToken(clientId, params, getAccessToken(clientId), 0); } private static void sendMSGtoUserWithToken(String clientId, JSONObject jsonObject, String access_token, int count) throws Exception { if (count < 3) { HttpResponse jsonResponse = buildPostResponceWithToken(jsonObject, APP_SENDMSG_TO_USER, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { LogKit.debug("==================== 发送个人成功!"); } else if (jsonResponse.getStatus() == EXPIRE_CODE || jsonResponse.getStatus() == ERROR_CODE) { LogKit.debug("==================== 发送个人! token失效,重新获取"); access_token = refreshToken(clientId); count++; sendMSGtoUserWithToken(clientId, jsonObject, access_token, count); } else { FineLoggerFactory.getLogger().debug("==================== 发送个人失败!"); FineLoggerFactory.getLogger().debug("==================== 发送个人失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); } } else { FineLoggerFactory.getLogger().debug("==================== 3次个人失败!"); } } /** * 发送聊天群消息 * * @param access_token * @param groupId * @param fromUserId * @param title * @param content * @param linkUrl * @throws Exception */ public static void sendMsgToGroupWithToken(String clientId, String access_token, String groupId, String fromUserId, String title, String content, String linkUrl, String image) throws Exception { LogKit.debug("==================== :发送聊天群消息 token=" + access_token); JSONObject jsonObject = new JSONObject(); jsonObject.put("groupId" , groupId); jsonObject.put("fromUserId" , fromUserId); jsonObject.put("message" , buildMessage(title, content, linkUrl, image)); LogKit.debug("==================== 消息内容为:" + jsonObject.toString()); sendMsgToGroupWithToken4ThreeTimes(clientId, jsonObject, access_token, 0); } private static void sendMsgToGroupWithToken4ThreeTimes(String clientId, JSONObject jsonObject, String access_token, int count) throws Exception { if (count < 3) { HttpResponse jsonResponse = buildPostResponceWithToken(jsonObject, GROUP_SENDMSG_URL, access_token); if (jsonResponse.getStatus() == SUCCESS_CODE) { LogKit.debug("==================== 发送聊天群消息成功!"); } else if (jsonResponse.getStatus() == EXPIRE_CODE || jsonResponse.getStatus() == ERROR_CODE) { LogKit.debug("==================== 发送聊天群消息失败! token失效,重新获取"); access_token = refreshToken(clientId); count++; sendMsgToGroupWithToken4ThreeTimes(clientId, jsonObject, access_token, count); } else { FineLoggerFactory.getLogger().debug("==================== 发送聊天群消息失败!"); FineLoggerFactory.getLogger().debug("==================== 发送聊天群消息失败! responseCode = " + jsonResponse.getStatus()); FineLoggerFactory.getLogger().debug("==================== responseBody = " + jsonResponse.getBody().toString()); } } else { FineLoggerFactory.getLogger().debug("==================== 3次发送聊天群消息失败!"); } } /** * 发送聊天群消息 * * @param groupId * @param fromUserId * @param title * @param content * @param linkUrl * @throws Exception */ public static void sendMsgToGroup(String clientId, String groupId, String fromUserId, String title, String content, String linkUrl, String image) throws Exception { sendMsgToGroupWithToken(clientId, getAccessToken(clientId), groupId, fromUserId, title, content, linkUrl, image); } /** * 发送公告号消息,未实现 * * @param pubOrGroupId * @param userIds * @param title * @param content * @param url * @throws Exception */ public static void sendMsgToUserFromPublicNum(String pubOrGroupId, List userIds, String title, String content, String url) throws Exception { LogKit.debug("==================== 发送公告号消息未实现!"); FineLoggerFactory.getLogger().warn("==================== 发送公告号消息未实现!"); } public static String getUserInfoByAccessToken(String accessToken) throws IOException { String url = ACCOUNT_URL; Map headers = new HashMap<>(); headers.put("Authorization" , "Bearer " + accessToken); headers.put("Content-Type" , "application/json; charset=utf-8"); String resp = HttpKit.get(url, new HashMap<>(), headers); LogKit.error("==================== 获取用户信息返回结果ByAccessToken:" + resp); com.fr.json.JSONObject jsonObject = new com.fr.json.JSONObject(resp); return jsonObject.getString("id"); } }