公众号开发永久下载图片和声音的接口 materialImageOrVoiceDownload 无法正常刷新 AccessToken
shenliuming opened this issue · comments
令狐冲 commented
第一次提Issue 暂时不会提PR 麻烦修复一下这个BUG
简要描述
请简单概括描述下你所遇到的问题。
模块版本情况
- WxJava 模块名: weixin-java-mp
- WxJava 版本号: 4.5.0
具体的包名:me.chanjar.weixin.mp.util.requestexecuter.material
详细描述
正常刷新Token的逻辑:只有抛出异常了,才会去刷新 AccessToken
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
int retryTimes = 0;
do {
try {
return this.executeInternal(executor, uri, data, false);
} catch (WxErrorException e) {
WxError error = e.getError();
// -1 系统繁忙, 1000ms后重试
if (error.getErrorCode() == -1) {
// 判断是否已经超了最大重试次数
if (retryTimes + 1 > this.maxRetryTimes) {
log.warn("重试达到最大次数【{}】", maxRetryTimes);
//最后一次重试失败后,直接抛出异常,不再等待
throw new WxRuntimeException("微信服务端异常,超出重试次数");
}
int sleepMillis = this.retrySleepMillis * (1 << retryTimes);
try {
log.warn("微信系统繁忙,{} ms 后重试(第{}次)", sleepMillis, retryTimes + 1);
Thread.sleep(sleepMillis);
} catch (InterruptedException e1) {
throw new WxRuntimeException(e1);
}
} else {
throw e;
}
}
} while (retryTimes++ < this.maxRetryTimes);
log.warn("重试达到最大次数【{}】", this.maxRetryTimes);
throw new WxRuntimeException("微信服务端异常,超出重试次数");
}
这三个是下载永久 声音和图片的实现类
public static RequestExecutor<InputStream, String> create(RequestHttp requestHttp, File tmpDirFile) {
switch (requestHttp.getRequestType()) {
case APACHE_HTTP:
return new MaterialVoiceAndImageDownloadApacheHttpRequestExecutor(requestHttp, tmpDirFile);
case JODD_HTTP:
return new MaterialVoiceAndImageDownloadJoddHttpRequestExecutor(requestHttp, tmpDirFile);
case OK_HTTP:
return new MaterialVoiceAndImageDownloadOkhttpRequestExecutor(requestHttp, tmpDirFile);
default:
return null;
}
}
问题发生在 获取微信IO流的时候,没有正确判断ContentType 导致没有及时报错导致的:
MaterialVoiceAndImageDownloadOkhttpRequestExecutor
@Override
public InputStream execute(String uri, String materialId, WxType wxType) throws WxErrorException, IOException {
logger.debug("MaterialVoiceAndImageDownloadOkhttpRequestExecutor is running");
OkHttpClient client = requestHttp.getRequestHttpClient();
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"),
WxGsonBuilder.create().toJson(ImmutableMap.of("media_id", materialId)));
Request request = new Request.Builder().url(uri).get().post(requestBody).build();
Response response = client.newCall(request).execute();
String contentTypeHeader = response.header("Content-Type");
// 问题发生在这个判断,没有及时抛出 微信异常,导致的,因为微信返回的ContentType 是application/json; encoding=utf-8
if ("text/plain".equals(contentTypeHeader)) {
String responseContent = response.body().string();
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MP));
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); BufferedSink sink = Okio.buffer(Okio.sink(outputStream))) {
sink.writeAll(response.body().source());
return new ByteArrayInputStream(outputStream.toByteArray());
}
}
代码修复 只需要增加 这个application/json判断即可