@@ -380,4 +380,19 @@ public class WxConsts { | |||||
public static final String VIDEO = "video"; | public static final String VIDEO = "video"; | ||||
} | } | ||||
/** | |||||
* 网络检测入参. | |||||
*/ | |||||
public static class NetCheckArgs { | |||||
public static final String ACTIONDNS = "dns"; | |||||
public static final String ACTIONPING = "ping"; | |||||
public static final String ACTIONALL = "all"; | |||||
public static final String OPERATORUNICOM = "UNICOM"; | |||||
public static final String OPERATORCHINANET = "CHINANET"; | |||||
public static final String OPERATORCAP = "CAP"; | |||||
public static final String OPERATORDEFAULT = "DEFAULT"; | |||||
} | |||||
} | } |
@@ -0,0 +1,43 @@ | |||||
package me.chanjar.weixin.common.bean; | |||||
import lombok.Data; | |||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||||
import java.io.Serializable; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* 网络检测. | |||||
* @author billytomato | |||||
*/ | |||||
@Data | |||||
public class WxNetCheckResult implements Serializable { | |||||
private static final long serialVersionUID = 6918924418847404172L; | |||||
private List<WxNetCheckDnsInfo> dnsInfos = new ArrayList<>(); | |||||
private List<WxNetCheckPingInfo> pingInfos = new ArrayList<>(); | |||||
public static WxNetCheckResult fromJson(String json) { | |||||
return WxGsonBuilder.create().fromJson(json, WxNetCheckResult.class); | |||||
} | |||||
@Data | |||||
public static class WxNetCheckDnsInfo implements Serializable{ | |||||
private static final long serialVersionUID = 82631178029516008L; | |||||
private String ip; | |||||
private String realOperator; | |||||
} | |||||
@Data | |||||
public static class WxNetCheckPingInfo implements Serializable{ | |||||
private static final long serialVersionUID = -1871970825359178319L; | |||||
private String ip; | |||||
private String fromOperator; | |||||
private String packageLoss; | |||||
private String time; | |||||
} | |||||
} | |||||
@@ -3,6 +3,7 @@ package me.chanjar.weixin.common.util.json; | |||||
import com.google.gson.Gson; | import com.google.gson.Gson; | ||||
import com.google.gson.GsonBuilder; | import com.google.gson.GsonBuilder; | ||||
import me.chanjar.weixin.common.bean.WxAccessToken; | import me.chanjar.weixin.common.bean.WxAccessToken; | ||||
import me.chanjar.weixin.common.bean.WxNetCheckResult; | |||||
import me.chanjar.weixin.common.bean.menu.WxMenu; | import me.chanjar.weixin.common.bean.menu.WxMenu; | ||||
import me.chanjar.weixin.common.error.WxError; | import me.chanjar.weixin.common.error.WxError; | ||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | ||||
@@ -21,6 +22,8 @@ public class WxGsonBuilder { | |||||
INSTANCE.registerTypeAdapter(WxError.class, new WxErrorAdapter()); | INSTANCE.registerTypeAdapter(WxError.class, new WxErrorAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMenu.class, new WxMenuGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMenu.class, new WxMenuGsonAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxMediaUploadResult.class, new WxMediaUploadResultAdapter()); | INSTANCE.registerTypeAdapter(WxMediaUploadResult.class, new WxMediaUploadResultAdapter()); | ||||
INSTANCE.registerTypeAdapter(WxNetCheckResult.class, new WxNetCheckResultGsonAdapter()); | |||||
} | } | ||||
public static Gson create() { | public static Gson create() { | ||||
@@ -0,0 +1,51 @@ | |||||
package me.chanjar.weixin.common.util.json; | |||||
import com.google.gson.*; | |||||
import me.chanjar.weixin.common.bean.WxNetCheckResult; | |||||
import java.lang.reflect.Type; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* @author billytomato | |||||
*/ | |||||
public class WxNetCheckResultGsonAdapter implements JsonDeserializer<WxNetCheckResult> { | |||||
@Override | |||||
public WxNetCheckResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||||
WxNetCheckResult result = new WxNetCheckResult(); | |||||
JsonArray dnssJson = json.getAsJsonObject().get("dns").getAsJsonArray(); | |||||
List<WxNetCheckResult.WxNetCheckDnsInfo> dnsInfoList = new ArrayList<>(); | |||||
if (dnssJson != null && dnssJson.size() > 0) { | |||||
for (int i = 0; i < dnssJson.size(); i++) { | |||||
JsonObject buttonJson = dnssJson.get(i).getAsJsonObject(); | |||||
WxNetCheckResult.WxNetCheckDnsInfo dnsInfo = new WxNetCheckResult.WxNetCheckDnsInfo(); | |||||
dnsInfo.setIp(GsonHelper.getString(buttonJson, "ip")); | |||||
dnsInfo.setRealOperator(GsonHelper.getString(buttonJson, "real_operator")); | |||||
dnsInfoList.add(dnsInfo); | |||||
} | |||||
} | |||||
JsonArray pingsJson = json.getAsJsonObject().get("ping").getAsJsonArray(); | |||||
List<WxNetCheckResult.WxNetCheckPingInfo> pingInfoList = new ArrayList<>(); | |||||
if (pingsJson != null && pingsJson.size() > 0) { | |||||
for (int i = 0; i < pingsJson.size(); i++) { | |||||
JsonObject pingJson = pingsJson.get(i).getAsJsonObject(); | |||||
WxNetCheckResult.WxNetCheckPingInfo pingInfo = new WxNetCheckResult.WxNetCheckPingInfo(); | |||||
pingInfo.setIp(GsonHelper.getString(pingJson, "ip")); | |||||
pingInfo.setFromOperator(GsonHelper.getString(pingJson, "from_operator")); | |||||
pingInfo.setPackageLoss(GsonHelper.getString(pingJson, "package_loss")); | |||||
pingInfo.setTime(GsonHelper.getString(pingJson, "time")); | |||||
pingInfoList.add(pingInfo); | |||||
} | |||||
} | |||||
result.setDnsInfos(dnsInfoList); | |||||
result.setPingInfos(pingInfoList); | |||||
return result; | |||||
} | |||||
} |
@@ -1,6 +1,7 @@ | |||||
package me.chanjar.weixin.mp.api; | package me.chanjar.weixin.mp.api; | ||||
import me.chanjar.weixin.common.bean.WxJsapiSignature; | import me.chanjar.weixin.common.bean.WxJsapiSignature; | ||||
import me.chanjar.weixin.common.bean.WxNetCheckResult; | |||||
import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; | ||||
import me.chanjar.weixin.common.util.http.RequestExecutor; | import me.chanjar.weixin.common.util.http.RequestExecutor; | ||||
@@ -178,6 +179,20 @@ public interface WxMpService { | |||||
*/ | */ | ||||
String[] getCallbackIP() throws WxErrorException; | String[] getCallbackIP() throws WxErrorException; | ||||
/** | |||||
* <pre> | |||||
* 网络检测 | |||||
* https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21541575776DtsuT | |||||
* 为了帮助开发者排查回调连接失败的问题,提供这个网络检测的API。它可以对开发者URL做域名解析,然后对所有IP进行一次ping操作,得到丢包率和耗时。 | |||||
* </pre> | |||||
* | |||||
* @param action 执行的检测动作 | |||||
* @param operator 指定平台从某个运营商进行检测 | |||||
* @throws WxErrorException | |||||
*/ | |||||
WxNetCheckResult netCheck(String action, String operator) throws WxErrorException; | |||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 获取公众号的自动回复规则. | * 获取公众号的自动回复规则. | ||||
@@ -8,6 +8,7 @@ import com.google.gson.JsonObject; | |||||
import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import me.chanjar.weixin.common.bean.WxJsapiSignature; | import me.chanjar.weixin.common.bean.WxJsapiSignature; | ||||
import me.chanjar.weixin.common.bean.WxNetCheckResult; | |||||
import me.chanjar.weixin.common.error.WxError; | import me.chanjar.weixin.common.error.WxError; | ||||
import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
import me.chanjar.weixin.common.session.StandardSessionManager; | import me.chanjar.weixin.common.session.StandardSessionManager; | ||||
@@ -236,6 +237,15 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||||
return ipArray; | return ipArray; | ||||
} | } | ||||
@Override | |||||
public WxNetCheckResult netCheck(String action, String operator) throws WxErrorException { | |||||
JsonObject o = new JsonObject(); | |||||
o.addProperty("action", action); | |||||
o.addProperty("check_operator", operator); | |||||
String responseContent = this.post(NETCHECK_URL, o.toString()); | |||||
return WxNetCheckResult.fromJson(responseContent); | |||||
} | |||||
@Override | @Override | ||||
public WxMpCurrentAutoReplyInfo getCurrentAutoReplyInfo() throws WxErrorException { | public WxMpCurrentAutoReplyInfo getCurrentAutoReplyInfo() throws WxErrorException { | ||||
return WxMpCurrentAutoReplyInfo.fromJson(this.get(GET_CURRENT_AUTOREPLY_INFO_URL, null)); | return WxMpCurrentAutoReplyInfo.fromJson(this.get(GET_CURRENT_AUTOREPLY_INFO_URL, null)); | ||||
@@ -110,6 +110,10 @@ public interface WxMpApiUrl { | |||||
* 获取微信服务器IP地址. | * 获取微信服务器IP地址. | ||||
*/ | */ | ||||
GET_CALLBACK_IP_URL(API_DEFAULT_HOST_URL, "/cgi-bin/getcallbackip"), | GET_CALLBACK_IP_URL(API_DEFAULT_HOST_URL, "/cgi-bin/getcallbackip"), | ||||
/** | |||||
* 网络检测. | |||||
*/ | |||||
NETCHECK_URL(API_DEFAULT_HOST_URL, "/cgi-bin/callback/check"), | |||||
/** | /** | ||||
* 第三方使用网站应用授权登录的url. | * 第三方使用网站应用授权登录的url. | ||||
*/ | */ | ||||
@@ -1,10 +1,13 @@ | |||||
package me.chanjar.weixin.mp.api.impl; | package me.chanjar.weixin.mp.api.impl; | ||||
import com.google.inject.Inject; | import com.google.inject.Inject; | ||||
import me.chanjar.weixin.common.api.WxConsts; | |||||
import me.chanjar.weixin.common.bean.WxNetCheckResult; | |||||
import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
import me.chanjar.weixin.mp.api.test.ApiTestModule; | import me.chanjar.weixin.mp.api.test.ApiTestModule; | ||||
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder; | import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder; | ||||
import org.testng.Assert; | |||||
import org.testng.annotations.Guice; | import org.testng.annotations.Guice; | ||||
import org.testng.annotations.Test; | import org.testng.annotations.Test; | ||||
@@ -37,4 +40,57 @@ public class BaseWxMpServiceImplTest { | |||||
assertThat(this.wxService.switchoverTo("another").getAccessToken()).isNotEmpty(); | assertThat(this.wxService.switchoverTo("another").getAccessToken()).isNotEmpty(); | ||||
assertThat(WxMpConfigStorageHolder.get()).isEqualTo("another"); | assertThat(WxMpConfigStorageHolder.get()).isEqualTo("another"); | ||||
} | } | ||||
@Test | |||||
public void testNetCheck() throws WxErrorException { | |||||
WxNetCheckResult result = this.wxService.netCheck(WxConsts.NetCheckArgs.ACTIONALL, WxConsts.NetCheckArgs.OPERATORDEFAULT); | |||||
Assert.assertNotNull(result); | |||||
} | |||||
@Test | |||||
public void testNectCheckResult() { | |||||
String json = "{\n" + | |||||
" \"dns\": [\n" + | |||||
" {\n" + | |||||
" \"ip\": \"111.161.64.40\", \n" + | |||||
" \"real_operator\": \"UNICOM\"\n" + | |||||
" }, \n" + | |||||
" {\n" + | |||||
" \"ip\": \"111.161.64.48\", \n" + | |||||
" \"real_operator\": \"UNICOM\"\n" + | |||||
" }\n" + | |||||
" ], \n" + | |||||
" \"ping\": [\n" + | |||||
" {\n" + | |||||
" \"ip\": \"111.161.64.40\", \n" + | |||||
" \"from_operator\": \"UNICOM\"," + | |||||
" \"package_loss\": \"0%\", \n" + | |||||
" \"time\": \"23.079ms\"\n" + | |||||
" }, \n" + | |||||
" {\n" + | |||||
" \"ip\": \"111.161.64.48\", \n" + | |||||
" \"from_operator\": \"UNICOM\", \n" + | |||||
" \"package_loss\": \"0%\", \n" + | |||||
" \"time\": \"21.434ms\"\n" + | |||||
" }\n" + | |||||
" ]\n" + | |||||
"}"; | |||||
WxNetCheckResult result = WxNetCheckResult.fromJson(json); | |||||
Assert.assertNotNull(result); | |||||
Assert.assertNotNull(result.getDnsInfos()); | |||||
WxNetCheckResult.WxNetCheckDnsInfo dnsInfo = new WxNetCheckResult.WxNetCheckDnsInfo(); | |||||
dnsInfo.setIp("111.161.64.40"); | |||||
dnsInfo.setRealOperator("UNICOM"); | |||||
Assert.assertEquals(result.getDnsInfos().get(0), dnsInfo); | |||||
WxNetCheckResult.WxNetCheckPingInfo pingInfo = new WxNetCheckResult.WxNetCheckPingInfo(); | |||||
pingInfo.setTime("21.434ms"); | |||||
pingInfo.setFromOperator("UNICOM"); | |||||
pingInfo.setIp("111.161.64.48"); | |||||
pingInfo.setPackageLoss("0%"); | |||||
Assert.assertEquals(result.getPingInfos().get(1), pingInfo); | |||||
} | |||||
} | } |