mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-11-01 03:25:35 +08:00 
			
		
		
		
	okhttp用法有错误;添加了枚举HttpType (#207)
This commit is contained in:
		| @ -0,0 +1,632 @@ | ||||
| package me.chanjar.weixin.cp.api.impl; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.util.List; | ||||
| import java.util.UUID; | ||||
|  | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import com.google.gson.*; | ||||
| import com.google.gson.reflect.TypeToken; | ||||
|  | ||||
| import me.chanjar.weixin.common.bean.WxJsapiSignature; | ||||
| import me.chanjar.weixin.common.bean.menu.WxMenu; | ||||
| import me.chanjar.weixin.common.bean.result.WxError; | ||||
| import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.session.StandardSessionManager; | ||||
| import me.chanjar.weixin.common.session.WxSession; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.common.util.RandomUtils; | ||||
| import me.chanjar.weixin.common.util.crypto.SHA1; | ||||
| import me.chanjar.weixin.common.util.fs.FileUtils; | ||||
| import me.chanjar.weixin.common.util.http.*; | ||||
| import me.chanjar.weixin.common.util.json.GsonHelper; | ||||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | ||||
| import me.chanjar.weixin.cp.api.WxCpService; | ||||
| import me.chanjar.weixin.cp.bean.WxCpDepart; | ||||
| import me.chanjar.weixin.cp.bean.WxCpMessage; | ||||
| import me.chanjar.weixin.cp.bean.WxCpTag; | ||||
| import me.chanjar.weixin.cp.bean.WxCpUser; | ||||
| import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; | ||||
|  | ||||
| public abstract class AbstractWxCpService<H, P> implements WxCpService, RequestHttp<H, P> { | ||||
|  | ||||
|   protected final Logger log = LoggerFactory.getLogger(AbstractWxCpService.class); | ||||
|  | ||||
|   /** | ||||
|    * 全局的是否正在刷新access token的锁 | ||||
|    */ | ||||
|   protected final Object globalAccessTokenRefreshLock = new Object(); | ||||
|  | ||||
|   /** | ||||
|    * 全局的是否正在刷新jsapi_ticket的锁 | ||||
|    */ | ||||
|   protected final Object globalJsapiTicketRefreshLock = new Object(); | ||||
|  | ||||
|   protected WxCpConfigStorage configStorage; | ||||
|  | ||||
|  | ||||
|   protected WxSessionManager sessionManager = new StandardSessionManager(); | ||||
|   /** | ||||
|    * 临时文件目录 | ||||
|    */ | ||||
|   protected File tmpDirFile; | ||||
|   private int retrySleepMillis = 1000; | ||||
|   private int maxRetryTimes = 5; | ||||
|  | ||||
|   @Override | ||||
|   public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data) { | ||||
|     try { | ||||
|       return SHA1.gen(this.configStorage.getToken(), timestamp, nonce, data) | ||||
|         .equals(msgSignature); | ||||
|     } catch (Exception e) { | ||||
|       return false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void userAuthenticated(String userId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId; | ||||
|     get(url, null); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getAccessToken() throws WxErrorException { | ||||
|     return getAccessToken(false); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   @Override | ||||
|   public String getJsapiTicket() throws WxErrorException { | ||||
|     return getJsapiTicket(false); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { | ||||
|     if (forceRefresh) { | ||||
|       this.configStorage.expireJsapiTicket(); | ||||
|     } | ||||
|     if (this.configStorage.isJsapiTicketExpired()) { | ||||
|       synchronized (this.globalJsapiTicketRefreshLock) { | ||||
|         if (this.configStorage.isJsapiTicketExpired()) { | ||||
|           String url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; | ||||
|           String responseContent = execute(new SimpleGetRequestExecutor(), url, null); | ||||
|           JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|           JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject(); | ||||
|           String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); | ||||
|           int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); | ||||
|           this.configStorage.updateJsapiTicket(jsapiTicket, | ||||
|             expiresInSeconds); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return this.configStorage.getJsapiTicket(); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException { | ||||
|     long timestamp = System.currentTimeMillis() / 1000; | ||||
|     String noncestr = RandomUtils.getRandomStr(); | ||||
|     String jsapiTicket = getJsapiTicket(false); | ||||
|     String signature = SHA1.genWithAmple( | ||||
|       "jsapi_ticket=" + jsapiTicket, | ||||
|       "noncestr=" + noncestr, | ||||
|       "timestamp=" + timestamp, | ||||
|       "url=" + url | ||||
|     ); | ||||
|     WxJsapiSignature jsapiSignature = new WxJsapiSignature(); | ||||
|     jsapiSignature.setTimestamp(timestamp); | ||||
|     jsapiSignature.setNonceStr(noncestr); | ||||
|     jsapiSignature.setUrl(url); | ||||
|     jsapiSignature.setSignature(signature); | ||||
|  | ||||
|     // Fixed bug | ||||
|     jsapiSignature.setAppId(this.configStorage.getCorpId()); | ||||
|  | ||||
|     return jsapiSignature; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void messageSend(WxCpMessage message) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"; | ||||
|     post(url, message.toJson()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void menuCreate(WxMenu menu) throws WxErrorException { | ||||
|     menuCreate(this.configStorage.getAgentId(), menu); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void menuCreate(Integer agentId, WxMenu menu) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" | ||||
|       + this.configStorage.getAgentId(); | ||||
|     post(url, menu.toJson()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void menuDelete() throws WxErrorException { | ||||
|     menuDelete(this.configStorage.getAgentId()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void menuDelete(Integer agentId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId; | ||||
|     get(url, null); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxMenu menuGet() throws WxErrorException { | ||||
|     return menuGet(this.configStorage.getAgentId()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxMenu menuGet(Integer agentId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId; | ||||
|     try { | ||||
|       String resultContent = get(url, null); | ||||
|       return WxMenu.fromJson(resultContent); | ||||
|     } catch (WxErrorException e) { | ||||
|       // 46003 不存在的菜单数据 | ||||
|       if (e.getError().getErrorCode() == 46003) { | ||||
|         return null; | ||||
|       } | ||||
|       throw e; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) | ||||
|     throws WxErrorException, IOException { | ||||
|     return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType)); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; | ||||
|     return execute(new MediaUploadRequestExecutor(), url, file); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public File mediaDownload(String mediaId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/media/get"; | ||||
|     return execute( | ||||
|       new MediaDownloadRequestExecutor( | ||||
|         this.configStorage.getTmpDirFile()), | ||||
|       url, "media_id=" + mediaId); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   @Override | ||||
|   public Integer departCreate(WxCpDepart depart) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create"; | ||||
|     String responseContent = execute( | ||||
|       new SimplePostRequestExecutor(), | ||||
|       url, | ||||
|       depart.toJson()); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return GsonHelper.getAsInteger(tmpJsonElement.getAsJsonObject().get("id")); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void departUpdate(WxCpDepart group) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update"; | ||||
|     post(url, group.toJson()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void departDelete(Integer departId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId; | ||||
|     get(url, null); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<WxCpDepart> departGet() throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list"; | ||||
|     String responseContent = get(url, null); | ||||
|     /* | ||||
|      * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } | ||||
|      * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } | ||||
|      */ | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return WxCpGsonBuilder.INSTANCE.create() | ||||
|       .fromJson( | ||||
|         tmpJsonElement.getAsJsonObject().get("department"), | ||||
|         new TypeToken<List<WxCpDepart>>() { | ||||
|         }.getType() | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void userCreate(WxCpUser user) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create"; | ||||
|     post(url, user.toJson()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void userUpdate(WxCpUser user) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update"; | ||||
|     post(url, user.toJson()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void userDelete(String userid) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid; | ||||
|     get(url, null); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void userDelete(String[] userids) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete"; | ||||
|     JsonObject jsonObject = new JsonObject(); | ||||
|     JsonArray jsonArray = new JsonArray(); | ||||
|     for (String userid : userids) { | ||||
|       jsonArray.add(new JsonPrimitive(userid)); | ||||
|     } | ||||
|     jsonObject.add("useridlist", jsonArray); | ||||
|     post(url, jsonObject.toString()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxCpUser userGet(String userid) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid; | ||||
|     String responseContent = get(url, null); | ||||
|     return WxCpUser.fromJson(responseContent); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<WxCpUser> userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId; | ||||
|     String params = ""; | ||||
|     if (fetchChild != null) { | ||||
|       params += "&fetch_child=" + (fetchChild ? "1" : "0"); | ||||
|     } | ||||
|     if (status != null) { | ||||
|       params += "&status=" + status; | ||||
|     } else { | ||||
|       params += "&status=0"; | ||||
|     } | ||||
|  | ||||
|     String responseContent = get(url, params); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return WxCpGsonBuilder.INSTANCE.create() | ||||
|       .fromJson( | ||||
|         tmpJsonElement.getAsJsonObject().get("userlist"), | ||||
|         new TypeToken<List<WxCpUser>>() { | ||||
|         }.getType() | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<WxCpUser> departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId; | ||||
|     String params = ""; | ||||
|     if (fetchChild != null) { | ||||
|       params += "&fetch_child=" + (fetchChild ? "1" : "0"); | ||||
|     } | ||||
|     if (status != null) { | ||||
|       params += "&status=" + status; | ||||
|     } else { | ||||
|       params += "&status=0"; | ||||
|     } | ||||
|  | ||||
|     String responseContent = get(url, params); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return WxCpGsonBuilder.INSTANCE.create() | ||||
|       .fromJson( | ||||
|         tmpJsonElement.getAsJsonObject().get("userlist"), | ||||
|         new TypeToken<List<WxCpUser>>() { | ||||
|         }.getType() | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String tagCreate(String tagName) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create"; | ||||
|     JsonObject o = new JsonObject(); | ||||
|     o.addProperty("tagname", tagName); | ||||
|     String responseContent = post(url, o.toString()); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return tmpJsonElement.getAsJsonObject().get("tagid").getAsString(); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void tagUpdate(String tagId, String tagName) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update"; | ||||
|     JsonObject o = new JsonObject(); | ||||
|     o.addProperty("tagid", tagId); | ||||
|     o.addProperty("tagname", tagName); | ||||
|     post(url, o.toString()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void tagDelete(String tagId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId; | ||||
|     get(url, null); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<WxCpTag> tagGet() throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list"; | ||||
|     String responseContent = get(url, null); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return WxCpGsonBuilder.INSTANCE.create() | ||||
|       .fromJson( | ||||
|         tmpJsonElement.getAsJsonObject().get("taglist"), | ||||
|         new TypeToken<List<WxCpTag>>() { | ||||
|         }.getType() | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId; | ||||
|     String responseContent = get(url, null); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return WxCpGsonBuilder.INSTANCE.create() | ||||
|       .fromJson( | ||||
|         tmpJsonElement.getAsJsonObject().get("userlist"), | ||||
|         new TypeToken<List<WxCpUser>>() { | ||||
|         }.getType() | ||||
|       ); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void tagAddUsers(String tagId, List<String> userIds, List<String> partyIds) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers"; | ||||
|     JsonObject jsonObject = new JsonObject(); | ||||
|     jsonObject.addProperty("tagid", tagId); | ||||
|     if (userIds != null) { | ||||
|       JsonArray jsonArray = new JsonArray(); | ||||
|       for (String userId : userIds) { | ||||
|         jsonArray.add(new JsonPrimitive(userId)); | ||||
|       } | ||||
|       jsonObject.add("userlist", jsonArray); | ||||
|     } | ||||
|     if (partyIds != null) { | ||||
|       JsonArray jsonArray = new JsonArray(); | ||||
|       for (String userId : partyIds) { | ||||
|         jsonArray.add(new JsonPrimitive(userId)); | ||||
|       } | ||||
|       jsonObject.add("partylist", jsonArray); | ||||
|     } | ||||
|     post(url, jsonObject.toString()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void tagRemoveUsers(String tagId, List<String> userIds) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers"; | ||||
|     JsonObject jsonObject = new JsonObject(); | ||||
|     jsonObject.addProperty("tagid", tagId); | ||||
|     JsonArray jsonArray = new JsonArray(); | ||||
|     for (String userId : userIds) { | ||||
|       jsonArray.add(new JsonPrimitive(userId)); | ||||
|     } | ||||
|     jsonObject.add("userlist", jsonArray); | ||||
|     post(url, jsonObject.toString()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String oauth2buildAuthorizationUrl(String state) { | ||||
|     return this.oauth2buildAuthorizationUrl( | ||||
|       this.configStorage.getOauth2redirectUri(), | ||||
|       state | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String oauth2buildAuthorizationUrl(String redirectUri, String state) { | ||||
|     String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; | ||||
|     url += "appid=" + this.configStorage.getCorpId(); | ||||
|     url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectUri); | ||||
|     url += "&response_type=code"; | ||||
|     url += "&scope=snsapi_base"; | ||||
|     if (state != null) { | ||||
|       url += "&state=" + state; | ||||
|     } | ||||
|     url += "#wechat_redirect"; | ||||
|     return url; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String[] oauth2getUserInfo(String code) throws WxErrorException { | ||||
|     return oauth2getUserInfo(this.configStorage.getAgentId(), code); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String[] oauth2getUserInfo(Integer agentId, String code) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?" | ||||
|       + "code=" + code | ||||
|       + "&agentid=" + agentId; | ||||
|     String responseText = get(url, null); | ||||
|     JsonElement je = new JsonParser().parse(responseText); | ||||
|     JsonObject jo = je.getAsJsonObject(); | ||||
|     return new String[]{GsonHelper.getString(jo, "UserId"), GsonHelper.getString(jo, "DeviceId"), GsonHelper.getString(jo, "OpenId")}; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public int invite(String userId, String inviteTips) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send"; | ||||
|     JsonObject jsonObject = new JsonObject(); | ||||
|     jsonObject.addProperty("userid", userId); | ||||
|     if (StringUtils.isNotEmpty(inviteTips)) { | ||||
|       jsonObject.addProperty("invite_tips", inviteTips); | ||||
|     } | ||||
|     String responseContent = post(url, jsonObject.toString()); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     return tmpJsonElement.getAsJsonObject().get("type").getAsInt(); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String[] getCallbackIp() throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip"; | ||||
|     String responseContent = get(url, null); | ||||
|     JsonElement tmpJsonElement = new JsonParser().parse(responseContent); | ||||
|     JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray(); | ||||
|     String[] ips = new String[jsonArray.size()]; | ||||
|     for (int i = 0; i < jsonArray.size(); i++) { | ||||
|       ips[i] = jsonArray.get(i).getAsString(); | ||||
|     } | ||||
|     return ips; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String get(String url, String queryParam) throws WxErrorException { | ||||
|     return execute(new SimpleGetRequestExecutor(), url, queryParam); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String post(String url, String postData) throws WxErrorException { | ||||
|     return execute(new SimplePostRequestExecutor(), url, postData); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 | ||||
|    */ | ||||
|   @Override | ||||
|   public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | ||||
|     int retryTimes = 0; | ||||
|     do { | ||||
|       try { | ||||
|         T result = this.executeInternal(executor, uri, data); | ||||
|         this.log.debug("\n[URL]:  {}\n[PARAMS]: {}\n[RESPONSE]: {}",uri, data, result); | ||||
|         return result; | ||||
|       } catch (WxErrorException e) { | ||||
|         if (retryTimes + 1 > this.maxRetryTimes) { | ||||
|           this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); | ||||
|           //最后一次重试失败后,直接抛出异常,不再等待 | ||||
|           throw new RuntimeException("微信服务端异常,超出重试次数"); | ||||
|         } | ||||
|  | ||||
|         WxError error = e.getError(); | ||||
|         /* | ||||
|          * -1 系统繁忙, 1000ms后重试 | ||||
|          */ | ||||
|         if (error.getErrorCode() == -1) { | ||||
|           int sleepMillis = this.retrySleepMillis * (1 << retryTimes); | ||||
|           try { | ||||
|             this.log.debug("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1); | ||||
|             Thread.sleep(sleepMillis); | ||||
|           } catch (InterruptedException e1) { | ||||
|             throw new RuntimeException(e1); | ||||
|           } | ||||
|         } else { | ||||
|           throw e; | ||||
|         } | ||||
|       } | ||||
|     } while (retryTimes++ < this.maxRetryTimes); | ||||
|  | ||||
|     this.log.warn("重试达到最大次数【{}】", this.maxRetryTimes); | ||||
|     throw new RuntimeException("微信服务端异常,超出重试次数"); | ||||
|   } | ||||
|  | ||||
|   public synchronized <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException { | ||||
|     if (uri.contains("access_token=")) { | ||||
|       throw new IllegalArgumentException("uri参数中不允许有access_token: " + uri); | ||||
|     } | ||||
|     String accessToken = getAccessToken(false); | ||||
|  | ||||
|     String uriWithAccessToken = uri; | ||||
|     uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken; | ||||
|  | ||||
|     try { | ||||
|       return executor.execute(this, uriWithAccessToken, data); | ||||
|     } catch (WxErrorException e) { | ||||
|       WxError error = e.getError(); | ||||
|       /* | ||||
|        * 发生以下情况时尝试刷新access_token | ||||
|        * 40001 获取access_token时AppSecret错误,或者access_token无效 | ||||
|        * 42001 access_token超时 | ||||
|        */ | ||||
|       if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001) { | ||||
|         // 强制设置wxCpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token | ||||
|         this.configStorage.expireAccessToken(); | ||||
|         return execute(executor, uri, data); | ||||
|       } | ||||
|  | ||||
|       if (error.getErrorCode() != 0) { | ||||
|         this.log.error("\n[URL]:  {}\n[PARAMS]: {}\n[RESPONSE]: {}", uri, data, error); | ||||
|         throw new WxErrorException(error); | ||||
|       } | ||||
|       return null; | ||||
|     } catch (IOException e) { | ||||
|       this.log.error("\n[URL]:  {}\n[PARAMS]: {}\n[EXCEPTION]: {}", uri, data, e.getMessage()); | ||||
|       throw new RuntimeException(e); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider) { | ||||
|     this.configStorage = wxConfigProvider; | ||||
|     this.initHttp(); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void setRetrySleepMillis(int retrySleepMillis) { | ||||
|     this.retrySleepMillis = retrySleepMillis; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   @Override | ||||
|   public void setMaxRetryTimes(int maxRetryTimes) { | ||||
|     this.maxRetryTimes = maxRetryTimes; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxSession getSession(String id) { | ||||
|     if (this.sessionManager == null) { | ||||
|       return null; | ||||
|     } | ||||
|     return this.sessionManager.getSession(id); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public WxSession getSession(String id, boolean create) { | ||||
|     if (this.sessionManager == null) { | ||||
|       return null; | ||||
|     } | ||||
|     return this.sessionManager.getSession(id, create); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   @Override | ||||
|   public void setSessionManager(WxSessionManager sessionManager) { | ||||
|     this.sessionManager = sessionManager; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String replaceParty(String mediaId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty"; | ||||
|     JsonObject jsonObject = new JsonObject(); | ||||
|     jsonObject.addProperty("media_id", mediaId); | ||||
|     return post(url, jsonObject.toString()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String replaceUser(String mediaId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser"; | ||||
|     JsonObject jsonObject = new JsonObject(); | ||||
|     jsonObject.addProperty("media_id", mediaId); | ||||
|     return post(url, jsonObject.toString()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getTaskResult(String joinId) throws WxErrorException { | ||||
|     String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=" + joinId; | ||||
|     return get(url, null); | ||||
|   } | ||||
|  | ||||
|   public File getTmpDirFile() { | ||||
|     return this.tmpDirFile; | ||||
|   } | ||||
|  | ||||
|   public void setTmpDirFile(File tmpDirFile) { | ||||
|     this.tmpDirFile = tmpDirFile; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @ -4,10 +4,11 @@ package me.chanjar.weixin.cp.api.impl.apache; | ||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
| import me.chanjar.weixin.common.bean.result.WxError; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.util.http.HttpType; | ||||
| import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; | ||||
| import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; | ||||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | ||||
| import me.chanjar.weixin.cp.api.impl.AbstractWxCpServiceImpl; | ||||
| import me.chanjar.weixin.cp.api.impl.AbstractWxCpService; | ||||
|  | ||||
| import org.apache.http.HttpHost; | ||||
| import org.apache.http.client.config.RequestConfig; | ||||
| @ -18,7 +19,7 @@ import org.apache.http.impl.client.CloseableHttpClient; | ||||
|  | ||||
| import java.io.IOException; | ||||
|  | ||||
| public class WxCpServiceImpl extends AbstractWxCpServiceImpl<CloseableHttpClient, HttpHost> { | ||||
| public class WxCpServiceImpl extends AbstractWxCpService<CloseableHttpClient, HttpHost> { | ||||
|   protected CloseableHttpClient httpClient; | ||||
|   protected HttpHost httpProxy; | ||||
|  | ||||
| @ -32,6 +33,11 @@ public class WxCpServiceImpl extends AbstractWxCpServiceImpl<CloseableHttpClient | ||||
|     return httpProxy; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public HttpType getRequestType() { | ||||
|     return HttpType.apacheHttp; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||
|     if (forceRefresh) { | ||||
|  | ||||
| @ -4,6 +4,7 @@ import jodd.http.*; | ||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
| import me.chanjar.weixin.common.bean.result.WxError; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.util.http.HttpType; | ||||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | ||||
| import me.chanjar.weixin.cp.api.impl.AbstractWxCpServiceImpl; | ||||
|  | ||||
| @ -22,6 +23,11 @@ public class WxCpServiceImpl extends AbstractWxCpServiceImpl<HttpConnectionProvi | ||||
|     return httpProxy; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public HttpType getRequestType() { | ||||
|     return HttpType.joddHttp; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||
|     if (forceRefresh) { | ||||
|  | ||||
| @ -5,6 +5,7 @@ import java.io.IOException; | ||||
| import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
| import me.chanjar.weixin.common.bean.result.WxError; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | ||||
| import me.chanjar.weixin.common.util.http.HttpType; | ||||
| import me.chanjar.weixin.common.util.http.okhttp.OkhttpProxyInfo; | ||||
| import me.chanjar.weixin.cp.api.WxCpConfigStorage; | ||||
| import me.chanjar.weixin.cp.api.impl.AbstractWxCpServiceImpl; | ||||
| @ -25,6 +26,11 @@ public class WxCpServiceImpl extends AbstractWxCpServiceImpl<ConnectionPool, Okh | ||||
|     return httpProxy; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public HttpType getRequestType() { | ||||
|     return HttpType.okHttp; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getAccessToken(boolean forceRefresh) throws WxErrorException { | ||||
|     if (forceRefresh) { | ||||
| @ -62,7 +68,12 @@ public class WxCpServiceImpl extends AbstractWxCpServiceImpl<ConnectionPool, Okh | ||||
|           } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|           } | ||||
|           String resultContent = response.body().toString(); | ||||
|           String resultContent = null; | ||||
|           try { | ||||
|             resultContent = response.body().string(); | ||||
|           } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|           } | ||||
|           WxError error = WxError.fromJson(resultContent); | ||||
|           if (error.getErrorCode() != 0) { | ||||
|             throw new WxErrorException(error); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 crskyp
					crskyp