Skip to content

公众号开发永久下载图片和声音的接口 materialImageOrVoiceDownload 无法正常刷新 AccessToken #3196

Closed
@shenliuming

Description

@shenliuming

第一次提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判断即可

ApiPost 返回

image

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions