diff --git a/README.md b/README.md
index f1cccac4b3..69d5efbf34 100644
--- a/README.md
+++ b/README.md
@@ -47,10 +47,8 @@
-
-
+ + * 使用单个 WxMaService 实例管理多个租户配置,通过 switchover 切换租户。 + * 相比 {@link WxMaMultiServicesImpl},此实现共享 HTTP 客户端,节省资源。 + *
+ *+ * 注意:由于使用 ThreadLocal 切换配置,在异步或多线程场景需要特别注意线程上下文切换。 + *
+ * + * @author Binary Wang + * created on 2026/1/9 + */ +@RequiredArgsConstructor +public class WxMaMultiServicesSharedImpl implements WxMaMultiServices { + private final WxMaService sharedWxMaService; + + @Override + public WxMaService getWxMaService(String tenantId) { + if (tenantId == null) { + return null; + } + // 使用 switchover 检查配置是否存在,保持与隔离模式 API 行为一致(不存在时返回 null) + if (!sharedWxMaService.switchover(tenantId)) { + return null; + } + return sharedWxMaService; + } + + @Override + public void removeWxMaService(String tenantId) { + if (tenantId != null) { + sharedWxMaService.removeConfig(tenantId); + } + } + + /** + * 添加租户配置到共享的 WxMaService 实例 + * + * @param tenantId 租户 ID + * @param wxMaService 要添加配置的 WxMaService(仅使用其配置,不使用其实例) + */ + public void addWxMaService(String tenantId, WxMaService wxMaService) { + if (tenantId != null && wxMaService != null) { + sharedWxMaService.addConfig(tenantId, wxMaService.getWxMaConfig()); + } + } +} diff --git a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml index bcc61b0309..7e9ffbe308 100644 --- a/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml +++ b/spring-boot-starters/wx-java-miniapp-spring-boot-starter/pom.xml @@ -4,7 +4,7 @@+ * 使用单个 WxMpService 实例管理多个租户配置,通过 switchover 切换租户。 + * 相比 {@link WxMpMultiServicesImpl},此实现共享 HTTP 客户端,节省资源。 + *
+ *+ * 注意:由于使用 ThreadLocal 切换配置,在异步或多线程场景需要特别注意线程上下文切换。 + *
+ * + * @author Binary Wang + * created on 2026/1/9 + */ +@RequiredArgsConstructor +public class WxMpMultiServicesSharedImpl implements WxMpMultiServices { + private final WxMpService sharedWxMpService; + + @Override + public WxMpService getWxMpService(String tenantId) { + if (tenantId == null) { + return null; + } + // 使用 switchover 检查配置是否存在,保持与隔离模式 API 行为一致(不存在时返回 null) + if (!sharedWxMpService.switchover(tenantId)) { + return null; + } + return sharedWxMpService; + } + + @Override + public void removeWxMpService(String tenantId) { + if (tenantId != null) { + sharedWxMpService.removeConfigStorage(tenantId); + } + } + + /** + * 添加租户配置到共享的 WxMpService 实例 + * + * @param tenantId 租户 ID + * @param wxMpService 要添加配置的 WxMpService(仅使用其配置,不使用其实例) + */ + public void addWxMpService(String tenantId, WxMpService wxMpService) { + if (tenantId != null && wxMpService != null) { + sharedWxMpService.addConfigStorage(tenantId, wxMpService.getWxMpConfigStorage()); + } + } +} diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md b/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md index 3e14f499d9..091912cfad 100644 --- a/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md +++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md @@ -27,7 +27,7 @@ #wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379 #wx.mp.config-storage.redis.sentinel-name=mymaster # http客户端配置 - wx.mp.config-storage.http-client-type=httpclient # http客户端类型: HttpClient(默认), OkHttp, JoddHttp + wx.mp.config-storage.http-client-type=HttpComponents # http客户端类型: HttpComponents(Apache HttpClient 5.x,推荐), HttpClient(Apache HttpClient 4.x), OkHttp, JoddHttp wx.mp.config-storage.http-proxy-host= wx.mp.config-storage.http-proxy-port= wx.mp.config-storage.http-proxy-username= diff --git a/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml index 273364c9a7..5d0c2d0269 100644 --- a/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml +++ b/spring-boot-starters/wx-java-mp-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@
+ * {@link me.chanjar.weixin.mp.api.impl.BaseWxMpServiceImpl#setMaxRetryTimes(int)}
+ * {@link cn.binarywang.wx.miniapp.api.impl.BaseWxMaServiceImpl#setMaxRetryTimes(int)}
+ *
+ */
+ private int maxRetryTimes = 5;
+
+ /**
+ * http 请求重试间隔
+ *
+ * {@link me.chanjar.weixin.mp.api.impl.BaseWxMpServiceImpl#setRetrySleepMillis(int)}
+ * {@link cn.binarywang.wx.miniapp.api.impl.BaseWxMaServiceImpl#setRetrySleepMillis(int)}
+ *
+ */
+ private int retrySleepMillis = 1000;
+
+ /**
+ * 连接超时时间,单位毫秒
+ */
+ private int connectionTimeout = 5000;
+
+ /**
+ * 读数据超时时间,即socketTimeout,单位毫秒
+ */
+ private int soTimeout = 5000;
+
+ /**
+ * 从连接池获取链接的超时时间,单位毫秒
+ */
+ private int connectionRequestTimeout = 5000;
+ }
+
+ public enum StorageType {
+ /**
+ * 内存
+ */
+ memory,
+ /**
+ * jedis
+ */
+ jedis,
+ /**
+ * redisson
+ */
+ redisson,
+ /**
+ * redisTemplate
+ */
+ redistemplate
+ }
+
+}
diff --git a/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenMultiRedisProperties.java b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenMultiRedisProperties.java
new file mode 100644
index 0000000000..ae6d5368d7
--- /dev/null
+++ b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenMultiRedisProperties.java
@@ -0,0 +1,57 @@
+package com.binarywang.spring.starter.wxjava.open.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 微信开放平台多账号Redis配置.
+ *
+ * @author Binary Wang
+ */
+@Data
+@NoArgsConstructor
+public class WxOpenMultiRedisProperties implements Serializable {
+ private static final long serialVersionUID = -5924815351660074401L;
+
+ /**
+ * 主机地址.
+ */
+ private String host = "127.0.0.1";
+
+ /**
+ * 端口号.
+ */
+ private int port = 6379;
+
+ /**
+ * 密码.
+ */
+ private String password;
+
+ /**
+ * 超时.
+ */
+ private int timeout = 2000;
+
+ /**
+ * 数据库.
+ */
+ private int database = 0;
+
+ /**
+ * sentinel ips
+ */
+ private String sentinelIps;
+
+ /**
+ * sentinel name
+ */
+ private String sentinelName;
+
+ private Integer maxActive;
+ private Integer maxIdle;
+ private Integer maxWaitMillis;
+ private Integer minIdle;
+}
diff --git a/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenSingleProperties.java b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenSingleProperties.java
new file mode 100644
index 0000000000..116da323dc
--- /dev/null
+++ b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/properties/WxOpenSingleProperties.java
@@ -0,0 +1,49 @@
+package com.binarywang.spring.starter.wxjava.open.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 微信开放平台单个应用配置.
+ *
+ * @author Binary Wang
+ */
+@Data
+@NoArgsConstructor
+public class WxOpenSingleProperties implements Serializable {
+ private static final long serialVersionUID = 1980986361098922525L;
+
+ /**
+ * 设置微信开放平台的appid.
+ */
+ private String appId;
+
+ /**
+ * 设置微信开放平台的app secret.
+ */
+ private String secret;
+
+ /**
+ * 设置微信开放平台的token.
+ */
+ private String token;
+
+ /**
+ * 设置微信开放平台的EncodingAESKey.
+ */
+ private String aesKey;
+
+ /**
+ * 自定义API主机地址,用于替换默认的 https://api.weixin.qq.com
+ * 例如:http://proxy.company.com:8080
+ */
+ private String apiHostUrl;
+
+ /**
+ * 自定义获取AccessToken地址,用于向自定义统一服务获取AccessToken
+ * 例如:http://proxy.company.com:8080/oauth/token
+ */
+ private String accessTokenUrl;
+}
diff --git a/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/service/WxOpenMultiServices.java b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/service/WxOpenMultiServices.java
new file mode 100644
index 0000000000..9228071a10
--- /dev/null
+++ b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/service/WxOpenMultiServices.java
@@ -0,0 +1,26 @@
+package com.binarywang.spring.starter.wxjava.open.service;
+
+
+import me.chanjar.weixin.open.api.WxOpenService;
+
+/**
+ * 微信开放平台 {@link WxOpenService} 所有实例存放类.
+ *
+ * @author binarywang
+ */
+public interface WxOpenMultiServices {
+ /**
+ * 通过租户 Id 获取 WxOpenService
+ *
+ * @param tenantId 租户 Id
+ * @return WxOpenService
+ */
+ WxOpenService getWxOpenService(String tenantId);
+
+ /**
+ * 根据租户 Id,从列表中移除一个 WxOpenService 实例
+ *
+ * @param tenantId 租户 Id
+ */
+ void removeWxOpenService(String tenantId);
+}
diff --git a/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/service/WxOpenMultiServicesImpl.java b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/service/WxOpenMultiServicesImpl.java
new file mode 100644
index 0000000000..76fb139e6c
--- /dev/null
+++ b/spring-boot-starters/wx-java-open-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/open/service/WxOpenMultiServicesImpl.java
@@ -0,0 +1,35 @@
+package com.binarywang.spring.starter.wxjava.open.service;
+
+import me.chanjar.weixin.open.api.WxOpenService;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 微信开放平台 {@link WxOpenMultiServices} 默认实现
+ *
+ * @author Binary Wang
+ */
+public class WxOpenMultiServicesImpl implements WxOpenMultiServices {
+ private final Map+ * 注意:configKey 是配置文件中定义的 key(如 wx.pay.configs.<configKey>.xxx), + * 而不是 appId。如果使用 appId 作为配置 key,则可以直接传入 appId。 + *
+ * + * @param configKey 配置标识(配置文件中 wx.pay.configs 下的 key) + * @return WxPayService + */ + WxPayService getWxPayService(String configKey); + + /** + * 根据配置标识,从列表中移除一个 WxPayService 实例. + *+ * 注意:configKey 是配置文件中定义的 key(如 wx.pay.configs.<configKey>.xxx), + * 而不是 appId。如果使用 appId 作为配置 key,则可以直接传入 appId。 + *
+ * + * @param configKey 配置标识(配置文件中 wx.pay.configs 下的 key) + */ + void removeWxPayService(String configKey); +} diff --git a/spring-boot-starters/wx-java-pay-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/service/WxPayMultiServicesImpl.java b/spring-boot-starters/wx-java-pay-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/service/WxPayMultiServicesImpl.java new file mode 100644 index 0000000000..459fe3b6c0 --- /dev/null +++ b/spring-boot-starters/wx-java-pay-multi-spring-boot-starter/src/main/java/com/binarywang/spring/starter/wxjava/pay/service/WxPayMultiServicesImpl.java @@ -0,0 +1,92 @@ +package com.binarywang.spring.starter.wxjava.pay.service; + +import com.binarywang.spring.starter.wxjava.pay.properties.WxPayMultiProperties; +import com.binarywang.spring.starter.wxjava.pay.properties.WxPaySingleProperties; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 微信支付多服务管理实现类. + * + * @author Binary Wang + */ +@Slf4j +public class WxPayMultiServicesImpl implements WxPayMultiServices { + private final Map+ * 本示例展示了如何使用 wx-java-pay-multi-spring-boot-starter 来管理多个公众号的支付配置。 + *
+ * + * @author Binary Wang + */ +@Slf4j +@Service +public class WxPayMultiExample { + + @Autowired + private WxPayMultiServices wxPayMultiServices; + + /** + * 示例1:根据appId创建支付订单. + *+ * 适用场景:系统需要支持多个公众号,根据用户所在的公众号动态选择支付配置 + *
+ * + * @param appId 公众号appId + * @param openId 用户的openId + * @param totalFee 支付金额(分) + * @param body 商品描述 + * @return JSAPI支付参数 + */ + public WxPayUnifiedOrderV3Result.JsapiResult createJsapiOrder(String appId, String openId, + Integer totalFee, String body) { + try { + // 根据appId获取对应的WxPayService + WxPayService wxPayService = wxPayMultiServices.getWxPayService(appId); + + if (wxPayService == null) { + log.error("未找到appId对应的微信支付配置: {}", appId); + throw new IllegalArgumentException("未找到appId对应的微信支付配置"); + } + + // 构建支付请求 + WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); + request.setOutTradeNo(generateOutTradeNo()); + request.setDescription(body); + request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(totalFee)); + request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(openId)); + request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl()); + + // 调用微信支付API创建订单 + WxPayUnifiedOrderV3Result.JsapiResult result = + wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request); + + log.info("创建JSAPI支付订单成功,appId: {}, outTradeNo: {}", appId, request.getOutTradeNo()); + return result; + + } catch (Exception e) { + log.error("创建JSAPI支付订单失败,appId: {}", appId, e); + throw new RuntimeException("创建支付订单失败", e); + } + } + + /** + * 示例2:服务商模式 - 为不同子商户创建订单. + *+ * 适用场景:服务商为多个子商户提供支付服务 + *
+ * + * @param configKey 配置标识(在配置文件中定义) + * @param subOpenId 子商户用户的openId + * @param totalFee 支付金额(分) + * @param body 商品描述 + * @return JSAPI支付参数 + */ + public WxPayUnifiedOrderV3Result.JsapiResult createPartnerOrder(String configKey, String subOpenId, + Integer totalFee, String body) { + try { + // 根据配置标识获取WxPayService + WxPayService wxPayService = wxPayMultiServices.getWxPayService(configKey); + + if (wxPayService == null) { + log.error("未找到配置: {}", configKey); + throw new IllegalArgumentException("未找到配置"); + } + + // 获取子商户信息 + String subAppId = wxPayService.getConfig().getSubAppId(); + String subMchId = wxPayService.getConfig().getSubMchId(); + log.info("使用服务商模式,子商户appId: {}, 子商户号: {}", subAppId, subMchId); + + // 构建支付请求 + WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); + request.setOutTradeNo(generateOutTradeNo()); + request.setDescription(body); + request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(totalFee)); + request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(subOpenId)); + request.setNotifyUrl(wxPayService.getConfig().getNotifyUrl()); + + // 调用微信支付API创建订单 + WxPayUnifiedOrderV3Result.JsapiResult result = + wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request); + + log.info("创建服务商支付订单成功,配置: {}, outTradeNo: {}", configKey, request.getOutTradeNo()); + return result; + + } catch (Exception e) { + log.error("创建服务商支付订单失败,配置: {}", configKey, e); + throw new RuntimeException("创建支付订单失败", e); + } + } + + /** + * 示例3:查询订单状态. + *+ * 适用场景:查询不同公众号的订单支付状态 + *
+ * + * @param appId 公众号appId + * @param outTradeNo 商户订单号 + * @return 订单状态 + */ + public String queryOrderStatus(String appId, String outTradeNo) { + try { + WxPayService wxPayService = wxPayMultiServices.getWxPayService(appId); + + if (wxPayService == null) { + log.error("未找到appId对应的微信支付配置: {}", appId); + throw new IllegalArgumentException("未找到appId对应的微信支付配置"); + } + + // 查询订单 + WxPayOrderQueryV3Result result = wxPayService.queryOrderV3(null, outTradeNo); + String tradeState = result.getTradeState(); + + log.info("查询订单状态成功,appId: {}, outTradeNo: {}, 状态: {}", appId, outTradeNo, tradeState); + return tradeState; + + } catch (Exception e) { + log.error("查询订单状态失败,appId: {}, outTradeNo: {}", appId, outTradeNo, e); + throw new RuntimeException("查询订单失败", e); + } + } + + /** + * 示例4:申请退款. + *+ * 适用场景:为不同公众号的订单申请退款 + *
+ * + * @param appId 公众号appId + * @param outTradeNo 商户订单号 + * @param refundFee 退款金额(分) + * @param totalFee 订单总金额(分) + * @param reason 退款原因 + * @return 退款单号 + */ + public String refund(String appId, String outTradeNo, Integer refundFee, + Integer totalFee, String reason) { + try { + WxPayService wxPayService = wxPayMultiServices.getWxPayService(appId); + + if (wxPayService == null) { + log.error("未找到appId对应的微信支付配置: {}", appId); + throw new IllegalArgumentException("未找到appId对应的微信支付配置"); + } + + // 构建退款请求 + com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request request = + new com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request(); + request.setOutTradeNo(outTradeNo); + request.setOutRefundNo(generateRefundNo()); + request.setReason(reason); + request.setNotifyUrl(wxPayService.getConfig().getRefundNotifyUrl()); + + com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request.Amount amount = + new com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request.Amount(); + amount.setRefund(refundFee); + amount.setTotal(totalFee); + amount.setCurrency("CNY"); + request.setAmount(amount); + + // 调用微信支付API申请退款 + WxPayRefundV3Result result = wxPayService.refundV3(request); + + log.info("申请退款成功,appId: {}, outTradeNo: {}, outRefundNo: {}", + appId, outTradeNo, request.getOutRefundNo()); + return request.getOutRefundNo(); + + } catch (Exception e) { + log.error("申请退款失败,appId: {}, outTradeNo: {}", appId, outTradeNo, e); + throw new RuntimeException("申请退款失败", e); + } + } + + /** + * 示例5:动态管理配置. + *+ * 适用场景:需要在运行时更新配置(如证书更新后需要重新加载) + *
+ * + * @param configKey 配置标识 + */ + public void reloadConfig(String configKey) { + try { + // 移除缓存的WxPayService实例 + wxPayMultiServices.removeWxPayService(configKey); + log.info("移除配置成功,下次获取时将重新创建: {}", configKey); + + // 下次调用 getWxPayService 时会重新创建实例 + WxPayService wxPayService = wxPayMultiServices.getWxPayService(configKey); + if (wxPayService != null) { + log.info("重新加载配置成功: {}", configKey); + } + + } catch (Exception e) { + log.error("重新加载配置失败: {}", configKey, e); + throw new RuntimeException("重新加载配置失败", e); + } + } + + /** + * 生成商户订单号. + * + * @return 商户订单号 + */ + private String generateOutTradeNo() { + return "ORDER_" + System.currentTimeMillis(); + } + + /** + * 生成商户退款单号. + * + * @return 商户退款单号 + */ + private String generateRefundNo() { + return "REFUND_" + System.currentTimeMillis(); + } +} diff --git a/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml b/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml index 8b67ade1ea..7bbfdbfbf1 100644 --- a/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml +++ b/spring-boot-starters/wx-java-pay-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@+ * 参考:{@code https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842} + *
* * @author Daniel Qian */ @@ -36,8 +39,10 @@ public class WxOAuth2AccessToken implements Serializable { private Integer snapshotUser; /** - * https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&announce_id=11513156443eZYea&version=&lang=zh_CN. * 本接口在scope参数为snsapi_base时不再提供unionID字段。 + *+ * 参考:{@code https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&announce_id=11513156443eZYea&version=&lang=zh_CN} + *
*/ @SerializedName("unionid") private String unionId; diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java index ea1e9e7c68..356d1dbbf9 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxCpErrorMsgEnum.java @@ -453,7 +453,7 @@ public enum WxCpErrorMsgEnum { */ CODE_60008(60008, "部门已存在;部门ID或者部门名称已存在"), /** - * 部门名称含有非法字符;不能含有 \\:?*“< >| 等字符. + * {@code 部门名称含有非法字符;不能含有 \\:?*"< >| 等字符.} */ CODE_60009(60009, "部门名称含有非法字符;不能含有 \\ :?*“< >| 等字符"), /** @@ -521,7 +521,7 @@ public enum WxCpErrorMsgEnum { */ CODE_60124(60124, "无效的父部门id;父部门不存在通讯录中"), /** - * 非法部门名字;不能为空,且不能超过64字节,且不能含有\\:*?”< >|等字符. + * {@code 非法部门名字;不能为空,且不能超过64字节,且不能含有\\:*?"< >|等字符.} */ CODE_60125(60125, "非法部门名字;不能为空,且不能超过64字节,且不能含有\\:*?”< >|等字符"), /** diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java index b45fba3411..1aab7f1f20 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxError.java @@ -12,11 +12,13 @@ /** * 微信错误码. + ** 请阅读: * 公众平台:全局返回码说明 * 企业微信:全局错误码 + *
* - * @author Daniel Qian & Binary Wang + * @author Daniel Qian, Binary Wang */ @Data @NoArgsConstructor diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java index 1bb3f6472b..ffe9b5e3ea 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java @@ -46,23 +46,23 @@ public enum WxMaErrorMsgEnum { */ CODE_40003(40003, "openid 不正确"), /** - *
* 无效媒体文件类型
- * 对应操作:uploadTempMedia
+ *
+ * 对应操作:{@code uploadTempMedia}
* 对应地址:
- * POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
+ * {@code POST https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE}
* 参考文档地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/uploadTempMedia.html
- *
+ *
*/
CODE_40004(40004, "无效媒体文件类型"),
/**
- *
* 无效媒体文件 ID.
- * 对应操作:getTempMedia
+ *
+ * 对应操作:{@code getTempMedia}
* 对应地址:
- * GET https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
+ * {@code GET https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID}
* 参考文档地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/getTempMedia.html
- *
+ *
*/
CODE_40007(40007, "无效媒体文件 ID"),
/**
@@ -99,29 +99,29 @@ public enum WxMaErrorMsgEnum {
*/
CODE_41028(41028, "form_id 不正确,或者过期"),
/**
- *
* code 或 template_id 不正确.
- * 对应操作:code2Session, sendUniformMessage, sendTemplateMessage
+ *
+ * 对应操作:{@code code2Session}, {@code sendUniformMessage}, {@code sendTemplateMessage}
* 对应地址:
- * GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
+ * {@code GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code}
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
* 参考文档地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/code2Session.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/template-message/sendTemplateMessage.html
- *
+ *
*/
CODE_41029(41029, "请求的参数不正确"),
/**
- *
* form_id 已被使用,或者所传page页面不存在,或者小程序没有发布
- * 对应操作:sendUniformMessage, getWXACodeUnlimit
+ *
+ * 对应操作:{@code sendUniformMessage}, {@code getWXACodeUnlimit}
* 对应地址:
* POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
* POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
* 参考文档地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/uniform-message/sendUniformMessage.html
- * https://developers.weixin.qq.com/miniprogram/dev/api/open-api/qr-code/getWXACodeUnlimit.html
- *
+ * https://developers.weixin.qq.com/miniprogram/dev/api/open-api/qr-code/getWXACodeUnlimit.html
+ *
*/
CODE_41030(41030, "请求的参数不正确"),
/**
@@ -138,13 +138,13 @@ public enum WxMaErrorMsgEnum {
*/
CODE_45009(45009, "调用分钟频率受限"),
/**
- *
* 频率限制,每个用户每分钟100次.
- * 对应操作:code2Session
+ *
+ * 对应操作:{@code code2Session}
* 对应地址:
- * GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
+ * {@code GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code}
* 参考文档地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/code2Session.html
- *
+ *
*/
CODE_45011(45011, "频率限制,每个用户每分钟100次"),
/**
@@ -190,12 +190,13 @@ public enum WxMaErrorMsgEnum {
*/
CODE_45072(45072, "command字段取值不对"),
/**
- *
* 下发输入状态,需要之前30秒内跟用户有过消息交互.
- * 对应操作:customerTyping
+ *
+ * 对应操作:{@code customerTyping}
* 对应地址:
* POST https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN
* 参考文档地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/customer-message/customerTyping.html
+ *
*/
CODE_45080(45080, "下发输入状态,需要之前30秒内跟用户有过消息交互"),
/**
@@ -686,7 +687,7 @@ public enum WxMaErrorMsgEnum {
/**
* 89252
- * 法人&企业信息一致性校验中 front checking
+ * {@code 法人&企业信息一致性校验中 front checking}
*/
CODE_89252(89252, "法人&企业信息一致性校验中"),
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxOpenErrorMsgEnum.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxOpenErrorMsgEnum.java
index 28fb5de8ad..ba910e988b 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxOpenErrorMsgEnum.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxOpenErrorMsgEnum.java
@@ -527,7 +527,7 @@ public enum WxOpenErrorMsgEnum {
CODE_40099(40099, "invalid code, this code has consumed."),
/**
- * invalid DateInfo, Make Sure OldDateInfoType==NewDateInfoType && NewBeginTime<=OldBeginTime && OldEndTime<= NewEndTime
+ * {@code invalid DateInfo, Make Sure OldDateInfoType==NewDateInfoType && NewBeginTime<=OldBeginTime && OldEndTime<= NewEndTime}
*/
CODE_40100(40100, "invalid DateInfo, Make Sure OldDateInfoType==NewDateInfoType && NewBeginTime<=OldBeginTime && OldEndTime<= NewEndTime"),
@@ -572,7 +572,7 @@ public enum WxOpenErrorMsgEnum {
CODE_40108(40108, "invalid client version"),
/**
- * too many code size, must <= 100
+ * {@code too many code size, must <= 100}
*/
CODE_40109(40109, "too many code size, must <= 100"),
@@ -702,7 +702,7 @@ public enum WxOpenErrorMsgEnum {
CODE_40135(40135, "invalid not supply bonus, can not change card_id which supply bonus to be not supply"),
/**
- * invalid use DepositCodeMode, make sure sku.quantity>DepositCode.quantity
+ * {@code invalid use DepositCodeMode, make sure sku.quantity>DepositCode.quantity}
*/
CODE_40136(40136, "invalid use DepositCodeMode, make sure sku.quantity>DepositCode.quantity"),
@@ -1082,7 +1082,7 @@ public enum WxOpenErrorMsgEnum {
CODE_40211(40211, "invalid scope_data"),
/**
- * paegs 当中存在不合法的query,query格式遵循URL标准,即k1=v1&k2=v2 invalid query
+ * {@code paegs 当中存在不合法的query,query格式遵循URL标准,即k1=v1&k2=v2 invalid query}
*/
CODE_40212(40212, "paegs 当中存在不合法的query,query格式遵循URL标准,即k1=v1&k2=v2"),
@@ -4242,7 +4242,7 @@ public enum WxOpenErrorMsgEnum {
CODE_71005(71005, "limit exe count"),
/**
- * limit coin count, 1 <= coin_count <= 100000
+ * {@code limit coin count, 1 <= coin_count <= 100000}
*/
CODE_71006(71006, "limit coin count, 1 <= coin_count <= 100000"),
@@ -4347,7 +4347,7 @@ public enum WxOpenErrorMsgEnum {
CODE_72018(72018, "duplicate order id, invoice had inserted to user"),
/**
- * limit msg operation card list size, must <= 5
+ * {@code limit msg operation card list size, must <= 5}
*/
CODE_72019(72019, "limit msg operation card list size, must <= 5"),
@@ -6432,7 +6432,7 @@ public enum WxOpenErrorMsgEnum {
CODE_88009(88009, "reply is not exists"),
/**
- * count range error. cout <= 0 or count > 50
+ * {@code count range error. cout <= 0 or count > 50}
*/
CODE_88010(88010, "count range error. cout <= 0 or count > 50"),
@@ -6682,7 +6682,7 @@ public enum WxOpenErrorMsgEnum {
CODE_89251(89251, "模板消息已下发,待法人人脸核身校验"),
/**
- * 法人&企业信息一致性校验中 front checking
+ * {@code 法人&企业信息一致性校验中 front checking}
*/
CODE_89253(89253, "法人&企业信息一致性校验中"),
@@ -7257,7 +7257,7 @@ public enum WxOpenErrorMsgEnum {
CODE_200021(200021, "场景描述 sceneDesc 参数错误"),
/**
- * 禁止创建/更新商品(如商品创建功能被封禁) 或 禁止编辑&更新房间
+ * {@code 禁止创建/更新商品(如商品创建功能被封禁) 或 禁止编辑&更新房间}
*/
CODE_300001(300001, "禁止创建/更新商品(如商品创建功能被封禁) 或 禁止编辑&更新房间"),
@@ -8382,7 +8382,7 @@ public enum WxOpenErrorMsgEnum {
CODE_9300003(9300003, "begin_time must less than end_time"),
/**
- * end_time - begin_time > 1year
+ * {@code end_time - begin_time > 1year}
*/
CODE_9300004(9300004, "end_time - begin_time > 1year"),
@@ -8397,7 +8397,7 @@ public enum WxOpenErrorMsgEnum {
CODE_9300006(9300006, "invalid activity status"),
/**
- * gift_num must >0 and <=15
+ * {@code gift_num must >0 and <=15}
*/
CODE_9300007(9300007, "gift_num must >0 and <=15"),
@@ -8412,7 +8412,7 @@ public enum WxOpenErrorMsgEnum {
CODE_9300009(9300009, "activity can not finish"),
/**
- * card_info_list must >= 2
+ * {@code card_info_list must >= 2}
*/
CODE_9300010(9300010, "card_info_list must >= 2"),
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/redis/RedisTemplateWxRedisOps.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/redis/RedisTemplateWxRedisOps.java
index 19d4046c92..d531a2a307 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/redis/RedisTemplateWxRedisOps.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/redis/RedisTemplateWxRedisOps.java
@@ -29,7 +29,7 @@ public void setValue(String key, String value, int expire, TimeUnit timeUnit) {
@Override
public Long getExpire(String key) {
- return redisTemplate.getExpire(key);
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
@Override
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOcrService.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOcrService.java
index 39a8a93754..d0aeef8491 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOcrService.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/service/WxOcrService.java
@@ -12,7 +12,9 @@
/**
* 基于小程序或 H5 的身份证、银行卡、行驶证 OCR 识别.
- * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21516712284rHWMX
+ *
+ * 参考:{@code https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21516712284rHWMX}
+ *
*
* @author Binary Wang
* created on 2019-06-22
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java
index e3d9ab8351..24ea58ef38 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/InternalSessionManager.java
@@ -7,13 +7,12 @@ public interface InternalSessionManager {
/**
* Return the active Session, associated with this Manager, with the
- * specified session id (if any); otherwise return null.
+ * specified session id (if any); otherwise return {@code null}.
*
* @param id The session id for the session to be returned
+ * @return the session or null
* @throws IllegalStateException if a new session cannot be
* instantiated for any reason
- * @throws java.io.IOException if an input/output error occurs while
- * processing this request
*/
InternalSession findSession(String id);
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java
index fc3579d45c..1886209f98 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/SignUtils.java
@@ -25,6 +25,7 @@ public class SignUtils {
*
* @param message 签名数据
* @param key 签名密钥
+ * @return 签名结果
*/
public static String createHmacSha256Sign(String message, String key) {
try {
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java
index 9b9f776768..43cc54b43d 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java
@@ -29,7 +29,10 @@ public static String gen(String... arr) {
}
/**
- * 用&串接arr参数,生成sha1 digest.
+ * {@code 用&串接arr参数,生成sha1 digest.}
+ *
+ * @param arr 参数数组
+ * @return sha1摘要
*/
public static String genWithAmple(String... arr) {
if (StringUtils.isAnyEmpty(arr)) {
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
index 0b0590b1e6..50362636fc 100755
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
@@ -197,6 +197,7 @@ public EncryptContext encryptContext(String plainText) {
/**
* 对明文进行加密.
*
+ * @param randomStr 随机字符串
* @param plainText 需要加密的明文
* @return 加密后base64编码的字符串
*/
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamData.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamData.java
index d07873f3c4..f03932984f 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamData.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/InputStreamData.java
@@ -10,8 +10,9 @@
/**
* 输入流数据.
- *
+ *
* InputStreamData
+ *
*
* @author zichuan.zhou91@gmail.com
* created on 2022/2/15
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java
index de34ca5bd1..5b13e7cc17 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheHttpClientBuilder.java
@@ -21,42 +21,66 @@ public interface ApacheHttpClientBuilder {
/**
* 代理服务器地址.
+ *
+ * @param httpProxyHost 代理服务器地址
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
/**
* 代理服务器端口.
+ *
+ * @param httpProxyPort 代理服务器端口
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
/**
* 代理服务器用户名.
+ *
+ * @param httpProxyUsername 代理服务器用户名
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
/**
* 代理服务器密码.
+ *
+ * @param httpProxyPassword 代理服务器密码
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword);
/**
* 重试策略.
+ *
+ * @param httpRequestRetryHandler 重试处理器
+ * @return ApacheHttpClientBuilder
*/
- ApacheHttpClientBuilder httpRequestRetryHandler(HttpRequestRetryHandler httpRequestRetryHandler );
+ ApacheHttpClientBuilder httpRequestRetryHandler(HttpRequestRetryHandler httpRequestRetryHandler);
/**
* 超时时间.
+ *
+ * @param keepAliveStrategy 保持连接策略
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy);
/**
* ssl连接socket工厂.
+ *
+ * @param sslConnectionSocketFactory SSL连接Socket工厂
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory);
/**
* 支持的TLS协议版本.
* Supported TLS protocol versions.
+ *
+ * @param supportedProtocols 支持的协议版本数组
+ * @return ApacheHttpClientBuilder
*/
ApacheHttpClientBuilder supportedProtocols(String[] supportedProtocols);
}
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java
index 6ea269f7e4..8f3dafe48a 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxGsonBuilder.java
@@ -43,6 +43,11 @@ public boolean shouldSkipClass(Class> aClass) {
});
}
+ /**
+ * 创建Gson实例
+ *
+ * @return Gson实例
+ */
public static Gson create() {
if (Objects.isNull(GSON_INSTANCE)) {
synchronized (INSTANCE) {
diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java
index 3fa91fa70e..51cd1e980c 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/xml/XStreamInitializer.java
@@ -22,6 +22,11 @@ public class XStreamInitializer {
public static ClassLoader classLoader;
+ /**
+ * 设置类加载器
+ *
+ * @param classLoaderInfo 类加载器
+ */
public static void setClassLoader(ClassLoader classLoaderInfo) {
classLoader = classLoaderInfo;
}
diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/redis/CommonWxRedisOpsTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/redis/CommonWxRedisOpsTest.java
index 96ba20ba2b..fb53c8c4b6 100644
--- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/redis/CommonWxRedisOpsTest.java
+++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/redis/CommonWxRedisOpsTest.java
@@ -35,6 +35,17 @@ public void testGetExpire() {
Assert.assertTrue(expireSeconds <= 4 && expireSeconds >= 0);
}
+ @Test
+ public void testGetExpireForNonExistentKey() {
+ String nonExistentKey = "non_existent_key_" + System.currentTimeMillis();
+ Long expire = wxRedisOps.getExpire(nonExistentKey);
+ // 对于不存在的 key,底层使用 getExpire(key, TimeUnit.SECONDS) 时应返回负值
+ // Spring Data Redis 2.x 和 3.x 约定:-2 表示 key 不存在,-1 表示 key 没有过期时间
+ // 因此这里不应返回 null,而应返回一个小于 0 的值
+ Assert.assertNotNull(expire, "Non-existent key should not have null expiration");
+ Assert.assertTrue(expire < 0, "Non-existent key should have negative expiration");
+ }
+
@Test
public void testExpire() {
String key = "access_token", value = String.valueOf(System.currentTimeMillis());
diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml
index 6c47176afc..922d4f6b84 100644
--- a/weixin-java-cp/pom.xml
+++ b/weixin-java-cp/pom.xml
@@ -7,7 +7,7 @@
com.github.binarywang
wx-java
- 4.8.0
+ 4.8.1.B
weixin-java-cp
@@ -30,6 +30,11 @@
okhttp
provided
+
+ *
* 请求方式:POST(HTTPS)
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_unassigned_list?access_token=ACCESS_TOKEN
*
@@ -496,17 +498,17 @@ WxCpExternalContactBatchInfo getContactDetailBatch(String[] userIdList, String c
/**
* 企业可通过此接口,转接在职成员的客户给其他成员。
- *
+ *
* 权限说明:
- * * 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。
- * 第三方应用需拥有“企业客户权限->客户联系->在职继承”权限
+ * 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。
+ * {@code 第三方应用需拥有“企业客户权限->客户联系->在职继承”权限}
* 接替成员必须在此第三方应用或自建应用的可见范围内。
* 接替成员需要配置了客户联系功能。
* 接替成员需要在企业微信激活且已经过实名认证。
- *
+ *
* 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。
- * 第三方应用需拥有“企业客户权限->客户联系->在职继承”权限
+ * {@code 第三方应用需拥有“企业客户权限->客户联系->在职继承”权限}
* 接替成员必须在此第三方应用或自建应用的可见范围内。
- *
+
+ *
* 权限说明:
- *
+
+ *
* 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。
- * 第三方应用需拥有“企业客户权限->客户联系->离职分配”权限
+ * {@code 第三方应用需拥有“企业客户权限->客户联系->离职分配”权限}
* 接替成员必须在此第三方应用或自建应用的可见范围内。
* 接替成员需要配置了客户联系功能。
* 接替成员需要在企业微信激活且已经过实名认证。
- *
+
+ *
* 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。
- * 第三方应用需拥有“企业客户权限->客户联系->在职继承”权限
+ * {@code 第三方应用需拥有“企业客户权限->客户联系->在职继承”权限}
* 接替成员必须在此第三方应用或自建应用的可见范围内。
- *
+
+ *
* 群主离职了的客户群,才可继承
* 继承给的新群主,必须是配置了客户联系功能的成员
* 继承给的新群主,必须有设置实名
* 继承给的新群主,必须有激活企业微信
* 同一个人的群,限制每天最多分配300个给新群主
- *
+
+ *
* 权限说明:
- *
+
+ *
* 企业需要使用“客户联系”secret或配置到“可调用应用”列表中的自建应用secret所获取的accesstoken来调用(accesstoken如何获取?)。
- * 第三方应用需拥有“企业客户权限->客户联系->分配离职成员的客户群”权限
+ * {@code 第三方应用需拥有“企业客户权限->客户联系->分配离职成员的客户群”权限}
* 对于第三方/自建应用,群主必须在应用的可见范围。
- *
+
+ *
* 请求方式: POST(HTTP)
- *
+
+ *
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_msg_template?access_token=ACCESS_TOKEN
- *
+
+ *
* 文档地址
*
* @param wxCpMsgTemplate the wx cp msg template
@@ -733,15 +744,18 @@ WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime, Integer
/**
* 提醒成员群发
* 企业和第三方应用可调用此接口,重新触发群发通知,提醒成员完成群发任务,24小时内每个群发最多触发三次提醒。
- *
+
+ *
* 请求方式: POST(HTTPS)
- *
+
+ *
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remind_groupmsg_send?access_token=ACCESS_TOKEN
- *
+ *
* 文档地址
*
* @param msgId 群发消息的id,通过获取群发记录列表接口返回
* @return the wx cp msg template add result
+ * @throws WxErrorException 微信错误异常
*/
WxCpBaseResp remindGroupMsgSend(String msgId) throws WxErrorException;
@@ -753,11 +767,12 @@ WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime, Integer
* 请求方式: POST(HTTPS)
*
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/cancel_groupmsg_send?access_token=ACCESS_TOKEN
- *
+ *
* 文档地址
*
* @param msgId 群发消息的id,通过获取群发记录列表接口返回
* @return the wx cp msg template add result
+ * @throws WxErrorException 微信错误异常
*/
WxCpBaseResp cancelGroupMsgSend(String msgId) throws WxErrorException;
@@ -1002,7 +1017,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
+ * 注意:
+ * 根据上面返回的文件类型,拼接好存放文件的绝对路径即可。此时绝对路径写入文件流,来达到获取媒体文件的目的。
+ * 详情可以看官方文档,亦可阅读此接口源码。
+ *
+ * @param sdkfileid 消息体内容中的sdkfileid信息
+ * @param proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081,如果没有传null
+ * @param passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123,如果没有传null
+ * @param timeout 超时时间,分片数据需累加到文件存储。单次最大返回512K字节,如果文件比较大,自行设置长一点,比如timeout=10000
+ * @param targetFilePath 目标文件绝对路径+实际文件名,比如:/usr/local/file/20220114/474f866b39d10718810d55262af82662.gif
+ * @throws WxErrorException the wx error exception
+ */
+ void downloadMediaFile(@NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout,
+ @NonNull String targetFilePath) throws WxErrorException;
+
/**
* 获取媒体文件 传入一个lambda,each所有的数据分片byte[],更加灵活
* 针对图片、文件等媒体数据,提供sdk接口拉取数据内容。
@@ -85,10 +152,29 @@ void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, St
* @param timeout 超时时间,分片数据需累加到文件存储。单次最大返回512K字节,如果文件比较大,自行设置长一点,比如timeout=10000
* @param action 传入一个lambda,each所有的数据分片
* @throws WxErrorException the wx error exception
+ * @deprecated 请使用 {@link #downloadMediaFile(String, String, String, long, Consumer)} 代替,
+ * 该方法需要传入SDK,容易导致SDK生命周期管理混乱,引发JVM崩溃
*/
+ @Deprecated
void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout,
@NonNull Consumer
+ *
+ *
+ * 注意:
+ * 1.批量更新请求中的各个操作会逐个按顺序执行,直到全部执行完成则请求返回,或者其中一个操作报错则不再继续执行后续的操作
+ * 2.每一个更新操作在执行之前都会做请求校验(包括权限校验、参数校验等等),如果校验未通过则该更新操作会报错并返回,不再执行后续操作
+ * 3.单次批量更新请求的操作数量 <= 5
+ *
+ * 请求方式:POST(HTTPS)
+ * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedoc/spreadsheet/batch_update?access_token=ACCESS_TOKEN
+ *
+ * @param request 编辑表格内容请求参数
+ * @return 编辑表格内容批量更新的响应结果
+ * @throws WxErrorException the wx error exception
+ */
+ WxCpDocSheetBatchUpdateResponse docBatchUpdate(@NonNull WxCpDocSheetBatchUpdateRequest request) throws WxErrorException;
+
+ /**
+ * 获取表格行列信息
+ * 该接口用于获取在线表格的工作表、行数、列数等。
+ *
+ * 请求方式:POST(HTTPS)
+ * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedoc/spreadsheet/get_sheet_properties?access_token=ACCESS_TOKEN
+ *
+ * @param docId 在线表格的docid
+ * @return 返回表格行列信息
+ * @throws WxErrorException
+ */
+ WxCpDocSheetProperties getSheetProperties(@NonNull String docId) throws WxErrorException;
+
+
+ /**
+ * 本接口用于获取指定范围内的在线表格信息,单次查询的范围大小需满足以下限制:
+ *
+ * 查询范围行数 <=1000
+ * 查询范围列数 <=200
+ * 范围内的总单元格数量 <=10000
+ *
+ * 请求方式:POST(HTTPS)
+ * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/wedoc/spreadsheet/get_sheet_range_data?access_token=ACCESS_TOKEN
+ *
+ * @param request 获取指定范围内的在线表格信息请求参数
+ * @return 返回指定范围内的在线表格信息
+ * @throws WxErrorException
+ */
+ WxCpDocSheetData getSheetRangeData(@NonNull WxCpDocSheetGetDataRequest request) throws WxErrorException;
+
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java
index 56687c9cb1..5f1d41c197 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolService.java
@@ -80,9 +80,10 @@ public interface WxCpSchoolService {
/**
* 获取直播详情
+ *
+ *
+ *
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=ACCESS_TOKEN&external_userid
- * =EXTERNAL_USERID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=ACCESS_TOKEN&external_userid=EXTERNAL_USERID}
*
* @param externalUserId 外部联系人的userid,注意不是学校成员的帐号
* @return external contact
@@ -306,9 +315,9 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 获取可使用的家长范围
* 获取可在微信「学校通知-学校应用」使用该应用的家长范围,以学生或部门列表的形式返回。应用只能给该列表下的家长发送「学校通知」。注意该范围只能由学校的系统管理员在「管理端-家校沟通-配置」配置。
- *
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/agent/get_allow_scope?access_token=ACCESS_TOKEN&agentid=AGENTID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/agent/get_allow_scope?access_token=ACCESS_TOKEN&agentid=AGENTID}
*
* @param agentId the agent id
* @return allow scope
@@ -332,7 +341,7 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 获取部门列表
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/list?access_token=ACCESS_TOKEN&id=ID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/list?access_token=ACCESS_TOKEN&id=ID}
*
* @param id 部门id。获取指定部门及其下的子部门。 如果不填,默认获取全量组织架构
* @return wx cp department list
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
index 0b601ca502..76012a2812 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
@@ -584,7 +584,7 @@ public interface WxCpService extends WxService {
/**
* 企业互联的服务类对象
*
- * @return
+ * @return 企业互联服务对象
*/
WxCpCorpGroupService getCorpGroupService();
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
index 2368386b23..7a7b5f40a8 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpUserService.java
@@ -38,7 +38,7 @@ public interface WxCpUserService {
*
- * Created by songfan on 2020/7/14.
*
- * @author songfan & Mr.Pan
+ * @author songfan, Mr.Pan
+ * @since 2020/7/14
*/
@Data
@Builder
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalUnassignList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalUnassignList.java
index 8605760fa7..f3fdd96ce7 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalUnassignList.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalUnassignList.java
@@ -12,7 +12,8 @@
/**
* 离职员工外部联系人列表
*
- * @author yqx & Wang_Wong created on 2020/3/15
+ * @author yqx, Wang_Wong
+ * @since 2020/3/15
*/
@Getter
@Setter
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/acquisition/WxCpCustomerAcquisitionStatistic.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/acquisition/WxCpCustomerAcquisitionStatistic.java
index bb02b039bd..87e3d5580a 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/acquisition/WxCpCustomerAcquisitionStatistic.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/acquisition/WxCpCustomerAcquisitionStatistic.java
@@ -10,7 +10,7 @@
* 获客链接的使用详情
*
* @author Hugo
- * @date 2023/12/11 10:31
+ * @since 2023/12/11 10:31
*/
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleInfo.java
index 20d6b32442..23bb70a240 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleInfo.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleInfo.java
@@ -10,9 +10,10 @@
import java.util.List;
/**
- * @Date: 2024-03-07 17:02
- * @Author: shenliuming
- * @return:
+ * 防骚扰规则详情
+ *
+ * @author shenliuming
+ * @since 2024-03-07 17:02
*/
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleList.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleList.java
index 6826413e13..543d32fcb9 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleList.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/interceptrule/WxCpInterceptRuleList.java
@@ -9,9 +9,10 @@
import java.util.List;
/**
- * @Date: 2024-03-07 15:54
- * @Author: shenliuming
- * @return:
+ * 防骚扰规则列表
+ *
+ * @author shenliuming
+ * @since 2024-03-07 15:54
*/
@Data
@EqualsAndHashCode(callSuper = true)
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/msg/Attachment.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/msg/Attachment.java
index be9dcc9dd0..1fff457f97 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/msg/Attachment.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/external/msg/Attachment.java
@@ -33,6 +33,7 @@ public class Attachment implements Serializable {
* Sets image.
*
* @param image the image
+ * @return this
*/
public Attachment setImage(Image image) {
this.image = image;
@@ -44,6 +45,7 @@ public Attachment setImage(Image image) {
* Sets link.
*
* @param link the link
+ * @return this
*/
public Attachment setLink(Link link) {
this.link = link;
@@ -55,6 +57,7 @@ public Attachment setLink(Link link) {
* Sets mini program.
*
* @param miniProgram the mini program
+ * @return this
*/
public Attachment setMiniProgram(MiniProgram miniProgram) {
this.miniProgram = miniProgram;
@@ -66,6 +69,7 @@ public Attachment setMiniProgram(MiniProgram miniProgram) {
* Sets video.
*
* @param video the video
+ * @return this
*/
public Attachment setVideo(Video video) {
this.video = video;
@@ -77,6 +81,7 @@ public Attachment setVideo(Video video) {
* Sets file.
*
* @param file the file
+ * @return this
*/
public Attachment setFile(File file) {
this.file = file;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfAccountLink.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfAccountLink.java
index a903d0fa54..38d25e61cd 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfAccountLink.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfAccountLink.java
@@ -27,10 +27,10 @@ public class WxCpKfAccountLink implements Serializable {
* 场景值,字符串类型,由开发者自定义。
* 不多于32字节
* 字符串取值范围(正则表达式):[0-9a-zA-Z_-]*
- *
+ *
* 1. 若scene非空,返回的客服链接开发者可拼接scene_param=SCENE_PARAM参数使用,用户进入会话事件会将SCENE_PARAM原样返回。
* 其中SCENE_PARAM需要urlencode,且长度不能超过128字节。
- * 如 https://work.weixin.qq.com/kf/kfcbf8f8d07ac7215f?enc_scene=ENCGFSDF567DF&scene_param=a%3D1%26b%3D2
+ * {@code 如 https://work.weixin.qq.com/kf/kfcbf8f8d07ac7215f?enc_scene=ENCGFSDF567DF&scene_param=a%3D1%26b%3D2}
* 2. 历史调用接口返回的客服链接(包含encScene=XXX参数),不支持scene_param参数。
* 3. 返回的客服链接,不能修改或复制参数到其他链接使用。否则进入会话事件参数校验不通过,导致无法回调。
*/
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlReq.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlReq.java
index c5cb21bde5..0149a426f6 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlReq.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlReq.java
@@ -5,8 +5,9 @@
/**
* 生成异步上传任务
+ *
* @author imyzt
- * @date 2025/04/27
+ * @since 2025/04/27
*/
@Data
public class MediaUploadByUrlReq {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlResult.java
index cc931eed39..595f85dffa 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlResult.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/media/MediaUploadByUrlResult.java
@@ -10,8 +10,9 @@
/**
* 异步上传企微素材
+ *
* @author imyzt
- * @date 2025/4/27
+ * @since 2025/4/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java
index 92209fd4e5..7e777384eb 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpLinkedCorpMessage.java
@@ -85,13 +85,13 @@ public class WxCpLinkedCorpMessage implements Serializable {
/**
*
* 文档地址
- *
* 文档地址
- *
* external_userid必须是handover_userid的客户(即配置了客户联系功能的成员所添加的联系人)。
* 在职成员的每位客户最多被分配2次。客户被转接成功后,将有90个自然日的服务关系保护期,保护期内的客户无法再次被分配。
- *
* 权限说明:
- *
* handover_userid必须是已离职用户。
* external_userid必须是handover_userid的客户(即配置了客户联系功能的成员所添加的联系人)。
* 在职成员的每位客户最多被分配2次。客户被转接成功后,将有90个自然日的服务关系保护期,保护期内的客户无法再次被分配。
- *
* 权限说明:
- *
* 注意::
- *
* 注意:
* 继承给的新群主,必须是配置了客户联系功能的成员
* 继承给的新群主,必须有设置实名
@@ -716,11 +724,14 @@ WxCpUserExternalGroupChatStatistic getGroupChatStatistic(Date startTime, Integer
* 企业可通过此接口添加企业群发消息的任务并通知客服人员发送给相关客户或客户群。(注:企业微信终端需升级到2.7.5版本及以上)
* 注意:调用该接口并不会直接发送消息给客户/客户群,需要相关的客服人员操作以后才会实际发送(客服人员的企业微信需要升级到2.7.5及以上版本)
* 同一个企业每个自然月内仅可针对一个客户/客户群发送4条消息,超过限制的用户将会被忽略。
- *
*
* @param mediaId 媒体id
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java
index e49a36ba50..534cc89b36 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageService.java
@@ -72,8 +72,9 @@ public interface WxCpMessageService {
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/recall?access_token=ACCESS_TOKEN
* 文档地址: https://developer.work.weixin.qq.com/document/path/94867
*
+ *
* @param msgId 消息id
- * @throws WxErrorException
+ * @throws WxErrorException 异常
*/
void recall(String msgId) throws WxErrorException;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java
index 221caf2e70..b754e32b7e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMsgAuditService.java
@@ -28,9 +28,26 @@ public interface WxCpMsgAuditService {
* @param timeout 超时时间,根据实际需要填写
* @return 返回是否调用成功 chat datas
* @throws Exception the exception
+ * @deprecated 请使用 {@link #getChatRecords(long, long, String, String, long)} 代替,
+ * 该方法会将SDK暴露给调用方,容易导致SDK生命周期管理混乱,引发JVM崩溃
*/
+ @Deprecated
WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, String passwd, @NonNull long timeout) throws Exception;
+ /**
+ * 拉取聊天记录函数(推荐使用)
+ * 该方法不会将SDK暴露给调用方,SDK生命周期由框架自动管理,更加安全
+ *
+ * @param seq 从指定的seq开始拉取消息,注意的是返回的消息从seq+1开始返回,seq为之前接口返回的最大seq值。首次使用请使用seq:0
+ * @param limit 一次拉取的消息条数,最大值1000条,超过1000条会返回错误
+ * @param proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081,如果没有传null
+ * @param passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123,如果没有传null
+ * @param timeout 超时时间,根据实际需要填写
+ * @return 返回聊天记录列表,不包含SDK信息
+ * @throws Exception the exception
+ */
+ List
* 企业和第三方应用可通过此接口获取企业与成员的群发记录。
- * 获取企业群发成员执行结果
+ * 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/93338
*
*
* @param msgid 群发消息的id,通过获取群发记录列表接口返回
@@ -1031,7 +1046,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
* 获取群发成员发送任务列表。
- * 获取群发成员发送任务列表
+ * 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/93338
*
*
* @param msgid 群发消息的id,通过获取群发记录列表接口返回
@@ -1045,7 +1060,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
* 添加入群欢迎语素材。
- * 添加入群欢迎语素材
+ * 文档地址:https://open.work.weixin.qq.com/api/doc/90000/90135/92366
*
*
* @param template 素材内容
@@ -1057,7 +1072,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
* 编辑入群欢迎语素材。
- * 编辑入群欢迎语素材
+ * 文档地址:https://open.work.weixin.qq.com/api/doc/90000/90135/92366
*
*
* @param template the template
@@ -1069,7 +1084,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
* 获取入群欢迎语素材。
- * 获取入群欢迎语素材
+ * 文档地址:https://open.work.weixin.qq.com/api/doc/90000/90135/92366
*
*
* @param templateId 群欢迎语的素材id
@@ -1082,7 +1097,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
*
* 删除入群欢迎语素材。
* 企业可通过此API删除入群欢迎语素材,且仅能删除调用方自己创建的入群欢迎语素材。
- * 删除入群欢迎语素材
+ * 文档地址:https://open.work.weixin.qq.com/api/doc/90000/90135/92366
*
*
* @param templateId 群欢迎语的素材id
@@ -1094,8 +1109,8 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
- * 获取商品图册
- * 获取商品图册列表
+ * 获取商品图册列表
+ * 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/95096
*
*
* @param limit 返回的最大记录数,整型,最大值100,默认值50,超过最大值时取默认值
@@ -1108,7 +1123,7 @@ WxCpGroupMsgListResult getGroupMsgListV2(String chatType, Date startTime, Date e
/**
*
* 获取商品图册
- * 获取商品图册
+ * 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/95096
*
*
* @param productId 商品id
@@ -1155,7 +1170,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* 企业和第三方应用可以通过此接口新建敏感词规则
* 请求方式:POST(HTTPS)
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_intercept_rule?access_token=ACCESS_TOKEN
- *
+ *
* @param ruleAddRequest the rule add request
* @return 规则id
* @throws WxErrorException the wx error exception
@@ -1169,7 +1184,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* 企业和第三方应用可以通过此接口修改敏感词规则
* 请求方式:POST(HTTPS)
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/update_intercept_rule?access_token=ACCESS_TOKEN
- *
+ *
* @param interceptRule the rule
* @throws WxErrorException the wx error exception
*/
@@ -1181,7 +1196,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* 企业和第三方应用可以通过此接口修改敏感词规则
* 请求方式:POST(HTTPS)
* 请求地址
- *
+ *
* @param ruleId 规则id
* @throws WxErrorException the wx error exception
*/
@@ -1220,7 +1235,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* 请求地址:
* https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_product_album?access_token=ACCESS_TOKEN
* 文档地址
- *
+ *
* @param wxCpProductAlbumInfo 商品图册信息
* @return 商品id string
* @throws WxErrorException the wx error exception
@@ -1235,7 +1250,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* 请求地址:
* https://qyapi.weixin.qq.com/cgi-bin/externalcontact/update_product_album?access_token=ACCESS_TOKEN
* 文档地址
- *
+ *
* @param wxCpProductAlbumInfo 商品图册信息
* @throws WxErrorException the wx error exception
*/
@@ -1250,7 +1265,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* https://qyapi.weixin.qq.com/cgi-bin/externalcontact/delete_product_album?access_token=ACCESS_TOKEN
*
* 文档地址
- *
+ *
* @param productId 商品id
* @throws WxErrorException the wx error exception
*/
@@ -1379,7 +1394,7 @@ WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, F
* 请求地址:https://qyapi.weixin.qq.com/cgi-bin/externalcontact/customer_acquisition/statistic?access_token=ACCESS_TOKEN
*
* @author Hugo
- * @date 2023/12/5 14:34
+ * @since 2023/12/5 14:34
* @param linkId 获客链接的id
* @param startTime 统计起始时间
* @param endTime 统计结束时间
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java
index c1a8d56255..b8ccea5e50 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpGroupRobotService.java
@@ -126,9 +126,10 @@ public interface WxCpGroupRobotService {
/**
* 发送模板卡片消息
- * @param webhookUrl
- * @param wxCpGroupRobotMessage
- * @throws WxErrorException
+ *
+ * @param webhookUrl webhook地址
+ * @param wxCpGroupRobotMessage 群机器人消息
+ * @throws WxErrorException 异常
*/
void sendTemplateCardMessage(String webhookUrl, WxCpGroupRobotMessage wxCpGroupRobotMessage) throws WxErrorException;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java
index 5a53829dc0..046cfbc5bb 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java
@@ -222,7 +222,7 @@ WxCpKfCustomerBatchGetResp customerBatchGet(List
+ *
* @param request 查询参数
* @return 客户数据统计 -企业汇总数据
* @throws WxErrorException the wx error exception
@@ -238,7 +238,7 @@ WxCpKfCustomerBatchGetResp customerBatchGet(List
+ *
* @param request 查询参数
* @return 客户数据统计 -企业汇总数据
* @throws WxErrorException the wx error exception
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index a2e2344190..63fabad7a1 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -27,7 +27,7 @@ public interface WxCpLivingService {
/**
* 获取直播详情
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_living_info?access_token=ACCESS_TOKEN&livingid=LIVINGID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_living_info?access_token=ACCESS_TOKEN&livingid=LIVINGID}
*
* @param livingId 直播id
* @return 获取的直播详情 living info
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java
index e874b26f42..dd5ce594b2 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMediaService.java
@@ -110,9 +110,9 @@ WxMediaUploadResult upload(String mediaType, String filename, String url)
* 获取高清语音素材.
* 可以使用本接口获取从JSSDK的uploadVoice接口上传的临时语音素材,格式为speex,16K采样率。该音频比上文的临时素材获取接口(格式为amr,8K采样率)更加清晰,适合用作语音识别等对音质要求较高的业务。
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get/jssdk?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get/jssdk?access_token=ACCESS_TOKEN&media_id=MEDIA_ID}
* 仅企业微信2.4及以上版本支持。
- * 文档地址:https://work.weixin.qq.com/api/doc#90000/90135/90255
+ * 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/90255
*
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE}
+ *
*
* @param code the code
* @return school user info
@@ -123,7 +124,7 @@ public interface WxCpOAuth2Service {
/**
*
* 获取用户登录身份
- * https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
+ * {@code https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=ACCESS_TOKEN&code=CODE}
* 该接口可使用用户登录成功颁发的code来获取成员信息,适用于自建应用与代开发应用
*
* 注意: 旧的/user/getuserinfo 接口的url已变更为auth/getuserinfo,不过旧接口依旧可以使用,建议是关注新接口即可
@@ -140,13 +141,15 @@ public interface WxCpOAuth2Service {
/**
* 获取用户二次验证信息
- *
*
* @param wxCpOaMeetingRoomBookingInfoRequest 会议室预定信息查询对象
+ * @return 会议室预定信息
* @throws WxErrorException .
*/
WxCpOaMeetingRoomBookingInfoResult getMeetingRoomBookingInfo(WxCpOaMeetingRoomBookingInfoRequest wxCpOaMeetingRoomBookingInfoRequest) throws WxErrorException;
@@ -99,6 +100,7 @@ public interface WxCpOaMeetingRoomService {
*
*
* @param wxCpOaMeetingRoomBookRequest 会议室预定对象
+ * @return 预定结果
* @throws WxErrorException .
*/
WxCpOaMeetingRoomBookResult bookingMeetingRoom(WxCpOaMeetingRoomBookRequest wxCpOaMeetingRoomBookRequest) throws WxErrorException;
@@ -114,6 +116,7 @@ public interface WxCpOaMeetingRoomService {
*
*
* @param wxCpOaMeetingRoomBookByScheduleRequest 会议室预定对象
+ * @return 预定结果
* @throws WxErrorException .
*/
WxCpOaMeetingRoomBookResult bookingMeetingRoomBySchedule(WxCpOaMeetingRoomBookByScheduleRequest wxCpOaMeetingRoomBookByScheduleRequest) throws WxErrorException;
@@ -129,6 +132,7 @@ public interface WxCpOaMeetingRoomService {
*
*
* @param wxCpOaMeetingRoomBookByMeetingRequest 会议室预定对象
+ * @return 预定结果
* @throws WxErrorException .
*/
WxCpOaMeetingRoomBookResult bookingMeetingRoomByMeeting(WxCpOaMeetingRoomBookByMeetingRequest wxCpOaMeetingRoomBookByMeetingRequest) throws WxErrorException;
@@ -147,10 +151,10 @@ public interface WxCpOaMeetingRoomService {
* @param wxCpOaMeetingRoomCancelBookRequest 取消预定会议室对象
* @throws WxErrorException .
*/
- void cancelBookMeetingRoom(WxCpOaMeetingRoomCancelBookRequest wxCpOaMeetingRoomCancelBookRequest) throws WxErrorException;
+ void cancelBookMeetingRoom(WxCpOaMeetingRoomCancelBookRequest wxCpOaMeetingRoomCancelBookRequest) throws WxErrorException;
- /**
+ /**
* 根据会议室预定ID查询预定详情.
*
* api: https://qyapi.weixin.qq.com/cgi-bin/auth/get_tfa_info?access_token=ACCESS_TOKEN
* 权限说明:仅『通讯录同步』或者自建应用可调用,如用自建应用调用,用户需要在二次验证范围和应用可见范围内。
* 并发限制:20
+ *
*
* @param code 用户进入二次验证页面时,企业微信颁发的code,每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期
- * @return me.chanjar.weixin.cp.bean.workbench.WxCpSecondVerificationInfo 二次验证授权码,开发者可以调用通过二次验证接口,解锁企业微信终端.tfa_code有效期五分钟,且只能使用一次。
+ * @return 二次验证授权码,开发者可以调用通过二次验证接口,解锁企业微信终端.tfa_code有效期五分钟,且只能使用一次。
+ * @throws WxErrorException 微信错误异常
*/
WxCpSecondVerificationInfo getTfaInfo(String code) throws WxErrorException;
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java
index c2e6c5c872..cc039fd9f5 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaMeetingRoomService.java
@@ -84,6 +84,7 @@ public interface WxCpOaMeetingRoomService {
*
* 企业可通过此接口根据预定id查询相关会议室的预定情况
@@ -161,8 +165,9 @@ public interface WxCpOaMeetingRoomService {
*
*
* @param wxCpOaMeetingRoomBookingInfoByBookingIdRequest 根据会议室预定ID查询预定详情对象
+ * @return 预定详情
* @throws WxErrorException .
*/
- WxCpOaMeetingRoomBookingInfoByBookingIdResult getBookingInfoByBookingId(WxCpOaMeetingRoomBookingInfoByBookingIdRequest wxCpOaMeetingRoomBookingInfoByBookingIdRequest) throws WxErrorException;
+ WxCpOaMeetingRoomBookingInfoByBookingIdResult getBookingInfoByBookingId(WxCpOaMeetingRoomBookingInfoByBookingIdRequest wxCpOaMeetingRoomBookingInfoByBookingIdRequest) throws WxErrorException;
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java
index ee57107b5c..3494dcfa4e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaService.java
@@ -11,7 +11,8 @@
/**
* 企业微信OA相关接口.
*
- * @author Element & Wang_Wong created on 2019-04-06 10:52
+ * @author Element, Wang_Wong
+ * @since 2019-04-06 10:52
*/
public interface WxCpOaService {
@@ -331,7 +332,7 @@ List
+ *
* @param userId 需要录入的用户id
* @param userFace 需要录入的人脸图片数据,需要将图片数据base64处理后填入,对已录入的人脸会进行更新处理
* @throws WxErrorException the wx error exception
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDocService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDocService.java
index 1356c839b2..d63d32694a 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDocService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpOaWeDocService.java
@@ -78,4 +78,53 @@ public interface WxCpOaWeDocService {
* @throws WxErrorException the wx error exception
*/
WxCpDocShare docShare(@NonNull String docId) throws WxErrorException;
+
+ /**
+ * 编辑表格内容
+ * 该接口可以对一个在线表格批量执行多个更新操作
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/living/get_living_info?access_token=ACCESS_TOKEN&livingid
- * =LIVINGID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/living/get_living_info?access_token=ACCESS_TOKEN&livingid=LIVINGID}
+ *
*
* @param livingId the living id
* @return living info
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java
index a92bfcc100..d004ca8aa5 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpSchoolUserService.java
@@ -19,9 +19,10 @@ public interface WxCpSchoolUserService {
/**
* 获取访问用户身份
* 该接口用于根据code获取成员信息
- *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE}
+ *
*
* @param code the code
* @return user info
@@ -32,9 +33,10 @@ public interface WxCpSchoolUserService {
/**
* 获取家校访问用户身份
* 该接口用于根据code获取家长或者学生信息
- *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/getuserinfo?access_token=ACCESS_TOKEN&code=CODE}
+ *
*
* @param code the code
* @return school user info
@@ -90,8 +92,10 @@ public interface WxCpSchoolUserService {
/**
* 删除学生
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/delete_student?access_token=ACCESS_TOKEN&userid=USERID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/delete_student?access_token=ACCESS_TOKEN&userid=USERID}
+ *
*
* @param studentUserId the student user id
* @return wx cp base resp
@@ -160,8 +164,10 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 读取学生或家长
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/get?access_token=ACCESS_TOKEN&userid=USERID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/get?access_token=ACCESS_TOKEN&userid=USERID}
+ *
*
* @param userId the user id
* @return user
@@ -171,9 +177,10 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 获取部门成员详情
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID
- * &fetch_child=FETCH_CHILD
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD}
+ *
*
* @param departmentId 获取的部门id
* @param fetchChild 1/0:是否递归获取子部门下面的成员
@@ -184,9 +191,10 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 获取部门家长详情
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/list_parent?access_token=ACCESS_TOKEN&department_id
- * =DEPARTMENT_ID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/list_parent?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID}
+ *
*
* @param departmentId 获取的部门id
* @return user list parent
@@ -207,8 +215,10 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 删除家长
+ *
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/delete_parent?access_token=ACCESS_TOKEN&userid=USERID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/user/delete_parent?access_token=ACCESS_TOKEN&userid=USERID}
+ *
*
* @param userId the user id
* @return wx cp base resp
@@ -256,7 +266,7 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 删除部门
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/delete?access_token=ACCESS_TOKEN&id=ID
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/school/department/delete?access_token=ACCESS_TOKEN&id=ID}
*
* @param id the id
* @return wx cp base resp
@@ -292,10 +302,9 @@ WxCpBaseResp updateStudent(@NonNull String studentUserId, String newStudentUserI
/**
* 获取外部联系人详情
* 学校可通过此接口,根据外部联系人的userid(如何获取?),拉取外部联系人详情。
- *
* 获取部门成员详情
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD}
*
* 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/90201
*
@@ -213,7 +213,7 @@ public interface WxCpUserService {
* 获取加入企业二维码。
*
* 请求方式:GET(HTTPS)
- * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/corp/get_join_qrcode?access_token=ACCESS_TOKEN&size_type=SIZE_TYPE
+ * {@code 请求地址:https://qyapi.weixin.qq.com/cgi-bin/corp/get_join_qrcode?access_token=ACCESS_TOKEN&size_type=SIZE_TYPE}
*
* 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/91714
*
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java
index 48bd952a83..e3dc1cbe1c 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpCorpGroupServiceImpl.java
@@ -18,7 +18,7 @@
* 企业互联相关接口实现类
*
* @author libo <422423229@qq.com>
- * Created on 27/2/2023 9:57 PM
+ * @since 2023-02-27 9:57 PM
*/
@RequiredArgsConstructor
public class WxCpCorpGroupServiceImpl implements WxCpCorpGroupService {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java
index 8e3a8d7b95..d43589595f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpExternalContactServiceImpl.java
@@ -38,7 +38,7 @@
/**
* The type Wx cp external contact service.
*
- * @author 曹祖鹏 & yuanqixun & Mr.Pan & Wang_Wong
+ * @author 曹祖鹏, yuanqixun, Mr.Pan, Wang_Wong
*/
@RequiredArgsConstructor
public class WxCpExternalContactServiceImpl implements WxCpExternalContactService {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java
index cdf559ad7a..63dc7ac007 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java
@@ -20,6 +20,7 @@
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
@@ -137,6 +138,49 @@ private synchronized long initSdk() throws WxErrorException {
return sdk;
}
+ /**
+ * 获取SDK并增加引用计数(原子操作)
+ * 如果SDK未初始化或已过期,会自动初始化
+ *
+ * @return sdk id
+ * @throws WxErrorException 初始化失败时抛出异常
+ */
+ private long acquireSdk() throws WxErrorException {
+ WxCpConfigStorage configStorage = cpService.getWxCpConfigStorage();
+
+ // 尝试获取现有的有效SDK并增加引用计数(原子操作)
+ long sdk = configStorage.acquireMsgAuditSdk();
+
+ if (sdk > 0) {
+ // 成功获取到有效的SDK
+ return sdk;
+ }
+
+ // SDK未初始化或已过期,需要初始化
+ // initSdk()方法已经是synchronized的,确保只有一个线程初始化
+ sdk = this.initSdk();
+
+ // 初始化后增加引用计数
+ int refCount = configStorage.incrementMsgAuditSdkRefCount(sdk);
+ if (refCount < 0) {
+ // SDK已经被替换,需要重新获取
+ return acquireSdk();
+ }
+
+ return sdk;
+ }
+
+ /**
+ * 释放SDK引用计数
+ *
+ * @param sdk sdk id
+ */
+ private void releaseSdk(long sdk) {
+ if (sdk > 0) {
+ cpService.getWxCpConfigStorage().releaseMsgAuditSdk(sdk);
+ }
+ }
+
@Override
public WxCpChatModel getDecryptData(@NonNull long sdk, @NonNull WxCpChatDatas.WxCpChatData chatData,
@NonNull Integer pkcs1) throws Exception {
@@ -280,4 +324,127 @@ public WxCpAgreeInfo checkSingleAgree(@NonNull WxCpCheckAgreeRequest checkAgreeR
return WxCpAgreeInfo.fromJson(responseContent);
}
+ @Override
+ public List
+ *
*
*
+ *
*
*
* 请使用.
- * {@link LinkedCorpMsgType#TEXT}
- * {@link LinkedCorpMsgType#IMAGE}
- * {@link LinkedCorpMsgType#VIDEO}
- * {@link LinkedCorpMsgType#NEWS}
- * {@link LinkedCorpMsgType#MPNEWS}
- * {@link LinkedCorpMsgType#MARKDOWN}
- * {@link LinkedCorpMsgType#MINIPROGRAM_NOTICE}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#TEXT}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#IMAGE}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#VIDEO}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#NEWS}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#MPNEWS}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#MARKDOWN}
+ * {@link me.chanjar.weixin.cp.constant.WxCpConsts.LinkedCorpMsgType#MINIPROGRAM_NOTICE}
*
*
* @param msgType 消息类型
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java
index 4001c7d0e4..08a0936317 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/message/WxCpXmlMessage.java
@@ -68,19 +68,19 @@ public class WxCpXmlMessage implements Serializable {
/**
*
* 当接受用户消息时,可能会获得以下值:
- * {@link WxConsts.XmlMsgType#TEXT}
- * {@link WxConsts.XmlMsgType#IMAGE}
- * {@link WxConsts.XmlMsgType#VOICE}
- * {@link WxConsts.XmlMsgType#VIDEO}
- * {@link WxConsts.XmlMsgType#LOCATION}
- * {@link WxConsts.XmlMsgType#LINK}
- * {@link WxConsts.XmlMsgType#EVENT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#LOCATION}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#LINK}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#EVENT}
* 当发送消息的时候使用:
- * {@link WxConsts.XmlMsgType#TEXT}
- * {@link WxConsts.XmlMsgType#IMAGE}
- * {@link WxConsts.XmlMsgType#VOICE}
- * {@link WxConsts.XmlMsgType#VIDEO}
- * {@link WxConsts.XmlMsgType#NEWS}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#NEWS}
*
*/
@XStreamAlias("MsgType")
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java
index d3cbb89a3d..1ab92630a9 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/messagebuilder/TemplateCardBuilder.java
@@ -12,7 +12,8 @@
* 用法: WxCustomMessage m = WxCustomMessage.TEMPLATECARD().title(...)....toUser(...).build();
*
*
- * @author yzts a> created on 2019-05-16
+ * @author yzts
+ * @since 2019-05-16
*/
public class TemplateCardBuilder extends BaseBuilder
+ *
* 取值范围:-604800 ~ 86399
*/
@SerializedName("remind_time_diffs")
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java
index 92ec8a43e8..848e377791 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/applydata/ContentValue.java
@@ -58,6 +58,9 @@ public class ContentValue implements Serializable {
private Formula formula;
+ @SerializedName("bank_account")
+ private BankAccount bankAccount;
+
/**
* The type Date.
*/
@@ -68,6 +71,23 @@ public static class Date implements Serializable {
@SerializedName("s_timestamp")
private String timestamp;
+
+ @SerializedName("timezone_info")
+ private TimezoneInfo timezoneInfo;
+
+ /**
+ * The type TimezoneInfo.
+ */
+ @Data
+ public static class TimezoneInfo implements Serializable {
+ private static final long serialVersionUID = 164839205748392017L;
+
+ @SerializedName("zone_offset")
+ private String zoneOffset;
+
+ @SerializedName("zone_desc")
+ private String zoneDesc;
+ }
}
/**
@@ -228,6 +248,8 @@ public static class DataRange implements Serializable {
private Long end;
@SerializedName("new_duration")
private Long duration;
+ @SerializedName("timezone_info")
+ private Date.TimezoneInfo timezoneInfo;
}
/**
@@ -341,4 +363,55 @@ public static class Formula implements Serializable {
private String value;
}
+ /**
+ * The type BankAccount
+ */
+ @Data
+ public static class BankAccount implements Serializable {
+ private static final long serialVersionUID = 938475610283746192L;
+
+ @SerializedName("account_type")
+ private Long accountType;
+
+ @SerializedName("account_name")
+ private String accountName;
+
+ @SerializedName("account_number")
+ private String accountNumber;
+
+ private String remark;
+
+ private Bank bank;
+
+ /**
+ * The type Bank
+ */
+ @Data
+ public static class Bank implements Serializable {
+ private static final long serialVersionUID = 527384916203847561L;
+
+ @SerializedName("bank_alias")
+ private String bankAlias;
+
+ @SerializedName("bank_alias_code")
+ private String bankAliasCode;
+
+ private String province;
+
+ @SerializedName("province_code")
+ private Long provinceCode;
+
+ private String city;
+
+ @SerializedName("city_code")
+ private Long cityCode;
+
+ @SerializedName("bank_branch_name")
+ private String bankBranchName;
+
+ @SerializedName("bank_branch_id")
+ private String bankBranchId;
+ }
+ }
+
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/doc/WxCpDocSheetBatchUpdateRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/doc/WxCpDocSheetBatchUpdateRequest.java
new file mode 100644
index 0000000000..37c42717e7
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/doc/WxCpDocSheetBatchUpdateRequest.java
@@ -0,0 +1,199 @@
+package me.chanjar.weixin.cp.bean.oa.doc;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.google.gson.annotations.SerializedName;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import me.chanjar.weixin.cp.bean.oa.doc.WxCpDocSheetData.GridData;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+/**
+ * 编辑表格内容请求
+ *
+ * @author zhongying
+ * @since 2026-01-07
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class WxCpDocSheetBatchUpdateRequest implements Serializable {
+ private static final long serialVersionUID = 584565591133421347L;
+
+ /**
+ * 文档的docid.必填
+ */
+ @SerializedName("docid")
+ private String docId;
+
+ /**
+ * 更新操作列表.必填
+ */
+ @SerializedName("requests")
+ private List
+ *
* 会议室冲突日期列表,为当天0点的时间戳;使用重复会议预定会议室,部分日期与会议室预定情况冲突时返回
*/
@SerializedName("conflict_date")
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTips.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTips.java
index 58daeb007c..eada2ad100 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTips.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTips.java
@@ -8,7 +8,7 @@
/**
* @author mrsiu@msn.com
* @version 1.0
- * @date 2025/1/16 09:40
+ * @since 2025/1/16 09:40
*/
@Data
public class TemplateTips {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsContent.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsContent.java
index 939e6819a0..0af8be8be5 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsContent.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsContent.java
@@ -5,7 +5,7 @@
/**
* @author mrsiu@msn.com
* @version 1.0
- * @date 2025/1/16 09:42
+ * @since 2025/1/16 09:42
*/
@Data
public class TemplateTipsContent {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubText.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubText.java
index ac4681038c..78e88562e8 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubText.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubText.java
@@ -5,7 +5,7 @@
/**
* @author mrsiu@msn.com
* @version 1.0
- * @date 2025/1/16 09:45
+ * @since 2025/1/16 09:45
*/
@Data
public class TemplateTipsSubText {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContent.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContent.java
index 9c99b2688e..f33c31d054 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContent.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContent.java
@@ -6,7 +6,7 @@
/**
* @author mrsiu@msn.com
* @version 1.0
- * @date 2025/1/16 09:46
+ * @since 2025/1/16 09:46
*/
@Data
public class TemplateTipsSubTextContent {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentLink.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentLink.java
index 4cd198409a..fd4db2c18f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentLink.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentLink.java
@@ -5,7 +5,7 @@
/**
* @author mrsiu@msn.com
* @version 1.0
- * @date 2025/1/16 09:49
+ * @since 2025/1/16 09:49
*/
@Data
public class TemplateTipsSubTextContentLink {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentPlainText.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentPlainText.java
index 12969cdcdb..0a2e792edb 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentPlainText.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsSubTextContentPlainText.java
@@ -3,9 +3,9 @@
import lombok.Data;
/**
- * @author mrsiu@msn.com
- * @date 2025/1/16 09:47
- * @version 1.0
+ * @author mrsiu@msn.com
+ * @version 1.0
+ * @since 2025/1/16 09:47
*/
@Data
public class TemplateTipsSubTextContentPlainText {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsText.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsText.java
index 100c5bb137..c9dbe68abf 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsText.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/oa/templatedata/TemplateTipsText.java
@@ -6,9 +6,9 @@
import java.util.List;
/**
- * @author mrsiu@msn.com
- * @date 2025/1/16 09:43
- * @version 1.0
+ * @author mrsiu@msn.com
+ * @version 1.0
+ * @since 2025/1/16 09:43
*/
@Data
public class TemplateTipsText {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java
index 8b968e540c..fd96d76c30 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpConfigStorage.java
@@ -292,4 +292,47 @@ public interface WxCpConfigStorage {
* 使会话存档SDK过期
*/
void expireMsgAuditSdk();
+
+ /**
+ * 增加会话存档SDK的引用计数
+ * 用于支持多线程安全的SDK生命周期管理
+ *
+ * @param sdk sdk id
+ * @return 增加后的引用计数,如果SDK不匹配返回-1
+ */
+ int incrementMsgAuditSdkRefCount(long sdk);
+
+ /**
+ * 减少会话存档SDK的引用计数
+ * 当引用计数降为0时,自动销毁SDK以释放资源
+ *
+ * @param sdk sdk id
+ * @return 减少后的引用计数,如果返回0表示SDK已被销毁,如果SDK不匹配返回-1
+ */
+ int decrementMsgAuditSdkRefCount(long sdk);
+
+ /**
+ * 获取会话存档SDK的引用计数
+ *
+ * @param sdk sdk id
+ * @return 当前引用计数,如果SDK不匹配返回-1
+ */
+ int getMsgAuditSdkRefCount(long sdk);
+
+ /**
+ * 获取当前SDK并增加引用计数(原子操作)
+ * 如果SDK未初始化或已过期,返回0而不增加引用计数
+ * 此方法用于在获取SDK后立即增加引用计数,避免并发问题
+ *
+ * @return 当前有效的SDK id并已增加引用计数,如果SDK无效返回0
+ */
+ long acquireMsgAuditSdk();
+
+ /**
+ * 减少SDK引用计数并在必要时释放(原子操作)
+ * 此方法确保引用计数递减和SDK检查在同一个同步块内完成
+ *
+ * @param sdk sdk id
+ */
+ void releaseMsgAuditSdk(long sdk);
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java
index 07acb189a8..df758ac3a2 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpCorpGroupConfigStorage.java
@@ -31,8 +31,8 @@ public interface WxCpCorpGroupConfigStorage {
/**
* Update corp access token.
*
- * @param corpId
- * @param agentId
+ * @param corpId 企业ID
+ * @param agentId 应用ID
* @param corpAccessToken the corp access token
* @param expiresInSeconds the expires in seconds
*/
@@ -41,8 +41,8 @@ public interface WxCpCorpGroupConfigStorage {
/**
* 授权企业的access token相关
*
- * @param corpId the corp id
- * @param agentId
+ * @param corpId 企业ID
+ * @param agentId 应用ID
* @return the access token
*/
String getCorpAccessToken(String corpId, Integer agentId);
@@ -50,8 +50,8 @@ public interface WxCpCorpGroupConfigStorage {
/**
* Gets access token entity.
*
- * @param corpId the corp id
- * @param agentId
+ * @param corpId 企业ID
+ * @param agentId 应用ID
* @return the access token entity
*/
WxAccessToken getCorpAccessTokenEntity(String corpId, Integer agentId);
@@ -59,8 +59,8 @@ public interface WxCpCorpGroupConfigStorage {
/**
* Is access token expired boolean.
*
- * @param corpId the corp id
- * @param agentId
+ * @param corpId 企业ID
+ * @param agentId 应用ID
* @return the boolean
*/
boolean isCorpAccessTokenExpired(String corpId, Integer agentId);
@@ -68,8 +68,8 @@ public interface WxCpCorpGroupConfigStorage {
/**
* Expire access token.
*
- * @param corpId the corp id
- * @param agentId
+ * @param corpId 企业ID
+ * @param agentId 应用ID
*/
void expireCorpAccessToken(String corpId, Integer agentId);
@@ -118,7 +118,8 @@ public interface WxCpCorpGroupConfigStorage {
/**
* Gets access token lock.
*
- * @param corpId the corp id
+ * @param corpId 企业ID
+ * @param agentId 应用ID
* @return the access token lock
*/
Lock getCorpAccessTokenLock(String corpId, Integer agentId);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpTpConfigStorage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpTpConfigStorage.java
index 2cd37821b5..0a2ed0e76a 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpTpConfigStorage.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/WxCpTpConfigStorage.java
@@ -133,7 +133,7 @@ public interface WxCpTpConfigStorage {
String getEncodingAESKey();
/**
- * 企微服务商企业ID & 企业secret
+ * {@code 企微服务商企业ID & 企业secret}
*
* @return the corp id
*/
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/AbstractWxCpTpInRedisConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/AbstractWxCpTpInRedisConfigImpl.java
index 08eed33c16..6d1260fe68 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/AbstractWxCpTpInRedisConfigImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/AbstractWxCpTpInRedisConfigImpl.java
@@ -187,7 +187,9 @@ public String getEncodingAESKey() {
/**
- * 企微服务商企业ID & 企业secret, 来自于企微配置
+ * {@code 企微服务商企业ID & 企业secret, 来自于企微配置}
+ *
+ * @return 企业ID
*/
@Override
public String getCorpId() {
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java
index 4bf13f24ea..f8047e846f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpDefaultConfigImpl.java
@@ -1,5 +1,6 @@
package me.chanjar.weixin.cp.config.impl;
+import com.tencent.wework.Finance;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@@ -54,6 +55,10 @@ public class WxCpDefaultConfigImpl implements WxCpConfigStorage, Serializable {
*/
private volatile long msgAuditSdk;
private volatile long msgAuditSdkExpiresTime;
+ /**
+ * 会话存档SDK引用计数,用于多线程安全的生命周期管理
+ */
+ private volatile int msgAuditSdkRefCount;
private volatile String oauth2redirectUri;
private volatile String httpProxyHost;
private volatile int httpProxyPort;
@@ -470,13 +475,77 @@ public boolean isMsgAuditSdkExpired() {
@Override
public synchronized void updateMsgAuditSdk(long sdk, int expiresInSeconds) {
+ // 如果有旧的SDK且不同于新的SDK,需要销毁旧的SDK
+ if (this.msgAuditSdk > 0 && this.msgAuditSdk != sdk) {
+ // 无论旧SDK是否仍有引用,都需要销毁它以避免资源泄漏
+ // 如果有飞行中的请求使用旧SDK,这些请求可能会失败,但这比资源泄漏更安全
+ Finance.DestroySdk(this.msgAuditSdk);
+ }
this.msgAuditSdk = sdk;
// 预留200秒的时间
this.msgAuditSdkExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
+ // 重置引用计数,因为这是一个全新的SDK
+ this.msgAuditSdkRefCount = 0;
}
@Override
public void expireMsgAuditSdk() {
this.msgAuditSdkExpiresTime = 0;
}
+
+ @Override
+ public synchronized int incrementMsgAuditSdkRefCount(long sdk) {
+ if (this.msgAuditSdk == sdk && sdk > 0) {
+ return ++this.msgAuditSdkRefCount;
+ }
+ return -1; // SDK不匹配,返回-1表示错误
+ }
+
+ @Override
+ public synchronized int decrementMsgAuditSdkRefCount(long sdk) {
+ if (this.msgAuditSdk == sdk && this.msgAuditSdkRefCount > 0) {
+ int newCount = --this.msgAuditSdkRefCount;
+ // 当引用计数降为0时,自动销毁SDK以释放资源
+ // 再次检查SDK是否仍然是当前缓存的SDK(防止并发重新初始化)
+ if (newCount == 0 && this.msgAuditSdk == sdk) {
+ Finance.DestroySdk(sdk);
+ this.msgAuditSdk = 0;
+ this.msgAuditSdkExpiresTime = 0;
+ }
+ return newCount;
+ }
+ return -1; // SDK不匹配或引用计数已为0,返回-1表示错误
+ }
+
+ @Override
+ public synchronized int getMsgAuditSdkRefCount(long sdk) {
+ if (this.msgAuditSdk == sdk && sdk > 0) {
+ return this.msgAuditSdkRefCount;
+ }
+ return -1; // SDK不匹配,返回-1表示错误
+ }
+
+ @Override
+ public synchronized long acquireMsgAuditSdk() {
+ // 检查SDK是否有效(已初始化且未过期)
+ if (this.msgAuditSdk > 0 && !isMsgAuditSdkExpired()) {
+ this.msgAuditSdkRefCount++;
+ return this.msgAuditSdk;
+ }
+ return 0; // SDK未初始化或已过期
+ }
+
+ @Override
+ public synchronized void releaseMsgAuditSdk(long sdk) {
+ if (this.msgAuditSdk == sdk && this.msgAuditSdkRefCount > 0) {
+ int newCount = --this.msgAuditSdkRefCount;
+ // 当引用计数降为0时,自动销毁SDK以释放资源
+ // 再次检查SDK是否仍然是当前缓存的SDK(防止并发重新初始化)
+ if (newCount == 0 && this.msgAuditSdk == sdk) {
+ Finance.DestroySdk(sdk);
+ this.msgAuditSdk = 0;
+ this.msgAuditSdkExpiresTime = 0;
+ }
+ }
+ }
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java
index 49cd7c4559..48e2445506 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpRedisConfigImpl.java
@@ -1,5 +1,6 @@
package me.chanjar.weixin.cp.config.impl;
+import com.tencent.wework.Finance;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@@ -55,6 +56,10 @@ public class WxCpRedisConfigImpl implements WxCpConfigStorage {
*/
private volatile long msgAuditSdk;
private volatile long msgAuditSdkExpiresTime;
+ /**
+ * 会话存档SDK引用计数,用于多线程安全的生命周期管理
+ */
+ private volatile int msgAuditSdkRefCount;
/**
* Instantiates a new Wx cp redis config.
@@ -488,13 +493,77 @@ public boolean isMsgAuditSdkExpired() {
@Override
public synchronized void updateMsgAuditSdk(long sdk, int expiresInSeconds) {
+ // 如果有旧的SDK且不同于新的SDK,需要销毁旧的SDK
+ if (this.msgAuditSdk > 0 && this.msgAuditSdk != sdk) {
+ // 无论旧SDK是否仍有引用,都需要销毁它以避免资源泄漏
+ // 如果有飞行中的请求使用旧SDK,这些请求可能会失败,但这比资源泄漏更安全
+ Finance.DestroySdk(this.msgAuditSdk);
+ }
this.msgAuditSdk = sdk;
// 预留200秒的时间
this.msgAuditSdkExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
+ // 重置引用计数,因为这是一个全新的SDK
+ this.msgAuditSdkRefCount = 0;
}
@Override
public void expireMsgAuditSdk() {
this.msgAuditSdkExpiresTime = 0;
}
+
+ @Override
+ public synchronized int incrementMsgAuditSdkRefCount(long sdk) {
+ if (this.msgAuditSdk == sdk && sdk > 0) {
+ return ++this.msgAuditSdkRefCount;
+ }
+ return -1; // SDK不匹配,返回-1表示错误
+ }
+
+ @Override
+ public synchronized int decrementMsgAuditSdkRefCount(long sdk) {
+ if (this.msgAuditSdk == sdk && this.msgAuditSdkRefCount > 0) {
+ int newCount = --this.msgAuditSdkRefCount;
+ // 当引用计数降为0时,自动销毁SDK以释放资源
+ // 再次检查SDK是否仍然是当前缓存的SDK(防止并发重新初始化)
+ if (newCount == 0 && this.msgAuditSdk == sdk) {
+ Finance.DestroySdk(sdk);
+ this.msgAuditSdk = 0;
+ this.msgAuditSdkExpiresTime = 0;
+ }
+ return newCount;
+ }
+ return -1; // SDK不匹配或引用计数已为0,返回-1表示错误
+ }
+
+ @Override
+ public synchronized int getMsgAuditSdkRefCount(long sdk) {
+ if (this.msgAuditSdk == sdk && sdk > 0) {
+ return this.msgAuditSdkRefCount;
+ }
+ return -1; // SDK不匹配,返回-1表示错误
+ }
+
+ @Override
+ public synchronized long acquireMsgAuditSdk() {
+ // 检查SDK是否有效(已初始化且未过期)
+ if (this.msgAuditSdk > 0 && !isMsgAuditSdkExpired()) {
+ this.msgAuditSdkRefCount++;
+ return this.msgAuditSdk;
+ }
+ return 0; // SDK未初始化或已过期
+ }
+
+ @Override
+ public synchronized void releaseMsgAuditSdk(long sdk) {
+ if (this.msgAuditSdk == sdk && this.msgAuditSdkRefCount > 0) {
+ int newCount = --this.msgAuditSdkRefCount;
+ // 当引用计数降为0时,自动销毁SDK以释放资源
+ // 再次检查SDK是否仍然是当前缓存的SDK(防止并发重新初始化)
+ if (newCount == 0 && this.msgAuditSdk == sdk) {
+ Finance.DestroySdk(sdk);
+ this.msgAuditSdk = 0;
+ this.msgAuditSdkExpiresTime = 0;
+ }
+ }
+ }
}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpTpDefaultConfigImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpTpDefaultConfigImpl.java
index fc124251f5..7fbbc9ccce 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpTpDefaultConfigImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/WxCpTpDefaultConfigImpl.java
@@ -29,7 +29,7 @@ public class WxCpTpDefaultConfigImpl implements WxCpTpConfigStorage, Serializabl
private final transient Map
+ * 服务商可通过本接口获取服务商所拥有的应用模板列表
+ * 文档地址:https://developer.work.weixin.qq.com/document/path/97111
+ *
+ *
+ * @return 应用模板列表
+ * @throws WxErrorException 微信错误异常
+ */
+ WxCpTpTemplateList getTemplateList() throws WxErrorException;
+
+ /**
+ * 获取代开发应用详情
+ *
+ * 服务商可通过本接口获取某个授权企业中已经安装的代开发自建应用的详情
+ * 文档地址:https://developer.work.weixin.qq.com/document/path/97111
+ *
+ *
+ * @param authCorpId 授权企业的corpid
+ * @param agentId 应用的agentid,为空时则返回该企业所有的代开发自建应用详情
+ * @return 代开发应用详情
+ * @throws WxErrorException 微信错误异常
+ */
+ WxCpTpCustomizedAppDetail getCustomizedAppDetail(String authCorpId, Integer agentId) throws WxErrorException;
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java
index 2c2f11628b..d539f03bca 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpEditionService.java
@@ -15,7 +15,7 @@ public interface WxCpTpEditionService {
* 延长试用期
*
*
- * 获取审批申请详情
+ * 获取审批申请详情
*
* @param spNo 审批单编号。
* @param corpId the corp id
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java
index 3aff90bb56..6e0acb7dee 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpOrderService.java
@@ -18,7 +18,7 @@ public interface WxCpTpOrderService {
* 获取订单详情
*
* 文档地址 - *
+ * * * @param startTime 起始时间 * @param endTime 终止时间 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java index b24be535da..92966c1d03 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpService.java @@ -199,7 +199,7 @@ public interface WxCpTpService { * @return permanent code info * @throws WxErrorException the wx error exception * @author yuan - * @since 2020 -03-18 + * @since 2020-03-18 */ WxCpTpPermanentCodeInfo getPermanentCodeInfo(String authCode) throws WxErrorException; @@ -227,7 +227,7 @@ public interface WxCpTpService { * @param authType 授权类型:0 正式授权, 1 测试授权。 * @return pre auth url * @throws WxErrorException the wx error exception - * @link https ://work.weixin.qq.com/api/doc/90001/90143/90602 + * @see 文档地址 */ String getPreAuthUrl(String redirectUri, String state, int authType) throws WxErrorException; @@ -558,12 +558,12 @@ WxCpTpXmlMessage fromEncryptedXml(String encryptedXml, WxCpTpAppQrcode getAppQrcode(String suiteId, String appId, String state, Integer style, Integer resultType) throws WxErrorException ; /** - * * 明文corpid转换为加密corpid 为更好地保护企业与用户的数据,第三方应用获取的corpid不再是明文的corpid,将升级为第三方服务商级别的加密corpid。文档说明 * 第三方可以将已有的明文corpid转换为第三方的加密corpid。 - * @param corpId - * @return - * @throws WxErrorException + * + * @param corpId 企业ID + * @return 加密的企业ID + * @throws WxErrorException 微信错误异常 */ WxCpTpCorpId2OpenCorpId corpId2OpenCorpId(String corpId) throws WxErrorException; @@ -655,9 +655,25 @@ WxCpTpXmlMessage fromEncryptedXml(String encryptedXml, /** * 构造第三方应用oauth2链接 + * + * @return OAuth2服务 */ WxCpTpOAuth2Service getWxCpTpOAuth2Service(); void setWxCpTpOAuth2Service(WxCpTpOAuth2Service wxCpTpOAuth2Service); + /** + * 获取代开发服务 + * + * @return 代开发服务 + */ + WxCpTpCustomizedService getWxCpTpCustomizedService(); + + /** + * 设置代开发服务 + * + * @param wxCpTpCustomizedService 代开发服务 + */ + void setWxCpTpCustomizedService(WxCpTpCustomizedService wxCpTpCustomizedService); + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpTagService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpTagService.java index b508df59a1..df60041865 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpTagService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/WxCpTpTagService.java @@ -13,7 +13,7 @@ * * * @author zhangq* 文档地址 - *
+ * ** 文档地址 - *
+ * * * @param orderId 订单号 * @return the order @@ -49,7 +49,7 @@ public WxCpTpOrderDetails getOrder(String orderId) throws WxErrorException { * 获取订单列表 ** 文档地址 - *
+ * * * @param startTime 起始时间 * @param endTime 终止时间 diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java index bba597a3ee..44b5fd8693 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpServiceHttpComponentsImpl.java @@ -10,7 +10,6 @@ import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder; import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder; import me.chanjar.weixin.common.util.json.GsonParser; -import me.chanjar.weixin.cp.config.WxCpTpConfigStorage; import me.chanjar.weixin.cp.constant.WxCpApiPathConsts; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.config.RequestConfig; @@ -87,9 +86,10 @@ public void initHttp() { HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get(); apacheHttpClientBuilder.httpProxyHost(this.configStorage.getHttpProxyHost()) - .httpProxyPort(this.configStorage.getHttpProxyPort()) - .httpProxyUsername(this.configStorage.getHttpProxyUsername()) - .httpProxyPassword(this.configStorage.getHttpProxyPassword().toCharArray()); + .httpProxyPort(this.configStorage.getHttpProxyPort()) + .httpProxyUsername(this.configStorage.getHttpProxyUsername()) + .httpProxyPassword(this.configStorage.getHttpProxyPassword() == null ? null : + this.configStorage.getHttpProxyPassword().toCharArray()); if (this.configStorage.getHttpProxyHost() != null && this.configStorage.getHttpProxyPort() > 0) { this.httpProxy = new HttpHost(this.configStorage.getHttpProxyHost(), this.configStorage.getHttpProxyPort()); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpTagServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpTagServiceImpl.java index b81760e72c..1b03f18c79 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpTagServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/tp/service/impl/WxCpTpTagServiceImpl.java @@ -25,7 +25,7 @@ * * * @author zhangq- * 文档地址:推送用工消息 + * 文档地址:推送用工消息 *
* * @author Binary Wang * created on 2025-12-19 + * update on 2026-01-22 15:13:28 */ @Data @Builder(builderMethodName = "newBuilder") @@ -27,33 +28,74 @@ public class WxMaSendEmployeeMsgRequest implements Serializable { /** *
- * 字段名:用户openid
+ * 字段名:模板id
* 是否必填:是
- * 描述:需要接收消息的用户openid
+ * 描述:需要在微信后台申请用工关系权限,通过后创建的模板审核通过后可以复制模板ID
*
*/
- @SerializedName("openid")
- private String openid;
+ @SerializedName("template_id")
+ private String templateId;
/**
*
- * 字段名:企业id
+ * 字段名:页面
* 是否必填:是
- * 描述:企业id,小程序管理员在微信开放平台配置
+ * 描述:用工消息通知跳转的page小程序链接(注意 小程序页面链接要是申请模板的小程序)
*
*/
- @SerializedName("corp_id")
- private String corpId;
+ @SerializedName("page")
+ private String page;
+
+ /**
+ * + * 字段名:被推送用户的openId + * 是否必填:是 + * 描述:被推送用户的openId + *+ */ + @SerializedName("touser") + private String touser; /** *
* 字段名:消息内容
* 是否必填:是
- * 描述:推送的消息内容,文本格式,最长不超过200个字符
+ * 描述:需要根据小程序后台审核通过的模板id的字段类型序列化json传递
+ *
+ *
+ *
+ * 参考组装代码
+ *
+ *
+ * // 使用 HashMap 构建数据结构
+ * Map data1 = new HashMap<>();
+ * // 内层字段
+ * Map thing1 = new HashMap<>();
+ * Map thing2 = new HashMap<>();
+ * Map time1 = new HashMap<>();
+ * Map character_string1 = new HashMap<>();
+ * Map time2 = new HashMap<>();
+ * thing1.put("value", "高和蓝枫箱体测试");
+ * thing2.put("value", "门口全英测试");
+ * time1.put("value", "2026年11月23日 19:19");
+ * character_string1.put("value", "50kg");
+ * time2.put("value", "2026年11月23日 19:19");
+ *
+ * // 模板消息变量,有顺序要求
+ * Map dataContent = new LinkedHashMap<>();
+ * dataContent.put("thing1", thing1);
+ * dataContent.put("thing2", thing2);
+ * dataContent.put("time1", time1);
+ * dataContent.put("character_string1", character_string1);
+ * dataContent.put("time2", time2);
+ *
+ * data1.put("data", dataContent);
+ *
*
*/
- @SerializedName("msg")
- private String msg;
+
+ @SerializedName("data")
+ private String data;
public String toJson() {
return WxMaGsonBuilder.create().toJson(this);
diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/employee/WxMaUnbindEmployeeRequest.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/employee/WxMaUnbindEmployeeRequest.java
index e56d84670c..e357f246a5 100644
--- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/employee/WxMaUnbindEmployeeRequest.java
+++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/employee/WxMaUnbindEmployeeRequest.java
@@ -8,15 +8,17 @@
import lombok.NoArgsConstructor;
import java.io.Serializable;
+import java.util.List;
/**
* 小程序解绑用工关系请求实体
* - * 文档地址:解绑用工关系 + * 文档地址:解绑用工关系 *
* * @author Binary Wang * created on 2025-12-19 + * update on 2026-01-22 15:14:09 */ @Data @Builder(builderMethodName = "newBuilder") @@ -27,23 +29,13 @@ public class WxMaUnbindEmployeeRequest implements Serializable { /** *
- * 字段名:用户openid
+ * 字段名:用户openid列表
* 是否必填:是
- * 描述:需要解绑的用户openid
+ * 描述:需要解绑的用户openid列表
*
*/
- @SerializedName("openid")
- private String openid;
-
- /**
- * - * 字段名:企业id - * 是否必填:是 - * 描述:企业id,小程序管理员在微信开放平台配置 - *- */ - @SerializedName("corp_id") - private String corpId; + @SerializedName("openid_list") + private List
+ * 文档地址: https://developers.weixin.qq.com/miniprogram/dev/server/API/laboruse/ + *+ */ public interface Employee { /** 解绑用工关系 */ - String UNBIND_EMPLOYEE_URL = "https://api.weixin.qq.com/wxa/unbinduserb2cauthinfo"; + String UNBIND_EMPLOYEE_URL = "https://api.weixin.qq.com/wxa/business/unbinduserb2cauthinfo"; /** 推送用工消息 */ - String SEND_EMPLOYEE_MSG_URL = "https://api.weixin.qq.com/wxa/sendemployeerelationmsg"; + String SEND_EMPLOYEE_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/wxopen/employeerelationmsg/send"; } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java index 08346dbbb8..2343634bfc 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java @@ -36,6 +36,7 @@ public WxMaCryptUtils(WxMaConfig config) { * @param sessionKey session_key * @param encryptedData 消息密文 * @param ivStr iv字符串 + * @return 解密后的字符串 */ public static String decrypt(String sessionKey, String encryptedData, String ivStr) { try { @@ -58,6 +59,7 @@ public static String decrypt(String sessionKey, String encryptedData, String ivS * @param sessionKey session_key * @param encryptedData 消息密文 * @param ivStr iv字符串 + * @return 解密后的字符串 */ public static String decryptAnotherWay(String sessionKey, String encryptedData, String ivStr) { byte[] keyBytes = Base64.decodeBase64(sessionKey.getBytes(UTF_8)); diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java index f36d8c8fbd..b9e80d7341 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/xml/XStreamTransformer.java @@ -24,7 +24,12 @@ public class XStreamTransformer { } /** - * xml -> pojo. + * {@code xml -> pojo.} + * + * @param
* 创建卡券
- *
*
- * @param cardCreateRequest 卡券创建请求对象
+ * @param cardCreateMessage 卡券创建请求对象
* @return 卡券创建结果对象
* @throws WxErrorException 微信API调用异常,可能包括:
*
* 获取图文群发总数据(getarticletotal)
- * 详情请见文档:图文分析数据接口
+ *
+ * {@code 详情请见文档:图文分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getarticletotal?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度1天,endDate不能早于begingDate
@@ -73,10 +76,13 @@ public interface WxMpDataCubeService {
List getArticleTotal(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取图文统计数据(getuserread)
- * 详情请见文档:图文分析数据接口
+ *
+ * {@code 详情请见文档:图文分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getuserread?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度3天,endDate不能早于begingDate
@@ -86,10 +92,13 @@ public interface WxMpDataCubeService {
List getUserRead(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取图文统计分时数据(getuserreadhour)
- * 详情请见文档:图文分析数据接口
+ *
+ * {@code 详情请见文档:图文分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getuserreadhour?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度1天,endDate不能早于begingDate
@@ -99,10 +108,13 @@ public interface WxMpDataCubeService {
List getUserReadHour(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取图文分享转发数据(getusershare)
- * 详情请见文档:图文分析数据接口
+ *
+ * {@code 详情请见文档:图文分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getusershare?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度7天,endDate不能早于begingDate
@@ -112,10 +124,13 @@ public interface WxMpDataCubeService {
List getUserShare(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取图文分享转发分时数据(getusersharehour)
- * 详情请见文档:图文分析数据接口
+ *
+ * {@code 详情请见文档:图文分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getusersharehour?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度1天,endDate不能早于begingDate
@@ -127,10 +142,13 @@ public interface WxMpDataCubeService {
//*******************消息分析数据接口***********************//
/**
- *
* 获取消息发送概况数据(getupstreammsg)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsg?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度7天,endDate不能早于begingDate
@@ -140,10 +158,13 @@ public interface WxMpDataCubeService {
List getUpstreamMsg(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取消息分送分时数据(getupstreammsghour)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsghour?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度1天,endDate不能早于begingDate
@@ -153,10 +174,13 @@ public interface WxMpDataCubeService {
List getUpstreamMsgHour(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取消息发送周数据(getupstreammsgweek)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsgweek?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度30天,endDate不能早于begingDate
@@ -166,10 +190,13 @@ public interface WxMpDataCubeService {
List getUpstreamMsgWeek(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取消息发送月数据(getupstreammsgmonth)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsgmonth?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度30天,endDate不能早于begingDate
@@ -179,10 +206,13 @@ public interface WxMpDataCubeService {
List getUpstreamMsgMonth(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取消息发送分布数据(getupstreammsgdist)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsgdist?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度15天,endDate不能早于begingDate
@@ -192,10 +222,13 @@ public interface WxMpDataCubeService {
List getUpstreamMsgDist(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取消息发送分布周数据(getupstreammsgdistweek)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsgdistweek?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度30天,endDate不能早于begingDate
@@ -205,10 +238,13 @@ public interface WxMpDataCubeService {
List getUpstreamMsgDistWeek(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取消息发送分布月数据(getupstreammsgdistmonth)
- * 详情请见文档:消息分析数据接口
+ *
+ * {@code 详情请见文档:消息分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getupstreammsgdistmonth?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度30天,endDate不能早于begingDate
@@ -220,10 +256,13 @@ public interface WxMpDataCubeService {
//*******************接口分析数据接口***********************//
/**
- *
* 获取接口分析数据(getinterfacesummary)
- * 详情请见文档:接口分析数据接口
+ *
+ * {@code 详情请见文档:接口分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getinterfacesummary?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度30天,endDate不能早于begingDate
@@ -233,10 +272,13 @@ public interface WxMpDataCubeService {
List getInterfaceSummary(Date beginDate, Date endDate) throws WxErrorException;
/**
- *
* 获取接口分析分时数据(getinterfacesummaryhour)
- * 详情请见文档:接口分析数据接口
+ *
+ * {@code 详情请见文档:接口分析数据接口}
+ *
+ *
* 接口url格式:https://api.weixin.qq.com/datacube/getinterfacesummaryhour?access_token=ACCESS_TOKEN
+ *
*
* @param beginDate 开始时间
* @param endDate 最大时间跨度1天,endDate不能早于begingDate
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
index 468dced138..2d965bf8de 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
@@ -54,10 +54,10 @@ public interface WxMpService extends WxService {
WxMpShortKeyResult fetchShorten(String shortKey) throws WxErrorException;
/**
- *
* 验证消息的确来自微信服务器.
- * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
- *
+ *
+ * {@code 详情请见: 接入指南}
+ *
*
* @param timestamp 时间戳,字符串格式
* @param nonce 随机串,字符串格式
@@ -76,16 +76,19 @@ public interface WxMpService extends WxService {
String getAccessToken() throws WxErrorException;
/**
- *
* 获取access_token,本方法线程安全.
+ *
* 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
- *
+ *
+ *
* 另:本service的所有方法都会在access_token过期时调用此方法
- *
+ *
+ *
* 程序员在非必要情况下尽量不要主动调用此方法
- *
- * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183&token=&lang=zh_CN
- *
+ *
+ *
+ * {@code 详情请见: 获取access_token}
+ *
*
* @param forceRefresh 是否强制刷新,true表示强制刷新,false表示使用缓存
* @return token access token,字符串格式
@@ -126,12 +129,13 @@ public interface WxMpService extends WxService {
String getJsapiTicket() throws WxErrorException;
/**
- *
* 获得jsapi_ticket.
+ *
* 获得时会检查jsapiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
- *
- * 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
- *
+ *
+ *
+ * {@code 详情请见:JS-SDK使用权限签名算法}
+ *
*
* @param forceRefresh 强制刷新,true表示强制刷新,false表示使用缓存
* @return jsapi ticket,字符串格式
@@ -140,11 +144,10 @@ public interface WxMpService extends WxService {
String getJsapiTicket(boolean forceRefresh) throws WxErrorException;
/**
- *
* 创建调用jsapi时所需要的签名.
- *
- * 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
- *
+ *
+ * {@code 详情请见:JS-SDK使用权限签名算法}
+ *
*
* @param url 当前网页的URL,不包括#及其后面部分
* @return 生成的签名对象,包含签名、时间戳、随机串等信息
@@ -153,10 +156,10 @@ public interface WxMpService extends WxService {
WxJsapiSignature createJsapiSignature(String url) throws WxErrorException;
/**
- *
* 长链接转短链接接口.
- * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口
- *
+ *
+ * 详情请见: 长链接转短链接接口
+ *
*
* @param longUrl 长url,需要转换的原始URL
* @return 生成的短地址,字符串格式
@@ -167,10 +170,10 @@ public interface WxMpService extends WxService {
String shortUrl(String longUrl) throws WxErrorException;
/**
- *
* 语义查询接口.
- * 详情请见:http://mp.weixin.qq.com/wiki/index.php?title=语义理解
- *
+ *
+ * 详情请见:语义理解
+ *
*
* @param semanticQuery 查询条件,包含查询内容、类型等信息
* @return 查询结果,包含语义理解的结果和建议回复
@@ -179,11 +182,13 @@ public interface WxMpService extends WxService {
WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException;
/**
- *
* 构造第三方使用网站应用授权登录的url.
- * 详情请见: 网站应用微信登录开发指南
- * URL格式为:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
- *
+ *
+ * {@code 详情请见: 网站应用微信登录开发指南}
+ *
+ *
+ * {@code URL格式为:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect}
+ *
*
* @param redirectUri 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode
* @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
@@ -193,10 +198,7 @@ public interface WxMpService extends WxService {
String buildQrConnectUrl(String redirectUri, String scope, String state);
/**
- *
* 获取微信服务器IP地址
- * http://mp.weixin.qq.com/wiki/0/2ad4b6bfd29f30f71d39616c2a0fcedc.html
- *
*
* @return 微信服务器ip地址数组,包含所有微信服务器IP地址
* @throws WxErrorException 微信API调用异常
@@ -204,11 +206,10 @@ public interface WxMpService extends WxService {
String[] getCallbackIP() throws WxErrorException;
/**
- *
- * 网络检测
- * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21541575776DtsuT
- * 为了帮助开发者排查回调连接失败的问题,提供这个网络检测的API。它可以对开发者URL做域名解析,然后对所有IP进行一次ping操作,得到丢包率和耗时。
- *
+ * 网络检测
+ *
+ * 为了帮助开发者排查回调连接失败的问题,提供这个网络检测的API。它可以对开发者URL做域名解析,然后对所有IP进行一次ping操作,得到丢包率和耗时。
+ *
*
* @param action 执行的检测动作,可选值:all(全部检测)、dns(仅域名解析)、ping(仅网络连通性检测)
* @param operator 指定平台从某个运营商进行检测,可选值:CHINANET(中国电信)、UNICOM(中国联通)、CAP(中国联通)、CUCC(中国联通)
@@ -239,12 +240,13 @@ public interface WxMpService extends WxService {
WxMpCurrentAutoReplyInfo getCurrentAutoReplyInfo() throws WxErrorException;
/**
- *
- * 公众号调用或第三方平台帮公众号调用对公众号的所有api调用(包括第三方帮其调用)次数进行清零:
- * HTTP调用:https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=ACCESS_TOKEN
- * 接口文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433744592
- *
- *
+ * 公众号调用或第三方平台帮公众号调用对公众号的所有api调用(包括第三方帮其调用)次数进行清零.
+ *
+ * HTTP调用:https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=ACCESS_TOKEN
+ *
+ *
+ * {@code 接口文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433744592}
+ *
*
* @param appid 公众号的APPID,需要清零调用的公众号的appid
* @throws WxErrorException 微信API调用异常
@@ -252,11 +254,9 @@ public interface WxMpService extends WxService {
void clearQuota(String appid) throws WxErrorException;
/**
- *
* Service没有实现某个API的时候,可以用这个,
* 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
* 可以参考,{@link MediaUploadRequestExecutor}的实现方法
- *
*
* @param 返回值类型
* @param 参数类型
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 63ca608eba..76ab466157 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
@@ -304,8 +304,9 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
/**
* 通过网络请求获取稳定版接口调用凭据
*
- * @return .
- * @throws IOException .
+ * @param forceRefresh 是否强制刷新
+ * @return access_token字符串
+ * @throws IOException IO异常
*/
protected abstract String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java
index bbf065acfc..c54202ad2f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceHttpComponentsImpl.java
@@ -51,7 +51,8 @@ public void initHttp() {
apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost())
.httpProxyPort(configStorage.getHttpProxyPort())
.httpProxyUsername(configStorage.getHttpProxyUsername())
- .httpProxyPassword(configStorage.getHttpProxyPassword().toCharArray());
+ .httpProxyPassword(configStorage.getHttpProxyPassword() == null ? null :
+ configStorage.getHttpProxyPassword().toCharArray());
if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort());
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
index 79c3fad266..7cef64e576 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java
@@ -2,11 +2,11 @@
/**
*
- * 默认接口实现类,使用apache httpclient实现
+ * 默认接口实现类,使用apache httpClient 5实现
* Created by Binary Wang on 2017-5-27.
*
*
* @author Binary Wang
*/
-public class WxMpServiceImpl extends WxMpServiceHttpClientImpl {
+public class WxMpServiceImpl extends WxMpServiceHttpComponentsImpl {
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java
index 80e1658c16..936996ef69 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java
@@ -25,11 +25,11 @@ public class WxMpMassOpenIdsMessage implements Serializable {
/**
*
* 请使用
- * {@link WxConsts.MassMsgType#IMAGE}
- * {@link WxConsts.MassMsgType#MPNEWS}
- * {@link WxConsts.MassMsgType#TEXT}
- * {@link WxConsts.MassMsgType#MPVIDEO}
- * {@link WxConsts.MassMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#MPNEWS}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#MPVIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#VOICE}
* 如果msgtype和media_id不匹配的话,会返回系统繁忙的错误
*
*/
@@ -60,6 +60,8 @@ public String toJson() {
/**
* 添加openid,最多支持10,000个
+ *
+ * @param openid 用户openid
*/
public void addUser(String openid) {
this.toUsers.add(openid);
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java
index dca743c9c3..57b34d352a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java
@@ -19,11 +19,11 @@ public class WxMpMassPreviewMessage implements Serializable {
*
* 消息类型
* 请使用
- * {@link WxConsts.MassMsgType#IMAGE}
- * {@link WxConsts.MassMsgType#MPNEWS}
- * {@link WxConsts.MassMsgType#TEXT}
- * {@link WxConsts.MassMsgType#MPVIDEO}
- * {@link WxConsts.MassMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#MPNEWS}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#MPVIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#VOICE}
* 如果msgtype和media_id不匹配的话,会返回系统繁忙的错误
*
*/
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java
index 598e5754f1..466ef8d96f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java
@@ -24,11 +24,11 @@ public class WxMpMassTagMessage implements Serializable {
*
* 消息类型.
* 请使用
- * {@link WxConsts.MassMsgType#IMAGE}
- * {@link WxConsts.MassMsgType#MPNEWS}
- * {@link WxConsts.MassMsgType#TEXT}
- * {@link WxConsts.MassMsgType#MPVIDEO}
- * {@link WxConsts.MassMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#MPNEWS}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#MPVIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.MassMsgType#VOICE}
* 如果msgtype和media_id不匹配的话,会返回系统繁忙的错误
*
*/
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java
index 9e73b46159..ac4a596dd8 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java
@@ -63,9 +63,8 @@ public WxMpUserQuery add(String openid, String lang) {
/**
* 添加一个OpenId到列表中,并返回本对象
*
- *
* 该方法默认lang = zh_CN
- *
+ *
*
* @param openid openid
* @return {@link WxMpUserQuery}
@@ -100,6 +99,8 @@ public WxMpUserQuery remove(String openid, String lang) {
/**
* 获取查询参数列表
+ *
+ * @return 查询参数列表
*/
public List getQueryParamList() {
return this.queryParamList;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/WxMpCardMpnewsGethtmlResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/WxMpCardMpnewsGethtmlResult.java
index 6d7dde1ad6..34a9c56b99 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/WxMpCardMpnewsGethtmlResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/WxMpCardMpnewsGethtmlResult.java
@@ -8,7 +8,9 @@
/**
- * @author S
+ * 卡券图文消息HTML结果
+ *
+ * @author S (sshzh90@gmail.com)
*/
@Data
public class WxMpCardMpnewsGethtmlResult implements Serializable {
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardActivateUserFormRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardActivateUserFormRequest.java
index d8634cfa3c..0adb413869 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardActivateUserFormRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardActivateUserFormRequest.java
@@ -39,8 +39,8 @@ public class MemberCardActivateUserFormRequest implements Serializable {
/**
* 绑定老会员卡信息
*
- * @param name
- * @param url
+ * @param name 名称
+ * @param url 链接地址
*/
public void setBindOldCard(String name, String url) {
if (StringUtils.isAnyEmpty(name, url)) {
@@ -56,8 +56,8 @@ public void setBindOldCard(String name, String url) {
/**
* 设置服务声明,用于放置商户会员卡守则
*
- * @param name
- * @param url
+ * @param name 名称
+ * @param url 链接地址
*/
public void setServiceStatement(String name, String url) {
if (StringUtils.isAnyEmpty(name, url)) {
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardUserForm.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardUserForm.java
index 0c0fae3e2b..b3b0c9be5e 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardUserForm.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/MemberCardUserForm.java
@@ -50,6 +50,7 @@ public class MemberCardUserForm implements Serializable {
/**
* 添加富文本类型字段
*
+ * @param field 富文本字段
*/
public void addRichField(MemberCardUserFormRichField field) {
if (field == null) {
@@ -64,6 +65,7 @@ public void addRichField(MemberCardUserFormRichField field) {
/**
* 添加微信选项类型字段
*
+ * @param fieldType 微信字段类型
*/
public void addWechatField(CardWechatFieldType fieldType) {
if (fieldType == null) {
@@ -78,6 +80,7 @@ public void addWechatField(CardWechatFieldType fieldType) {
/**
* 添加文本类型字段
*
+ * @param field 文本字段
*/
public void addCustomField(String field) {
if (StringUtils.isBlank(field)) {
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/NotifyOptional.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/NotifyOptional.java
index 139db68557..1ba8a0e60c 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/NotifyOptional.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/NotifyOptional.java
@@ -6,12 +6,13 @@
import java.io.Serializable;
/**
- *
* 控制原生消息结构体,包含各字段的消息控制字段。
- *
+ *
* 用于 `7 更新会员信息` 的接口参数调用
- * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283
- *
+ *
+ *
+ * {@code 参考:会员卡接口}
+ *
*
* @author YuJian(mgcnrx11@gmail.com)
* @version 2017/7/15
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUpdateResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUpdateResult.java
index 663fe1f1e5..b4ad8eb139 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUpdateResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUpdateResult.java
@@ -6,10 +6,10 @@
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
/**
- *
* 用于 `7 更新会员信息` 的接口调用后的返回结果
- * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283
- *
+ *
+ * {@code 参考:会员卡接口}
+ *
*
* @author YuJian(mgcnrx11@gmail.com)
* @version 2017/7/15
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUserInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUserInfoResult.java
index 8fad40ccf8..9a2b47f5bf 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUserInfoResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/card/membercard/WxMpMemberCardUserInfoResult.java
@@ -6,11 +6,10 @@
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
/**
- *
* 拉取会员信息返回的结果
- *
- * 字段格式参考https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283 6.2.1小节的步骤5
- *
+ *
+ * {@code 字段格式参考:会员卡接口 6.2.1小节的步骤5}
+ *
*
* @author YuJian
* @version 2017/7/9
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java
index f066c1d934..01be3c08d2 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java
@@ -45,6 +45,8 @@ public class WxMpKefuMessage implements Serializable {
/**
* 获得文本消息builder.
+ *
+ * @return 文本消息builder
*/
public static TextBuilder TEXT() {
return new TextBuilder();
@@ -52,6 +54,8 @@ public static TextBuilder TEXT() {
/**
* 获得图片消息builder.
+ *
+ * @return 图片消息builder
*/
public static ImageBuilder IMAGE() {
return new ImageBuilder();
@@ -59,6 +63,8 @@ public static ImageBuilder IMAGE() {
/**
* 获得语音消息builder.
+ *
+ * @return 语音消息builder
*/
public static VoiceBuilder VOICE() {
return new VoiceBuilder();
@@ -66,6 +72,8 @@ public static VoiceBuilder VOICE() {
/**
* 获得视频消息builder.
+ *
+ * @return 视频消息builder
*/
public static VideoBuilder VIDEO() {
return new VideoBuilder();
@@ -73,6 +81,8 @@ public static VideoBuilder VIDEO() {
/**
* 获得音乐消息builder.
+ *
+ * @return 音乐消息builder
*/
public static MusicBuilder MUSIC() {
return new MusicBuilder();
@@ -80,6 +90,8 @@ public static MusicBuilder MUSIC() {
/**
* 获得图文消息(点击跳转到外链)builder.
+ *
+ * @return 图文消息builder
*/
public static NewsBuilder NEWS() {
return new NewsBuilder();
@@ -87,6 +99,8 @@ public static NewsBuilder NEWS() {
/**
* 获得图文消息(点击跳转到图文消息页面)builder.
+ *
+ * @return 图文消息builder
*/
public static MpNewsBuilder MPNEWS() {
return new MpNewsBuilder();
@@ -94,6 +108,8 @@ public static MpNewsBuilder MPNEWS() {
/**
* 获得卡券消息builder.
+ *
+ * @return 卡券消息builder
*/
public static WxCardBuilder WXCARD() {
return new WxCardBuilder();
@@ -101,6 +117,8 @@ public static WxCardBuilder WXCARD() {
/**
* 获得菜单消息builder.
+ *
+ * @return 菜单消息builder
*/
public static WxMsgMenuBuilder MSGMENU() {
return new WxMsgMenuBuilder();
@@ -108,20 +126,25 @@ public static WxMsgMenuBuilder MSGMENU() {
/**
* 小程序卡片.
+ *
+ * @return 小程序卡片builder
*/
public static MiniProgramPageBuilder MINIPROGRAMPAGE() {
return new MiniProgramPageBuilder();
}
/**
- * 发送图文消息(点击跳转到图文消息页面)使用通过 “发布” 系列接口得到的 article_id(草稿箱功能上线后不再支持客服接口中带 media_id 的 mpnews 类型的图文消息)
+ * 发送图文消息(点击跳转到图文消息页面)使用通过 “发布” 系列接口得到的 article_id
+ *
+ * @return 图文消息builder
*/
public static MpNewsArticleBuilder MPNEWSARTICLE() {
return new MpNewsArticleBuilder();
}
/**
- *
+ * 设置消息类型
+ *
* 请使用
* {@link me.chanjar.weixin.common.api.WxConsts.KefuMsgType#TEXT}
* {@link me.chanjar.weixin.common.api.WxConsts.KefuMsgType#IMAGE}
@@ -135,7 +158,9 @@ public static MpNewsArticleBuilder MPNEWSARTICLE() {
* {@link me.chanjar.weixin.common.api.WxConsts.KefuMsgType#TASKCARD}
* {@link me.chanjar.weixin.common.api.WxConsts.KefuMsgType#MSGMENU}
* {@link me.chanjar.weixin.common.api.WxConsts.KefuMsgType#MP_NEWS_ARTICLE}
- *
+ *
+ *
+ * @param msgType 消息类型
*/
public void setMsgType(String msgType) {
this.msgType = msgType;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
index 3d5f4ac3a0..dfc88ab13b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
@@ -927,6 +927,7 @@ public static WxMpXmlMessage fromXml(InputStream is) {
* @param timestamp 时间戳
* @param nonce 随机串
* @param msgSignature 签名串
+ * @return 解密后的消息对象
*/
public static WxMpXmlMessage fromEncryptedXml(String encryptedXml, WxMpConfigStorage wxMpConfigStorage,
String timestamp, String nonce, String msgSignature) {
@@ -956,14 +957,16 @@ public WxMpXmlMessage decryptField(WxMpConfigStorage wxMpConfigStorage,
/**
*
* 当接受用户消息时,可能会获得以下值:
- * {@link WxConsts.XmlMsgType#TEXT}
- * {@link WxConsts.XmlMsgType#IMAGE}
- * {@link WxConsts.XmlMsgType#VOICE}
- * {@link WxConsts.XmlMsgType#VIDEO}
- * {@link WxConsts.XmlMsgType#LOCATION}
- * {@link WxConsts.XmlMsgType#LINK}
- * {@link WxConsts.XmlMsgType#EVENT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#LOCATION}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#LINK}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#EVENT}
*
+ *
+ * @return 消息类型
*/
public String getMsgType() {
return this.msgType;
@@ -972,13 +975,15 @@ public String getMsgType() {
/**
*
* 当发送消息的时候使用:
- * {@link WxConsts.XmlMsgType#TEXT}
- * {@link WxConsts.XmlMsgType#IMAGE}
- * {@link WxConsts.XmlMsgType#VOICE}
- * {@link WxConsts.XmlMsgType#VIDEO}
- * {@link WxConsts.XmlMsgType#NEWS}
- * {@link WxConsts.XmlMsgType#MUSIC}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#TEXT}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#IMAGE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VOICE}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#VIDEO}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#NEWS}
+ * {@link me.chanjar.weixin.common.api.WxConsts.XmlMsgType#MUSIC}
*
+ *
+ * @param msgType 消息类型
*/
public void setMsgType(String msgType) {
this.msgType = msgType;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java
index a44aea740c..1f3143df7e 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java
@@ -70,6 +70,8 @@ public abstract class WxMpXmlOutMessage implements Serializable {
/**
* 获得文本消息builder
+ *
+ * @return 文本消息构建器
*/
public static TextBuilder TEXT() {
return new TextBuilder();
@@ -77,6 +79,8 @@ public static TextBuilder TEXT() {
/**
* 获得图片消息builder
+ *
+ * @return 图片消息构建器
*/
public static ImageBuilder IMAGE() {
return new ImageBuilder();
@@ -84,6 +88,8 @@ public static ImageBuilder IMAGE() {
/**
* 获得语音消息builder
+ *
+ * @return 语音消息构建器
*/
public static VoiceBuilder VOICE() {
return new VoiceBuilder();
@@ -91,6 +97,8 @@ public static VoiceBuilder VOICE() {
/**
* 获得视频消息builder
+ *
+ * @return 视频消息构建器
*/
public static VideoBuilder VIDEO() {
return new VideoBuilder();
@@ -98,6 +106,8 @@ public static VideoBuilder VIDEO() {
/**
* 获得音乐消息builder
+ *
+ * @return 音乐消息构建器
*/
public static MusicBuilder MUSIC() {
return new MusicBuilder();
@@ -105,6 +115,8 @@ public static MusicBuilder MUSIC() {
/**
* 获得图文消息builder
+ *
+ * @return 图文消息构建器
*/
public static NewsBuilder NEWS() {
return new NewsBuilder();
@@ -112,6 +124,8 @@ public static NewsBuilder NEWS() {
/**
* 获得客服消息builder
+ *
+ * @return 客服消息构建器
*/
public static TransferCustomerServiceBuilder TRANSFER_CUSTOMER_SERVICE() {
return new TransferCustomerServiceBuilder();
@@ -119,11 +133,18 @@ public static TransferCustomerServiceBuilder TRANSFER_CUSTOMER_SERVICE() {
/**
* 获得设备消息builder
+ *
+ * @return 设备消息builder
*/
public static DeviceBuilder DEVICE() {
return new DeviceBuilder();
}
+ /**
+ * 转换成xml格式
+ *
+ * @return xml格式字符串
+ */
@SuppressWarnings("unchecked")
public String toXml() {
return XStreamTransformer.toXml((Class) this.getClass(), this);
@@ -131,6 +152,9 @@ public String toXml() {
/**
* 转换成加密的结果
+ *
+ * @param wxMpConfigStorage 公众号配置
+ * @return 加密后的消息对象
*/
public WxMpXmlOutMessage toEncrypted(WxMpConfigStorage wxMpConfigStorage) {
String plainXml = toXml();
@@ -146,6 +170,9 @@ public WxMpXmlOutMessage toEncrypted(WxMpConfigStorage wxMpConfigStorage) {
/**
* 转换成加密的xml格式
+ *
+ * @param wxMpConfigStorage 公众号配置
+ * @return 加密后的xml格式字符串
*/
public String toEncryptedXml(WxMpConfigStorage wxMpConfigStorage) {
String plainXml = toXml();
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpMassGetResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpMassGetResult.java
index fe8f6e4043..58f2ea2693 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpMassGetResult.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpMassGetResult.java
@@ -9,7 +9,8 @@
/**
*
* 查询群发消息发送状态【订阅号与服务号认证后均可用】
- * https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Batch_Sends_and_Originality_Checks.html#%E6%9F%A5%E8%AF%A2%E7%BE%A4%E5%8F%91%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E7%8A%B6%E6%80%81%E3%80%90%E8%AE%A2%E9%98%85%E5%8F%B7%E4%B8%8E%E6%9C%8D%E5%8A%A1%E5%8F%B7%E8%AE%A4%E8%AF%81%E5%90%8E%E5%9D%87%E5%8F%AF%E7%94%A8%E3%80%91
+ * 文档地址:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Batch_Sends_and_Originality_Checks.html
+ *
* @author S
*/
@Data
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/WxMpConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/WxMpConfigStorage.java
index 11aeef6124..1bebe86885 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/WxMpConfigStorage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/WxMpConfigStorage.java
@@ -24,7 +24,7 @@ public interface WxMpConfigStorage {
* Is use stable access token api
*
* @return the boolean
- * @link https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/getStableAccessToken.html
+ * @see 文档
*/
boolean isStableAccessToken();
@@ -211,6 +211,8 @@ public interface WxMpConfigStorage {
*
* {@link me.chanjar.weixin.mp.api.impl.BaseWxMpServiceImpl#setRetrySleepMillis(int)}
*
+ *
+ * @return 重试间隔毫秒数
*/
int getRetrySleepMillis();
@@ -219,6 +221,8 @@ public interface WxMpConfigStorage {
*
* {@link me.chanjar.weixin.mp.api.impl.BaseWxMpServiceImpl#setMaxRetryTimes(int)}
*
+ *
+ * @return 最大重试次数
*/
int getMaxRetryTimes();
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedisConfigImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedisConfigImpl.java
index 870fa1e276..7939d57a18 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedisConfigImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedisConfigImpl.java
@@ -39,6 +39,8 @@ public WxMpRedisConfigImpl(WxRedisOps redisOps, String keyPrefix) {
/**
* 每个公众号生成独有的存储key.
+ *
+ * @param appId 公众号appId
*/
@Override
public void setAppId(String appId) {
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedissonConfigImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedissonConfigImpl.java
index e0d9e92af1..4982336f8a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedissonConfigImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/config/impl/WxMpRedissonConfigImpl.java
@@ -42,6 +42,8 @@ private WxMpRedissonConfigImpl(@NonNull WxRedisOps redisOps, String keyPrefix) {
/**
* 每个公众号生成独有的存储key.
+ *
+ * @param appId 公众号appId
*/
@Override
public void setAppId(String appId) {
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/constant/WxMpEventConstants.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/constant/WxMpEventConstants.java
index b2e984b0f9..4dfee6295e 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/constant/WxMpEventConstants.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/constant/WxMpEventConstants.java
@@ -20,7 +20,7 @@ public class WxMpEventConstants {
public static final String SUBMIT_MEMBERCARD_USER_INFO = "submit_membercard_user_info";
/**
- * 微信摇一摇周边>>摇一摇事件通知.
+ * 微信摇一摇周边-摇一摇事件通知.
*/
public static final String SHAKEAROUND_USER_SHAKE = "ShakearoundUserShake";
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java
index 99d759f32f..7757ad78bf 100755
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/crypto/WxMpCryptUtil.java
@@ -27,7 +27,7 @@ public class WxMpCryptUtil extends me.chanjar.weixin.common.util.crypto.WxCryptU
/**
* 构造函数
*
- * @param wxMpConfigStorage
+ * @param wxMpConfigStorage 公众号配置存储
*/
public WxMpCryptUtil(WxMpConfigStorage wxMpConfigStorage) {
/*
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java
index ace711a236..55e92700de 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java
@@ -33,7 +33,12 @@ public class XStreamTransformer {
}
/**
- * xml -> pojo.
+ * {@code xml -> pojo.}
+ *
+ * @param 返回类型
+ * @param clazz 类型
+ * @param xml xml字符串
+ * @return 转换后的对象
*/
@SuppressWarnings("unchecked")
public static T fromXml(Class clazz, String xml) {
@@ -41,6 +46,14 @@ public static T fromXml(Class clazz, String xml) {
return object;
}
+ /**
+ * {@code xml -> pojo.}
+ *
+ * @param 返回类型
+ * @param clazz 类型
+ * @param is 输入流
+ * @return 转换后的对象
+ */
@SuppressWarnings("unchecked")
public static T fromXml(Class clazz, InputStream is) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(is);
@@ -48,7 +61,12 @@ public static T fromXml(Class clazz, InputStream is) {
}
/**
- * pojo -> xml.
+ * {@code pojo -> xml.}
+ *
+ * @param 类型参数
+ * @param clazz 类型
+ * @param object 对象
+ * @return xml字符串
*/
public static String toXml(Class clazz, T object) {
return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpCommentServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpCommentServiceImplTest.java
index 0109f676ae..060dee10f8 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpCommentServiceImplTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpCommentServiceImplTest.java
@@ -10,7 +10,7 @@
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java
index 2cc8b80119..7e9d477872 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java
@@ -24,7 +24,7 @@
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpWifiServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpWifiServiceImplTest.java
index d9225c7bc5..a8f79603fc 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpWifiServiceImplTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpWifiServiceImplTest.java
@@ -11,8 +11,8 @@
import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Wifi.BIZWIFI_SHOP_GET;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
diff --git a/weixin-java-open/pom.xml b/weixin-java-open/pom.xml
index 4c34786dad..c05fc52705 100644
--- a/weixin-java-open/pom.xml
+++ b/weixin-java-open/pom.xml
@@ -7,7 +7,7 @@
com.github.binarywang
wx-java
- 4.8.0
+ 4.8.1.B
weixin-java-open
@@ -48,6 +48,16 @@
okhttp
provided
+ * 微工卡批量转账API请求参数 + * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_1_8.shtml + * + * 适用对象:服务商 + * 请求URL:https://api.mch.weixin.qq.com/v3/payroll-card/transfer-batches + * 请求方式:POST + *+ * + * @author binarywang + * created on 2025/01/19 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PayrollTransferBatchesRequest implements Serializable { + private static final long serialVersionUID = 1L; + + /** + *
+ * 字段名:应用ID + * 变量名:appid + * 是否必填:二选一 + * 类型:string[1, 32] + * 描述: + * 服务商在微信申请公众号/小程序或移动应用成功后分配的账号ID + * 示例值:wxa1111111 + *+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+ * 字段名:子商户应用ID + * 变量名:sub_appid + * 是否必填:二选一 + * 类型:string[1, 32] + * 描述: + * 特约商户在微信申请公众号/小程序或移动应用成功后分配的账号ID + * 示例值:wxa1111111 + *+ */ + @SerializedName(value = "sub_appid") + private String subAppid; + + /** + *
+ * 字段名:子商户号 + * 变量名:sub_mchid + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 微信服务商下特约商户的商户号,由微信支付生成并下发 + * 示例值:1111111 + *+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+ * 字段名:商家批次单号 + * 变量名:out_batch_no + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一 + * 示例值:plfk2020042013 + *+ */ + @SerializedName(value = "out_batch_no") + private String outBatchNo; + + /** + *
+ * 字段名:批次名称 + * 变量名:batch_name + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 该笔批量转账的名称 + * 示例值:2019年1月深圳分部报销单 + *+ */ + @SerializedName(value = "batch_name") + private String batchName; + + /** + *
+ * 字段名:批次备注 + * 变量名:batch_remark + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 转账说明,UTF8编码,最多允许32个字符 + * 示例值:2019年1月深圳分部报销单 + *+ */ + @SerializedName(value = "batch_remark") + private String batchRemark; + + /** + *
+ * 字段名:转账总金额 + * 变量名:total_amount + * 是否必填:是 + * 类型:int64 + * 描述: + * 转账金额单位为"分"。转账总金额必须与批次内所有明细转账金额之和保持一致,否则无法发起转账操作 + * 示例值:4000000 + *+ */ + @SerializedName(value = "total_amount") + private Long totalAmount; + + /** + *
+ * 字段名:转账总笔数 + * 变量名:total_num + * 是否必填:是 + * 类型:int + * 描述: + * 一个转账批次单最多发起一千笔转账。转账总笔数必须与批次内所有明细之和保持一致,否则无法发起转账操作 + * 示例值:200 + *+ */ + @SerializedName(value = "total_num") + private Integer totalNum; + + /** + *
+ * 字段名:用工类型 + * 变量名:employment_type + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 微工卡服务仅支持用于与商户有用工关系的用户,需明确用工类型;参考值: + * LONG_TERM_EMPLOYMENT:长期用工, + * SHORT_TERM_EMPLOYMENT:短期用工, + * COOPERATION_EMPLOYMENT:合作关系 + * 示例值:LONG_TERM_EMPLOYMENT + *+ */ + @SerializedName(value = "employment_type") + private String employmentType; + + /** + *
+ * 字段名:用工场景 + * 变量名:employment_scene + * 是否必填:否 + * 类型:string[1, 32] + * 描述: + * 用工场景,参考值: + * LOGISTICS:物流; + * MANUFACTURING:制造业; + * HOTEL:酒店; + * CATERING:餐饮业; + * EVENT:活动促销; + * RETAIL:零售; + * OTHERS:其他 + * 示例值:LOGISTICS + *+ */ + @SerializedName(value = "employment_scene") + private String employmentScene; + + /** + *
+ * 字段名:特约商户授权类型 + * 变量名:authorization_type + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 特约商户授权类型: + * INFORMATION_AUTHORIZATION_TYPE:特约商户信息授权类型, + * FUND_AUTHORIZATION_TYPE:特约商户资金授权类型, + * INFORMATION_AND_FUND_AUTHORIZATION_TYPE:特约商户信息和资金授权类型 + * 示例值:INFORMATION_AUTHORIZATION_TYPE + *+ */ + @SerializedName(value = "authorization_type") + private String authorizationType; + + /** + *
+ * 字段名:转账明细列表 + * 变量名:transfer_detail_list + * 是否必填:是 + * 类型:array + * 描述: + * 发起批量转账的明细列表,最多一千笔 + *+ */ + @SerializedName(value = "transfer_detail_list") + private List
+ * 字段名:商家明细单号 + * 变量名:out_detail_no + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 商户系统内部区分转账批次单下不同转账明细单的唯一标识 + * 示例值:x23zy545Bd5436 + *+ */ + @SerializedName(value = "out_detail_no") + private String outDetailNo; + + /** + *
+ * 字段名:转账金额 + * 变量名:transfer_amount + * 是否必填:是 + * 类型:int64 + * 描述: + * 转账金额单位为"分" + * 示例值:200000 + *+ */ + @SerializedName(value = "transfer_amount") + private Long transferAmount; + + /** + *
+ * 字段名:转账备注 + * 变量名:transfer_remark + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符 + * 示例值:2020年4月报销 + *+ */ + @SerializedName(value = "transfer_remark") + private String transferRemark; + + /** + *
+ * 字段名:用户标识 + * 变量名:openid + * 是否必填:是 + * 类型:string[1, 64] + * 描述: + * 用户在商户对应appid下的唯一标识 + * 示例值:o-MYE42l80oelYMDE34nYD456Xoy + *+ */ + @SerializedName(value = "openid") + private String openid; + + /** + *
+ * 字段名:收款用户姓名 + * 变量名:user_name + * 是否必填:否 + * 类型:string[1, 1024] + * 描述: + * 收款用户真实姓名。该字段需进行加密处理,加密方法详见敏感信息加密说明 + * 示例值:757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45 + *+ */ + @SpecEncrypt + @SerializedName(value = "user_name") + private String userName; + + /** + *
+ * 字段名:收款用户身份证 + * 变量名:user_id_card + * 是否必填:否 + * 类型:string[1, 1024] + * 描述: + * 收款用户身份证号。该字段需进行加密处理,加密方法详见敏感信息加密说明 + * 示例值:8609cb22e1774a50a930e414cc71eca06121bcd266335cda230d24a7886a8d9f + *+ */ + @SpecEncrypt + @SerializedName(value = "user_id_card") + private String userIdCard; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PayrollTransferBatchesResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PayrollTransferBatchesResult.java new file mode 100644 index 0000000000..628c75d5f7 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PayrollTransferBatchesResult.java @@ -0,0 +1,241 @@ +package com.github.binarywang.wxpay.bean.marketing.payroll; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *
+ * 微工卡批量转账API返回结果 + * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_1_8.shtml + * + * 适用对象:服务商 + * 请求URL:https://api.mch.weixin.qq.com/v3/payroll-card/transfer-batches + * 请求方式:POST + *+ * + * @author binarywang + * created on 2025/01/19 + */ +@Data +@NoArgsConstructor +public class PayrollTransferBatchesResult implements Serializable { + private static final long serialVersionUID = 1L; + + /** + *
+ * 字段名:商家批次单号 + * 变量名:out_batch_no + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 商户系统内部的商家批次单号 + * 示例值:plfk2020042013 + *+ */ + @SerializedName(value = "out_batch_no") + private String outBatchNo; + + /** + *
+ * 字段名:微信批次单号 + * 变量名:batch_id + * 是否必填:是 + * 类型:string[1, 64] + * 描述: + * 微信批次单号,微信商家转账系统返回的唯一标识 + * 示例值:1030000071100999991182020050700019480001 + *+ */ + @SerializedName(value = "batch_id") + private String batchId; + + /** + *
+ * 字段名:批次状态 + * 变量名:batch_status + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * ACCEPTED:已受理,批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。商户可查询账户资金流水,若该笔转账批次单的扣款已经发生,则表示批次已经进入转账中,请再次查单确认 + * PROCESSING:转账中,已开始处理批次内的转账明细单 + * FINISHED:已完成,批次内的所有转账明细单都已处理完成 + * CLOSED:已关闭,可查询具体的批次关闭原因确认 + * 示例值:ACCEPTED + *+ */ + @SerializedName(value = "batch_status") + private String batchStatus; + + /** + *
+ * 字段名:批次类型 + * 变量名:batch_type + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 批次类型 + * API:API方式发起 + * WEB:WEB方式发起 + * 示例值:API + *+ */ + @SerializedName(value = "batch_type") + private String batchType; + + /** + *
+ * 字段名:批次名称 + * 变量名:batch_name + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 该笔批量转账的名称 + * 示例值:2019年1月深圳分部报销单 + *+ */ + @SerializedName(value = "batch_name") + private String batchName; + + /** + *
+ * 字段名:批次备注 + * 变量名:batch_remark + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 转账说明,UTF8编码,最多允许32个字符 + * 示例值:2019年1月深圳分部报销单 + *+ */ + @SerializedName(value = "batch_remark") + private String batchRemark; + + /** + *
+ * 字段名:批次关闭原因 + * 变量名:close_reason + * 是否必填:否 + * 类型:string[1, 32] + * 描述: + * 如果批次单状态为"CLOSED"(已关闭),则有关闭原因 + * 示例值:OVERDUE_CLOSE + *+ */ + @SerializedName(value = "close_reason") + private String closeReason; + + /** + *
+ * 字段名:转账总金额 + * 变量名:total_amount + * 是否必填:是 + * 类型:int64 + * 描述: + * 转账金额单位为"分" + * 示例值:4000000 + *+ */ + @SerializedName(value = "total_amount") + private Long totalAmount; + + /** + *
+ * 字段名:转账总笔数 + * 变量名:total_num + * 是否必填:是 + * 类型:int + * 描述: + * 一个转账批次单最多发起一千笔转账 + * 示例值:200 + *+ */ + @SerializedName(value = "total_num") + private Integer totalNum; + + /** + *
+ * 字段名:批次创建时间 + * 变量名:create_time + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 批次受理成功时返回,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE + * 示例值:2015-05-20T13:29:35.120+08:00 + *+ */ + @SerializedName(value = "create_time") + private String createTime; + + /** + *
+ * 字段名:批次更新时间 + * 变量名:update_time + * 是否必填:是 + * 类型:string[1, 32] + * 描述: + * 批次最近一次状态变更的时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE + * 示例值:2015-05-20T13:29:35.120+08:00 + *+ */ + @SerializedName(value = "update_time") + private String updateTime; + + /** + *
+ * 字段名:转账成功金额 + * 变量名:success_amount + * 是否必填:否 + * 类型:int64 + * 描述: + * 转账成功的金额,单位为"分" + * 示例值:3900000 + *+ */ + @SerializedName(value = "success_amount") + private Long successAmount; + + /** + *
+ * 字段名:转账成功笔数 + * 变量名:success_num + * 是否必填:否 + * 类型:int + * 描述: + * 转账成功的笔数 + * 示例值:199 + *+ */ + @SerializedName(value = "success_num") + private Integer successNum; + + /** + *
+ * 字段名:转账失败金额 + * 变量名:fail_amount + * 是否必填:否 + * 类型:int64 + * 描述: + * 转账失败的金额,单位为"分" + * 示例值:100000 + *+ */ + @SerializedName(value = "fail_amount") + private Long failAmount; + + /** + *
+ * 字段名:转账失败笔数 + * 变量名:fail_num + * 是否必填:否 + * 类型:int + * 描述: + * 转账失败的笔数 + * 示例值:1 + *+ */ + @SerializedName(value = "fail_num") + private Integer failNum; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PreOrderWithAuthRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PreOrderWithAuthRequest.java index 1556fbc343..0e20fc8fa6 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PreOrderWithAuthRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/payroll/PreOrderWithAuthRequest.java @@ -166,4 +166,22 @@ public class PreOrderWithAuthRequest implements Serializable { */ @SerializedName(value = "employment_type") private String employmentType; + + /** + *
+ * 字段名:核身类型 + * 变量名:authenticate_type + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * 核身类型,用于标识本次核身的业务类型;枚举值: + * NORMAL_AUTHENTICATE:普通核身 + * LOGIN_AUTHENTICATE:登录核身 + * INSURANCE_AUTHENTICATE:保险核身 + * CONTRACT_AUTHENTICATE:合同核身 + * 示例值:NORMAL_AUTHENTICATE + *+ */ + @SerializedName(value = "authenticate_type") + private String authenticateType; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java index 4ca7958ed5..854fd6ba5a 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/marketing/transfer/BatchDetailsResult.java @@ -235,4 +235,30 @@ public String toString() { */ @SerializedName(value = "update_time") private String updateTime; + /** + *
+ * 字段名:开户银行全称(含支行) + * 变量名:bank_name + * 是否必填:否 + * 类型:string[1, 128] + * 描述: + * 转账到银行卡时返回,开户银行全称(含支行) + * 示例值:中国农业银行股份有限公司深圳分行 + *+ */ + @SerializedName(value = "bank_name") + private String bankName; + /** + *
+ * 字段名:银行卡号后四位 + * 变量名:bank_card_number_tail + * 是否必填:否 + * 类型:string[4, 4] + * 描述: + * 转账到银行卡时返回,用于标识银行卡的后四位 + * 示例值:1234 + *+ */ + @SerializedName(value = "bank_card_number_tail") + private String bankCardNumberTail; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/VideoUploadResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/VideoUploadResult.java new file mode 100644 index 0000000000..615cbbff5f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/media/VideoUploadResult.java @@ -0,0 +1,29 @@ +package com.github.binarywang.wxpay.bean.media; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +/** + * 视频文件上传返回结果对象 + * + * @author copilot + */ +@NoArgsConstructor +@Data +public class VideoUploadResult { + + public static VideoUploadResult fromJson(String json) { + return WxGsonBuilder.create().fromJson(json, VideoUploadResult.class); + } + + /** + * 媒体文件标识 Id + *
+ * 微信返回的媒体文件标识Id。
+ * 示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
+ */
+ @SerializedName("media_id")
+ private String mediaId;
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java
index a0641379fb..346d427fc4 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java
@@ -13,7 +13,7 @@
*
*
* @author xgl
- * @date 2025/12/20
+ * @since 2025/12/20
*/
@Data
@NoArgsConstructor
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayBaseNotifyV3Result.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayBaseNotifyV3Result.java
index 86915d0956..364c9080d8 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayBaseNotifyV3Result.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayBaseNotifyV3Result.java
@@ -5,7 +5,8 @@
*
* @author Pursuer
* @version 1.0
- * @date 2023/6/15
+ * @since 2023/6/15
+ * @param
+ * 单据创建后,用户24小时内不领取将过期关闭,建议拉起用户确认收款页面前,先查单据状态:如单据状态为WAIT_USER_CONFIRM,可用之前的package信息拉起;单据到终态时需更换单号重新发起转账。
+ */
+ @SerializedName("package_info")
+ private String packageInfo;
/**
* 发起转账的时间
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
index a3a9dc7a92..88e544e675 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java
@@ -97,9 +97,13 @@ public class WxPayConfig {
*/
private String subMchId;
/**
- * 微信支付异步回掉地址,通知url必须为直接可访问的url,不能携带参数.
+ * 微信支付异步回调地址,通知url必须为直接可访问的url,不能携带参数.
*/
private String notifyUrl;
+ /**
+ * 退款结果异步回调地址,通知url必须为直接可访问的url,不能携带参数.
+ */
+ private String refundNotifyUrl;
/**
* 交易类型.
*
@@ -325,7 +329,8 @@ public SSLContext initSSLContext() throws WxPayException {
*
* @return org.apache.http.impl.client.CloseableHttpClient
* @author doger.wang
- **/
+ * @throws WxPayException 微信支付异常
+ */
public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
if (StringUtils.isBlank(this.getApiV3Key())) {
throw new WxPayException("请确保apiV3Key值已设置");
@@ -663,6 +668,8 @@ public CloseableHttpClient initSslHttpClient() throws WxPayException {
/**
* 配置HTTP代理
+ *
+ * @param httpClientBuilder HttpClient构建器
*/
private void configureProxy(org.apache.http.impl.client.HttpClientBuilder httpClientBuilder) {
if (StringUtils.isNotBlank(this.getHttpProxyHost()) && this.getHttpProxyPort() > 0) {
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java
index d11738816b..117395ba62 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/example/BusinessOperationTransferExample.java
@@ -8,6 +8,8 @@
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import java.util.Arrays;
+
/**
* 运营工具-商家转账API使用示例
*
@@ -41,10 +43,15 @@ public void init() {
public void createOperationTransferExample() {
try {
// 构建转账请求
+ BusinessOperationTransferRequest.TransferSceneReportInfo reportInfo = new BusinessOperationTransferRequest.TransferSceneReportInfo();
+ reportInfo.setInfoType("活动名称");
+ reportInfo.setInfoContent("新会员有礼");
+
BusinessOperationTransferRequest request = BusinessOperationTransferRequest.newBuilder()
.appid("your_app_id") // 应用ID
.outBillNo("OT" + System.currentTimeMillis()) // 商户转账单号
- .operationSceneId(WxPayConstants.OperationSceneId.OPERATION_CASH_MARKETING) // 运营工具转账场景ID
+ .transferSceneId(WxPayConstants.OperationSceneId.OPERATION_CASH_MARKETING) // 运营工具转账场景ID
+ .transferSceneReportInfos(Arrays.asList(reportInfo)) // 转账场景报备信息
.openid("user_openid") // 用户openid
.userName("张三") // 用户姓名(可选)
.transferAmount(100) // 转账金额,单位分
@@ -59,7 +66,8 @@ public void createOperationTransferExample() {
System.out.println("转账成功!");
System.out.println("商户单号: " + result.getOutBillNo());
System.out.println("微信转账单号: " + result.getTransferBillNo());
- System.out.println("转账状态: " + result.getTransferState());
+ System.out.println("单据状态: " + result.getState());
+ System.out.println("跳转领取页面的package信息: " + result.getPackageInfo());
System.out.println("创建时间: " + result.getCreateTime());
} catch (WxPayException e) {
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantMediaService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantMediaService.java
index 0e35dbb68b..f7f0aaaf3e 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantMediaService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MerchantMediaService.java
@@ -1,6 +1,7 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.media.ImageUploadResult;
+import com.github.binarywang.wxpay.bean.media.VideoUploadResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import java.io.File;
@@ -42,5 +43,34 @@ public interface MerchantMediaService {
*/
ImageUploadResult imageUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException;
+ /**
+ *
+ * 通用接口-视频上传API
+ * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_2.shtml
+ * 接口链接:https://api.mch.weixin.qq.com/v3/merchant/media/video_upload
+ *
+ *
+ * @param videoFile 需要上传的视频文件
+ * @return VideoUploadResult 微信返回的媒体文件标识Id。示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
+ * @throws WxPayException the wx pay exception
+ * @throws IOException the io exception
+ */
+ VideoUploadResult videoUploadV3(File videoFile) throws WxPayException, IOException;
+
+ /**
+ *
+ * 通用接口-视频上传API
+ * 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_2.shtml
+ * 接口链接:https://api.mch.weixin.qq.com/v3/merchant/media/video_upload
+ * 注意:此方法会将整个视频流读入内存计算SHA256后再上传,大文件可能导致OOM,建议大文件使用File方式上传
+ *
+ *
+ * @param inputStream 需要上传的视频文件流
+ * @param fileName 需要上传的视频文件名
+ * @return VideoUploadResult 微信返回的媒体文件标识Id。示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
+ * @throws WxPayException the wx pay exception
+ * @throws IOException the io exception
+ */
+ VideoUploadResult videoUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException;
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PayrollService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PayrollService.java
index b3f788815c..581e3230b7 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PayrollService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/PayrollService.java
@@ -101,4 +101,16 @@ public interface PayrollService {
*/
WxPayApplyBillV3Result merchantFundWithdrawBillType(String billType, String billDate, String tarType) throws WxPayException;
+ /**
+ * 微工卡批量转账API
+ * 适用对象:服务商
+ * 请求URL:https://api.mch.weixin.qq.com/v3/payroll-card/transfer-batches
+ * 请求方式:POST
+ *
+ * @param request 请求参数
+ * @return 返回数据
+ * @throws WxPayException the wx pay exception
+ */
+ PayrollTransferBatchesResult payrollCardTransferBatches(PayrollTransferBatchesRequest request) 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 dab89a0142..2db2987d12 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
@@ -78,6 +78,18 @@ public interface WxPayService {
*/
boolean switchover(String mchId, String appId);
+ /**
+ * 仅根据商户号进行切换.
+ * 适用于一个商户号对应多个appId的场景,切换时会匹配符合该商户号的配置.
+ * 注意:由于HashMap迭代顺序不确定,当存在多个匹配项时返回的配置是不可预测的,建议使用精确匹配方式.
+ *
+ * @param mchId 商户标识
+ * @return 切换是否成功,如果找不到匹配的配置则返回false
+ */
+ default boolean switchover(String mchId) {
+ return false;
+ }
+
/**
* 进行相应的商户切换.
*
@@ -87,6 +99,19 @@ public interface WxPayService {
*/
WxPayService switchoverTo(String mchId, String appId);
+ /**
+ * 仅根据商户号进行切换.
+ * 适用于一个商户号对应多个appId的场景,切换时会匹配符合该商户号的配置.
+ * 注意:由于HashMap迭代顺序不确定,当存在多个匹配项时返回的配置是不可预测的,建议使用精确匹配方式.
+ *
+ * @param mchId 商户标识
+ * @return 切换成功,则返回当前对象,方便链式调用
+ * @throws me.chanjar.weixin.common.error.WxRuntimeException 如果找不到匹配的配置
+ */
+ default WxPayService switchoverTo(String mchId) {
+ throw new me.chanjar.weixin.common.error.WxRuntimeException("子类需要实现此方法");
+ }
+
/**
* 发送post请求,得到响应字节数组.
*
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 2e896cda7e..4b51c498d2 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
@@ -212,6 +212,34 @@ public boolean switchover(String mchId, String appId) {
return false;
}
+ @Override
+ public boolean switchover(String mchId) {
+ // 参数校验
+ if (StringUtils.isBlank(mchId)) {
+ log.error("商户号mchId不能为空");
+ return false;
+ }
+
+ // 先尝试精确匹配(针对只有mchId没有appId的配置)
+ if (this.configMap.containsKey(mchId)) {
+ WxPayConfigHolder.set(mchId);
+ return true;
+ }
+
+ // 尝试前缀匹配(查找以 mchId_ 开头的配置)
+ String prefix = mchId + "_";
+ for (String key : this.configMap.keySet()) {
+ if (key.startsWith(prefix)) {
+ WxPayConfigHolder.set(key);
+ log.debug("根据mchId=【{}】找到配置key=【{}】", mchId, key);
+ return true;
+ }
+ }
+
+ log.error("无法找到对应mchId=【{}】的商户号配置信息,请核实!", mchId);
+ return false;
+ }
+
@Override
public WxPayService switchoverTo(String mchId, String appId) {
String configKey = this.getConfigKey(mchId, appId);
@@ -222,6 +250,32 @@ public WxPayService switchoverTo(String mchId, String appId) {
throw new WxRuntimeException(String.format("无法找到对应mchId=【%s】,appId=【%s】的商户号配置信息,请核实!", mchId, appId));
}
+ @Override
+ public WxPayService switchoverTo(String mchId) {
+ // 参数校验
+ if (StringUtils.isBlank(mchId)) {
+ throw new WxRuntimeException("商户号mchId不能为空");
+ }
+
+ // 先尝试精确匹配(针对只有mchId没有appId的配置)
+ if (this.configMap.containsKey(mchId)) {
+ WxPayConfigHolder.set(mchId);
+ return this;
+ }
+
+ // 尝试前缀匹配(查找以 mchId_ 开头的配置)
+ String prefix = mchId + "_";
+ for (String key : this.configMap.keySet()) {
+ if (key.startsWith(prefix)) {
+ WxPayConfigHolder.set(key);
+ log.debug("根据mchId=【{}】找到配置key=【{}】", mchId, key);
+ return this;
+ }
+ }
+
+ throw new WxRuntimeException(String.format("无法找到对应mchId=【%s】的商户号配置信息,请核实!", mchId));
+ }
+
public String getConfigKey(String mchId, String appId) {
return mchId + "_" + appId;
}
@@ -263,6 +317,9 @@ public WxPayRefundResult refundV2(WxPayRefundRequest request) throws WxPayExcept
@Override
public WxPayRefundV3Result refundV3(WxPayRefundV3Request request) throws WxPayException {
+ if (StringUtils.isBlank(request.getNotifyUrl())) {
+ request.setNotifyUrl(this.getConfig().getRefundNotifyUrl());
+ }
String url = String.format("%s/v3/refund/domestic/refunds", this.getPayBaseUrl());
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayRefundV3Result.class);
@@ -270,6 +327,9 @@ public WxPayRefundV3Result refundV3(WxPayRefundV3Request request) throws WxPayEx
@Override
public WxPayRefundV3Result partnerRefundV3(WxPayPartnerRefundV3Request request) throws WxPayException {
+ if (StringUtils.isBlank(request.getNotifyUrl())) {
+ request.setNotifyUrl(this.getConfig().getRefundNotifyUrl());
+ }
if (StringUtils.isBlank(request.getSubMchid())) {
request.setSubMchid(this.getConfig().getSubMchId());
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantMediaServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantMediaServiceImpl.java
index 7952513f56..ee77f5e974 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantMediaServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MerchantMediaServiceImpl.java
@@ -1,6 +1,7 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.wxpay.bean.media.ImageUploadResult;
+import com.github.binarywang.wxpay.bean.media.VideoUploadResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.MerchantMediaService;
import com.github.binarywang.wxpay.service.WxPayService;
@@ -40,7 +41,7 @@ public ImageUploadResult imageUploadV3(File imageFile) throws WxPayException,IOE
@Override
public ImageUploadResult imageUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException {
String url = String.format("%s/v3/merchant/media/upload", this.payService.getPayBaseUrl());
- try(ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[2048];
int len;
while ((len = inputStream.read(buffer)) > -1) {
@@ -57,4 +58,40 @@ public ImageUploadResult imageUploadV3(InputStream inputStream, String fileName)
}
}
+ @Override
+ public VideoUploadResult videoUploadV3(File videoFile) throws WxPayException, IOException {
+ String url = String.format("%s/v3/merchant/media/video_upload", this.payService.getPayBaseUrl());
+
+ try (FileInputStream s1 = new FileInputStream(videoFile)) {
+ String sha256 = DigestUtils.sha256Hex(s1);
+ try (InputStream s2 = new FileInputStream(videoFile)) {
+ WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url))
+ .withVideo(videoFile.getName(), sha256, s2)
+ .build();
+ String result = this.payService.postV3(url, request);
+ return VideoUploadResult.fromJson(result);
+ }
+ }
+ }
+
+ @Override
+ public VideoUploadResult videoUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException {
+ String url = String.format("%s/v3/merchant/media/video_upload", this.payService.getPayBaseUrl());
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[2048];
+ int len;
+ while ((len = inputStream.read(buffer)) > -1) {
+ bos.write(buffer, 0, len);
+ }
+ bos.flush();
+ byte[] data = bos.toByteArray();
+ String sha256 = DigestUtils.sha256Hex(data);
+ WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url))
+ .withVideo(fileName, sha256, new ByteArrayInputStream(data))
+ .build();
+ String result = this.payService.postV3(url, request);
+ return VideoUploadResult.fromJson(result);
+ }
+ }
+
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PayrollServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PayrollServiceImpl.java
index 3d8c831271..85f7ee23dd 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PayrollServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/PayrollServiceImpl.java
@@ -193,4 +193,27 @@ public WxPayApplyBillV3Result merchantFundWithdrawBillType(String billType, Stri
return GSON.fromJson(response, WxPayApplyBillV3Result.class);
}
+ /**
+ * 微工卡批量转账API
+ * 适用对象:服务商
+ * 请求URL:https://api.mch.weixin.qq.com/v3/payroll-card/transfer-batches
+ * 请求方式:POST
+ *
+ * @param request 请求参数
+ * @return 返回数据
+ * @throws WxPayException the wx pay exception
+ */
+ @Override
+ public PayrollTransferBatchesResult payrollCardTransferBatches(PayrollTransferBatchesRequest request) throws WxPayException {
+ String url = String.format("%s/v3/payroll-card/transfer-batches", payService.getPayBaseUrl());
+ // 对敏感信息进行加密
+ if (request.getTransferDetailList() != null && !request.getTransferDetailList().isEmpty()) {
+ for (PayrollTransferBatchesRequest.TransferDetail detail : request.getTransferDetailList()) {
+ RsaCryptoUtil.encryptFields(detail, payService.getConfig().getVerifier().getValidCertificate());
+ }
+ }
+ String response = payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
+ return GSON.fromJson(response, PayrollTransferBatchesResult.class);
+ }
+
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java
index 8e795966f4..4316bafa40 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceImpl.java
@@ -2,11 +2,11 @@
/**
*
- * 微信支付接口请求实现类,默认使用Apache HttpClient实现
+ * 微信支付接口请求实现类,默认使用Apache HttpClient 5实现
* Created by Binary Wang on 2017-7-8.
*
*
* @author Binary Wang
*/
-public class WxPayServiceImpl extends WxPayServiceApacheHttpImpl {
+public class WxPayServiceImpl extends WxPayServiceHttpComponentsImpl {
}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java
index b641cbe537..c4ad966415 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java
@@ -17,7 +17,7 @@ public class RequestUtils {
/**
* 获取请求头数据,微信V3版本回调使用
*
- * @param request
+ * @param request HTTP请求对象
* @return 字符串
*/
public static String readData(HttpServletRequest request) {
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ResourcesUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ResourcesUtils.java
index ac68b00bb4..51dd8fbbb6 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ResourcesUtils.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/ResourcesUtils.java
@@ -23,6 +23,10 @@ public class ResourcesUtils {
* callingClass is provided: {@link Class#getClassLoader() callingClass.getClassLoader()}
- * 默认接口实现类,使用apache httpclient实现 + * 默认接口实现类,使用apache httpClient 5实现 * Created by Binary Wang on 2017-5-27. ** * @author Binary Wang */ -public class WxQidianServiceImpl extends WxQidianServiceHttpClientImpl { +public class WxQidianServiceImpl extends WxQidianServiceHttpComponentsImpl { }