Wechat-Group / WxJava

微信开发 Java SDK ,支持包括微信支付,开放平台,小程序,企业微信,视频号,公众号等的后端开发

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

shenliuming opened this issue · comments

第一次提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