From 774579186cf0bf0de87a7b41af5b194aa2b4b3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E6=9C=9D=E7=BA=A2=E9=9B=A8?= <44485373+tianchaohongyu@users.noreply.github.com> Date: Fri, 12 Jan 2024 20:01:42 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20=E3=80=90=E5=BC=80=E6=94=BE=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E3=80=91=E6=8E=A5=E5=85=A5=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=EF=BC=88=E5=B9=B4=E5=AE=A1=EF=BC=89=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=85=AC=E5=85=B1=E7=9A=84=E6=96=87=E4=BB=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/impl/BaseWxChannelServiceImpl.java | 39 +++---- .../weixin/common/bean/CommonUploadData.java | 76 ++++++++++++ .../weixin/common/bean/CommonUploadParam.java | 65 +++++++++++ .../executor/CommonUploadRequestExecutor.java | 50 ++++++++ ...CommonUploadRequestExecutorApacheImpl.java | 83 +++++++++++++ ...mmonUploadRequestExecutorJoddHttpImpl.java | 91 +++++++++++++++ ...CommonUploadRequestExecutorOkHttpImpl.java | 91 +++++++++++++++ .../weixin/common/service/WxService.java | 11 ++ .../util/http/MediaUploadRequestExecutor.java | 14 ++- .../cp/api/impl/BaseWxCpServiceImpl.java | 10 +- .../miniapp/api/impl/BaseWxMaServiceImpl.java | 12 +- .../api/impl/WxMaMediaServiceImpl.java | 6 +- ...ApacheAuditMediaUploadRequestExecutor.java | 58 --------- .../AuditMediaUploadRequestExecutor.java | 47 -------- ...ddHttpAuditMediaUploadRequestExecutor.java | 45 ------- ...OkHttpAuditMediaUploadRequestExecutor.java | 49 -------- .../impl/WxMaLiveGoodsServiceImplTest.java | 3 +- .../miniapp/api/impl/WxMaServiceImplTest.java | 11 ++ .../mp/api/impl/BaseWxMpServiceImpl.java | 14 ++- .../weixin/open/api/WxOpenMaAuthService.java | 82 +++++++++++++ .../weixin/open/api/WxOpenMaService.java | 9 +- .../api/impl/WxOpenMaAuthServiceImpl.java | 56 +++++++++ .../open/api/impl/WxOpenMaServiceImpl.java | 8 +- .../auth/MaAuthQueryIdentityTreeResult.java | 29 +++++ ...thQueryIdentityTreeResultIdentityLeaf.java | 20 ++++ ...thQueryIdentityTreeResultIdentityNode.java | 47 ++++++++ .../open/bean/auth/MaAuthQueryResult.java | 64 ++++++++++ .../auth/MaAuthQueryResultDispatchInfo.java | 36 ++++++ .../open/bean/auth/MaAuthResubmitParam.java | 22 ++++ .../auth/MaAuthResubmitParamAuthData.java | 24 ++++ .../open/bean/auth/MaAuthSubmitParam.java | 27 +++++ .../bean/auth/MaAuthSubmitParamAuthData.java | 110 ++++++++++++++++++ .../auth/MaAuthSubmitParamContactInfo.java | 28 +++++ .../MaAuthSubmitParamInvoiceElectronic.java | 29 +++++ .../auth/MaAuthSubmitParamInvoiceInfo.java | 44 +++++++ .../auth/MaAuthSubmitParamInvoiceVat.java | 102 ++++++++++++++++ .../open/bean/auth/MaAuthSubmitResult.java | 34 ++++++ .../open/bean/auth/MaAuthUploadResult.java | 27 +++++ .../api/impl/BaseWxQidianServiceImpl.java | 50 ++++---- 39 files changed, 1353 insertions(+), 270 deletions(-) create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadData.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadParam.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorJoddHttpImpl.java create mode 100644 weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorOkHttpImpl.java delete mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheAuditMediaUploadRequestExecutor.java delete mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/AuditMediaUploadRequestExecutor.java delete mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/JoddHttpAuditMediaUploadRequestExecutor.java delete mode 100644 weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/OkHttpAuditMediaUploadRequestExecutor.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthService.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthServiceImpl.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResult.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityLeaf.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityNode.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResult.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResultDispatchInfo.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParam.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParamAuthData.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParam.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamAuthData.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamContactInfo.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceElectronic.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceInfo.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceVat.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitResult.java create mode 100644 weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthUploadResult.java diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java index 6dd12a5b5..6eb07981f 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java @@ -2,36 +2,19 @@ package me.chanjar.weixin.channel.api.impl; import com.google.gson.JsonObject; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; import lombok.extern.slf4j.Slf4j; -import me.chanjar.weixin.channel.api.WxChannelAddressService; -import me.chanjar.weixin.channel.api.WxChannelAfterSaleService; -import me.chanjar.weixin.channel.api.WxChannelBasicService; -import me.chanjar.weixin.channel.api.WxChannelBrandService; -import me.chanjar.weixin.channel.api.WxChannelCategoryService; -import me.chanjar.weixin.channel.api.WxChannelCouponService; -import me.chanjar.weixin.channel.api.WxChannelFreightTemplateService; -import me.chanjar.weixin.channel.api.WxChannelFundService; -import me.chanjar.weixin.channel.api.WxChannelOrderService; -import me.chanjar.weixin.channel.api.WxChannelProductService; -import me.chanjar.weixin.channel.api.WxChannelService; -import me.chanjar.weixin.channel.api.WxChannelSharerService; -import me.chanjar.weixin.channel.api.WxChannelWarehouseService; -import me.chanjar.weixin.channel.api.WxLeagueProductService; -import me.chanjar.weixin.channel.api.WxLeaguePromoterService; -import me.chanjar.weixin.channel.api.WxLeagueSupplierService; -import me.chanjar.weixin.channel.api.WxLeagueWindowService; +import me.chanjar.weixin.channel.api.*; import me.chanjar.weixin.channel.config.WxChannelConfig; import me.chanjar.weixin.channel.util.JsonUtils; import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.ToJson; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.executor.CommonUploadRequestExecutor; import me.chanjar.weixin.common.util.DataUtils; import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.http.RequestExecutor; @@ -40,6 +23,10 @@ import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import org.apache.commons.lang3.StringUtils; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; + /** * @author <a href="https://github.com/lixize">Zeyes</a> * @see #doGetAccessTokenRequest @@ -119,7 +106,6 @@ public abstract class BaseWxChannelServiceImpl<H, P> implements WxChannelService * 通过网络请求获取AccessToken * * @return . - * * @throws IOException . */ protected abstract String doGetAccessTokenRequest() throws IOException; @@ -145,6 +131,12 @@ public abstract class BaseWxChannelServiceImpl<H, P> implements WxChannelService return this.post(url, obj.toJson()); } + @Override + public String upload(String url, CommonUploadParam param) throws WxErrorException { + RequestExecutor<String, CommonUploadParam> executor = CommonUploadRequestExecutor.create(getRequestHttp()); + return this.execute(executor, url, param); + } + @Override public String post(String url, JsonObject jsonObject) throws WxErrorException { return this.post(url, jsonObject.toString()); @@ -200,7 +192,7 @@ public abstract class BaseWxChannelServiceImpl<H, P> implements WxChannelService } protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data, boolean doNotAutoRefreshToken, - boolean printResult) throws WxErrorException { + boolean printResult) throws WxErrorException { E dataForLog = DataUtils.handleDataWithSecret(data); if (uri.contains("access_token=")) { @@ -259,7 +251,6 @@ public abstract class BaseWxChannelServiceImpl<H, P> implements WxChannelService * * @param resultContent 响应内容 * @return access token - * * @throws WxErrorException 异常 */ protected String extractAccessToken(String resultContent) throws WxErrorException { @@ -372,7 +363,7 @@ public abstract class BaseWxChannelServiceImpl<H, P> implements WxChannelService } @Override - public synchronized WxLeaguePromoterService getLeaguePromoterService() { + public synchronized WxLeaguePromoterService getLeaguePromoterService() { if (leaguePromoterService == null) { leaguePromoterService = new WxLeaguePromoterServiceImpl(this); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadData.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadData.java new file mode 100644 index 000000000..ea76137f6 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadData.java @@ -0,0 +1,76 @@ +package me.chanjar.weixin.common.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.lang.Nullable; + +import java.io.*; +import java.nio.file.Files; + +/** + * 通用文件上传数据 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Slf4j +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CommonUploadData implements Serializable { + + /** + * 文件名,如:1.jpg + */ + @Nullable + private String fileName; + + /** + * 文件内容 + * + * @see FileInputStream 文件输入流 + * @see ByteArrayInputStream 字节输入流 + */ + @NotNull + private InputStream inputStream; + + /** + * 文件内容长度(字节数) + */ + private long length; + + /** + * 从文件构造 + * + * @param file 文件 + * @return 通用文件上传数据 + */ + @SneakyThrows + public static CommonUploadData fromFile(File file) { + return new CommonUploadData(file.getName(), Files.newInputStream(file.toPath()), file.length()); + } + + + /** + * 读取所有字节,此方法会关闭输入流 + * + * @return 字节数组 + */ + @SneakyThrows + public byte[] readAllBytes() { + byte[] bytes = new byte[(int) length]; + //noinspection ResultOfMethodCallIgnored + inputStream.read(bytes); + inputStream.close(); + return bytes; + } + + @Override + public String toString() { + return String.format("{fileName:%s, length:%s}", fileName, length); + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadParam.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadParam.java new file mode 100644 index 000000000..3a9872fc9 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/CommonUploadParam.java @@ -0,0 +1,65 @@ +package me.chanjar.weixin.common.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; +import org.springframework.lang.Nullable; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.Serializable; + +/** + * 通用文件上传参数 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CommonUploadParam implements Serializable { + + /** + * 文件对应的接口参数名称(非文件名),如:media + */ + @NotNull + private String name; + + /** + * 上传数据 + */ + @NotNull + private CommonUploadData data; + + /** + * 从文件构造 + * + * @param name 参数名,如:media + * @param file 文件 + * @return 文件上传参数对象 + */ + @SneakyThrows + public static CommonUploadParam fromFile(String name, File file) { + return new CommonUploadParam(name, CommonUploadData.fromFile(file)); + } + + /** + * 从字节数组构造 + * + * @param name 参数名,如:media + * @param bytes 字节数组 + * @return 文件上传参数对象 + */ + @SneakyThrows + public static CommonUploadParam fromBytes(String name, @Nullable String fileName, byte[] bytes) { + return new CommonUploadParam(name, new CommonUploadData(fileName, new ByteArrayInputStream(bytes), bytes.length)); + } + + @Override + public String toString() { + return String.format("{name:%s, data:%s}", name, data); + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java new file mode 100644 index 000000000..2c9a4d752 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutor.java @@ -0,0 +1,50 @@ +package me.chanjar.weixin.common.executor; + +import me.chanjar.weixin.common.bean.CommonUploadParam; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.ResponseHandler; + +import java.io.IOException; + +/** + * 通用文件上传执行器 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +public abstract class CommonUploadRequestExecutor<H, P> implements RequestExecutor<String, CommonUploadParam> { + + protected RequestHttp<H, P> requestHttp; + + public CommonUploadRequestExecutor(RequestHttp<H, P> requestHttp) { + this.requestHttp = requestHttp; + } + + @Override + public void execute(String uri, CommonUploadParam data, ResponseHandler<String> handler, WxType wxType) throws WxErrorException, IOException { + handler.handle(this.execute(uri, data, wxType)); + } + + /** + * 构造通用文件上传执行器 + * + * @param requestHttp 请求信息 + * @return 执行器 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static RequestExecutor<String, CommonUploadParam> create(RequestHttp requestHttp) { + switch (requestHttp.getRequestType()) { + case APACHE_HTTP: + return new CommonUploadRequestExecutorApacheImpl(requestHttp); + case JODD_HTTP: + return new CommonUploadRequestExecutorJoddHttpImpl(requestHttp); + case OK_HTTP: + return new CommonUploadRequestExecutorOkHttpImpl(requestHttp); + default: + throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType()); + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java new file mode 100644 index 000000000..6a3c05dd2 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorApacheImpl.java @@ -0,0 +1,83 @@ +package me.chanjar.weixin.common.executor; + +import lombok.Getter; +import me.chanjar.weixin.common.bean.CommonUploadData; +import me.chanjar.weixin.common.bean.CommonUploadParam; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.InputStreamBody; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Apache HttpClient 通用文件上传器 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +public class CommonUploadRequestExecutorApacheImpl + extends CommonUploadRequestExecutor<CloseableHttpClient, HttpHost> { + + public CommonUploadRequestExecutorApacheImpl(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, CommonUploadParam param, WxType wxType) throws WxErrorException, IOException { + HttpPost httpPost = new HttpPost(uri); + if (requestHttp.getRequestHttpProxy() != null) { + RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); + httpPost.setConfig(config); + } + if (param != null) { + CommonUploadData data = param.getData(); + InnerStreamBody part = new InnerStreamBody(data.getInputStream(), ContentType.DEFAULT_BINARY, data.getFileName(), data.getLength()); + HttpEntity entity = MultipartEntityBuilder + .create() + .addPart(param.getName(), part) + .setMode(HttpMultipartMode.RFC6532) + .build(); + httpPost.setEntity(entity); + } + try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); + if (responseContent == null || responseContent.isEmpty()) { + throw new WxErrorException(String.format("上传失败,服务器响应空 url:%s param:%s", uri, param)); + } + WxError error = WxError.fromJson(responseContent, wxType); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } finally { + httpPost.releaseConnection(); + } + } + + /** + * 内部流 请求体 + */ + @Getter + public static class InnerStreamBody extends InputStreamBody { + + private final long contentLength; + + public InnerStreamBody(final InputStream in, final ContentType contentType, final String filename, long contentLength) { + super(in, contentType, filename); + this.contentLength = contentLength; + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorJoddHttpImpl.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorJoddHttpImpl.java new file mode 100644 index 000000000..36e8660f7 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorJoddHttpImpl.java @@ -0,0 +1,91 @@ +package me.chanjar.weixin.common.executor; + +import jodd.http.HttpConnectionProvider; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.http.upload.Uploadable; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.SneakyThrows; +import me.chanjar.weixin.common.bean.CommonUploadData; +import me.chanjar.weixin.common.bean.CommonUploadParam; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +/** + * JoddHttp 通用文件上传器 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +public class CommonUploadRequestExecutorJoddHttpImpl extends CommonUploadRequestExecutor<HttpConnectionProvider, ProxyInfo> { + + public CommonUploadRequestExecutorJoddHttpImpl(RequestHttp<HttpConnectionProvider, ProxyInfo> requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, CommonUploadParam param, WxType wxType) throws WxErrorException, IOException { + HttpRequest request = HttpRequest.post(uri); + if (requestHttp.getRequestHttpProxy() != null) { + requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); + } + request.withConnectionProvider(requestHttp.getRequestHttpClient()); + request.form(param.getName(), new CommonUploadParamToUploadableAdapter(param.getData())); + HttpResponse response = request.send(); + response.charset(StandardCharsets.UTF_8.name()); + String responseContent = response.bodyText(); + if (responseContent.isEmpty()) { + throw new WxErrorException(String.format("上传失败,服务器响应空 url:%s param:%s", uri, param)); + } + WxError error = WxError.fromJson(responseContent, wxType); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + + /** + * 通用上传参数 到 Uploadable 的适配器 + */ + @Getter + @AllArgsConstructor + public static class CommonUploadParamToUploadableAdapter implements Uploadable<CommonUploadData> { + + private CommonUploadData content; + + @SneakyThrows + @Override + public byte[] getBytes() { + return content.readAllBytes(); + } + + @Override + public String getFileName() { + return content.getFileName(); + } + + @Override + public String getMimeType() { + return null; + } + + @SneakyThrows + @Override + public int getSize() { + return (int) content.getLength(); + } + + @Override + public InputStream openInputStream() { + return content.getInputStream(); + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorOkHttpImpl.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorOkHttpImpl.java new file mode 100644 index 000000000..40a4622b8 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/executor/CommonUploadRequestExecutorOkHttpImpl.java @@ -0,0 +1,91 @@ +package me.chanjar.weixin.common.executor; + +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.bean.CommonUploadData; +import me.chanjar.weixin.common.bean.CommonUploadParam; +import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestHttp; +import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; +import okhttp3.*; +import okio.BufferedSink; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.InputStream; + +/** + * OkHttp 通用文件上传器 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +public class CommonUploadRequestExecutorOkHttpImpl extends CommonUploadRequestExecutor<OkHttpClient, OkHttpProxyInfo> { + + public CommonUploadRequestExecutorOkHttpImpl(RequestHttp<OkHttpClient, OkHttpProxyInfo> requestHttp) { + super(requestHttp); + } + + @Override + public String execute(String uri, CommonUploadParam param, WxType wxType) throws WxErrorException, IOException { + RequestBody requestBody = new CommonUpdateDataToRequestBodyAdapter(param.getData()); + RequestBody body = new MultipartBody.Builder() + .setType(MediaType.get("multipart/form-data")) + .addFormDataPart(param.getName(), param.getData().getFileName(), requestBody) + .build(); + Request request = new Request.Builder().url(uri).post(body).build(); + + try (Response response = requestHttp.getRequestHttpClient().newCall(request).execute()) { + ResponseBody responseBody = response.body(); + String responseContent = responseBody == null ? "" : responseBody.string(); + if (responseContent.isEmpty()) { + throw new WxErrorException(String.format("上传失败,服务器响应空 url:%s param:%s", uri, param)); + } + WxError error = WxError.fromJson(responseContent, wxType); + if (error.getErrorCode() != 0) { + throw new WxErrorException(error); + } + return responseContent; + } + } + + /** + * 通用上传输入 到 OkHttp 请求提 适配器 + */ + @AllArgsConstructor + public static class CommonUpdateDataToRequestBodyAdapter extends RequestBody { + + private static final MediaType CONTENT_TYPE = MediaType.get("application/octet-stream"); + + private CommonUploadData data; + + @Override + public long contentLength() { + return data.getLength(); + } + + @Nullable + @Override + public MediaType contentType() { + return CONTENT_TYPE; + } + + @Override + public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException { + InputStream inputStream = data.getInputStream(); + int count; + byte[] buffer = new byte[4096]; + while ((count = inputStream.read(buffer)) != -1) { + bufferedSink.write(buffer, 0, count); + } + inputStream.close(); + } + + @Override + public boolean isOneShot() { + return true; + } + } +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxService.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxService.java index 497c1c054..f894cba44 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxService.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxService.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.common.service; import com.google.gson.JsonObject; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.ToJson; import me.chanjar.weixin.common.error.WxErrorException; @@ -60,4 +61,14 @@ public interface WxService { * @throws WxErrorException 异常 */ String post(String url, ToJson obj) throws WxErrorException; + + /** + * 当本Service没有实现某个上传API的时候,可以用这个,针对所有微信API中的POST文件上传请求 + * + * @param url 请求接口地址 + * @param param 文件上传对象 + * @return 接口响应字符串 + * @throws WxErrorException 异常 + */ + String upload(String url, CommonUploadParam param) throws WxErrorException; } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java index 14724412f..83d0c099b 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/MediaUploadRequestExecutor.java @@ -1,21 +1,27 @@ package me.chanjar.weixin.common.util.http; -import java.io.File; -import java.io.IOException; - -import me.chanjar.weixin.common.enums.WxType; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.service.WxService; import me.chanjar.weixin.common.util.http.apache.ApacheMediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.jodd.JoddHttpMediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.okhttp.OkHttpMediaUploadRequestExecutor; +import java.io.File; +import java.io.IOException; + /** * 上传媒体文件请求执行器. * 请求的参数是File, 返回的结果是String * * @author Daniel Qian + * @see WxService#upload(String, CommonUploadParam) 通用的上传,封装接口是推荐调用此方法 + * @see CommonUploadParam 通用的上传参数 + * @deprecated 不应该继续使用执行器的方式上传文件,封装上传接口时应调用通用的文件上传,而旧代码也应该逐步迁移为新的上传方式 */ +@Deprecated public abstract class MediaUploadRequestExecutor<H, P> implements RequestExecutor<WxMediaUploadResult, File> { protected RequestHttp<H, P> requestHttp; 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 0d4314548..a66b059c5 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 @@ -5,12 +5,14 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.ToJson; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.executor.CommonUploadRequestExecutor; import me.chanjar.weixin.common.session.StandardSessionManager; import me.chanjar.weixin.common.session.WxSession; import me.chanjar.weixin.common.session.WxSessionManager; @@ -24,8 +26,6 @@ import me.chanjar.weixin.cp.bean.WxCpAgentJsapiSignature; import me.chanjar.weixin.cp.bean.WxCpMaJsCode2SessionResult; import me.chanjar.weixin.cp.bean.WxCpProviderToken; import me.chanjar.weixin.cp.config.WxCpConfigStorage; -import me.chanjar.weixin.cp.corpgroup.service.WxCpLinkedCorpService; -import me.chanjar.weixin.cp.corpgroup.service.impl.WxCpLinkedCorpServiceImpl; import org.apache.commons.lang3.StringUtils; import java.io.File; @@ -268,6 +268,12 @@ public abstract class BaseWxCpServiceImpl<H, P> implements WxCpService, RequestH return this.post(url, obj.toJson()); } + @Override + public String upload(String url, CommonUploadParam param) throws WxErrorException { + RequestExecutor<String, CommonUploadParam> executor = CommonUploadRequestExecutor.create(getRequestHttp()); + return this.execute(executor, url, param); + } + @Override public String post(String url, Object obj) throws WxErrorException { return this.post(url, obj.toString()); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java index 37a25db14..7f2bf53ff 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/BaseWxMaServiceImpl.java @@ -12,12 +12,14 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.ToJson; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.executor.CommonUploadRequestExecutor; import me.chanjar.weixin.common.service.WxImgProcService; import me.chanjar.weixin.common.service.WxOcrService; import me.chanjar.weixin.common.util.DataUtils; @@ -237,6 +239,12 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH return this.post(url, obj.toJson()); } + @Override + public String upload(String url, CommonUploadParam param) throws WxErrorException { + RequestExecutor<String, CommonUploadParam> executor = CommonUploadRequestExecutor.create(getRequestHttp()); + return this.execute(executor, url, param); + } + @Override public String post(String url, JsonObject jsonObject) throws WxErrorException { return this.post(url, jsonObject.toString()); @@ -378,7 +386,7 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH @JsonDeserialize public void setMultiConfigs(Map<String, WxMaConfig> configs, String defaultMiniappId) { // 防止覆盖配置 - if(this.configMap != null) { + if (this.configMap != null) { this.configMap.putAll(configs); } else { this.configMap = Maps.newHashMap(configs); @@ -689,7 +697,7 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH } @Override - public WxMaExpressDeliveryReturnService getWxMaExpressDeliveryReturnService(){ + public WxMaExpressDeliveryReturnService getWxMaExpressDeliveryReturnService() { return this.wxMaExpressDeliveryReturnService; } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java index d362d0183..0310cd099 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaMediaServiceImpl.java @@ -3,12 +3,12 @@ package cn.binarywang.wx.miniapp.api.impl; import cn.binarywang.wx.miniapp.api.WxMaMediaService; import cn.binarywang.wx.miniapp.api.WxMaService; import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.error.WxError; 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.common.util.http.RequestExecutor; import java.io.File; @@ -38,8 +38,10 @@ public class WxMaMediaServiceImpl implements WxMaMediaService { @Override public WxMediaUploadResult uploadMedia(String mediaType, File file) throws WxErrorException { +// return this.wxMaService.execute(MediaUploadRequestExecutor.create(this.wxMaService.getRequestHttp()), url, file); String url = String.format(MEDIA_UPLOAD_URL, mediaType); - return this.wxMaService.execute(MediaUploadRequestExecutor.create(this.wxMaService.getRequestHttp()), url, file); + String result = wxMaService.upload(url, CommonUploadParam.fromFile("media", file)); + return WxMediaUploadResult.fromJson(result); } @Override diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheAuditMediaUploadRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheAuditMediaUploadRequestExecutor.java deleted file mode 100644 index 782dc46f2..000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/ApacheAuditMediaUploadRequestExecutor.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.binarywang.wx.miniapp.executor; - -import java.io.File; -import java.io.IOException; - -import me.chanjar.weixin.common.enums.WxType; -import me.chanjar.weixin.common.error.WxError; -import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestHttp; - -import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler; -import cn.binarywang.wx.miniapp.bean.WxMaAuditMediaUploadResult; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; - -/** - * @author yangyh22 - * @since 2020/11/14 - */ -public class ApacheAuditMediaUploadRequestExecutor extends AuditMediaUploadRequestExecutor<CloseableHttpClient, HttpHost> { - - public ApacheAuditMediaUploadRequestExecutor(RequestHttp requestHttp) { - super(requestHttp); - } - - @Override - public WxMaAuditMediaUploadResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException { - HttpPost httpPost = new HttpPost(uri); - if (requestHttp.getRequestHttpProxy() != null) { - RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build(); - httpPost.setConfig(config); - } - if (file != null) { - HttpEntity entity = MultipartEntityBuilder - .create() - .addBinaryBody("media", file) - .setMode(HttpMultipartMode.RFC6532) - .build(); - httpPost.setEntity(entity); - } - try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpPost)) { - String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); - WxError error = WxError.fromJson(responseContent, wxType); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMaAuditMediaUploadResult.fromJson(responseContent); - } finally { - httpPost.releaseConnection(); - } - } -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/AuditMediaUploadRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/AuditMediaUploadRequestExecutor.java deleted file mode 100644 index 6aad5cfdc..000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/AuditMediaUploadRequestExecutor.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.binarywang.wx.miniapp.executor; - -import java.io.File; -import java.io.IOException; - -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.RequestHttp; -import me.chanjar.weixin.common.util.http.ResponseHandler; -import me.chanjar.weixin.common.enums.WxType; -import me.chanjar.weixin.common.error.WxErrorException; -import cn.binarywang.wx.miniapp.bean.WxMaAuditMediaUploadResult; - -/** - * 小程序 提审素材上传接口 - * 上传媒体文件请求执行器. - * 请求的参数是File, 返回的结果是String - * - * @author yangyh22 - * @since 2020/11/14 - */ -public abstract class AuditMediaUploadRequestExecutor<H, P> implements RequestExecutor<WxMaAuditMediaUploadResult, File> { - - protected RequestHttp<H, P> requestHttp; - - public AuditMediaUploadRequestExecutor(RequestHttp requestHttp) { - this.requestHttp = requestHttp; - } - - @Override - public void execute(String uri, File data, ResponseHandler<WxMaAuditMediaUploadResult> handler, WxType wxType) throws WxErrorException, IOException { - handler.handle(this.execute(uri, data, wxType)); - } - - public static RequestExecutor<WxMaAuditMediaUploadResult, File> create(RequestHttp requestHttp) { - switch (requestHttp.getRequestType()) { - case APACHE_HTTP: - return new ApacheAuditMediaUploadRequestExecutor(requestHttp); - case JODD_HTTP: - return new JoddHttpAuditMediaUploadRequestExecutor(requestHttp); - case OK_HTTP: - return new OkHttpAuditMediaUploadRequestExecutor(requestHttp); - default: - return null; - } - } - -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/JoddHttpAuditMediaUploadRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/JoddHttpAuditMediaUploadRequestExecutor.java deleted file mode 100644 index cce799098..000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/JoddHttpAuditMediaUploadRequestExecutor.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.binarywang.wx.miniapp.executor; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import jodd.http.HttpConnectionProvider; -import jodd.http.HttpRequest; -import jodd.http.HttpResponse; -import jodd.http.ProxyInfo; -import me.chanjar.weixin.common.enums.WxType; -import me.chanjar.weixin.common.error.WxError; -import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestHttp; -import cn.binarywang.wx.miniapp.bean.WxMaAuditMediaUploadResult; - -/** - * @author yangyh22 - * @since 2020/11/14 - */ -public class JoddHttpAuditMediaUploadRequestExecutor extends AuditMediaUploadRequestExecutor<HttpConnectionProvider, ProxyInfo> { - - public JoddHttpAuditMediaUploadRequestExecutor(RequestHttp requestHttp) { - super(requestHttp); - } - - @Override - public WxMaAuditMediaUploadResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException { - HttpRequest request = HttpRequest.post(uri); - if (requestHttp.getRequestHttpProxy() != null) { - requestHttp.getRequestHttpClient().useProxy(requestHttp.getRequestHttpProxy()); - } - request.withConnectionProvider(requestHttp.getRequestHttpClient()); - request.form("media", file); - HttpResponse response = request.send(); - response.charset(StandardCharsets.UTF_8.name()); - - String responseContent = response.bodyText(); - WxError error = WxError.fromJson(responseContent, wxType); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMaAuditMediaUploadResult.fromJson(responseContent); - } -} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/OkHttpAuditMediaUploadRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/OkHttpAuditMediaUploadRequestExecutor.java deleted file mode 100644 index 808f16d83..000000000 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/executor/OkHttpAuditMediaUploadRequestExecutor.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.binarywang.wx.miniapp.executor; - -import java.io.File; -import java.io.IOException; - -import me.chanjar.weixin.common.enums.WxType; -import me.chanjar.weixin.common.error.WxError; -import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestHttp; -import cn.binarywang.wx.miniapp.bean.WxMaAuditMediaUploadResult; -import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; -import okhttp3.MediaType; -import okhttp3.MultipartBody; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -/** - * @author yangyh22 - * @since 2020/11/14 - */ -public class OkHttpAuditMediaUploadRequestExecutor extends AuditMediaUploadRequestExecutor<OkHttpClient, OkHttpProxyInfo> { - - public OkHttpAuditMediaUploadRequestExecutor(RequestHttp requestHttp) { - super(requestHttp); - } - - @Override - public WxMaAuditMediaUploadResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException { - - RequestBody body = new MultipartBody.Builder() - .setType(MediaType.parse("multipart/form-data")) - .addFormDataPart("media", - file.getName(), - RequestBody.create(MediaType.parse("application/octet-stream"), file)) - .build(); - Request request = new Request.Builder().url(uri).post(body).build(); - - Response response = requestHttp.getRequestHttpClient().newCall(request).execute(); - String responseContent = response.body().string(); - WxError error = WxError.fromJson(responseContent, wxType); - if (error.getErrorCode() != 0) { - throw new WxErrorException(error); - } - return WxMaAuditMediaUploadResult.fromJson(responseContent); - } - -} diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveGoodsServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveGoodsServiceImplTest.java index 5ea3b11ea..1cbdd6974 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveGoodsServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaLiveGoodsServiceImplTest.java @@ -30,7 +30,8 @@ public class WxMaLiveGoodsServiceImplTest { @Test public void addGoods() throws Exception { //上传临时素材 - WxMediaUploadResult mediaUpload = this.wxService.getMediaService().uploadMedia("image", new File("E:\\1.png")); + WxMediaUploadResult mediaUpload = this.wxService.getMediaService() + .uploadMedia("image", new File("./static/temp.jpg")); WxMaLiveGoodInfo goods = new WxMaLiveGoodInfo(); goods.setCoverImgUrl(mediaUpload.getMediaId()); diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImplTest.java index b31dea2dd..afb7f7212 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImplTest.java @@ -5,6 +5,8 @@ import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; import cn.binarywang.wx.miniapp.test.ApiTestModule; import com.google.inject.Inject; +import lombok.SneakyThrows; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.bean.WxAccessTokenEntity; import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; @@ -16,6 +18,7 @@ import org.testng.Assert; import org.testng.annotations.Guice; import org.testng.annotations.Test; +import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -184,6 +187,14 @@ public class WxMaServiceImplTest { } } + @SneakyThrows + @Test + public void upload() { + CommonUploadParam param = CommonUploadParam.fromFile("media", new File("./static/1.jpg")); + String result = wxService.upload("https://api.weixin.qq.com/wxa/sec/uploadauthmaterial", param); + System.out.println(result); + } + @Test public void testGetWxMaConfig() { } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java index d7c0f53ab..901a6637b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java @@ -8,15 +8,13 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; -import me.chanjar.weixin.common.bean.ToJson; -import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.WxNetCheckResult; +import me.chanjar.weixin.common.bean.*; import me.chanjar.weixin.common.enums.TicketType; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.executor.CommonUploadRequestExecutor; import me.chanjar.weixin.common.service.WxImgProcService; import me.chanjar.weixin.common.service.WxOAuth2Service; import me.chanjar.weixin.common.service.WxOcrService; @@ -401,6 +399,12 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH return this.post(url, obj.toJson()); } + @Override + public String upload(String url, CommonUploadParam param) throws WxErrorException { + RequestExecutor<String, CommonUploadParam> executor = CommonUploadRequestExecutor.create(getRequestHttp()); + return this.execute(executor, url, param); + } + @Override public String post(String url, JsonObject jsonObject) throws WxErrorException { return this.post(url, jsonObject.toString()); @@ -543,7 +547,7 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH @Override public void setMultiConfigStorages(Map<String, WxMpConfigStorage> configStorages, String defaultMpId) { // 防止覆盖配置 - if(this.configStorageMap != null) { + if (this.configStorageMap != null) { this.configStorageMap.putAll(configStorages); } else { this.configStorageMap = Maps.newHashMap(configStorages); diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthService.java new file mode 100644 index 000000000..c59929d81 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthService.java @@ -0,0 +1,82 @@ +package me.chanjar.weixin.open.api; + +import me.chanjar.weixin.common.bean.CommonUploadData; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.open.bean.auth.*; + +/** + * 微信第三方平台 小程序认证接口 (年审) + * https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/product/weapp_wxverify.html + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +public interface WxOpenMaAuthService { + + /** + * 1 小程程序认证 + */ + String OPEN_MA_AUTH_SUBMIT = "https://api.weixin.qq.com/wxa/sec/wxaauth"; + + /** + * 2 小程程序认证任务进度查询. + */ + String OPEN_MA_AUTH_QUERY = "https://api.weixin.qq.com/wxa/sec/queryauth"; + + /** + * 3 小程序认证上传补充材料. + */ + String OPEN_MA_AUTH_UPLOAD = "https://api.weixin.qq.com/wxa/sec/uploadauthmaterial"; + + /** + * 4 小程序认证重新提审. + */ + String OPEN_MA_AUTH_RESUBMIT = "https://api.weixin.qq.com/wxa/sec/reauth"; + + /** + * 5 查询个人认证身份选项列表. + */ + String OPEN_MA_AUTH_IDENTITY = "https://api.weixin.qq.com/wxa/sec/authidentitytree"; + + + /** + * 小程序认证(提审) + * + * @param param 参数 + * @return 提交结果,须保存任务ID 和 授权链接 + */ + MaAuthSubmitResult submit(MaAuthSubmitParam param) throws WxErrorException; + + + /** + * 进度查询 + * + * @param taskId 任务ID,提交任务时返回 + */ + MaAuthQueryResult query(String taskId) throws WxErrorException; + + + /** + * 上传补充材料 + * + * @param data 上传数据,仅支持png\jpeg\jpg\gif格式,文件后缀名如果填写不对会导致上传失败,建议写死1.jpg + */ + MaAuthUploadResult upload(CommonUploadData data) throws WxErrorException; + + + /** + * 重新提审 + * + * @param param 参数 + * @return 提交结果 + */ + MaAuthSubmitResult resubmit(MaAuthResubmitParam param) throws WxErrorException; + + + /** + * 查询个人认证身份选项列表 + * + * @return 职业身份认证树 + */ + MaAuthQueryIdentityTreeResult queryIdentityTree() throws WxErrorException; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java index b54df7841..deb6098c3 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaService.java @@ -702,6 +702,13 @@ public interface WxOpenMaService extends WxMaService { */ WxOpenMaBasicService getBasicService(); + /** + * 小程序认证(年审)服务 + * + * @return 小程序认证(年审)服务 + */ + WxOpenMaAuthService getAuthService(); + /** * 小程序用户隐私保护指引服务 * @@ -719,7 +726,7 @@ public interface WxOpenMaService extends WxMaService { /** * 小程序审核 提审素材上传接口 * - * @return + * @return 结果 */ WxMaAuditMediaUploadResult uploadMedia(File file) throws WxErrorException; diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthServiceImpl.java new file mode 100644 index 000000000..eae12acae --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthServiceImpl.java @@ -0,0 +1,56 @@ +package me.chanjar.weixin.open.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import kotlin.Pair; +import kotlin.collections.MapsKt; +import me.chanjar.weixin.common.bean.CommonUploadData; +import me.chanjar.weixin.common.bean.CommonUploadParam; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.open.api.WxOpenMaAuthService; +import me.chanjar.weixin.open.bean.auth.*; + +/** + * 微信第三方平台 小程序认证接口 (年审) + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * Created on 2024/01/11 + */ +public class WxOpenMaAuthServiceImpl implements WxOpenMaAuthService { + + private final WxMaService wxMaService; + + public WxOpenMaAuthServiceImpl(WxMaService wxMaService) { + this.wxMaService = wxMaService; + } + + @Override + public MaAuthSubmitResult submit(MaAuthSubmitParam param) throws WxErrorException { + String response = wxMaService.post(OPEN_MA_AUTH_SUBMIT, param); + return WxMaGsonBuilder.create().fromJson(response, MaAuthSubmitResult.class); + } + + @Override + public MaAuthQueryResult query(String taskId) throws WxErrorException { + String response = wxMaService.post(OPEN_MA_AUTH_QUERY, MapsKt.mapOf(new Pair<>("taskid", taskId))); + return WxMaGsonBuilder.create().fromJson(response, MaAuthQueryResult.class); + } + + @Override + public MaAuthUploadResult upload(CommonUploadData data) throws WxErrorException { + String response = wxMaService.upload(OPEN_MA_AUTH_UPLOAD, new CommonUploadParam("media", data)); + return WxMaGsonBuilder.create().fromJson(response, MaAuthUploadResult.class); + } + + @Override + public MaAuthSubmitResult resubmit(MaAuthResubmitParam param) throws WxErrorException { + String response = wxMaService.post(OPEN_MA_AUTH_RESUBMIT, param); + return WxMaGsonBuilder.create().fromJson(response, MaAuthSubmitResult.class); + } + + @Override + public MaAuthQueryIdentityTreeResult queryIdentityTree() throws WxErrorException { + String response = wxMaService.get(OPEN_MA_AUTH_IDENTITY, null); + return WxMaGsonBuilder.create().fromJson(response, MaAuthQueryIdentityTreeResult.class); + } +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java index 5cc8e677a..c56264028 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaServiceImpl.java @@ -14,6 +14,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; +import me.chanjar.weixin.common.bean.CommonUploadParam; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.open.api.*; import me.chanjar.weixin.open.bean.ma.WxMaPrefetchDomain; @@ -47,6 +48,8 @@ public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaServ @Getter private final WxOpenMaBasicService basicService; @Getter + private final WxOpenMaAuthService authService; + @Getter private final WxOpenMaPrivacyService privacyService; @Getter private final WxOpenMaShoppingOrdersService shoppingOrdersService; @@ -56,6 +59,7 @@ public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaServ this.appId = appId; this.wxMaConfig = wxMaConfig; this.basicService = new WxOpenMaBasicServiceImpl(this); + this.authService = new WxOpenMaAuthServiceImpl(this); this.privacyService = new WxOpenMaPrivacyServiceImpl(this); this.shoppingOrdersService = new WxOpenMaShoppingOrdersServiceImpl(this); initHttp(); @@ -429,7 +433,9 @@ public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaServ @Override public WxMaAuditMediaUploadResult uploadMedia(File file) throws WxErrorException { - return (WxMaAuditMediaUploadResult) this.execute(AuditMediaUploadRequestExecutor.create(getRequestHttp()), API_AUDIT_UPLOAD_MEDIA, file); + CommonUploadParam param = CommonUploadParam.fromFile("media", file); + String result = upload(API_AUDIT_UPLOAD_MEDIA, param); + return WxMaAuditMediaUploadResult.fromJson(result); } private JsonArray toJsonArray(List<String> strList) { diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResult.java new file mode 100644 index 000000000..c3960a2b5 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResult.java @@ -0,0 +1,29 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.chanjar.weixin.open.bean.result.WxOpenResult; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * 小程序认证 查询个人认证身份选项列表 响应 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Getter +@Setter +@NoArgsConstructor +public class MaAuthQueryIdentityTreeResult extends WxOpenResult { + + /** + * 子节点信息 非叶子节点必有 + */ + @Nullable + @SerializedName("node_list") + private List<MaAuthQueryIdentityTreeResultIdentityNode> nodeList; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityLeaf.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityLeaf.java new file mode 100644 index 000000000..48a247827 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityLeaf.java @@ -0,0 +1,20 @@ +package me.chanjar.weixin.open.bean.auth; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 职业身份叶子信息 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthQueryIdentityTreeResultIdentityLeaf { + + /** + * 要求说明 + */ + private String requirement; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityNode.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityNode.java new file mode 100644 index 000000000..ed4298aa4 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryIdentityTreeResultIdentityNode.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * 职业身份 节点信息 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthQueryIdentityTreeResultIdentityNode { + + /** + * 职业身份名 + */ + @NotNull + private String name; + + /** + * 职业身份节点ID + */ + @NotNull + @SerializedName("node_id") + private Integer nodeId; + + /** + * 要求信息 叶子节点特有 + */ + @Nullable + @SerializedName("leaf_info") + private MaAuthQueryIdentityTreeResultIdentityLeaf leafInfo; + + /** + * 子节点信息 非叶子节点必有 + */ + @Nullable + @SerializedName("node_list") + private List<MaAuthQueryIdentityTreeResultIdentityNode> nodeList; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResult.java new file mode 100644 index 000000000..806490f72 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResult.java @@ -0,0 +1,64 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.open.bean.result.WxOpenResult; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 查询操作 响应 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Getter +@Setter +public class MaAuthQueryResult extends WxOpenResult { + + /** + * 小程序ID + */ + @NotNull + @SerializedName("appid") + private String appId; + + /** + * 状态 0初始 1超24小时 2用户拒绝 3用户同意 4发起人脸 5人脸失败 6人脸ok 7人脸认证后手机验证码 8手机验证失败 9手机验证成功 11创建审核单失败 12创建审核单成功 14验证失败 15等待支付 + */ + @NotNull + @SerializedName("task_status") + private Integer taskStatus; + + /** + * 授权链接 + */ + @NotNull + @SerializedName("auth_url") + private String authUrl; + + /** + * 审核单状态,创建审核单成功后有效 0审核单不存在 1待支付 2审核中 3打回重填 4认证通过 5认证最终失败(不能再修改) + */ + @SerializedName("apply_status") + private Integer applyStatus; + + /** + * 小程序后台展示的认证订单号 + */ + @SerializedName("orderid") + private String orderId; + + /** + * 当审核单被打回重填(apply_status=3)时有效 + */ + @SerializedName("refill_reason") + private String refillReason; + + /** + * 审核最终失败的原因(apply_status=5)时有效 + */ + @SerializedName("fail_reason") + private String failReason; + +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResultDispatchInfo.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResultDispatchInfo.java new file mode 100644 index 000000000..022e47cd2 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthQueryResultDispatchInfo.java @@ -0,0 +1,36 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 查询操作 响应数据 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthQueryResultDispatchInfo { + + /** + * 提供商,如:上海倍通企业信用征信有限公司 + */ + @NotNull + private String provider; + + /** + * 联系方式,如:咨询电话:0411-84947888,咨询时间:周一至周五(工作日)8:30-17:30 + */ + @NotNull + private String contact; + + /** + * 派遣时间戳(秒),如:1704952913 + */ + @NotNull + @SerializedName("dispatch_time") + private Integer dispatchTime; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParam.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParam.java new file mode 100644 index 000000000..5f28a2a68 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParam.java @@ -0,0 +1,22 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 重新提交操作 参数 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +public class MaAuthResubmitParam { + + /** + * 认证信息 + */ + @NotNull + @SerializedName("auth_data") + private MaAuthResubmitParamAuthData authData; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParamAuthData.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParamAuthData.java new file mode 100644 index 000000000..9073dfdfe --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthResubmitParamAuthData.java @@ -0,0 +1,24 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 重新提交操作 认证参数 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Getter +@Setter +public class MaAuthResubmitParamAuthData extends MaAuthSubmitParamAuthData { + + /** + * 认证任务id + */ + @NotNull + @SerializedName("taskid") + private String taskId; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParam.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParam.java new file mode 100644 index 000000000..fd1218525 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParam.java @@ -0,0 +1,27 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 提交操作 参数 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthSubmitParam { + + /** + * 认证信息 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ + @NotNull + @SerializedName("auth_data") + private MaAuthSubmitParamAuthData authData; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamAuthData.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamAuthData.java new file mode 100644 index 000000000..9063ca543 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamAuthData.java @@ -0,0 +1,110 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.lang.Nullable; + +import java.util.List; + +/** + * 小程序认证 提交操作 参数 数据 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthSubmitParamAuthData { + + /** + * 1企业 12个体户 15个人 参考:https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/basic-info-management/getAccountBasicInfo.html#realname-status-%E5%AE%9E%E5%90%8D%E8%AE%A4%E8%AF%81%E7%8A%B6%E6%80%81%E6%9E%9A%E4%B8%BE%E5%80%BC + */ + @NotNull + @SerializedName("customer_type") + private String customerType; + + /** + * 联系人信息 + */ + @NotNull + @SerializedName("contact_info") + private MaAuthSubmitParamContactInfo contactInfo; + + /** + * 发票信息,如果是服务商代缴模式,不需要改参数 + */ + @Nullable + @SerializedName("invoice_info") + private MaAuthSubmitParamInvoiceInfo invoiceInfo; + + /** + * 非个人类型必填。主体资质材料 media_id 支持jpg,jpeg .bmp.gif .png格式,仅支持一张图片 + */ + @Nullable + private String qualification; + + /** + * 主体资质其他证明材料 media_id 支持jpg,jpeg .bmp.gif .png格式,最多上传10张图片 + */ + @Nullable + @SerializedName("qualification_other") + private List<String> qualificationOther; + + /** + * 小程序账号名称 + */ + @NotNull + @SerializedName("account_name") + private String accountName; + + /** + * 小程序账号名称命名类型 1:基于自选词汇命名 2:基于商标命名 + */ + @NotNull + @SerializedName("account_name_type") + private Integer accountNameType; + + /** + * 名称命中关键词-补充材料 media_id 支持jpg,jpeg .bmp.gif .png格式,支持上传多张图片 + */ + @Nullable + @SerializedName("account_supplemental") + private List<String> accountSupplemental; + + /** + * 支付方式 1:消耗服务商预购包 2:小程序开发者自行支付 + */ + @NotNull + @SerializedName("pay_type") + private String payType; + + /** + * 认证类型为个人类型时可以选择要认证的身份,从/wxa/sec/authidentitytree 里获取,填叶节点的name + */ + @Nullable + @SerializedName("auth_identification") + private String authIdentification; + + /** + * 填了auth_identification则必填。身份证明材料 media_id (1)基于不同认证身份上传不同的材料;(2)认证类型=1时选填,支持上传10张图片(3)支持jpg,jpeg .bmp.gif .png格式 + */ + @Nullable + @SerializedName("auth_ident_material") + private String authIdentMaterial; + + /** + * 第三方联系电话 + */ + @NotNull + @SerializedName("third_party_phone") + private String thirdPartyPhone; + + /** + * 选择服务商代缴模式时必填。服务市场appid + */ + @Nullable + @SerializedName("service_appid") + private String serviceAppid; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamContactInfo.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamContactInfo.java new file mode 100644 index 000000000..02c162bb9 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamContactInfo.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.open.bean.auth; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; + +/** + * 联系人信息 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthSubmitParamContactInfo { + + /** + * 姓名 + */ + @NotNull + private String name; + + /** + * 邮箱 + */ + @NotNull + private String email; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceElectronic.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceElectronic.java new file mode 100644 index 000000000..825878fcd --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceElectronic.java @@ -0,0 +1,29 @@ +package me.chanjar.weixin.open.bean.auth; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.lang.Nullable; + +/** + * 发票 - 电子发票 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthSubmitParamInvoiceElectronic { + + /** + * 纳税识别号(15位、17、18或20位) + */ + @NotNull + private String id; + + /** + * 发票备注(选填) + */ + @Nullable + private String desc; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceInfo.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceInfo.java new file mode 100644 index 000000000..36020a8eb --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceInfo.java @@ -0,0 +1,44 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.lang.Nullable; + +/** + * 发票信息 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthSubmitParamInvoiceInfo { + + /** + * 发票类型 1: 不开发票 2: 电子发票 3: 增值税专票 + */ + @NotNull + @SerializedName("invoice_type") + private Integer invoiceType; + + /** + * 发票类型=2时必填 电子发票开票信息 + */ + @Nullable + private MaAuthSubmitParamInvoiceElectronic electronic; + + /** + * 发票类型=3时必填 增值税专票开票信息 + */ + @Nullable + private MaAuthSubmitParamInvoiceVat vat; + + /** + * 发票抬头,发票类型!=1时必填 需要和认证主体名称一样 + */ + @Nullable + @SerializedName("invoice_title") + private String invoiceTitle; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceVat.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceVat.java new file mode 100644 index 000000000..33bb8fb60 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitParamInvoiceVat.java @@ -0,0 +1,102 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.lang.Nullable; + +/** + * 发票 - 增值税专票 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Data +@NoArgsConstructor +public class MaAuthSubmitParamInvoiceVat { + + + /** + * 企业电话 + */ + @NotNull + @SerializedName("enterprise_phone") + private String enterprisePhone; + + /** + * 纳税识别号(15位、17、18或20位) + */ + @NotNull + private String id; + + /** + * 企业注册地址 + */ + @NotNull + @SerializedName("enterprise_address") + private String enterpriseAddress; + + /** + * 企业开户银行 + */ + @NotNull + @SerializedName("bank_name") + private String bankName; + + /** + * 企业银行账号 + */ + @NotNull + @SerializedName("bank_account") + private String bankAccount; + + /** + * 发票邮寄地址邮编 + */ + @NotNull + @SerializedName("mailing_address") + private String mailingAddress; + + /** + * 街道地址 + */ + @NotNull + private String address; + + /** + * 联系人 + */ + @NotNull + private String name; + + /** + * 联系电话 + */ + @NotNull + private String phone; + + /** + * 省份 + */ + @NotNull + private String province; + + /** + * 城市 + */ + @NotNull + private String city; + + /** + * 县区 + */ + @NotNull + private String district; + + /** + * 发票备注(选填) + */ + @Nullable + private String desc; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitResult.java new file mode 100644 index 000000000..ddc681ba5 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthSubmitResult.java @@ -0,0 +1,34 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.chanjar.weixin.open.bean.result.WxOpenResult; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 提交操作 响应 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Getter +@Setter +@NoArgsConstructor +public class MaAuthSubmitResult extends WxOpenResult { + + /** + * 任务ID + */ + @NotNull + @SerializedName("taskid") + private String taskId; + + /** + * 小程序管理员授权链接 + */ + @NotNull + @SerializedName("auth_url") + private String authUrl; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthUploadResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthUploadResult.java new file mode 100644 index 000000000..0e0c511a2 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/auth/MaAuthUploadResult.java @@ -0,0 +1,27 @@ +package me.chanjar.weixin.open.bean.auth; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.chanjar.weixin.open.bean.result.WxOpenResult; +import org.jetbrains.annotations.NotNull; + +/** + * 小程序认证 上传补充材料操作 响应 + * + * @author <a href="https://www.sacoc.cn">广州跨界</a> + * created on 2024/01/11 + */ +@Getter +@Setter +@NoArgsConstructor +public class MaAuthUploadResult extends WxOpenResult { + + /** + * 媒体ID + */ + @NotNull + @SerializedName("mediaid") + private String mediaId; +} diff --git a/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/BaseWxQidianServiceImpl.java b/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/BaseWxQidianServiceImpl.java index 0bc089608..2b7c7057a 100644 --- a/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/BaseWxQidianServiceImpl.java +++ b/weixin-java-qidian/src/main/java/me/chanjar/weixin/qidian/api/impl/BaseWxQidianServiceImpl.java @@ -1,44 +1,23 @@ package me.chanjar.weixin.qidian.api.impl; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.CLEAR_QUOTA_URL; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.GET_CALLBACK_IP_URL; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.GET_CURRENT_AUTOREPLY_INFO_URL; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.GET_TICKET_URL; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.NETCHECK_URL; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.QRCONNECT_URL; -import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.SHORTURL_API_URL; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.locks.Lock; - import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.gson.JsonArray; import com.google.gson.JsonObject; - -import org.apache.commons.lang3.StringUtils; - import lombok.Getter; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; -import me.chanjar.weixin.common.bean.ToJson; -import me.chanjar.weixin.common.bean.WxAccessToken; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.WxNetCheckResult; +import me.chanjar.weixin.common.bean.*; import me.chanjar.weixin.common.enums.TicketType; import me.chanjar.weixin.common.enums.WxType; import me.chanjar.weixin.common.error.WxError; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.executor.CommonUploadRequestExecutor; import me.chanjar.weixin.common.util.DataUtils; import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.common.util.http.RequestExecutor; -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.common.util.http.URIUtil; +import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.common.util.json.GsonParser; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.qidian.api.WxQidianCallDataService; @@ -47,6 +26,13 @@ import me.chanjar.weixin.qidian.api.WxQidianService; import me.chanjar.weixin.qidian.config.WxQidianConfigStorage; import me.chanjar.weixin.qidian.enums.WxQidianApiUrl; import me.chanjar.weixin.qidian.util.WxQidianConfigStorageHolder; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.locks.Lock; + +import static me.chanjar.weixin.qidian.enums.WxQidianApiUrl.Other.*; /** * 基础实现类. @@ -56,9 +42,9 @@ import me.chanjar.weixin.qidian.util.WxQidianConfigStorageHolder; @Slf4j public abstract class BaseWxQidianServiceImpl<H, P> implements WxQidianService, RequestHttp<H, P> { @Getter - private WxQidianDialService dialService = new WxQidianDialServiceImpl(this); + private final WxQidianDialService dialService = new WxQidianDialServiceImpl(this); @Getter - private WxQidianCallDataService callDataService = new WxQidianCallDataServiceImpl(this); + private final WxQidianCallDataService callDataService = new WxQidianCallDataServiceImpl(this); private Map<String, WxQidianConfigStorage> configStorageMap; @@ -93,7 +79,7 @@ public abstract class BaseWxQidianServiceImpl<H, P> implements WxQidianService, try { if (this.getWxMpConfigStorage().isTicketExpired(type)) { String responseContent = execute(SimpleGetRequestExecutor.create(this), - GET_TICKET_URL.getUrl(this.getWxMpConfigStorage()) + type.getCode(), null); + GET_TICKET_URL.getUrl(this.getWxMpConfigStorage()) + type.getCode(), null); JsonObject tmpJsonObject = GsonParser.parse(responseContent); String jsapiTicket = tmpJsonObject.get("ticket").getAsString(); int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt(); @@ -123,7 +109,7 @@ public abstract class BaseWxQidianServiceImpl<H, P> implements WxQidianService, String randomStr = RandomUtils.getRandomStr(); String jsapiTicket = getJsapiTicket(false); String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket, "noncestr=" + randomStr, - "timestamp=" + timestamp, "url=" + url); + "timestamp=" + timestamp, "url=" + url); WxJsapiSignature jsapiSignature = new WxJsapiSignature(); jsapiSignature.setAppId(this.getWxMpConfigStorage().getAppId()); jsapiSignature.setTimestamp(timestamp); @@ -154,7 +140,7 @@ public abstract class BaseWxQidianServiceImpl<H, P> implements WxQidianService, @Override public String buildQrConnectUrl(String redirectUri, String scope, String state) { return String.format(QRCONNECT_URL.getUrl(this.getWxMpConfigStorage()), this.getWxMpConfigStorage().getAppId(), - URIUtil.encodeURIComponent(redirectUri), scope, StringUtils.trimToEmpty(state)); + URIUtil.encodeURIComponent(redirectUri), scope, StringUtils.trimToEmpty(state)); } @Override @@ -215,6 +201,12 @@ public abstract class BaseWxQidianServiceImpl<H, P> implements WxQidianService, return this.post(url, obj.toJson()); } + @Override + public String upload(String url, CommonUploadParam param) throws WxErrorException { + RequestExecutor<String, CommonUploadParam> executor = CommonUploadRequestExecutor.create(getRequestHttp()); + return this.execute(executor, url, param); + } + @Override public String post(String url, JsonObject jsonObject) throws WxErrorException { return this.post(url, jsonObject.toString());