diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/storage/AbstractWxMaConfigStorageConfiguration.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/storage/AbstractWxMaConfigStorageConfiguration.java index 6f44ac27ee835f3bcb963c677655cc616e8f4f08..bb01022538771fd43158bc98f36eee8fcc2e186c 100644 --- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/storage/AbstractWxMaConfigStorageConfiguration.java +++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/config/storage/AbstractWxMaConfigStorageConfiguration.java @@ -2,6 +2,8 @@ package com.binarywang.spring.starter.wxjava.miniapp.config.storage; import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import org.apache.commons.lang3.StringUtils; /** @@ -10,6 +12,7 @@ import org.apache.commons.lang3.StringUtils; public abstract class AbstractWxMaConfigStorageConfiguration { protected WxMaDefaultConfigImpl config(WxMaDefaultConfigImpl config, WxMaProperties properties) { + WxMaProperties.ConfigStorage storage = properties.getConfigStorage(); config.setAppid(StringUtils.trimToNull(properties.getAppid())); config.setSecret(StringUtils.trimToNull(properties.getSecret())); config.setToken(StringUtils.trimToNull(properties.getToken())); @@ -24,6 +27,19 @@ public abstract class AbstractWxMaConfigStorageConfiguration { config.setHttpProxyPort(configStorageProperties.getHttpProxyPort()); } + // 设置自定义的HttpClient超时配置 + ApacheHttpClientBuilder clientBuilder = config.getApacheHttpClientBuilder(); + if (clientBuilder == null) { + clientBuilder = DefaultApacheHttpClientBuilder.get(); + } + if (clientBuilder instanceof DefaultApacheHttpClientBuilder) { + DefaultApacheHttpClientBuilder defaultBuilder = (DefaultApacheHttpClientBuilder) clientBuilder; + defaultBuilder.setConnectionTimeout(storage.getConnectionTimeout()); + defaultBuilder.setSoTimeout(storage.getSoTimeout()); + defaultBuilder.setConnectionRequestTimeout(storage.getConnectionRequestTimeout()); + config.setApacheHttpClientBuilder(defaultBuilder); + } + int maxRetryTimes = configStorageProperties.getMaxRetryTimes(); if (configStorageProperties.getMaxRetryTimes() < 0) { maxRetryTimes = 0; diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java index b7ccb45374281e2af8956318e46dc4efa344e6a2..39fc9b29a81bdd689c7fc6c032324fe8a2cb56e6 100644 --- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java +++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/miniapp/properties/WxMaProperties.java @@ -107,6 +107,21 @@ public class WxMaProperties { * */ private int maxRetryTimes = 5; + + /** + * 连接超时时间,单位毫秒 + */ + private int connectionTimeout = 5000; + + /** + * 读数据超时时间,即socketTimeout,单位毫秒 + */ + private int soTimeout = 5000; + + /** + * 从连接池获取链接的超时时间,单位毫秒 + */ + private int connectionRequestTimeout = 5000; } } diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java index deb527e69f5a3fdceb8eb67d67eac9958bbdd7a8..4c0938454abe637fd4cbbcd765710c348da92539 100644 --- a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java +++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/config/WxMpStorageAutoConfiguration.java @@ -9,6 +9,8 @@ import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.redis.JedisWxRedisOps; import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; import me.chanjar.weixin.common.redis.WxRedisOps; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import me.chanjar.weixin.mp.config.WxMpConfigStorage; import me.chanjar.weixin.mp.config.WxMpHostConfig; import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; @@ -122,6 +124,19 @@ public class WxMpStorageAutoConfiguration { config.setSecret(properties.getSecret()); config.setToken(properties.getToken()); config.setAesKey(properties.getAesKey()); + WxMpProperties.ConfigStorage storage = properties.getConfigStorage(); + // 设置自定义的HttpClient超时配置 + ApacheHttpClientBuilder clientBuilder = config.getApacheHttpClientBuilder(); + if (clientBuilder == null) { + clientBuilder = DefaultApacheHttpClientBuilder.get(); + } + if (clientBuilder instanceof DefaultApacheHttpClientBuilder) { + DefaultApacheHttpClientBuilder defaultBuilder = (DefaultApacheHttpClientBuilder) clientBuilder; + defaultBuilder.setConnectionTimeout(storage.getConnectionTimeout()); + defaultBuilder.setSoTimeout(storage.getSoTimeout()); + defaultBuilder.setConnectionRequestTimeout(storage.getConnectionRequestTimeout()); + config.setApacheHttpClientBuilder(defaultBuilder); + } config.setUseStableAccessToken(wxMpProperties.isUseStableAccessToken()); config.setHttpProxyHost(configStorageProperties.getHttpProxyHost()); config.setHttpProxyUsername(configStorageProperties.getHttpProxyUsername()); diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpProperties.java b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpProperties.java index a01fc0a5216c03440513ec0a92d3318b547804e2..ebd6f57720cec1df61e75c6b840b8e0d5884a1fa 100644 --- a/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpProperties.java +++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/mp/properties/WxMpProperties.java @@ -102,6 +102,21 @@ public class WxMpProperties { */ private String httpProxyPassword; + /** + * 连接超时时间,单位毫秒 + */ + private int connectionTimeout = 5000; + + /** + * 读数据超时时间,即socketTimeout,单位毫秒 + */ + private int soTimeout = 1; + + /** + * 从连接池获取链接的超时时间,单位毫秒 + */ + private int connectionRequestTimeout = 5000; + } } diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java index ee0443c9ae4a8e3e29d898609a56e6a97987e2b2..748ce80cd7ee92a093dff0ef2767df9cf26a60fe 100644 --- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java +++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/config/storage/AbstractWxOpenConfigStorageConfiguration.java @@ -1,6 +1,8 @@ package com.binarywang.spring.starter.wxjava.open.config.storage; import com.binarywang.spring.starter.wxjava.open.properties.WxOpenProperties; +import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder; import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage; /** @@ -28,6 +30,20 @@ public abstract class AbstractWxOpenConfigStorageConfiguration { } config.setRetrySleepMillis(retrySleepMillis); config.setMaxRetryTimes(maxRetryTimes); + + // 设置自定义的HttpClient超时配置 + ApacheHttpClientBuilder clientBuilder = config.getApacheHttpClientBuilder(); + if (clientBuilder == null) { + clientBuilder = DefaultApacheHttpClientBuilder.get(); + } + if (clientBuilder instanceof DefaultApacheHttpClientBuilder) { + DefaultApacheHttpClientBuilder defaultBuilder = (DefaultApacheHttpClientBuilder) clientBuilder; + defaultBuilder.setConnectionTimeout(storage.getConnectionTimeout()); + defaultBuilder.setSoTimeout(storage.getSoTimeout()); + defaultBuilder.setConnectionRequestTimeout(storage.getConnectionRequestTimeout()); + config.setApacheHttpClientBuilder(defaultBuilder); + } + return config; } } diff --git a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java index 641c57b005e11683694501cb7da125a13829c1e3..293d251397c16258d7bd6c94007982f0bede0a80 100644 --- a/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java +++ b/spring-boot-starters/wx-java-open-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenProperties.java @@ -108,6 +108,21 @@ public class WxOpenProperties { */ private int maxRetryTimes = 5; + /** + * 连接超时时间,单位毫秒 + */ + private int connectionTimeout = 5000; + + /** + * 读数据超时时间,即socketTimeout,单位毫秒 + */ + private int soTimeout = 1; + + /** + * 从连接池获取链接的超时时间,单位毫秒 + */ + private int connectionRequestTimeout = 5000; + } public enum StorageType { diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java index 7a004b845c5072ac6850ada26138e23f86193c43..d6543492c203e000eada4b9b2d1d5830cb251cd6 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java @@ -212,6 +212,51 @@ public class WxMaMessage implements Serializable { @XStreamAlias("SubscribeMsgSentEvent") private WxMaSubscribeMsgEvent.SubscribeMsgSentEvent subscribeMsgSentEvent; + // 小程序基本信息 + + //region 小程序基本信息 infoType=notify_3rd_wxa_auth_and_icp + + /** + * 返回值 + */ + @XStreamAlias("ret") + private String ret; + + /** + * 一级类目id + */ + @XStreamAlias("first") + private String first; + + /** + * 二级类目id + */ + @XStreamAlias("second") + private String second; + + /** + * 驳回原因 + */ + @XStreamAlias("reason") + private String reason; + + /** + * 小程序代码审核驳回原因 + */ + @XStreamAlias("Reason") + private String weAppReason; + + /** + * 昵称 + */ + @XStreamAlias("nickname") + private String nickname; + + /** + * 原始通知内容 + */ + private String context; + /** * 不要直接使用这个字段, * 这个字段只是为了适配 SubscribeMsgPopupEvent SubscribeMsgChangeEvent SubscribeMsgSentEvent @@ -261,7 +306,9 @@ public class WxMaMessage implements Serializable { WxMaConfig wxMaConfig, String timestamp, String nonce, String msgSignature) { String plainText = new WxMaCryptUtils(wxMaConfig).decryptXml(msgSignature, timestamp, nonce, encryptedXml); - return fromXml(plainText); + WxMaMessage wxMaMessage = fromXml(plainText); + wxMaMessage.setContext(plainText); + return wxMaMessage; } public static WxMaMessage fromEncryptedXml(InputStream is, WxMaConfig wxMaConfig, String timestamp, diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthAndIcpService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthAndIcpService.java new file mode 100644 index 0000000000000000000000000000000000000000..de2c0a0de2a06275d3cd17c898a66b208399d014 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaAuthAndIcpService.java @@ -0,0 +1,32 @@ +package me.chanjar.weixin.open.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.open.bean.authandicp.WxOpenQueryAuthAndIcpResult; +import me.chanjar.weixin.open.bean.authandicp.WxOpenSubmitAuthAndIcpParam; +import me.chanjar.weixin.open.bean.authandicp.WxOpenSubmitAuthAndIcpResult; + +/** + * 微信第三方平台 小程序认证及备案 + * @author 痴货 + * @createTime 2025/06/18 23:00 + */ +public interface WxOpenMaAuthAndIcpService { + + String QUERY_AUTH_AND_ICP = "https://api.weixin.qq.com/wxa/sec/query_auth_and_icp"; + + String SUBMIT_AUTH_AND_ICP = "https://api.weixin.qq.com/wxa/sec/submit_auth_and_icp"; + + /** + * 查询小程序认证及备案进度。 + * @param procedureId 小程序认证及备案任务流程id + * @return 小程序认证及备案进度 + */ + WxOpenQueryAuthAndIcpResult queryAuthAndIcp(String procedureId) throws WxErrorException; + + /** + * 提交小程序认证及备案信息。 + * @param param 提交小程序认证及备案信息参数 + * @return 提交结果 + */ + WxOpenSubmitAuthAndIcpResult submitAuthAndIcp(WxOpenSubmitAuthAndIcpParam param) throws WxErrorException; +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaBasicService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaBasicService.java index cae5faa78313935c9b680ae06bfbbf24b0559606..6ef8484bd0717eea4fdc95155e72286b53f9f447 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaBasicService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaBasicService.java @@ -54,19 +54,23 @@ public interface WxOpenMaBasicService { */ String OPEN_GET_ALL_CATEGORIES = "https://api.weixin.qq.com/cgi-bin/wxopen/getallcategories"; /** - * 8.2 添加类目 + * 8.2 获取不同类型主体可设置的类目 + */ + String OPEN_GET_ALL_CATEGORIES_BY_TYPE = "https://api.weixin.qq.com/cgi-bin/wxopen/getcategoriesbytype"; + /** + * 8.3 添加类目 */ String OPEN_ADD_CATEGORY = "https://api.weixin.qq.com/cgi-bin/wxopen/addcategory"; /** - * 8.3 删除类目 + * 8.4 删除类目 */ String OPEN_DELETE_CATEGORY = "https://api.weixin.qq.com/cgi-bin/wxopen/deletecategory"; /** - * 8.4 获取账号已经设置的所有类目 + * 8.5 获取账号已经设置的所有类目 */ String OPEN_GET_CATEGORY = "https://api.weixin.qq.com/cgi-bin/wxopen/getcategory"; /** - * 8.5 修改类目 + * 8.6 修改类目 */ String OPEN_MODIFY_CATEGORY = "https://api.weixin.qq.com/cgi-bin/wxopen/modifycategory"; @@ -168,7 +172,12 @@ public interface WxOpenMaBasicService { String getAllCategories() throws WxErrorException; /** - * 8.2添加类目 + * 8.2获取不同类型主体可设置的类目 + */ + WxOpenGetAllCategoriesByTypeResult getAllCategoriesByType(String verifyType) throws WxErrorException; + + /** + * 8.3添加类目 * * @param categoryList 类目列表 * @return . @@ -177,7 +186,7 @@ public interface WxOpenMaBasicService { WxOpenResult addCategory(List categoryList) throws WxErrorException; /** - * 8.3删除类目 + * 8.4删除类目 * * @param first 一级类目ID * @param second 二级类目ID @@ -187,7 +196,7 @@ public interface WxOpenMaBasicService { WxOpenResult deleteCategory(int first, int second) throws WxErrorException; /** - * 8.4获取账号已经设置的所有类目 + * 8.5获取账号已经设置的所有类目 * * @return . * @throws WxErrorException . @@ -195,7 +204,7 @@ public interface WxOpenMaBasicService { WxFastMaBeenSetCategoryResult getCategory() throws WxErrorException; /** - * 8.5修改类目 + * 8.6修改类目 * * @param category 实体 * @return . diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaIcpService.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaIcpService.java index ad59b246c7e77443342ccca2e49313214f97cb97..182e12c2b22899c8034800af79611db88d52ea6f 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaIcpService.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/WxOpenMaIcpService.java @@ -112,7 +112,7 @@ public interface WxOpenMaIcpService { * @return 人脸核验任务结果 * @throws WxErrorException e */ - WxOpenIcpCreateIcpVerifyTaskResult createIcpVerifyTask() throws WxErrorException; + WxOpenIcpCreateIcpVerifyTaskResult createIcpVerifyTask(WxOpenCreateIcpVerifyTaskParam param) 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 7a3bbca44a3dc1e628489e0797334fd278bea7c9..fef85d7f2ec2f9cf6e7c123e14b96f65c4938cbc 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 @@ -731,6 +731,13 @@ public interface WxOpenMaService extends WxMaService { */ WxOpenMaIcpService getIcpService(); + /** + * 小程序认证及备案服务 + * + * @return 小程序认证及备案服务 + */ + WxOpenMaAuthAndIcpService getAuthAndIcpService(); + /** * 小程序用户隐私保护指引服务 * diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthAndIcpServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthAndIcpServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..50e07d94d19ba5a1140b9b82b13e2292d89faa51 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaAuthAndIcpServiceImpl.java @@ -0,0 +1,40 @@ +package me.chanjar.weixin.open.api.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder; +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.open.api.WxOpenMaAuthAndIcpService; +import me.chanjar.weixin.open.bean.authandicp.WxOpenQueryAuthAndIcpResult; +import me.chanjar.weixin.open.bean.authandicp.WxOpenSubmitAuthAndIcpParam; +import me.chanjar.weixin.open.bean.authandicp.WxOpenSubmitAuthAndIcpResult; +import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; + +/** + * 微信第三方平台 小程序认证及备案 + * + * @author 痴货 + * @createTime 2025/06/18 23:00 + */ +public class WxOpenMaAuthAndIcpServiceImpl implements WxOpenMaAuthAndIcpService { + + private final WxMaService wxMaService; + + public WxOpenMaAuthAndIcpServiceImpl(WxMaService wxMaService) { + this.wxMaService = wxMaService; + } + + @Override + public WxOpenQueryAuthAndIcpResult queryAuthAndIcp(String procedureId) throws WxErrorException { + JsonObject params = new JsonObject(); + params.addProperty("procedure_id", procedureId); + String response = wxMaService.post(QUERY_AUTH_AND_ICP, params); + return WxOpenGsonBuilder.create().fromJson(response, WxOpenQueryAuthAndIcpResult.class); + } + + @Override + public WxOpenSubmitAuthAndIcpResult submitAuthAndIcp(WxOpenSubmitAuthAndIcpParam param) throws WxErrorException { + String response = wxMaService.post(SUBMIT_AUTH_AND_ICP, param); + return WxMaGsonBuilder.create().fromJson(response, WxOpenSubmitAuthAndIcpResult.class); + } +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaBasicServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaBasicServiceImpl.java index 943d61011325e615a0dd103003a23e1660602d91..26a03a0656fff3d2e419d702ed268a251b094556 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaBasicServiceImpl.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaBasicServiceImpl.java @@ -95,6 +95,14 @@ public class WxOpenMaBasicServiceImpl implements WxOpenMaBasicService { return wxMaService.get(OPEN_GET_ALL_CATEGORIES, ""); } + @Override + public WxOpenGetAllCategoriesByTypeResult getAllCategoriesByType(String verifyType) throws WxErrorException { + JsonObject params = new JsonObject(); + params.addProperty("verify_type", verifyType); + String response = wxMaService.post(OPEN_GET_ALL_CATEGORIES_BY_TYPE, params); + return WxOpenGsonBuilder.create().fromJson(response, WxOpenGetAllCategoriesByTypeResult.class); + } + @Override public WxOpenResult addCategory(List categoryList) throws WxErrorException { Map map = new HashMap<>(); diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaIcpServiceImpl.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaIcpServiceImpl.java index dc78f22fe39e4651fd324d0afd571d9f6afb7941..5999fee87d4bbbdeb5597fab8e264b96809f56c5 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaIcpServiceImpl.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/api/impl/WxOpenMaIcpServiceImpl.java @@ -53,8 +53,8 @@ public class WxOpenMaIcpServiceImpl implements WxOpenMaIcpService { * @throws WxErrorException e */ @Override - public WxOpenIcpCreateIcpVerifyTaskResult createIcpVerifyTask() throws WxErrorException { - String response = wxMaService.post(CREATE_ICP_VERIFY_TASK, ""); + public WxOpenIcpCreateIcpVerifyTaskResult createIcpVerifyTask(WxOpenCreateIcpVerifyTaskParam param) throws WxErrorException { + String response = wxMaService.post(CREATE_ICP_VERIFY_TASK, param); return WxMaGsonBuilder.create().fromJson(response, WxOpenIcpCreateIcpVerifyTaskResult.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 08bfc92bf7be285e34999b9ae80734d6cad3cd0e..3489060355fd1784a2599bd968cdfc3f18bbb631 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 @@ -56,6 +56,8 @@ public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaServ private final WxOpenMaShoppingOrdersService shoppingOrdersService; @Getter private final WxOpenMaEmbeddedService embeddedService; + @Getter + private final WxOpenMaAuthAndIcpService authAndIcpService; public WxOpenMaServiceImpl(WxOpenComponentService wxOpenComponentService, String appId, WxMaConfig wxMaConfig) { this.wxOpenComponentService = wxOpenComponentService; @@ -67,6 +69,7 @@ public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaServ this.privacyService = new WxOpenMaPrivacyServiceImpl(this); this.shoppingOrdersService = new WxOpenMaShoppingOrdersServiceImpl(this); this.embeddedService = new WxOpenMaEmbeddedServiceImpl(this); + this.authAndIcpService = new WxOpenMaAuthAndIcpServiceImpl(this); initHttp(); } 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 index c3960a2b5583fae417ff5b46566e7c67d7d26527..b7660d6da49fd91477f091047cbcaf79986a6f54 100644 --- 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 @@ -24,6 +24,6 @@ public class MaAuthQueryIdentityTreeResult extends WxOpenResult { * 子节点信息 非叶子节点必有 */ @Nullable - @SerializedName("node_list") + @SerializedName("identity_tree_list") private List nodeList; } diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenQueryAuthAndIcpResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenQueryAuthAndIcpResult.java new file mode 100644 index 0000000000000000000000000000000000000000..2c2e9e16b6e6606a8356c6b70e255a1f4bfe1dec --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenQueryAuthAndIcpResult.java @@ -0,0 +1,134 @@ +package me.chanjar.weixin.open.bean.authandicp; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import me.chanjar.weixin.open.bean.result.WxOpenResult; + +import java.io.Serializable; +import java.util.List; + +/** + * @author 痴货 + * @Description + * @createTime 2025/06/18 23:00 + */ +@Getter +@Setter +@NoArgsConstructor +public class WxOpenQueryAuthAndIcpResult extends WxOpenResult { + + private static final long serialVersionUID = -1175687030580654852L; + + /** + * 当前任务流程状态,见下方任务流程状态枚举 + * 9 手机验证成功 + * 15 等待支付认证审核费用 + * 16 认证审核费用支付成功 + * 17 认证审核中 + * 18 认证审核驳回 + * 19 认证审核通过 + * 20 认证审核最终失败(不能再修改) + * 21 创建备案审核单失败 + * 22 备案平台审核中 + * 23 备案平台审核驳回 + * 24 备案管局审核中 + * 25 管局审核驳回 + * 26 认证及备案完成 + * 27 流程已过期 + * 28 流程已终止 + * 29 备案已撤回 + */ + @SerializedName("procedure_status") + private Integer procedureStatus; + + /** + * 小程序后台展示的认证订单号 + */ + @SerializedName("orderid") + private Integer orderId; + + /** + * 小程序认证审核单被驳回(procedure_status 为 18)时有效 + */ + @SerializedName("refill_reason") + private String refillReason; + + /** + * 小程序认证审核最终失败的原因(procedure_status 为 20)时有效 + */ + @SerializedName("fail_reason") + private String failReason; + + /** + * 小程序备案相关信息 + */ + @SerializedName("icp_audit") + private IcpAudit icpAudit; + + @Getter + @Setter + @NoArgsConstructor + public static class IcpAudit implements Serializable { + + private static final long serialVersionUID = 879913578852421216L; + + /** + * 错误提示,创建备案审核单失败时返回(procedure_status 为 21) + */ + @SerializedName("hints") + private List hints; + + /** + * 驳回原因,备案不通过时返回(procedure_status 为 23、25) + */ + @SerializedName("audit_data") + private AuditData auditData; + + /** + * 管局短信核验状态,仅当任务流程状态为 24(备案管局审核中)的时候才有效。1:等待核验中,2:核验完成,3:核验超时。 + */ + @SerializedName("sms_verify_status") + private Integer smsVerifyStatus; + + } + + @Getter + @Setter + @NoArgsConstructor + public static class AuditData implements Serializable { + + private static final long serialVersionUID = 2217833539540191890L; + + /** + * 审核不通过的字段中文名 + */ + @SerializedName("key_name") + private String keyName; + + /** + * 字段不通过的原因 + */ + @SerializedName("error") + private String error; + + /** + * 修改建议 + */ + @SerializedName("suggest") + private String suggest; + } + + @Data + @EqualsAndHashCode(callSuper = true) + public static class Hint extends WxOpenResult { + + private static final long serialVersionUID = 6585787444231265854L; + + /** + * 校验失败的字段 + */ + @SerializedName("err_field") + private String errField; + } + +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenSubmitAuthAndIcpParam.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenSubmitAuthAndIcpParam.java new file mode 100644 index 0000000000000000000000000000000000000000..c3377c3a8b4c51d9c9344edfbaf18fd6833f092a --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenSubmitAuthAndIcpParam.java @@ -0,0 +1,767 @@ +package me.chanjar.weixin.open.bean.authandicp; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.open.api.WxOpenMaIcpService; + +import java.io.Serializable; +import java.util.List; + +/** + * @author 痴货 + * @Description + * @createTime 2025/06/18 23:00 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxOpenSubmitAuthAndIcpParam implements Serializable { + + private static final long serialVersionUID = 5545621231231213158L; + + /** + * 认证数据 + */ + @SerializedName("auth_data") + private AuthData authData; + + /** + * 备案主体信息 + */ + @SerializedName("icp_subject") + private IcpSubject icpSubject; + + /** + * 微信小程序信息 + */ + @SerializedName("icp_applets") + private IcpApplets icpApplets; + + /** + * 其他备案媒体材料 + */ + @SerializedName("icp_materials") + private IcpMaterials icpMaterials; + + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class AuthData implements Serializable { + + private static final long serialVersionUID = 5545289494161613158L; + + /** + * 联系人信息 + */ + @SerializedName("contact_info") + private ContactInfo contactInfo; + + /** + * 发票信息,如果是服务商代缴模式,不需要填写 + */ + @SerializedName("invoice_info") + private InvoiceInfo invoiceInfo; + + /** + * 认证主体类型:1.企业;12.个体工商户;15.个人 + */ + @SerializedName("customer_type") + private Integer customerType; + + /** + * 支付方式 1:消耗服务商预购包 2:小程序开发者自行支付 + */ + @SerializedName("pay_type") + private Integer payType; + + /** + * 主体资质其他证明材料,最多上传10张图片 + */ + @SerializedName("qualification_other") + private List qualificationOther; + + /** + * 小程序账号名称 + */ + @SerializedName("account_name") + private String accountName; + + /** + * 小程序账号名称命名类型 1:基于自选词汇命名 2:基于商标命名 + */ + @SerializedName("account_name_type") + private String accountNameType; + + /** + * 名称命中关键词-补充材料,支持上传多张图片 + */ + @SerializedName("account_supplemental") + private List accountSupplemental; + + /** + * 认证类型为个人类型时可以选择要认证的身份,从 查询个人认证身份选项列表 里获取,填叶节点的name + */ + @SerializedName("auth_identification") + private String authIdentification; + + /** + * 填了 auth_identification 则必填。身份证明材料 (1)基于不同认证身份上传不同的材料;(2)认证类型=1时选填,支持上传10张图片 + */ + @SerializedName("auth_ident_material") + private List authIdentMaterial; + + /** + * 第三方联系电话 + */ + @SerializedName("third_party_phone") + private String thirdPartyPhone; + + /** + * 选择服务商代缴模式时必填。服务市场 appid,该服务市场账号主体必须与服务商账号主体一致 + */ + @SerializedName("service_appid") + private String serviceAppid; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ContactInfo implements Serializable { + + private static final long serialVersionUID = -2962862643438222305L; + + /** + * 认证联系人姓名 + */ + @SerializedName("name") + private String name; + + /** + * 认证联系人邮箱 + */ + @SerializedName("email") + private String email; + + /** + * 认证联系人手机号 + */ + @SerializedName("mobile") + private String mobile; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class InvoiceInfo implements Serializable { + + private static final long serialVersionUID = 4564894651613131322L; + + /** + * 发票类型 1: 不开发票 2: 电子发票 4: 增值税专票(数电类型) + */ + @SerializedName("invoice_type") + private String invoiceType; + + /** + * 发票类型=2时必填 电子发票开票信息 + */ + @SerializedName("electronic") + private Electronic electronic; + + /** + * 发票类型=4时必填 增值税专票(数电类型)开票信息 + */ + @SerializedName("vat") + private Vat vat; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Electronic implements Serializable { + + private static final long serialVersionUID = 189498465135131444L; + + /** + * 纳税识别号(15位、17、18或20位) + */ + @SerializedName("id") + private String id; + + /** + * 发票备注(选填) + */ + @SerializedName("desc") + private String desc; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Vat implements Serializable { + + private static final long serialVersionUID = 829892829816551512L; + + /** + * 企业电话 + */ + @SerializedName("enterprise_phone") + private String enterprisePhone; + + /** + * 纳税识别号(15位、17、18或20位) + */ + @SerializedName("id") + private String id; + + /** + * 企业注册地址 + */ + @SerializedName("enterprise_address") + private String enterpriseAddress; + + /** + * 企业开户银行(选填) + */ + @SerializedName("bank_name") + private String bankName; + + /** + * 企业银行账号(选填) + */ + @SerializedName("bank_account") + private String bankAccount; + + /** + * 发票备注(选填) + */ + @SerializedName("desc") + private String desc; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class IcpSubject implements Serializable { + + private static final long serialVersionUID = -1256165165165165165L; + + /** + * 主体基本信息 + */ + @SerializedName("base_info") + private SubjectBaseInfo baseInfo; + + /** + * 个人主体额外信息 + */ + @SerializedName("personal_info") + private SubjectPersonalInfo personalInfo; + + /** + * 主体额外信息(个人备案时,如果存在与主体负责人信息相同的字段,则填入相同的值) + */ + @SerializedName("organize_info") + private SubjectOrganizeInfo organizeInfo; + + /** + * 主体负责人信息 + */ + @SerializedName("principal_info") + private SubjectPrincipalInfo principalInfo; + + /** + * 法人信息(非个人备案,且主体负责人不是法人时,必填) + */ + @SerializedName("legal_person_info") + private SubjectLegalPersonInfo legalPersonInfo; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class SubjectBaseInfo implements Serializable { + + private static final long serialVersionUID = -1561561613212313445L; + + /** + * 主体性质,选项参考 获取单位性质,**仅支持企业、个体工商户、个人** + * {@link WxOpenMaIcpService#queryIcpSubjectTypes } + */ + @SerializedName("type") + private Integer type; + + /** + * 主办单位名称 + */ + @SerializedName("name") + private String name; + + /** + * 备案省份,使用省份代码 + */ + @SerializedName("province") + private String province; + + /** + * 备案城市,使用城市代码 + */ + @SerializedName("city") + private String city; + + /** + * 备案县区,使用县区代码 + */ + @SerializedName("district") + private String district; + + /** + * 通讯地址,必须属于备案省市区,地址开头的省市区不用填入 + */ + @SerializedName("address") + private String address; + + /** + * 主体信息备注,根据需要,如实填写 + */ + @SerializedName("comment") + private String comment; + + /** + * 主体备案号 + */ + @SerializedName("record_number") + private String recordNumber; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class SubjectPersonalInfo implements Serializable { + + private static final long serialVersionUID = -2151981561916519288L; + + /** + * 临时居住证明照片 media_id,个人备案且非本省人员,需要提供居住证、暂住证、社保证明、房产证等临时居住证明 + */ + @SerializedName("residence_permit") + private String residencePermit; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class SubjectOrganizeInfo implements Serializable { + + private static final long serialVersionUID = -1181121318132185161L; + + /** + * 主体证件类型 + * {@link WxOpenMaIcpService#queryIcpCertificateTypes} + */ + @SerializedName("certificate_type") + private Integer certificateType; + + /** + * 主体证件号码 + */ + @SerializedName("certificate_number") + private String certificateNumber; + + /** + * 主体证件住所 + */ + @SerializedName("certificate_address") + private String certificateAddress; + + /** + * 主体证件照片 media_id,如果小程序主体为非个人类型 + */ + @SerializedName("certificate_photo") + private String certificatePhoto; + + } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class SubjectPrincipalInfo implements Serializable { + + private static final long serialVersionUID = -2984191321918916511L; + + /** + * 负责人姓名 + */ + @SerializedName("name") + private String name; + + /** + * 负责人联系方式 + */ + @SerializedName("mobile") + private String mobile; + + /** + * 负责人电子邮件 + */ + @SerializedName("email") + private String email; + + /** + * 负责人应急联系方式 + */ + @SerializedName("emergency_contact") + private String emergencyContact; + + /** + * 负责人证件类型(获取证件类型 + * {@link WxOpenMaIcpService#queryIcpCertificateTypes()}) + */ + @SerializedName("certificate_type") + private Integer certificateType; + + /** + * 负责人证件号码 + */ + @SerializedName("certificate_number") + private String certificateNumber; + + /** + * 负责人证件有效期起始日期,格式为 YYYYmmdd + */ + @SerializedName("certificate_validity_date_start") + private String certificateValidityDateStart; + + /** + * 负责人证件有效期终止日期,格式为 YYYYmmdd + */ + @SerializedName("certificate_validity_date_end") + private String certificateValidityDateEnd; + + /** + * 负责人证件正面照片 media_id(身份证为人像面) + */ + @SerializedName("certificate_photo_front") + private String certificatePhotoFront; + + /** + * 负责人证件背面照片 media_id(身份证为国徽面) + */ + @SerializedName("certificate_photo_back") + private String certificatePhotoBack; + + /** + * 授权书 media_id,当主体负责人不是法人时需要主体负责人授权书,当小程序负责人不是法人时需要小程序负责人授权书 + */ + @SerializedName("authorization_letter") + private String authorizationLetter; + + /** + * 扫脸认证任务id(扫脸认证接口返回的task_id),仅小程序负责人需要扫脸,主体负责人无需扫脸 + */ + @SerializedName("verify_task_id") + private String verifyTaskId; + + } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class SubjectLegalPersonInfo implements Serializable { + + private static final long serialVersionUID = -1259198165316516161L; + + /** + * 法人代表姓名 + */ + @SerializedName("name") + private String name; + + /** + * 法人证件号码 + */ + @SerializedName("certificate_number") + private String certificateNumber; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class IcpApplets implements Serializable { + + private static final long serialVersionUID = -2156129841651651651L; + + /** + * 微信小程序基本信息 + */ + @SerializedName("base_info") + private AppletsBaseInfo AppleBaseInfo; + + /** + * 小程序负责人信息 + */ + @SerializedName("principal_info") + private AppletsPrincipalInfo principalInfo; + + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class AppletsBaseInfo implements Serializable { + + private static final long serialVersionUID = 8404017028547715919L; + + /** + * 小程序ID,不用填写,后台自动拉取 + */ + @SerializedName("appid") + private String appId; + + /** + * 小程序名称,不用填写,后台自动拉取 + */ + @SerializedName("name") + private String name; + + /** + * 小程序服务内容类型,只能填写二级服务内容类型,最多5个 + * {@link WxOpenMaIcpService#queryIcpServiceContentTypes} + */ + @SerializedName("service_content_types") + private List serviceContentTypes; + + /** + * 前置审批项,列表中不能存在重复的前置审批类型id,如不涉及前置审批项,也需要填“以上都不涉及” + */ + @SerializedName("nrlx_details") + private List nrlxDetails; + + /** + * 请具体描述小程序实际经营内容、主要服务内容,该信息为主管部门审核重要依据,备注内容字数限制20-200字,请认真填写。 + */ + @SerializedName("comment") + private String comment; + + /** + * 小程序备案号,示例值:粤B2-20090059-1626X + * (申请小程序备案时不用填写,查询已备案详情时会返回) + */ + @SerializedName("record_number") + private String recordNumber; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class AppletsNrlxDetailItem implements Serializable { + + private static final long serialVersionUID = -9144721738792167000L; + + /** + * 前置审批类型 + * {@link WxOpenMaIcpService#queryIcpNrlxTypes} + */ + @SerializedName("type") + private Integer type; + + /** + * 前置审批号,如果前置审批类型不是“以上都不涉及”, + * 则必填,示例值:"粤-12345号 + */ + @SerializedName("code") + private String code; + + /** + * 前置审批媒体材料 media_id + */ + @SerializedName("media") + private String media; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class AppletsPrincipalInfo implements Serializable { + + private static final long serialVersionUID = 5088256283066784463L; + + /** + * 负责人姓名 + */ + @SerializedName("name") + private String name; + + /** + * 负责人联系方式 + */ + @SerializedName("mobile") + private String mobile; + + /** + * 负责人电子邮件 + */ + @SerializedName("email") + private String email; + + /** + * 负责人应急联系方式 + */ + @SerializedName("emergency_contact") + private String emergencyContact; + + /** + * 负责人证件类型 + * {@link WxOpenMaIcpService#queryIcpCertificateTypes} + */ + @SerializedName("certificate_type") + private Integer certificateType; + + /** + * 负责人证件号码 + */ + @SerializedName("certificate_number") + private String certificateNumber; + + /** + * 负责人证件有效期起始日期, + * 格式为 YYYYmmdd,示例值:"20230815" + */ + @SerializedName("certificate_validity_date_start") + private String certificateValidityDateStart; + + /** + * 负责人证件有效期终止日期, + * 格式为 YYYYmmdd, + * 如证件长期有效,请填写 "长期",示例值:"20330815" + */ + @SerializedName("certificate_validity_date_end") + private String certificateValidityDateEnd; + + /** + * 负责人证件正面照片 media_id + * (身份证为人像面) + */ + @SerializedName("certificate_photo_front") + private String certificatePhotoFront; + + /** + * 负责人证件背面照片 media_id + * (身份证为国徽面) + */ + @SerializedName("certificate_photo_back") + private String certificatePhotoBack; + + /** + * 授权书 media_id, + * 当主体负责人不是法人时需要主体负责人授权书, + * 当小程序负责人不是法人时需要小程序负责人授权书 + */ + @SerializedName("authorization_letter") + private String authorizationLetter; + + /** + * 扫脸认证任务id(扫脸认证接口返回的task_id), + * 仅小程序负责人需要扫脸,主体负责人无需扫脸 + */ + @SerializedName("verify_task_id") + private String verifyTaskId; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class IcpMaterials implements Serializable { + + private static final long serialVersionUID = -2651654844198165191L; + + /** + * 互联网信息服务承诺书 media_id,最多上传1个 + */ + @SerializedName("commitment_letter") + private List commitmentLetter; + + /** + * 主体更名函 media_id(非个人类型,且发生过更名时需要上传),最多上传1个 + */ + @SerializedName("business_name_change_letter") + private List businessNameChangeLetter; + + /** + * 党建确认函 media_id,最多上传1个 + */ + @SerializedName("party_building_confirmation_letter") + private List partyBuildingConfirmationLetter; + + /** + * 承诺视频 media_id,最多上传1个 + */ + @SerializedName("promise_video") + private List promiseVideo; + + /** + * 网站备案信息真实性责任告知书 media_id,最多上传1个 + */ + @SerializedName("authenticity_responsibility_letter") + private List authenticityResponsibilityLetter; + + /** + * 小程序备案信息真实性承诺书 media_id,最多上传1个 + */ + @SerializedName("authenticity_commitment_letter") + private List authenticityCommitmentLetter; + + /** + * 小程序建设方案书 media_id,最多上传1个 + */ + @SerializedName("website_construction_proposal") + private List websiteConstructionProposal; + + /** + * 主体其它附件 media_id,最多上传10个 + */ + @SerializedName("subject_other_materials") + private List subjectOtherMaterials; + + /** + * 小程序其它附件 media_id,最多上传10个 + */ + @SerializedName("applets_other_materials") + private List appletsOtherMaterials; + + /** + * 手持证件照 media_id,最多上传1个 + */ + @SerializedName("holding_certificate_photo") + private List holdingCertificatePhoto; + + } + +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenSubmitAuthAndIcpResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenSubmitAuthAndIcpResult.java new file mode 100644 index 0000000000000000000000000000000000000000..08dbc80f2bafe4ea227f6c40a8e2a2ed61766daf --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/authandicp/WxOpenSubmitAuthAndIcpResult.java @@ -0,0 +1,52 @@ +package me.chanjar.weixin.open.bean.authandicp; + +import com.google.gson.annotations.SerializedName; +import lombok.*; +import me.chanjar.weixin.open.bean.result.WxOpenResult; + +import java.util.List; + +/** + * @author 痴货 + * @Description + * @createTime 2025/06/18 23:00 + */ +@Getter +@Setter +@NoArgsConstructor +public class WxOpenSubmitAuthAndIcpResult extends WxOpenResult { + + private static final long serialVersionUID = -1175687058498454852L; + + /** + * 错误提示 + */ + @SerializedName("hints") + private List hints; + + /** + * 小程序认证及备案任务流程 id + */ + @SerializedName("procedure_id") + private String procedureId; + + /** + * 小程序认证认证审核费用付费链接,当 pay_type 为 2 时返回 + */ + @SerializedName("pay_url") + private String payUrl; + + @Data + @EqualsAndHashCode(callSuper = true) + public static class Hint extends WxOpenResult { + + private static final long serialVersionUID = 6585787444231265854L; + + /** + * 校验失败的字段 + */ + @SerializedName("err_field") + private String errField; + } + +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenCreateIcpVerifyTaskParam.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenCreateIcpVerifyTaskParam.java new file mode 100644 index 0000000000000000000000000000000000000000..25be43a33754e4cff27bdc1629447f014ec66a61 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenCreateIcpVerifyTaskParam.java @@ -0,0 +1,26 @@ +package me.chanjar.weixin.open.bean.icp; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author 痴货 + * @Description 发起小程序管理员人脸核身 + * @createTime 2025/06/21 00:20 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WxOpenCreateIcpVerifyTaskParam { + + /** + * 小程序认证及备案二合一场景,填 true,否则为小程序备案场景。默认值为 false + */ + @SerializedName("along_with_auth") + private Boolean alongWithAuth; + +} diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenIcpCreateIcpVerifyTaskResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenIcpCreateIcpVerifyTaskResult.java index 8deb40133578b307487c8fde5a988cac0b183022..f2ff3d166dc32e34518bae4cc26fbd31f1148edb 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenIcpCreateIcpVerifyTaskResult.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/icp/WxOpenIcpCreateIcpVerifyTaskResult.java @@ -1,7 +1,5 @@ package me.chanjar.weixin.open.bean.icp; -import com.fasterxml.jackson.annotation.JsonProperty; - import com.google.gson.annotations.SerializedName; import lombok.Getter; import lombok.NoArgsConstructor; @@ -26,4 +24,10 @@ public class WxOpenIcpCreateIcpVerifyTaskResult extends WxOpenResult { @SerializedName("task_id") private String taskId; + /** + * 人脸核验任务url,{@link WxOpenCreateIcpVerifyTaskParam#alongWithAuth } 填 true 时返回 + */ + @SerializedName("verify_url") + private String verifyUrl; + } diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java index dc6839c1a5c2494b52afe891a6184f2d606d1db2..dfa950123d1309e6d0a105fcf69102ac576af590 100644 --- a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/message/WxOpenXmlMessage.java @@ -155,6 +155,45 @@ public class WxOpenXmlMessage implements Serializable { private Integer beianStatus; //endregion + //region 小程序认证及备案的事件 infoType=notify_3rd_wxa_auth_and_icp + + /** + * 小程序认证及备案任务流程id + */ + @XStreamAlias("procedure_id") + private String procedureId; + + /** + * 任务流程状态 + * 9 手机验证成功 + * 15 等待支付认证审核费用 + * 16 认证审核费用支付成功 + * 17 认证审核中 + * 18 认证审核驳回 + * 19 认证审核通过 + * 20 认证审核最终失败(不能再修改) + * 21 创建备案审核单失败 + * 22 备案平台审核中 + * 23 备案平台审核驳回 + * 24 备案管局审核中 + * 25 管局审核驳回 + * 26 认证及备案完成 + * 27 流程已过期 + * 28 流程已终止 + * 29 备案已撤回 + */ + @XStreamAlias("procedure_status") + private Integer procedureStatus; + + //endregion + + /** + * 原始通知内容 + */ + private String context; + + //endregion + /** * 快速创建的小程序appId,已弃用,未来将删除 * @@ -277,7 +316,9 @@ public class WxOpenXmlMessage implements Serializable { WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage); String plainText = cryptUtil.decryptXml(msgSignature, timestamp, nonce, encryptedXml); log.debug("解密后的原始xml消息内容:{}", plainText); - return fromXml(plainText); + WxOpenXmlMessage wxOpenXmlMessage = fromXml(plainText); + wxOpenXmlMessage.setContext(plainText); + return wxOpenXmlMessage; } public static WxMpXmlMessage fromEncryptedMpXml(String encryptedXml, WxOpenConfigStorage wxOpenConfigStorage, diff --git a/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenGetAllCategoriesByTypeResult.java b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenGetAllCategoriesByTypeResult.java new file mode 100644 index 0000000000000000000000000000000000000000..00cefeb37c39d5549044b7298007c0a5c0e520c1 --- /dev/null +++ b/weixin-java-open/src/main/java/me/chanjar/weixin/open/bean/result/WxOpenGetAllCategoriesByTypeResult.java @@ -0,0 +1,153 @@ +package me.chanjar.weixin.open.bean.result; + +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +/** + * 获取所有类目 + * author 痴货 + */ +@Getter +@Setter +@NoArgsConstructor +public class WxOpenGetAllCategoriesByTypeResult extends WxOpenResult { + + private static final long serialVersionUID = -2845321894615646115L; + + /** + * 类目信息列表 + */ + @SerializedName("categories_list") + private CategoriesList categorieslist; + + @Getter + @Setter + @NoArgsConstructor + public static class CategoriesList implements Serializable { + + private static final long serialVersionUID = -2845321894615646115L; + + /** + * 类目信息 + */ + @SerializedName("categories") + private List categories; + } + + @Getter + @Setter + @NoArgsConstructor + public static class Categories implements Serializable { + + private static final long serialVersionUID = -284532256461546115L; + + /** + * 类目 ID + */ + @SerializedName("id") + private Integer id; + + /** + * 类目名称 + */ + @SerializedName("name") + private String name; + + /** + * 类目层级 + */ + @SerializedName("level") + private Integer level; + + /** + * 父类目 ID + */ + @SerializedName("father") + private Integer father; + + /** + * 子类目 ID + */ + @SerializedName("children") + private List children; + + /** + * 是否敏感类目(1 为敏感类目,需要提供相应资质审核;0 为非敏感类目,无需审核) + */ + @SerializedName("sensitive_type") + private Integer sensitiveType; + + /** + * sensitive_type 为 1 的类目需要提供的资质证明 + */ + @SerializedName("qualify") + private Qualify qualify; + + /** + * 类目权限范围 + */ + @SerializedName("scope") + private String scope; + + } + + @Getter + @Setter + @NoArgsConstructor + public static class Qualify implements Serializable { + + private static final long serialVersionUID = -2841894318945616115L; + + /** + * 资质证明列表 + */ + @SerializedName("exter_list") + private List exterList; + + /** + * 备注 + */ + @SerializedName("remark") + private String remark; + + } + + @Getter + @Setter + @NoArgsConstructor + public static class Exter implements Serializable { + + private static final long serialVersionUID = -2841894318945616115L; + + @SerializedName("inner_list") + private List innerList; + + } + + @Getter + @Setter + @NoArgsConstructor + public static class Inner implements Serializable { + + private static final long serialVersionUID = -15646131313516531L; + + /** + * 资质文件名称 + */ + @SerializedName("name") + private String name; + + /** + * 资质文件示例 + */ + @SerializedName("url") + private String url; + + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsNotifyResult.java new file mode 100644 index 0000000000000000000000000000000000000000..80709a102253bd2a5d03931988eeff0258c9a6ca --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsNotifyResult.java @@ -0,0 +1,79 @@ +package com.github.binarywang.wxpay.bean.transfer; + +import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse; +import com.github.binarywang.wxpay.bean.notify.WxPayBaseNotifyV3Result; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *
+ *    商家转账到零钱接口将转账结果通知用户
+ *    文档地址:https://pay.weixin.qq.com/doc/v3/merchant/4012716434
+ *  
+ */ +@Data +public class TransferBillsNotifyResult implements Serializable, WxPayBaseNotifyV3Result { + /** + * 源数据 + */ + private OriginNotifyResponse rawData; + /** + * 解密后的数据 + */ + private TransferBillsNotifyResult.DecryptNotifyResult result; + + @Data + @NoArgsConstructor + public static class DecryptNotifyResult implements Serializable { + /** + * 商户号 + */ + @SerializedName(value = "mch_id") + private String mchId; + /** + * 商家批次单号 + */ + @SerializedName(value = "out_bill_no") + private String outBillNo; + /** + * 微信批次单号 + */ + @SerializedName(value = "transfer_bill_no") + private String transferBillNo; + /** + * 批次状态 + */ + @SerializedName(value = "state") + private String state; + /** + * 转账金额 + */ + @SerializedName(value = "transfer_amount") + private Integer transferAmount; + + /** + * 批次状态 + */ + @SerializedName(value = "openid") + private String openid; + + /** + * 单据创建时间 + */ + @SerializedName(value = "create_time") + private String createTime; + /** + * 最后一次状态变更时间 + */ + @SerializedName(value = "update_time") + private String updateTime; + /** + * 错误原因 + */ + @SerializedName(value = "fail_reason") + private String failReason; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..230e564e4b6bd888dcb12d2f75c7fdee8b365f7b --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsRequest.java @@ -0,0 +1,108 @@ +package com.github.binarywang.wxpay.bean.transfer; + +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 发起商家转账API参数 + * + * @author allovine + * created on 2025/1/15 + **/ +@Data +@Builder(builderMethodName = "newBuilder") +@NoArgsConstructor +@AllArgsConstructor +public class TransferBillsRequest implements Serializable { + private static final long serialVersionUID = -2175582517588397437L; + + /** + * 直连商户的appid + */ + @SerializedName("appid") + private String appid; + + /** + * 商户系统内部的商家单号 + */ + @SerializedName("out_bill_no") + private String outBillNo; + + /** + * 转账场景ID + * 商户平台-产品中心-商家转账 申请 + * 佣金报酬 ID:1005 + */ + @SerializedName("transfer_scene_id") + private String transferSceneId; + + /** + * 用户在直连商户应用下的用户标示 + */ + @SerializedName("openid") + private String openid; + + /** + * 收款用户姓名 + */ + @SpecEncrypt + @SerializedName("user_name") + private String userName; + + /** + * 转账金额 + */ + @SerializedName("transfer_amount") + private Integer transferAmount; + + /** + * 转账备注 + */ + @SerializedName("transfer_remark") + private String transferRemark; + + /** + * 异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的url,必须为https,不能携带参数 + */ + @SerializedName("notify_url") + private String notifyUrl; + + /** + * 用户收款感知 + */ + @SerializedName("user_recv_perception") + private String userRecvPerception; + + + /** + * 转账场景报备信息 + */ + @SerializedName("transfer_scene_report_infos") + private List transferSceneReportInfos; + + + @Data + @Builder(builderMethodName = "newBuilder") + @AllArgsConstructor + @NoArgsConstructor + public static class TransferSceneReportInfo { + /** + * 信息类型 + */ + @SerializedName("info_type") + private String infoType; + + /** + * 信息内容 + */ + @SerializedName("info_content") + private String infoContent; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java new file mode 100644 index 0000000000000000000000000000000000000000..9f7aac7fbb40343d3ecbc636c226e6d8ba10786f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/transfer/TransferBillsResult.java @@ -0,0 +1,55 @@ +package com.github.binarywang.wxpay.bean.transfer; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 商家转账结果 + * + * @author allovine + * created on 2025/1/15 + **/ +@Data +@NoArgsConstructor +public class TransferBillsResult implements Serializable { + private static final long serialVersionUID = -2175582517588397437L; + + /** + * 商户单号 + */ + @SerializedName("out_bill_no") + private String outBillNo; + + /** + * 微信转账单号 + */ + @SerializedName("transfer_bill_no") + private String transferBillNo; + + /** + * 单据创建时间 + */ + @SerializedName("create_time") + private String createTime; + + /** + * 单据状态 + */ + @SerializedName("status") + private String status; + + /** + * 失败原因 + */ + @SerializedName("fail_reason") + private String failReason; + + /** + * 跳转领取页面的package信息 + */ + @SerializedName("package_info") + private String packageInfo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java index ebf746214d795f8b56c2e27d73e5f74beedd9449..c02430a960ea8a5ac147f93990a254955857e5a7 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/TransferService.java @@ -111,4 +111,31 @@ public interface TransferService { */ TransferBatchDetailResult transferBatchesOutBatchNoDetail(String outBatchNo, String outDetailNo) throws WxPayException; + /** + *
+   *
+   * 2025.1.15 开始新接口 发起商家转账API
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:请求地址
+   *
+   * 文档地址:发起商家转账API
+   * 
+ * + * @param request 转账请求参数 + * @return TransferBillsResult 转账结果 + * @throws WxPayException . + */ + TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException; + + /** + * 2025.1.15 开始新接口 解析商家转账结果 + * 详见 + * + * @param notifyData 通知数据 + * @param header 通知头部数据,不传则表示不校验头 + * @return the wx transfer notify result + * @throws WxPayException the wx pay exception + */ + TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 57c2937c629fc25907335eaf53565035dad0f462..19b4ed0a07a38d1d1a5ce2e20ed522b21086b5d3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -6,6 +6,7 @@ import com.github.binarywang.wxpay.bean.notify.*; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; +import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.exception.WxPayException; @@ -991,6 +992,17 @@ public interface WxPayService { */ WxPayTransferBatchesNotifyV3Result parseTransferBatchesNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException; + /** + * 解析商家转账批次回调通知 + * https://pay.weixin.qq.com/doc/v3/merchant/4012712115 + * + * @param notifyData + * @param header + * @return + * @throws WxPayException + */ + TransferBillsNotifyResult parseTransferBillsNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException; + /** * 解析服务商模式退款结果通知 * 详见https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_11.shtml diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index c9fc1e7bd2616e173e519258bb18a155390dade3..7c2055cec30070b0f3fbc031288818af4ad7e6fd 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -11,6 +11,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; +import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.config.WxPayConfigHolder; import com.github.binarywang.wxpay.constant.WxPayConstants; @@ -442,6 +443,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayTransferBatchesNotifyV3Result.class, WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult.class); } + @Override + public TransferBillsNotifyResult parseTransferBillsNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException { + return this.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class); + } + @Override public WxPayPartnerRefundNotifyV3Result parsePartnerRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException { return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayPartnerRefundNotifyV3Result.class, WxPayPartnerRefundNotifyV3Result.DecryptNotifyResult.class); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java index e62dc9c0538fa0370c113b9c01bcb38b5ba621d1..23bf7b13eef703246c081f1baf461fcab22fe50c 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/TransferServiceImpl.java @@ -85,4 +85,20 @@ public class TransferServiceImpl implements TransferService { String result = this.payService.getV3(url); return GSON.fromJson(result, TransferBatchDetailResult.class); } + + @Override + public TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException { + String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills", this.payService.getPayBaseUrl()); + if (request.getUserName() != null && request.getUserName().length() > 0) { + X509Certificate validCertificate = this.payService.getConfig().getVerifier().getValidCertificate(); + RsaCryptoUtil.encryptFields(request, validCertificate); + } + String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); + return GSON.fromJson(result, TransferBillsResult.class); + } + + @Override + public TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException { + return this.payService.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class); + } } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java index 7f89bd47211fd0d565ea6e1fb7c3cf143ac55920..cd607dff03caec89658aacddf804354b08cb5014 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/TransferServiceImplTest.java @@ -2,6 +2,7 @@ package com.github.binarywang.wxpay.service.impl; import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest; import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest; +import com.github.binarywang.wxpay.bean.transfer.TransferBillsRequest; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.testbase.ApiTestModule; @@ -73,4 +74,17 @@ public class TransferServiceImplTest { public void testTransferBatchesOutBatchNoDetail() throws WxPayException { log.info("商家明细单号查询明细单:{}", this.payService.getTransferService().transferBatchesOutBatchNoDetail("1655447999520", "1655447989156")); } + + @Test + public void testTransferBills() throws WxPayException { + TransferBillsRequest transferBillsRequest = TransferBillsRequest.newBuilder() + .appid("wxf636efh5xxxxx") + .outBillNo("1655447989156") + .transferSceneId("1005") + .transferAmount(100) + .transferRemark("测试转账") + .openid("oX_7Jzr9gSZz4X_Xc9-_7HGf8XzI") + .userName("测试用户").build(); + log.info("发起商家转账:{}", this.payService.getTransferService().transferBills(transferBillsRequest)); + } }