diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpChatService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpChatService.java index 95f747e356..7c484fd2c8 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpChatService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpChatService.java @@ -1,20 +1,20 @@ package me.chanjar.weixin.cp.api; -import java.util.List; - import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpAppChatMessage; import me.chanjar.weixin.cp.bean.WxCpChat; +import java.util.List; + /** * 群聊服务. * * @author gaigeshen */ public interface WxCpChatService { - String APPCHAT_CREATE = "https://qyapi.weixin.qq.com/cgi-bin/appchat/create"; - String APPCHAT_UPDATE = "https://qyapi.weixin.qq.com/cgi-bin/appchat/update"; - String APPCHAT_GET_CHATID = "https://qyapi.weixin.qq.com/cgi-bin/appchat/get?chatid="; + String APPCHAT_CREATE = "/cgi-bin/appchat/create"; + String APPCHAT_UPDATE = "/cgi-bin/appchat/update"; + String APPCHAT_GET_CHATID = "/cgi-bin/appchat/get?chatid="; /** * 创建群聊会话,注意:刚创建的群,如果没有下发消息,在企业微信不会出现该群. diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java index 31ce6b5991..67c67ec625 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java @@ -1,12 +1,12 @@ package me.chanjar.weixin.cp.api; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.error.WxErrorException; + import java.io.File; import java.io.IOException; import java.io.InputStream; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.error.WxErrorException; - /** *
  *  媒体管理接口.
@@ -16,10 +16,10 @@
  * @author Binary Wang
  */
 public interface WxCpMediaService {
-  String MEDIA_GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/get";
-  String MEDIA_UPLOAD_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?type=";
-  String IMG_UPLOAD_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/uploadimg";
-  String JSSDK_MEDIA_GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/get/jssdk";
+  String MEDIA_GET_URL = "/cgi-bin/media/get";
+  String MEDIA_UPLOAD_URL = "/cgi-bin/media/upload?type=";
+  String IMG_UPLOAD_URL = "/cgi-bin/media/uploadimg";
+  String JSSDK_MEDIA_GET_URL = "/cgi-bin/media/get/jssdk";
 
   /**
    * 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java
index c6d9063fbb..913013f627 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOAuth2Service.java
@@ -13,9 +13,9 @@
  * @author Binary Wang
  */
 public interface WxCpOAuth2Service {
-  String URL_GET_USER_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=%s&agentid=%d";
-  String URL_GET_USER_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail";
-  String URL_OAUTH_2_AUTHORIZE = "https://open.weixin.qq.com/connect/oauth2/authorize";
+  String URL_GET_USER_INFO = "/cgi-bin/user/getuserinfo?code=%s&agentid=%d";
+  String URL_GET_USER_DETAIL = "/cgi-bin/user/getuserdetail";
+  String URL_OAUTH_2_AUTHORIZE = "/connect/oauth2/authorize";
 
   /**
    * 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
index 364723db87..38bab86f95 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
@@ -17,14 +17,14 @@
  * @author chanjaster
  */
 public interface WxCpService {
-  String GET_JSAPI_TICKET = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket";
-  String GET_AGENT_CONFIG_TICKET = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?&type=agent_config";
-  String MESSAGE_SEND = "https://qyapi.weixin.qq.com/cgi-bin/message/send";
-  String GET_CALLBACK_IP = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip";
-  String BATCH_REPLACE_PARTY = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceparty";
-  String BATCH_REPLACE_USER = "https://qyapi.weixin.qq.com/cgi-bin/batch/replaceuser";
-  String BATCH_GET_RESULT = "https://qyapi.weixin.qq.com/cgi-bin/batch/getresult?jobid=";
-  String JSCODE_TO_SESSION_URL = "https://qyapi.weixin.qq.com/cgi-bin/miniprogram/jscode2session";
+  String GET_JSAPI_TICKET = "/cgi-bin/get_jsapi_ticket";
+  String GET_AGENT_CONFIG_TICKET = "/cgi-bin/ticket/get?&type=agent_config";
+  String MESSAGE_SEND = "/cgi-bin/message/send";
+  String GET_CALLBACK_IP = "/cgi-bin/getcallbackip";
+  String BATCH_REPLACE_PARTY = "/cgi-bin/batch/replaceparty";
+  String BATCH_REPLACE_USER = "/cgi-bin/batch/replaceuser";
+  String BATCH_GET_RESULT = "/cgi-bin/batch/getresult?jobid=";
+  String JSCODE_TO_SESSION_URL = "/cgi-bin/miniprogram/jscode2session";
 
   /**
    * 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java
index 3eb99b79d2..40ad11f4e7 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java
@@ -18,7 +18,18 @@
 import me.chanjar.weixin.common.util.http.RequestHttp;
 import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
 import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
-import me.chanjar.weixin.cp.api.*;
+import me.chanjar.weixin.cp.WxCpConsts;
+import me.chanjar.weixin.cp.api.WxCpAgentService;
+import me.chanjar.weixin.cp.api.WxCpChatService;
+import me.chanjar.weixin.cp.api.WxCpDepartmentService;
+import me.chanjar.weixin.cp.api.WxCpMediaService;
+import me.chanjar.weixin.cp.api.WxCpMenuService;
+import me.chanjar.weixin.cp.api.WxCpOAService;
+import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.api.WxCpTagService;
+import me.chanjar.weixin.cp.api.WxCpTaskCardService;
+import me.chanjar.weixin.cp.api.WxCpUserService;
 import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult;
 import me.chanjar.weixin.cp.bean.WxCpMessage;
 import me.chanjar.weixin.cp.bean.WxCpMessageSendResult;
@@ -104,7 +115,7 @@ public String getAgentJsapiTicket(boolean forceRefresh) throws WxErrorException
     if (this.configStorage.isAgentJsapiTicketExpired()) {
       synchronized (this.globalAgentJsapiTicketRefreshLock) {
         if (this.configStorage.isAgentJsapiTicketExpired()) {
-          String responseContent = this.get(WxCpService.GET_AGENT_CONFIG_TICKET, null);
+          String responseContent = this.get(this.configStorage.getApiUrl(WxCpService.GET_AGENT_CONFIG_TICKET), null);
           JsonObject jsonObject = new JsonParser().parse(responseContent).getAsJsonObject();
           this.configStorage.updateAgentJsapiTicket(jsonObject.get("ticket").getAsString(),
             jsonObject.get("expires_in").getAsInt());
@@ -129,7 +140,7 @@ public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
     if (this.configStorage.isJsapiTicketExpired()) {
       synchronized (this.globalJsapiTicketRefreshLock) {
         if (this.configStorage.isJsapiTicketExpired()) {
-          String responseContent = this.get(WxCpService.GET_JSAPI_TICKET, null);
+          String responseContent = this.get(this.configStorage.getApiUrl(WxCpService.GET_JSAPI_TICKET), null);
           JsonObject tmpJsonObject = new JsonParser().parse(responseContent).getAsJsonObject();
           this.configStorage.updateJsapiTicket(tmpJsonObject.get("ticket").getAsString(),
             tmpJsonObject.get("expires_in").getAsInt());
@@ -170,7 +181,7 @@ public WxCpMessageSendResult messageSend(WxCpMessage message) throws WxErrorExce
       message.setAgentId(this.getWxCpConfigStorage().getAgentId());
     }
 
-    return WxCpMessageSendResult.fromJson(this.post(WxCpService.MESSAGE_SEND, message.toJson()));
+    return WxCpMessageSendResult.fromJson(this.post(this.configStorage.getApiUrl(WxCpService.MESSAGE_SEND), message.toJson()));
   }
 
   @Override
@@ -179,13 +190,13 @@ public WxCpMaJsCode2SessionResult jsCode2Session(String jsCode) throws WxErrorEx
     params.put("js_code", jsCode);
     params.put("grant_type", "authorization_code");
 
-    String result = this.get(JSCODE_TO_SESSION_URL, Joiner.on("&").withKeyValueSeparator("=").join(params));
+    String result = this.get(this.configStorage.getApiUrl(JSCODE_TO_SESSION_URL), Joiner.on("&").withKeyValueSeparator("=").join(params));
     return WxCpMaJsCode2SessionResult.fromJson(result);
   }
 
   @Override
   public String[] getCallbackIp() throws WxErrorException {
-    String responseContent = get(WxCpService.GET_CALLBACK_IP, null);
+    String responseContent = get(this.configStorage.getApiUrl(WxCpService.GET_CALLBACK_IP), null);
     JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
     JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray();
     String[] ips = new String[jsonArray.size()];
@@ -329,19 +340,19 @@ public WxSessionManager getSessionManager() {
   public String replaceParty(String mediaId) throws WxErrorException {
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("media_id", mediaId);
-    return post(WxCpService.BATCH_REPLACE_PARTY, jsonObject.toString());
+    return post(this.configStorage.getApiUrl(WxCpService.BATCH_REPLACE_PARTY), jsonObject.toString());
   }
 
   @Override
   public String replaceUser(String mediaId) throws WxErrorException {
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("media_id", mediaId);
-    return post(WxCpService.BATCH_REPLACE_USER, jsonObject.toString());
+    return post(this.configStorage.getApiUrl(WxCpService.BATCH_REPLACE_USER), jsonObject.toString());
   }
 
   @Override
   public String getTaskResult(String joinId) throws WxErrorException {
-    String url = WxCpService.BATCH_GET_RESULT + joinId;
+    String url = this.configStorage.getApiUrl(WxCpService.BATCH_GET_RESULT + joinId);
     return get(url, null);
   }
 
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java
index 3a977b81d8..e5a2298670 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImpl.java
@@ -1,11 +1,8 @@
 package me.chanjar.weixin.cp.api.impl;
 
-import java.util.List;
-
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.reflect.TypeToken;
-
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.api.WxCpAgentService;
@@ -13,6 +10,8 @@
 import me.chanjar.weixin.cp.bean.WxCpAgent;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
+import java.util.List;
+
 
 /**
  * 
@@ -37,14 +36,14 @@ public WxCpAgent get(Integer agentId) throws WxErrorException {
       throw new IllegalArgumentException("缺少agentid参数");
     }
 
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/get?agentid=" + agentId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/agent/get?agentid=" + agentId);
     String responseContent = this.mainService.get(url, null);
     return WxCpAgent.fromJson(responseContent);
   }
 
   @Override
   public void set(WxCpAgent agentInfo) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/set";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/agent/set");
     String responseContent = this.mainService.post(url, agentInfo.toJson());
     JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
     if (jsonObject.get("errcode").getAsInt() != 0) {
@@ -54,7 +53,7 @@ public void set(WxCpAgent agentInfo) throws WxErrorException {
 
   @Override
   public List list() throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/agent/list";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/agent/list");
     String responseContent = this.mainService.get(url, null);
     JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject();
     if (jsonObject.get("errcode").getAsInt() != 0) {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpChatServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpChatServiceImpl.java
index 05d298c9ad..d4b59b44db 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpChatServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpChatServiceImpl.java
@@ -47,7 +47,7 @@ public String chatCreate(String name, String owner, List users, String c
     if (StringUtils.isNotBlank(chatId)) {
       data.put("chatid", chatId);
     }
-    String result = this.cpService.post(APPCHAT_CREATE, WxGsonBuilder.create().toJson(data));
+    String result = this.cpService.post(this.cpService.getWxCpConfigStorage().getApiUrl(APPCHAT_CREATE), WxGsonBuilder.create().toJson(data));
     return new JsonParser().parse(result).getAsJsonObject().get("chatid").getAsString();
   }
 
@@ -76,7 +76,7 @@ public void chatUpdate(String chatId, String name, String owner, List us
       data.put("del_user_list", usersToDelete);
     }
 
-    this.cpService.post(APPCHAT_UPDATE, WxGsonBuilder.create().toJson(data));
+    this.cpService.post(this.cpService.getWxCpConfigStorage().getApiUrl(APPCHAT_UPDATE), WxGsonBuilder.create().toJson(data));
   }
 
   @Override
@@ -86,7 +86,7 @@ public void update(String chatId, String name, String owner, List usersT
 
   @Override
   public WxCpChat chatGet(String chatId) throws WxErrorException {
-    String result = this.cpService.get(APPCHAT_GET_CHATID + chatId, null);
+    String result = this.cpService.get(this.cpService.getWxCpConfigStorage().getApiUrl(APPCHAT_GET_CHATID + chatId), null);
     return WxCpGsonBuilder.create()
       .fromJson(JSON_PARSER.parse(result).getAsJsonObject().getAsJsonObject("chat_info").toString(), WxCpChat.class);
   }
@@ -98,7 +98,7 @@ public WxCpChat get(String chatId) throws WxErrorException {
 
   @Override
   public void sendMsg(WxCpAppChatMessage message) throws WxErrorException {
-    this.cpService.post("https://qyapi.weixin.qq.com/cgi-bin/appchat/send", message.toJson());
+    this.cpService.post(this.cpService.getWxCpConfigStorage().getApiUrl("/cgi-bin/appchat/send"), message.toJson());
   }
 
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java
index 481115fa51..c637c78479 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java
@@ -1,7 +1,5 @@
 package me.chanjar.weixin.cp.api.impl;
 
-import java.util.List;
-
 import com.google.gson.JsonElement;
 import com.google.gson.JsonParser;
 import com.google.gson.reflect.TypeToken;
@@ -12,6 +10,8 @@
 import me.chanjar.weixin.cp.bean.WxCpDepart;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
+import java.util.List;
+
 /**
  * 
  *  部门管理接口
@@ -29,7 +29,7 @@ public WxCpDepartmentServiceImpl(WxCpService mainService) {
 
   @Override
   public Long create(WxCpDepart depart) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/department/create";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/department/create");
     String responseContent = this.mainService.post(url, depart.toJson());
     JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
     return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("id"));
@@ -37,19 +37,19 @@ public Long create(WxCpDepart depart) throws WxErrorException {
 
   @Override
   public void update(WxCpDepart group) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/department/update");
     this.mainService.post(url, group.toJson());
   }
 
   @Override
   public void delete(Long departId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/department/delete?id=" + departId);
     this.mainService.get(url, null);
   }
 
   @Override
   public List list(Long id) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/department/list");
     if (id != null) {
       url += "?id=" + id;
     }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java
index 7a3dc444cf..fa31a033ba 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMediaServiceImpl.java
@@ -1,18 +1,19 @@
 package me.chanjar.weixin.cp.api.impl;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.UUID;
-
 import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.fs.FileUtils;
 import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
 import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.api.WxCpMediaService;
 import me.chanjar.weixin.cp.api.WxCpService;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.UUID;
+
 /**
  * 
  * 媒体管理接口.
@@ -37,7 +38,7 @@ public WxMediaUploadResult upload(String mediaType, String fileType, InputStream
   @Override
   public WxMediaUploadResult upload(String mediaType, File file) throws WxErrorException {
     return this.mainService.execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()),
-      MEDIA_UPLOAD_URL + mediaType, file);
+      this.mainService.getWxCpConfigStorage().getApiUrl(MEDIA_UPLOAD_URL + mediaType), file);
   }
 
   @Override
@@ -45,7 +46,7 @@ public File download(String mediaId) throws WxErrorException {
     return this.mainService.execute(
       BaseMediaDownloadRequestExecutor.create(this.mainService.getRequestHttp(),
         this.mainService.getWxCpConfigStorage().getTmpDirFile()),
-      MEDIA_GET_URL, "media_id=" + mediaId);
+      this.mainService.getWxCpConfigStorage().getApiUrl(MEDIA_GET_URL), "media_id=" + mediaId);
   }
 
   @Override
@@ -53,13 +54,13 @@ public File getJssdkFile(String mediaId) throws WxErrorException {
     return this.mainService.execute(
       BaseMediaDownloadRequestExecutor.create(this.mainService.getRequestHttp(),
         this.mainService.getWxCpConfigStorage().getTmpDirFile()),
-      JSSDK_MEDIA_GET_URL, "media_id=" + mediaId);
+      this.mainService.getWxCpConfigStorage().getApiUrl(JSSDK_MEDIA_GET_URL), "media_id=" + mediaId);
   }
 
   @Override
   public String uploadImg(File file) throws WxErrorException {
     final WxMediaUploadResult result = this.mainService
-      .execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()), IMG_UPLOAD_URL, file);
+      .execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()), this.mainService.getWxCpConfigStorage().getApiUrl(IMG_UPLOAD_URL), file);
     return result.getUrl();
   }
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java
index f58eff4763..53a4cc7478 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMenuServiceImpl.java
@@ -2,6 +2,7 @@
 
 import me.chanjar.weixin.common.bean.menu.WxMenu;
 import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.api.WxCpMenuService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
@@ -27,7 +28,7 @@ public void create(WxMenu menu) throws WxErrorException {
 
   @Override
   public void create(Integer agentId, WxMenu menu) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" + agentId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/menu/create?agentid=" + agentId);
     this.mainService.post(url, menu.toJson());
   }
 
@@ -38,7 +39,7 @@ public void delete() throws WxErrorException {
 
   @Override
   public void delete(Integer agentId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + agentId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/menu/delete?agentid=" + agentId);
     this.mainService.get(url, null);
   }
 
@@ -49,7 +50,7 @@ public WxMenu get() throws WxErrorException {
 
   @Override
   public WxMenu get(Integer agentId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + agentId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/menu/get?agentid=" + agentId);
     try {
       String resultContent = this.mainService.get(url, null);
       return WxCpGsonBuilder.create().fromJson(resultContent, WxMenu.class);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAServiceImpl.java
index 2d1ca6ab0b..1bdce23c7c 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAServiceImpl.java
@@ -49,7 +49,7 @@ public List getCheckinData(Integer openCheckinDataType, Date st
       throw new RuntimeException("获取记录时间跨度不超过一个月");
     }
 
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/checkin/getcheckindata");
 
     JsonObject jsonObject = new JsonObject();
     JsonArray jsonArray = new JsonArray();
@@ -76,7 +76,7 @@ public List getCheckinData(Integer openCheckinDataType, Date st
 
   @Override
   public List getCheckinOption(Date datetime, List userIdList) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckinoption";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/checkin/getcheckinoption");
     if (datetime == null) {
       throw new RuntimeException("datetime can't be null");
     }
@@ -108,7 +108,7 @@ public List getCheckinOption(Date datetime, List user
   @Override
   public WxCpApprovalDataResult getApprovalData(Date starttime, Date endtime, Long nextSpnum) throws WxErrorException {
 
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/corp/getapprovaldata";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/corp/getapprovaldata");
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("starttime", starttime.getTime() / 1000L);
     jsonObject.addProperty("endtime", endtime.getTime() / 1000L);
@@ -123,7 +123,7 @@ public WxCpApprovalDataResult getApprovalData(Date starttime, Date endtime, Long
   @Override
   public List getDialRecord(Date starttime, Date endtime, Integer offset, Integer limit) throws WxErrorException {
 
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/dial/get_dial_record";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/dial/get_dial_record");
     JsonObject jsonObject = new JsonObject();
 
     if (offset == null) {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java
index 6ff91fc35a..4b00cbf9bd 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpOAuth2ServiceImpl.java
@@ -44,7 +44,7 @@ public String buildAuthorizationUrl(String redirectUri, String state) {
 
   @Override
   public String buildAuthorizationUrl(String redirectUri, String state, String scope) {
-    StringBuilder url = new StringBuilder(WxCpOAuth2Service.URL_OAUTH_2_AUTHORIZE);
+    StringBuilder url = new StringBuilder(this.mainService.getWxCpConfigStorage().getApiUrl(WxCpOAuth2Service.URL_OAUTH_2_AUTHORIZE));
     url.append("?appid=").append(this.mainService.getWxCpConfigStorage().getCorpId());
     url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectUri));
     url.append("&response_type=code");
@@ -69,7 +69,7 @@ public WxCpOauth2UserInfo getUserInfo(String code) throws WxErrorException {
 
   @Override
   public WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErrorException {
-    String responseText = this.mainService.get(String.format(WxCpOAuth2Service.URL_GET_USER_INFO, code, agentId), null);
+    String responseText = this.mainService.get(String.format(this.mainService.getWxCpConfigStorage().getApiUrl(WxCpOAuth2Service.URL_GET_USER_INFO), code, agentId), null);
     JsonElement je = new JsonParser().parse(responseText);
     JsonObject jo = je.getAsJsonObject();
 
@@ -86,7 +86,7 @@ public WxCpOauth2UserInfo getUserInfo(Integer agentId, String code) throws WxErr
   public WxCpUserDetail getUserDetail(String userTicket) throws WxErrorException {
     JsonObject param = new JsonObject();
     param.addProperty("user_ticket", userTicket);
-    String responseText = this.mainService.post(WxCpOAuth2Service.URL_GET_USER_DETAIL, param.toString());
+    String responseText = this.mainService.post(this.mainService.getWxCpConfigStorage().getApiUrl(WxCpOAuth2Service.URL_GET_USER_DETAIL), param.toString());
     return WxCpGsonBuilder.create().fromJson(responseText, WxCpUserDetail.class);
   }
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java
index 86e237168d..b7ddf91ff1 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceApacheHttpClientImpl.java
@@ -8,7 +8,7 @@
 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.WxCpOAService;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import org.apache.http.HttpHost;
 import org.apache.http.client.config.RequestConfig;
@@ -45,9 +45,10 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
     }
 
     synchronized (this.globalAccessTokenRefreshLock) {
-      String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
+      String url = this.configStorage.getApiUrl("/cgi-bin/gettoken?"
         + "&corpid=" + this.configStorage.getCorpId()
-        + "&corpsecret=" + this.configStorage.getCorpSecret();
+        + "&corpsecret=" + this.configStorage.getCorpSecret()
+      );
       try {
         HttpGet httpGet = new HttpGet(url);
         if (this.httpProxy != null) {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java
index 3603a59b17..c08b2bac20 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceJoddHttpImpl.java
@@ -1,11 +1,16 @@
 package me.chanjar.weixin.cp.api.impl;
 
-import jodd.http.*;
+import jodd.http.HttpConnectionProvider;
+import jodd.http.HttpRequest;
+import jodd.http.HttpResponse;
+import jodd.http.JoddHttp;
+import jodd.http.ProxyInfo;
 import me.chanjar.weixin.common.WxType;
 import me.chanjar.weixin.common.bean.WxAccessToken;
 import me.chanjar.weixin.common.error.WxError;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.HttpType;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 
 public class WxCpServiceJoddHttpImpl extends BaseWxCpServiceImpl {
@@ -35,9 +40,10 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
     }
 
     synchronized (this.globalAccessTokenRefreshLock) {
-      String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
+      String url = this.configStorage.getApiUrl("/cgi-bin/gettoken?"
         + "&corpid=" + this.configStorage.getCorpId()
-        + "&corpsecret=" + this.configStorage.getCorpSecret();
+        + "&corpsecret=" + this.configStorage.getCorpSecret()
+      );
 
       HttpRequest request = HttpRequest.get(url);
       if (this.httpProxy != null) {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java
index 9163ce03a6..48a56f6dca 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpServiceOkHttpImpl.java
@@ -6,8 +6,14 @@
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.http.HttpType;
 import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
-import okhttp3.*;
+import okhttp3.Authenticator;
+import okhttp3.Credentials;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.Route;
 
 import java.io.IOException;
 
@@ -38,9 +44,10 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
     }
 
     synchronized (this.globalAccessTokenRefreshLock) {
-        String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"
+        String url = this.configStorage.getApiUrl("/cgi-bin/gettoken?"
           + "&corpid=" + this.configStorage.getCorpId()
-          + "&corpsecret=" + this.configStorage.getCorpSecret();
+          + "&corpsecret=" + this.configStorage.getCorpSecret()
+        );
         //得到httpClient
         OkHttpClient client = getRequestHttpClient();
         //请求的request
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java
index 22bb0fcf96..880e3753c3 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImpl.java
@@ -1,7 +1,5 @@
 package me.chanjar.weixin.cp.api.impl;
 
-import java.util.List;
-
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
@@ -17,6 +15,8 @@
 import me.chanjar.weixin.cp.bean.WxCpUser;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
+import java.util.List;
+
 /**
  * 
  *  标签管理接口
@@ -33,7 +33,7 @@ public WxCpTagServiceImpl(WxCpService mainService) {
 
   @Override
   public String create(String tagName) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/create");
     JsonObject o = new JsonObject();
     o.addProperty("tagname", tagName);
     String responseContent = this.mainService.post(url, o.toString());
@@ -43,7 +43,7 @@ public String create(String tagName) throws WxErrorException {
 
   @Override
   public void update(String tagId, String tagName) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/update";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/update");
     JsonObject o = new JsonObject();
     o.addProperty("tagid", tagId);
     o.addProperty("tagname", tagName);
@@ -52,13 +52,13 @@ public void update(String tagId, String tagName) throws WxErrorException {
 
   @Override
   public void delete(String tagId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/delete?tagid=" + tagId);
     this.mainService.get(url, null);
   }
 
   @Override
   public List listAll() throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/list");
     String responseContent = this.mainService.get(url, null);
     JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
     return WxCpGsonBuilder.create()
@@ -71,7 +71,7 @@ public List listAll() throws WxErrorException {
 
   @Override
   public List listUsersByTagId(String tagId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/get?tagid=" + tagId);
     String responseContent = this.mainService.get(url, null);
     JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
     return WxCpGsonBuilder.create()
@@ -84,7 +84,7 @@ public List listUsersByTagId(String tagId) throws WxErrorException {
 
   @Override
   public WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List userIds, List partyIds) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/addtagusers";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/addtagusers");
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("tagid", tagId);
     this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject);
@@ -94,7 +94,7 @@ public WxCpTagAddOrRemoveUsersResult addUsers2Tag(String tagId, List use
 
   @Override
   public WxCpTagAddOrRemoveUsersResult removeUsersFromTag(String tagId, List userIds, List partyIds) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/deltagusers";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/deltagusers");
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("tagid", tagId);
     this.addUserIdsAndPartyIdsToJson(userIds, partyIds, jsonObject);
@@ -122,7 +122,7 @@ private void addUserIdsAndPartyIdsToJson(List userIds, List part
 
   @Override
   public WxCpTagGetResult get(String tagId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/get");
     if (tagId != null) {
       url += "?tagId=" + tagId;
     } else {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java
index 3011320d50..658b02247f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpTaskCardServiceImpl.java
@@ -3,6 +3,7 @@
 import lombok.RequiredArgsConstructor;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.WxCpTaskCardService;
 
@@ -33,7 +34,7 @@ public void update(List userIds, String taskId, String clickedKey) throw
     data.put("task_id", taskId);
     data.put("clicked_key", clickedKey);
 
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/message/update_taskcard";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/message/update_taskcard");
     this.mainService.post(url, WxGsonBuilder.create().toJson(data));
   }
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java
index 84a16f3496..3e432ce39c 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpUserServiceImpl.java
@@ -1,8 +1,5 @@
 package me.chanjar.weixin.cp.api.impl;
 
-import java.util.List;
-import java.util.Map;
-
 import com.google.common.collect.Maps;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
@@ -11,6 +8,7 @@
 import com.google.gson.JsonPrimitive;
 import com.google.gson.reflect.TypeToken;
 import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.WxCpUserService;
 import me.chanjar.weixin.cp.bean.WxCpInviteResult;
@@ -18,6 +16,9 @@
 import me.chanjar.weixin.cp.bean.WxCpUserExternalContactInfo;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * 
  *  Created by BinaryWang on 2017/6/24.
@@ -34,31 +35,31 @@ public WxCpUserServiceImpl(WxCpService mainService) {
 
   @Override
   public void authenticate(String userId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/authsucc?userid=" + userId);
     this.mainService.get(url, null);
   }
 
   @Override
   public void create(WxCpUser user) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/create");
     this.mainService.post(url, user.toJson());
   }
 
   @Override
   public void update(WxCpUser user) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/update");
     this.mainService.post(url, user.toJson());
   }
 
   @Override
   public void delete(String... userIds) throws WxErrorException {
     if (userIds.length == 1) {
-      String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userIds[0];
+      String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/delete?userid=" + userIds[0]);
       this.mainService.get(url, null);
       return;
     }
 
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/batchdelete");
     JsonObject jsonObject = new JsonObject();
     JsonArray jsonArray = new JsonArray();
     for (String userid : userIds) {
@@ -70,14 +71,14 @@ public void delete(String... userIds) throws WxErrorException {
 
   @Override
   public WxCpUser getById(String userid) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/get?userid=" + userid);
     String responseContent = this.mainService.get(url, null);
     return WxCpUser.fromJson(responseContent);
   }
 
   @Override
   public List listByDepartment(Long departId, Boolean fetchChild, Integer status) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/list?department_id=" + departId);
     String params = "";
     if (fetchChild != null) {
       params += "&fetch_child=" + (fetchChild ? "1" : "0");
@@ -99,7 +100,7 @@ public List listByDepartment(Long departId, Boolean fetchChild, Intege
 
   @Override
   public List listSimpleByDepartment(Long departId, Boolean fetchChild, Integer status) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/simplelist?department_id=" + departId);
     String params = "";
     if (fetchChild != null) {
       params += "&fetch_child=" + (fetchChild ? "1" : "0");
@@ -122,7 +123,7 @@ public List listSimpleByDepartment(Long departId, Boolean fetchChild,
 
   @Override
   public WxCpInviteResult invite(List userIds, List partyIds, List tagIds) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/batch/invite";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/batch/invite");
     JsonObject jsonObject = new JsonObject();
     if (userIds != null) {
       JsonArray jsonArray = new JsonArray();
@@ -153,7 +154,7 @@ public WxCpInviteResult invite(List userIds, List partyIds, List
 
   @Override
   public Map userId2Openid(String userId, Integer agentId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/convert_to_openid");
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("userid", userId);
     if (agentId != null) {
@@ -176,7 +177,7 @@ public Map userId2Openid(String userId, Integer agentId) throws
 
   @Override
   public String openid2UserId(String openid) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid";
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/user/convert_to_userid");
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("openid", openid);
     String responseContent = this.mainService.post(url, jsonObject.toString());
@@ -186,7 +187,7 @@ public String openid2UserId(String openid) throws WxErrorException {
 
   @Override
   public WxCpUserExternalContactInfo getExternalContact(String userId) throws WxErrorException {
-    String url = "https://qyapi.weixin.qq.com/cgi-bin/crm/get_external_contact?external_userid=" + userId;
+    String url = this.mainService.getWxCpConfigStorage().getApiUrl("/cgi-bin/crm/get_external_contact?external_userid=" + userId);
     String responseContent = this.mainService.get(url, null);
     return WxCpUserExternalContactInfo.fromJson(responseContent);
   }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java
index e13738142f..a75ad1dfb1 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java
@@ -12,6 +12,22 @@
  */
 public interface WxCpConfigStorage {
 
+  /**
+   * 设置企业微信服务器 baseUrl.
+   *
+   * 默认值是 https://qyapi.weixin.qq.com , 如果使用默认值,则不需要调用 setBaseApiUrl
+   *
+   * @param baseUrl 企业微信服务器 Url
+   */
+  void setBaseApiUrl(String baseUrl);
+
+  /**
+   * 读取企业微信 API Url.
+   *
+   * 支持私有化企业微信服务器.
+   */
+  String getApiUrl(String path);
+
   String getAccessToken();
 
   boolean isAccessTokenExpired();
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
index a501edeb6e..e4ae7515bc 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpInMemoryConfigStorage.java
@@ -39,6 +39,18 @@ public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
 
   private volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
 
+  protected volatile String baseApiUrl;
+
+  @Override
+  public void setBaseApiUrl(String baseUrl) {
+    this.baseApiUrl = baseUrl;
+  }
+
+  @Override
+  public String getApiUrl(String path) {
+    return baseApiUrl;
+  }
+
   @Override
   public String getAccessToken() {
     return this.accessToken;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
index 7c72de0e1b..2d893d7879 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpJedisConfigStorage.java
@@ -38,6 +38,18 @@ public class WxCpJedisConfigStorage implements WxCpConfigStorage {
   private volatile File tmpDirFile;
   private volatile ApacheHttpClientBuilder apacheHttpClientBuilder;
 
+  protected volatile String baseApiUrl;
+
+  @Override
+  public void setBaseApiUrl(String baseUrl) {
+    this.baseApiUrl = baseUrl;
+  }
+
+  @Override
+  public String getApiUrl(String path) {
+    return baseApiUrl;
+  }
+
   public WxCpJedisConfigStorage(JedisPool jedisPool) {
     this.jedisPool = jedisPool;
   }
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java
index 4ce497243d..28d9e2b743 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpAgentServiceImplTest.java
@@ -2,11 +2,11 @@
 
 import com.google.inject.Inject;
 import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.api.ApiTestModule;
 import me.chanjar.weixin.cp.api.WxCpAgentService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.WxCpAgent;
-import org.testng.Assert;
 import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
@@ -15,7 +15,6 @@
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertEquals;
 
 
 /**
@@ -71,7 +70,7 @@ public static class MockTest {
     @Test
     public void testGet() throws Exception {
       String returnJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"agentid\": 9,\"name\": \"测试应用\",\"square_logo_url\": \"http://wx.qlogo.cn/mmhead/alksjf;lasdjf;lasjfuodiuj3rj2o34j/0\",\"description\": \"这是一个企业号应用\",\"allow_userinfos\": {\"user\": [{\"userid\": \"0009854\"}, {\"userid\": \"1723\"}, {\"userid\": \"5625\"}]},\"allow_partys\": {\"partyid\": [42762742]},\"allow_tags\": {\"tagid\": [23, 22, 35, 19, 32, 125, 133, 46, 150, 38, 183, 9, 7]},\"close\": 0,\"redirect_domain\": \"weixin.com.cn\",\"report_location_flag\": 0,\"isreportenter\": 0,\"home_url\": \"\"}";
-      when(wxService.get("https://qyapi.weixin.qq.com/cgi-bin/agent/get?agentid=9", null)).thenReturn(returnJson);
+      when(wxService.get(wxService.getWxCpConfigStorage().getApiUrl("/cgi-bin/agent/get?agentid=9"), null)).thenReturn(returnJson);
       when(wxService.getAgentService()).thenReturn(new WxCpAgentServiceImpl(wxService));
 
       WxCpAgentService wxAgentService = this.wxService.getAgentService();
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java
index 5a6e8ccabd..2f487b6182 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/impl/WxCpTagServiceImplTest.java
@@ -3,6 +3,7 @@
 import com.google.common.base.Splitter;
 import com.google.inject.Inject;
 import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.WxCpConsts;
 import me.chanjar.weixin.cp.api.ApiTestModule;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.WxCpTagService;
@@ -17,7 +18,6 @@
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotEquals;
 
 /**
@@ -83,7 +83,7 @@ public void testDelete() throws Exception {
   public void testGet() throws WxErrorException {
     String apiResultJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"userlist\": [{\"userid\": \"0124035\",\"name\": \"王五\"},{\"userid\": \"0114035\",\"name\": \"梦雪\"}],\"partylist\": [9576,9567,9566],\"tagname\": \"测试标签-001\"}";
     WxCpService wxService = mock(WxCpService.class);
-    when(wxService.get("https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagId=150", null)).thenReturn(apiResultJson);
+    when(wxService.get(wxService.getWxCpConfigStorage().getApiUrl("/cgi-bin/tag/get?tagId=150"), null)).thenReturn(apiResultJson);
     when(wxService.getTagService()).thenReturn(new WxCpTagServiceImpl(wxService));
 
     WxCpTagService wxCpTagService = wxService.getTagService();