52 Commits

Author SHA1 Message Date
Binary Wang
fb57af7409 🔖 发布 4.7.5.B 测试版本 2025-05-08 23:04:32 +08:00
jimson
88a5bc4f43 🎨 企微客户群回调事件添加MemChangeList字段 2025-05-08 22:15:06 +08:00
Binary Wang
dc674ce024 🎨 优化部分javadoc 2025-04-29 12:12:34 +08:00
Binary Wang
854b50bd51 🎨 修复日志代码报错问题 2025-04-29 11:33:58 +08:00
imyzt
2d8d1df00e 🆕 #3320【企业微信】增加异步上传临时素材相关接口 2025-04-29 11:29:09 +08:00
Binary Wang
2279105fef :art: 优化微信支付请求代码,抽取合并重复代码 2025-04-26 11:18:56 +08:00
SynchPj
cbb3b24577 🎨 #3553【微信支付】v3请求统一加上Wechatpay-Serial请求头 2025-04-22 11:08:50 +08:00
giveup
ddfbee25e1 🐛 #3557 【企业微信】修复agentId数据类型不一致导致的WxCpTpMessageRouterRule.test()方法匹配失败的问题 2025-04-21 10:00:39 +08:00
友人A
6a4ed91ae2 🎨 #3558 【企业微信】修复会话内容存档接口获取解密的聊天数据时文件信息转换出错的问题 2025-04-21 09:58:51 +08:00
西东
59f5a99fda 🆕 添加wx-java-channel-solon-plugin README.md 2025-04-21 09:55:13 +08:00
Henry Heng
3718b499a0 🎨 #3554【企业微信】修复审批通知节点获取不到用户ID的问题 2025-04-16 10:43:55 +08:00
Henry Heng
bb76db052d 🎨 #3554【企业微信】修复审批通知节点获取不到用户ID的问题 2025-04-15 19:32:54 +08:00
HerveyHall
e16e0e9373 🎨 #3548【微信支付】修复公钥模式下V3接口未设置Wechatpay-Serial请求头导致的验签失败 2025-04-15 15:14:12 +08:00
Holy
89280abd00 🎨 #3547【微信支付】修复验证器未正确初始化导致的v3请求构造异常问题 2025-04-14 11:32:34 +08:00
Binary Wang
0423e6849d 🔖 发布 4.7.4.B 测试版本 2025-04-08 08:39:24 +08:00
zhangrongguang
833ff70680 【企业微信】接待人员管理 添加接待人员/删除接待人员 增加 department_id_list 2025-04-07 09:50:19 +00:00
jimmyjimmy-sw
373c1e65cb 🐛 #3522 【公众号】修复WxMpMapConfigImpl静态属性存储token导致多个实例时出现token没有隔离的情况 2025-04-07 17:47:48 +08:00
谈笑
b44dd2e347 🎨 #3541【企业微信】增加设置WebView型应用在用户工作台展示的参数 2025-04-07 07:01:35 +00:00
谈笑
b6c3d74cba 🆕 #3529 【企业微信】增加批量设置应用在用户工作台展示的数据的接口 2025-04-07 13:05:46 +08:00
cxiaoxifeng
0452a05dd4 🎨 【小程序】修复物流服务查询组件更新物品信息接口的地址 2025-04-07 13:05:46 +08:00
yangmengyu2021
4828a314e9 🎨 #3534 为connectionRequestTimeout设置默认值,避免开发者在虚拟线程中调用框架的httpClient时造成的无限等待 2025-04-07 13:04:33 +08:00
cloudX
3f0b8d4e2b 🎨 #3538 【微信支付】V3接口增加实名支付参数 2025-04-07 13:03:10 +08:00
SynchPj
dd407141b0 🎨 #3530 【微信支付】修复未设置平台证书引起的v3请求构造异常 2025-04-07 13:01:53 +08:00
yangmengyu2021
b225afbd68 🎨 #3532 【微信支付】修复支付通知回调解析方法报错的问题 2025-03-23 20:07:01 +08:00
Binary Wang
5604a16ae8 🎨 fix doc 2025-03-23 20:00:52 +08:00
Binary Wang
25309e06ad 🔖 发布 4.7.3.B 测试版本 2025-03-18 12:58:09 +08:00
SynchPj
5ac9922f8d 🎨 #3498【微信支付】服务商模式-兼容公钥模式下请求头序列号以及灰度切换 2025-03-17 10:58:50 +08:00
zhongjq
03790d64bc 🎨 WxMaMessage.allFieldsMap支持json格式数据存放 2025-03-06 20:56:12 +08:00
Lyx Fly
1f0dbcc2aa 🎨 #3516【公众号】修正代理认证请求头设置错误的问题 2025-03-03 15:43:38 +08:00
wzl
404102a4c8 🎨 #3493 【微信支付】修复合单支付combineTransactions接口参数错误问题 2025-03-03 15:42:26 +08:00
raven
5decfcb917 🎨 #3505【微信支付】修复微信支付异步通知请求解析失败问题 2025-03-03 15:40:52 +08:00
sober
44a95578d9 🐛 #3508 【企业微信】获取企业用户信息接口修复用户信息大小写导致的问题 2025-03-03 15:39:23 +08:00
altusea
2bf31411c0 🎨 #3492【视频号】 微信小店获取订单详情接口增加新带货平台Id字段 2025-03-03 15:34:00 +08:00
giveup
71fbc2b1e8 🎨 #3499 【企业微信】配置客户联系「联系我」方式的接口增加 is_exclusive字段 2025-03-03 15:28:35 +08:00
Binary Wang
15b7460d92 🎨 增加新的赞助商logo 2025-03-03 15:25:33 +08:00
zhangruhong
933840e3b2 🎨 消息类增加first/second字段 2025-03-03 15:11:44 +08:00
zhangruhong
5da939647c 🎨 #3500【公众号】消息接受类添加名称审核结果事件推送所需字段 2025-02-19 19:50:49 +08:00
Binary Wang
22ec3f0eca 🎨 增加注释防止误解,同时优化重构代码 2025-02-17 11:12:32 +08:00
je45
410cc9dfd7 🎨 #3490【微信支付】消费者投诉相关接口补充最新增加的一些参数 2025-02-07 21:22:39 +08:00
imyzt
783c89523d 🆕 #3488【企业微信】增加获取企业已配置的「联系我」列表的接口 2025-02-07 19:58:53 +08:00
Binary Wang
3e48dc7f83 🔖 发布 4.7.2.B 测试版本 2025-01-24 22:18:57 +08:00
superffan
f3c1422354 :art:【微信支付】spring-boot-starter模块增加公钥ID和证书文件路径等配置项 2025-01-24 21:27:34 +08:00
giveup
d65e2f27a9 🎨 WxMpSubscribeMessage实现序列化接口 2025-01-24 21:26:02 +08:00
Neror
c3b16228c0 🎨 【微信支付】完善微信商家转账功能API !151 2025-01-21 11:49:38 +00:00
Neror
24ebc91dca 🎨 【微信支付】增加多配置切换功能 2025-01-21 19:36:25 +08:00
GadflyFang
1e003ee571 🎨 修复 94aaff4 引入的错误读取证书的问题 2025-01-21 18:44:33 +08:00
giveup
8e5ee97378 🎨 #3458 【企业微信】家校沟通获取部门列表接口优化,如果部门id为空则获取全量组织架构 2025-01-21 18:41:11 +08:00
julb
704fba4d85 🎨 【微信支付】兼容公钥模式下请求头序列号 !148 2025-01-20 10:52:35 +08:00
Molzx
b0daf8428e 🆕 #3479 【小程序】新增订单管理的配置和查询订单配置路径的接口 2025-01-17 12:02:48 +08:00
mrsiu
ab1c150feb 🎨 #3478 【企业微信】OA审批接口增加对说明文字控件(control参数为Tips)的支持 2025-01-16 13:50:24 +08:00
潘安
b4b73ad40a 🎨 #3467 【微信支付】商户进件开户意愿接口相关字段调整 2025-01-16 13:47:55 +08:00
allovine
be0dd8b692 🆕 #3474 【微信支付】增加2025.1.15正式上线的商户转账新版本的相关接口 2025-01-16 13:46:02 +08:00
119 changed files with 2605 additions and 322 deletions

View File

@@ -28,7 +28,7 @@ $ git push
* 定期使用项目仓库内容更新自己仓库内容。
```bash
$ git remote add upstream https://github.com/Wechat-Group/WxJava
$ git remote add upstream https://github.com/binarywang/WxJava
$ git fetch upstream
$ git checkout develop
$ git rebase upstream/develop

View File

@@ -21,24 +21,29 @@
</td>
</tr>
<tr>
<td align="center" valign="middle" colspan="3">
<td align="center" valign="middle" colspan="2">
<a href="https://www.jeequan.com/product/jeepay.html" target="_blank">
<img height="120" src="https://jeequan.oss-cn-beijing.aliyuncs.com/jeepay/img/wxjava_jeepay.png" alt="计全支付Jeepay,开源支付系统">
</a>
</td>
<td align="center" valign="middle" colspan="1">
<a href="https://www.mall4j.com/cn/?statId=9" target="_blank">
<img height="120" src="https://img.mall4j.com/mall.png" alt="Mall4j">
</a>
</td>
</tr>
<tr>
<td align="left" valign="middle">
<td align="center" valign="middle">
<a href="http://mp.weixin.qq.com/mp/homepage?__biz=MzI3MzAwMzk4OA==&hid=1&sn=f31af3bf562b116b061c9ab4edf70b61&scene=18#wechat_redirect" target="_blank">
<img height="120" src="https://gitee.com/binary/weixin-java-tools/raw/develop/images/qrcodes/mp.png" alt="mp qrcode">
</a>
</td>
<td valign="middle">
<td align="center" valign="middle">
<a href="https://www.diboot.com?from=wxjava" target="_blank">
<img height="120" src="https://www.diboot.com/img/diboot_ad.png" alt="diboot低代码开发平台"/>
</a>
</td>
<td align="right" valign="middle">
<td align="center" valign="middle">
<a href="https://www.iyque.cn/" target="_blank">
<img height="120" src="https://iyque-1251309172.cos.ap-nanjing.myqcloud.com/advert/wxjava.jpg" alt="aliyun ad">
</a>

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
<packaging>pom</packaging>
<name>WxJava - Weixin/Wechat Java SDK</name>
<description>微信开发Java SDK</description>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<packaging>pom</packaging>
<artifactId>wx-java-solon-plugins</artifactId>
@@ -14,7 +14,7 @@
<description>WxJava 各个模块的 Solon Plugin</description>
<properties>
<solon.version>3.0.1</solon.version>
<solon.version>3.2.0</solon.version>
</properties>
<modules>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,92 @@
# wx-java-channel-solon-plugin
## 快速开始
1. 引入依赖
```xml
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-channel-solon-plugin</artifactId>
<version>${version}</version>
</dependency>
<!-- 配置存储方式为jedis 则引入jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!-- 配置存储方式为redisson 则引入redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
</dependencies>
```
2. 添加配置(app.properties)
```properties
# 视频号配置(必填)
## 视频号小店的appId和secret
wx.channel.app-id=@appId
wx.channel.secret=@secret
# 视频号配置 选填
## 设置视频号小店消息服务器配置的token
wx.channel.token=@token
## 设置视频号小店消息服务器配置的EncodingAESKey
wx.channel.aes-key=
## 支持JSON或者XML格式默认JSON
wx.channel.msg-data-format=JSON
## 是否使用稳定版 Access Token
wx.channel.use-stable-access-token=false
# ConfigStorage 配置(选填)
## 配置类型: memory(默认), jedis, redisson, redis_template
wx.channel.config-storage.type=memory
## 相关redis前缀配置: wx:channel(默认)
wx.channel.config-storage.key-prefix=wx:channel
wx.channel.config-storage.redis.host=127.0.0.1
wx.channel.config-storage.redis.port=6379
wx.channel.config-storage.redis.password=123456
# http 客户端配置(选填)
## # http客户端类型: http_client(默认)
wx.channel.config-storage.http-client-type=http_client
wx.channel.config-storage.http-proxy-host=
wx.channel.config-storage.http-proxy-port=
wx.channel.config-storage.http-proxy-username=
wx.channel.config-storage.http-proxy-password=
## 最大重试次数默认5 次,如果小于 0则为 0
wx.channel.config-storage.max-retry-times=5
## 重试时间间隔步进默认1000 毫秒,如果小于 0则为 1000
wx.channel.config-storage.retry-sleep-millis=1000
```
3. 自动注入的类型
- `WxChannelService`
- `WxChannelConfig`
4. 使用样例
```java
import me.chanjar.weixin.channel.api.WxChannelService;
import me.chanjar.weixin.channel.bean.shop.ShopInfoResponse;
import me.chanjar.weixin.channel.util.JsonUtils;
import me.chanjar.weixin.common.error.WxErrorException;
import org.noear.solon.annotation.Inject;
@Component
public class DemoService {
@Inject
private WxChannelService wxChannelService;
public String getShopInfo() throws WxErrorException {
// 获取店铺基本信息
ShopInfoResponse response = wxChannelService.getBasicService().getShopInfo();
// 此处为演示如果要返回response的结果建议自己封装一个VO避免直接返回response
return JsonUtils.encode(response);
}
}
```

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>wx-java-solon-plugins</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<packaging>pom</packaging>
<artifactId>wx-java-spring-boot-starters</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -57,6 +57,8 @@ public class WxPayAutoConfiguration {
payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getCertSerialNo()));
payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiv3Key()));
payConfig.setPublicKeyId(StringUtils.trimToNull(this.properties.getPublicKeyId()));
payConfig.setPublicKeyPath(StringUtils.trimToNull(this.properties.getPublicKeyPath()));
wxPayService.setConfig(payConfig);
return wxPayService;

View File

@@ -73,7 +73,17 @@ public class WxPayProperties {
* apiv3 商户apiclient_cert.pem
*/
private String privateCertPath;
/**
* 公钥ID
*/
private String publicKeyId;
/**
* pub_key.pem证书文件的绝对路径或者以classpath:开头的类路径.
*/
private String publicKeyPath;
/**
* 微信支付是否使用仿真测试环境.
* 默认不使用

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>wx-java-spring-boot-starters</artifactId>
<groupId>com.github.binarywang</groupId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-graal</artifactId>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-java-channel</artifactId>

View File

@@ -42,4 +42,8 @@ public class OrderCommissionInfo implements Serializable {
/** 达人openfinderid */
@JsonProperty("openfinderid")
private String openFinderId;
/** 新带货平台 id */
@JsonProperty("talent_id")
private String talentId;
}

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-java-common</artifactId>

View File

@@ -59,7 +59,7 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder {
* 设置为负数是使用系统默认设置(非3000ms的默认值,而是httpClient的默认设置).
* </p>
*/
private int connectionRequestTimeout = -1;
private int connectionRequestTimeout = 3000;
/**
* 建立链接的超时时间,默认为5000ms.由于是在链接池获取链接,此设置应该并不起什么作用

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-java-cp</artifactId>

View File

@@ -36,4 +36,12 @@ public interface WxCpAgentWorkBenchService {
* @throws WxErrorException the wx error exception
*/
void setWorkBenchData(WxCpAgentWorkBench wxCpAgentWorkBench) throws WxErrorException;
/**
* Batch sets work bench data.
*
* @param wxCpAgentWorkBench the wx cp agent work bench
* @throws WxErrorException the wx error exception
*/
void batchSetWorkBenchData(WxCpAgentWorkBench wxCpAgentWorkBench) throws WxErrorException;
}

View File

@@ -38,6 +38,7 @@ public interface WxCpExternalContactService {
* 用户需要妥善存储返回的config_idconfig_id丢失可能导致用户无法编辑或删除「联系我」。
* 临时会话模式不占用「联系我」数量但每日最多添加10万个并且仅支持单人。
* 临时会话模式的二维码,添加好友完成后该二维码即刻失效。
* <a href="https://developer.work.weixin.qq.com/document/path/92228">文档地址</a>
* </pre>
*
* @param info 客户联系「联系我」方式
@@ -59,6 +60,25 @@ public interface WxCpExternalContactService {
*/
WxCpContactWayInfo getContactWay(String configId) throws WxErrorException;
/**
* 获取企业已配置的「联系我」列表
*
* <pre>
* 获取企业配置的「联系我」二维码和「联系我」小程序插件列表。不包含临时会话。
* 注意,<b>该接口仅可获取2021年7月10日以后创建的「联系我」</b>
* </pre>
*
* 文档地址: <a href="https://developer.work.weixin.qq.com/document/path/92228#%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%B7%B2%E9%85%8D%E7%BD%AE%E7%9A%84%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E5%88%97%E8%A1%A8">获取企业已配置的「联系我」列表</a>
*
* @param startTime 「联系我」创建起始时间戳, 默认为90天前
* @param endTime 「联系我」创建结束时间戳, 默认为当前时间
* @param cursor 分页查询使用的游标,为上次请求返回的 next_cursor
* @param limit 每次查询的分页大小默认为100条最多支持1000条
* @return contact way configId
* @throws WxErrorException the wx error exception
*/
WxCpContactWayList listContactWay(Long startTime, Long endTime, String cursor, Long limit) throws WxErrorException;
/**
* 更新企业已配置的「联系我」方式
*

View File

@@ -75,6 +75,19 @@ public interface WxCpKfService {
*/
WxCpKfServicerOpResp addServicer(String openKfid, List<String> userIdList) throws WxErrorException;
/**
* 接待人员管理
* 添加指定客服账号的接待人员每个客服账号目前最多可添加2000个接待人员20个部门。
* userid_list和department_id_list至少需要填其中一个
*
* @param openKfid 客服帐号ID
* @param userIdList 接待人员userid列表。第三方应用填密文userid即open_userid 可填充个数1 ~ 100。超过100个需分批调用。
* @param departmentIdList 接待人员部门id列表 可填充个数0 ~ 20。
* @return 添加客服账号结果 wx cp kf servicer op resp
* @throws WxErrorException 异常
*/
WxCpKfServicerOpResp addServicer(String openKfid, List<String> userIdList,List<String> departmentIdList) throws WxErrorException;
/**
* 接待人员管理
* 从客服帐号删除接待人员
@@ -86,6 +99,19 @@ public interface WxCpKfService {
*/
WxCpKfServicerOpResp delServicer(String openKfid, List<String> userIdList) throws WxErrorException;
/**
* 接待人员管理
* 从客服帐号删除接待人员
* userid_list和department_id_list至少需要填其中一个
*
* @param openKfid 客服帐号ID
* @param userIdList 接待人员userid列表。第三方应用填密文userid即open_userid 可填充个数1 ~ 100。超过100个需分批调用。
* @param departmentIdList 接待人员部门id列表 可填充个数0 ~ 100。超过100个需分批调用。
* @return 删除客服账号结果 wx cp kf servicer op resp
* @throws WxErrorException 异常
*/
WxCpKfServicerOpResp delServicer(String openKfid, List<String> userIdList, List<String> departmentIdList) throws WxErrorException;
/**
* 接待人员管理
* 获取某个客服帐号的接待人员列表

View File

@@ -2,6 +2,8 @@ package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.media.MediaUploadByUrlReq;
import me.chanjar.weixin.cp.bean.media.MediaUploadByUrlResult;
import java.io.File;
import java.io.IOException;
@@ -133,4 +135,21 @@ public interface WxCpMediaService {
* @throws WxErrorException the wx error exception
*/
String uploadImg(File file) throws WxErrorException;
/**
* 生成异步上传任务
* 跟上传临时素材拿到的media_id使用场景是不通用的目前适配的接口如下https://developer.work.weixin.qq.com/document/path/96488#%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E8%AF%B4%E6%98%8E
* @param req 请求参数
* @return 返回异步任务id
* @throws WxErrorException the wx error exception
*/
String uploadByUrl(MediaUploadByUrlReq req) throws WxErrorException;
/**
* 查询异步任务结果
* @param jobId 任务id。最长为128字节60分钟内有效
* @return 返回异步任务结果
* @throws WxErrorException the wx error exception
*/
MediaUploadByUrlResult uploadByUrl(String jobId) throws WxErrorException;
}

View File

@@ -22,7 +22,7 @@ public interface WxCpOaService {
*
* 请求方式POSTHTTPS
* 请求地址: https://qyapi.weixin.qq.com/cgi-bin/oa/applyevent?access_token=ACCESS_TOKEN
* 文档地址:https://work.weixin.qq.com/api/doc/90000/90135/91853
* <a href="https://work.weixin.qq.com/api/doc/90000/90135/91853">文档地址</a>
* </pre>
*
* @param request 请求
@@ -34,7 +34,7 @@ public interface WxCpOaService {
/**
* <pre>
* 获取打卡数据
* API doc : https://work.weixin.qq.com/api/doc#90000/90135/90262
* <a href="https://work.weixin.qq.com/api/doc#90000/90135/90262">文档地址</a>
* </pre>
*
* @param openCheckinDataType 打卡类型。1上下班打卡2外出打卡3全部打卡
@@ -50,7 +50,7 @@ public interface WxCpOaService {
/**
* <pre>
* 获取打卡规则
* API doc : https://work.weixin.qq.com/api/doc#90000/90135/90263
* <a href="https://work.weixin.qq.com/api/doc#90000/90135/90263">文档地址</a>
* </pre>
*
* @param datetime 需要获取规则的当天日期
@@ -64,7 +64,7 @@ public interface WxCpOaService {
/**
* <pre>
* 获取企业所有打卡规则
* API doc : https://work.weixin.qq.com/api/doc/90000/90135/93384
* <a href="https://work.weixin.qq.com/api/doc/90000/90135/93384">文档地址</a>
* </pre>
*
* @return 打卡规则列表 crop checkin option
@@ -82,7 +82,7 @@ public interface WxCpOaService {
*
* 一次拉取调用最多拉取100个审批记录可以通过多次拉取的方式来满足需求但调用频率不可超过600次/分。
*
* API doc : https://work.weixin.qq.com/api/doc/90000/90135/91816
* <a href="https://work.weixin.qq.com/api/doc/90000/90135/91816">文档地址</a>
* </pre>
*
* @param startTime 开始时间
@@ -121,7 +121,7 @@ public interface WxCpOaService {
*
* 一次拉取调用最多拉取100个审批记录可以通过多次拉取的方式来满足需求但调用频率不可超过600次/分。
*
* API doc : https://work.weixin.qq.com/api/doc/90000/90135/91816
* <a href="https://work.weixin.qq.com/api/doc/90000/90135/91816">文档地址</a>
*
* 1 接口频率限制 600次/分钟
* 2 请求的参数endtime需要大于startime 起始时间跨度不能超过31天
@@ -146,7 +146,7 @@ public interface WxCpOaService {
*
* 企业可通过审批应用或自建应用Secret调用本接口根据审批单号查询企业微信“审批应用”的审批申请详情。
*
* API Doc : https://work.weixin.qq.com/api/doc/90000/90135/91983
* <a href="https://work.weixin.qq.com/api/doc/90000/90135/91983">文档地址</a>
* </pre>
*
* @param spNo 审批单编号。

View File

@@ -334,7 +334,7 @@ public interface WxCpSchoolUserService {
* 请求方式GETHTTPS
* 请求地址https://qyapi.weixin.qq.com/cgi-bin/school/department/list?access_token=ACCESS_TOKEN&id=ID
*
* @param id the id
* @param id 部门id。获取指定部门及其下的子部门。 如果不填,默认获取全量组织架构
* @return wx cp department list
* @throws WxErrorException the wx error exception
*/

View File

@@ -38,4 +38,10 @@ public class WxCpAgentWorkBenchServiceImpl implements WxCpAgentWorkBenchService
final String url = String.format(this.mainService.getWxCpConfigStorage().getApiUrl(WORKBENCH_DATA_SET));
this.mainService.post(url, wxCpAgentWorkBench.toUserDataString());
}
@Override
public void batchSetWorkBenchData(WxCpAgentWorkBench wxCpAgentWorkBench) throws WxErrorException {
final String url = String.format(this.mainService.getWxCpConfigStorage().getApiUrl(WORKBENCH_BATCH_DATA_SET));
this.mainService.post(url, wxCpAgentWorkBench.toBatchUserDataString());
}
}

View File

@@ -65,6 +65,17 @@ public class WxCpExternalContactServiceImpl implements WxCpExternalContactServic
return WxCpContactWayInfo.fromJson(this.mainService.post(url, json.toString()));
}
@Override
public WxCpContactWayList listContactWay(Long startTime, Long endTime, String cursor, Long limit) throws WxErrorException {
JsonObject json = new JsonObject();
json.addProperty("start_time", startTime);
json.addProperty("end_time", endTime);
json.addProperty("cursor", cursor);
json.addProperty("limit", limit);
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(LIST_CONTACT_WAY);
return WxCpContactWayList.fromJson(this.mainService.post(url, json.toString()));
}
@Override
public WxCpBaseResp updateContactWay(WxCpContactWayInfo info) throws WxErrorException {
if (StringUtils.isBlank(info.getContactWay().getConfigId())) {

View File

@@ -70,23 +70,62 @@ public class WxCpKfServiceImpl implements WxCpKfService {
@Override
public WxCpKfServicerOpResp addServicer(String openKfid, List<String> userIdList) throws WxErrorException {
return servicerOp(openKfid, userIdList, SERVICER_ADD);
return servicerOp(openKfid, userIdList, null, SERVICER_ADD);
}
@Override
public WxCpKfServicerOpResp addServicer(String openKfId, List<String> userIdList, List<String> departmentIdList) throws WxErrorException {
validateParameters(SERVICER_ADD, userIdList, departmentIdList);
return servicerOp(openKfId, userIdList, departmentIdList, SERVICER_ADD);
}
@Override
public WxCpKfServicerOpResp delServicer(String openKfid, List<String> userIdList) throws WxErrorException {
return servicerOp(openKfid, userIdList, SERVICER_DEL);
return servicerOp(openKfid, userIdList, null, SERVICER_DEL);
}
private WxCpKfServicerOpResp servicerOp(String openKfid, List<String> userIdList, String uri) throws WxErrorException {
@Override
public WxCpKfServicerOpResp delServicer(String openKfid, List<String> userIdList, List<String> departmentIdList) throws WxErrorException {
validateParameters(SERVICER_DEL, userIdList, departmentIdList);
return servicerOp(openKfid, userIdList, departmentIdList, SERVICER_DEL);
}
private void validateParameters(String uri, List<String> userIdList, List<String> departmentIdList) {
if ((userIdList == null || userIdList.isEmpty()) && (departmentIdList == null || departmentIdList.isEmpty())) {
throw new IllegalArgumentException("userid_list和department_id_list至少需要填其中一个");
}
if (SERVICER_DEL.equals(uri)) {
if (userIdList != null && userIdList.size() > 100) {
throw new IllegalArgumentException("可填充个数0 ~ 100。超过100个需分批调用。");
}
if (departmentIdList != null && departmentIdList.size() > 100) {
throw new IllegalArgumentException("可填充个数0 ~ 100。超过100个需分批调用。");
}
} else {
if (userIdList != null && userIdList.size() > 100) {
throw new IllegalArgumentException("可填充个数0 ~ 100。超过100个需分批调用。");
}
if (departmentIdList != null && departmentIdList.size() > 20) {
throw new IllegalArgumentException("可填充个数0 ~ 20。");
}
}
}
private WxCpKfServicerOpResp servicerOp(String openKfid, List<String> userIdList, List<String> departmentIdList, String uri) throws WxErrorException {
String url = cpService.getWxCpConfigStorage().getApiUrl(uri);
JsonObject json = new JsonObject();
json.addProperty("open_kfid", openKfid);
JsonArray userIdArray = new JsonArray();
userIdList.forEach(userIdArray::add);
json.add("userid_list", userIdArray);
if (userIdList != null && !userIdList.isEmpty()) {
JsonArray userIdArray = new JsonArray();
userIdList.forEach(userIdArray::add);
json.add("userid_list", userIdArray);
}
if (departmentIdList != null && !departmentIdList.isEmpty()) {
JsonArray departmentIdArray = new JsonArray();
departmentIdList.forEach(departmentIdArray::add);
json.add("department_id_list", departmentIdArray);
}
String responseContent = cpService.post(url, json.toString());
return WxCpKfServicerOpResp.fromJson(responseContent);
}

View File

@@ -1,5 +1,6 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
@@ -9,8 +10,12 @@ import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.InputStreamData;
import me.chanjar.weixin.common.util.http.MediaInputStreamUploadRequestExecutor;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonParser;
import me.chanjar.weixin.cp.api.WxCpMediaService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.media.MediaUploadByUrlReq;
import me.chanjar.weixin.cp.bean.media.MediaUploadByUrlResult;
import java.io.File;
import java.io.IOException;
@@ -20,7 +25,12 @@ import java.net.URL;
import java.nio.file.Files;
import java.util.UUID;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.*;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.GET_UPLOAD_BY_URL_RESULT;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.IMG_UPLOAD;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.JSSDK_MEDIA_GET;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.MEDIA_GET;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.MEDIA_UPLOAD;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Media.UPLOAD_BY_URL;
/**
* <pre>
@@ -119,4 +129,20 @@ public class WxCpMediaServiceImpl implements WxCpMediaService {
return this.mainService.execute(MediaUploadRequestExecutor.create(this.mainService.getRequestHttp()), url, file)
.getUrl();
}
@Override
public String uploadByUrl(MediaUploadByUrlReq req) throws WxErrorException {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(UPLOAD_BY_URL);
String responseContent = this.mainService.post(url, req.toJson());
return GsonHelper.getString(GsonParser.parse(responseContent), "jobid");
}
@Override
public MediaUploadByUrlResult uploadByUrl(String jobId) throws WxErrorException {
final String url = this.mainService.getWxCpConfigStorage().getApiUrl(GET_UPLOAD_BY_URL_RESULT);
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("jobid", jobId);
String post = this.mainService.post(url, jsonObject.toString());
return MediaUploadByUrlResult.fromJson(post);
}
}

View File

@@ -13,6 +13,8 @@ import me.chanjar.weixin.cp.bean.WxCpUserDetail;
import me.chanjar.weixin.cp.bean.workbench.WxCpSecondVerificationInfo;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.util.Optional;
import static me.chanjar.weixin.common.api.WxConsts.OAuth2Scope.*;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.OAuth2.*;
@@ -74,9 +76,9 @@ public class WxCpOAuth2ServiceImpl implements WxCpOAuth2Service {
JsonObject jo = GsonParser.parse(responseText);
return WxCpOauth2UserInfo.builder()
.userId(GsonHelper.getString(jo, "UserId"))
.userId(Optional.ofNullable(GsonHelper.getString(jo, "UserId")).orElse(GsonHelper.getString(jo, "userid")))
.deviceId(GsonHelper.getString(jo, "DeviceId"))
.openId(GsonHelper.getString(jo, "OpenId"))
.openId(Optional.ofNullable(GsonHelper.getString(jo, "OpenId")).orElse(GsonHelper.getString(jo, "openid")))
.userTicket(GsonHelper.getString(jo, "user_ticket"))
.expiresIn(GsonHelper.getString(jo, "expires_in"))
.externalUserId(GsonHelper.getString(jo, "external_userid"))

View File

@@ -16,6 +16,7 @@ import me.chanjar.weixin.cp.bean.school.user.*;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Objects;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.ExternalContact.*;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.*;
@@ -246,7 +247,7 @@ public class WxCpSchoolUserServiceImpl implements WxCpSchoolUserService {
@Override
public WxCpDepartmentList listDepartment(Integer id) throws WxErrorException {
String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST) + id;
String apiUrl = Objects.isNull(id) ? this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST) : String.format("%s?id=%s", this.cpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST), id);
String responseContent = this.cpService.get(apiUrl, null);
return WxCpDepartmentList.fromJson(responseContent);
}

View File

@@ -6,6 +6,7 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.cp.bean.workbench.WorkBenchKeyData;
import me.chanjar.weixin.cp.bean.workbench.WorkBenchList;
import me.chanjar.weixin.cp.constant.WxCpConsts;
@@ -33,6 +34,10 @@ public class WxCpAgentWorkBench implements Serializable {
* 用户的userid
*/
private String userId;
/**
* 用户的userIds
*/
private List<String> useridList;
/**
* 应用id
*/
@@ -58,6 +63,15 @@ public class WxCpAgentWorkBench implements Serializable {
* 参考示例:<a href="wxwork://openurl?url=https%3A%2F%2Fwork.weixin.qq.com%2F">今日要闻</a>
*/
private Boolean enableWebviewClick;
/**
* 高度。可以有两种选择single_row与double_row。当为single_row时高度为106px如果隐藏标题则为147px
* 当为double_row时高度固定为171px如果隐藏标题则为212px。默认值为double_row
*/
private String height;
/**
* 是否要隐藏展示了应用名称的标题部分默认值为false。
*/
private Boolean hideTitle;
private List<WorkBenchKeyData> keyDataList;
@@ -93,6 +107,20 @@ public class WxCpAgentWorkBench implements Serializable {
return userDataObject.toString();
}
/**
* 生成批量用户数据Json字符串
*
* @return the string
*/
public String toBatchUserDataString() {
JsonObject userDataObject = new JsonObject();
userDataObject.addProperty("agentid", this.agentId);
JsonArray useridList = WxGsonBuilder.create().toJsonTree(this.useridList).getAsJsonArray();
userDataObject.add("userid_list", useridList);
this.handleBatch(userDataObject);
return userDataObject.toString();
}
/**
* 处理不用类型的工作台数据
*/
@@ -140,9 +168,9 @@ public class WxCpAgentWorkBench implements Serializable {
webview.addProperty("url", this.url);
webview.addProperty("jump_url", this.jumpUrl);
webview.addProperty("pagepath", this.pagePath);
if (null != this.enableWebviewClick) {
webview.addProperty("enable_webview_click", this.enableWebviewClick);
}
webview.addProperty("enable_webview_click", this.enableWebviewClick);
webview.addProperty("height", this.height);
webview.addProperty("hide_title", this.hideTitle);
templateObject.add("webview", webview);
break;
}
@@ -152,4 +180,75 @@ public class WxCpAgentWorkBench implements Serializable {
}
}
/**
* 处理不用类型的工作台数据
*/
private void handleBatch(JsonObject templateObject) {
switch (this.getType()) {
case WxCpConsts.WorkBenchType.KEYDATA: {
JsonArray keyDataArray = new JsonArray();
JsonObject itemsObject = new JsonObject();
for (WorkBenchKeyData keyDataItem : this.keyDataList) {
JsonObject keyDataObject = new JsonObject();
keyDataObject.addProperty("key", keyDataItem.getKey());
keyDataObject.addProperty("data", keyDataItem.getData());
keyDataObject.addProperty("jump_url", keyDataItem.getJumpUrl());
keyDataObject.addProperty("pagepath", keyDataItem.getPagePath());
keyDataArray.add(keyDataObject);
}
itemsObject.add("items", keyDataArray);
JsonObject dataObject = new JsonObject();
dataObject.addProperty("type", WxCpConsts.WorkBenchType.KEYDATA);
dataObject.add("keydata", itemsObject);
templateObject.add("data", dataObject);
break;
}
case WxCpConsts.WorkBenchType.IMAGE: {
JsonObject image = new JsonObject();
image.addProperty("url", this.url);
image.addProperty("jump_url", this.jumpUrl);
image.addProperty("pagepath", this.pagePath);
JsonObject dataObject = new JsonObject();
dataObject.addProperty("type", WxCpConsts.WorkBenchType.IMAGE);
dataObject.add("image", image);
templateObject.add("data", dataObject);
break;
}
case WxCpConsts.WorkBenchType.LIST: {
JsonArray listArray = new JsonArray();
JsonObject itemsObject = new JsonObject();
for (WorkBenchList listItem : this.lists) {
JsonObject listObject = new JsonObject();
listObject.addProperty("title", listItem.getTitle());
listObject.addProperty("jump_url", listItem.getJumpUrl());
listObject.addProperty("pagepath", listItem.getPagePath());
listArray.add(listObject);
}
itemsObject.add("items", listArray);
JsonObject dataObject = new JsonObject();
dataObject.addProperty("type", WxCpConsts.WorkBenchType.LIST);
dataObject.add("list", itemsObject);
templateObject.add("data", dataObject);
break;
}
case WxCpConsts.WorkBenchType.WEBVIEW: {
JsonObject webview = new JsonObject();
webview.addProperty("url", this.url);
webview.addProperty("jump_url", this.jumpUrl);
webview.addProperty("pagepath", this.pagePath);
webview.addProperty("enable_webview_click", this.enableWebviewClick);
webview.addProperty("height", this.height);
webview.addProperty("hide_title", this.hideTitle);
JsonObject dataObject = new JsonObject();
dataObject.addProperty("type", WxCpConsts.WorkBenchType.WEBVIEW);
dataObject.add("webview", webview);
templateObject.add("data", dataObject);
break;
}
default: {
//do nothing
}
}
}
}

View File

@@ -152,6 +152,13 @@ public class WxCpContactWayInfo implements Serializable {
@SerializedName("unionid")
private String unionId;
/**
*非必填,是否开启同一外部企业客户只能添加同一个员工,默认为否,开启后,同一个企业的客户会优先添加到同一个跟进人
*/
@SerializedName("is_exclusive")
private boolean isExclusive;
/**
* <pre>
* 非必填

View File

@@ -0,0 +1,63 @@
package me.chanjar.weixin.cp.bean.external;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
import java.util.List;
/**
* 「联系我」方式 列表返回对象
*
* @author <a href="https://github.com/imyzt">imyzt</a>
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
public class WxCpContactWayList extends WxCpBaseResp implements Serializable {
private static final long serialVersionUID = -8697184659526210472L;
@SerializedName("contact_way")
private List<ContactWay> contactWay;
/**
* The type Contact way.
*/
@Getter
@Setter
public static class ContactWay implements Serializable {
private static final long serialVersionUID = -8697184659526210472L;
/**
* 联系方式的配置id
*/
@SerializedName("config_id")
private String configId;
}
/**
* From json wx cp contact way list.
*
* @param json the json
* @return the wx cp contact way list
*/
public static WxCpContactWayList fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, WxCpContactWayList.class);
}
/**
* To json string.
*
* @return the string
*/
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@@ -0,0 +1,58 @@
package me.chanjar.weixin.cp.bean.media;
import lombok.Data;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
/**
* 生成异步上传任务
* @author <a href="https://github.com/imyzt">imyzt</a>
* @date 2025/04/27
*/
@Data
public class MediaUploadByUrlReq {
/**
* 场景值。1-客户联系入群欢迎语素材目前仅支持1。 注意:每个场景值有对应的使用范围,详见上面的「使用场景说明」
*/
private Integer scene;
/**
* 媒体文件类型。目前仅支持video-视频file-普通文件 不超过32字节。
*/
private String type;
/**
* 文件名标识文件展示的名称。比如使用该media_id发消息时展示的文件名由该字段控制。 不超过128字节。
*/
private String filename;
/**
* 文件cdn url。url要求支持Range分块下载 不超过1024字节。 如果为腾讯云cos链接则需要设置为「公有读」权限。
*/
private String url;
/**
* 文件md5。对比从url下载下来的文件md5是否一致。 不超过32字节。
*/
private String md5;
/**
* From json wx cp base resp.
*
* @param json the json
* @return the wx cp base resp
*/
public static MediaUploadByUrlReq fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, MediaUploadByUrlReq.class);
}
/**
* To json string.
*
* @return the string
*/
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@@ -0,0 +1,82 @@
package me.chanjar.weixin.cp.bean.media;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.io.Serializable;
/**
* 异步上传企微素材
* @author <a href="https://github.com/imyzt">imyzt</a>
* @date 2025/4/27
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MediaUploadByUrlResult extends WxCpBaseResp implements Serializable {
private static final long serialVersionUID = 330834334738622341L;
/**
* 任务状态。1-处理中2-完成3-异常失败
*/
@SerializedName("status")
private Integer status;
@SerializedName("detail")
private Detail detail;
@Data
public static class Detail {
/**
* 任务失败返回码。当status为3时返回非0其他返回0
* 830001 url非法 确认url是否支持Range分块下载
* 830003 url下载数据失败 确认url本身是否能正常访问
* 45001 文件大小超过限制 确认文件在5字节~200M范围内
* 301019 文件MD5不匹配 确认url对应的文件内容md5跟所填的md5参数是否一致
* 注意: status=2时,此处微信并未返回任何值
*/
@SerializedName("errcode")
private Integer errCode;
/**
* 注意: status=2时,此处微信并未返回任何值
*/
@SerializedName("errmsg")
private String errMsg;
/**
* 媒体文件上传后获取的唯一标识3天内有效。当status为2时返回。
*/
@SerializedName("media_id")
private String mediaId;
/**
* 媒体文件创建的时间戳。当status为2时返回。
*/
@SerializedName("created_at")
private String createdAt;
}
/**
* From json wx cp media upload by url result.
*
* @param json the json
* @return the wx cp media upload by url result
*/
public static MediaUploadByUrlResult fromJson(String json) {
return WxCpGsonBuilder.create().fromJson(json, MediaUploadByUrlResult.class);
}
/**
* To json string.
*
* @return the string
*/
public String toJson() {
return WxCpGsonBuilder.create().toJson(this);
}
}

View File

@@ -403,7 +403,7 @@ public class WxCpTpXmlMessage implements Serializable {
* The Agent id.
*/
@XStreamAlias("AgentID")
protected String agentID;
protected Integer agentID;
/**
* The Pic url.

View File

@@ -118,7 +118,7 @@ public class WxCpXmlApprovalInfo implements Serializable {
/**
* 抄送人userid
*/
@XStreamAlias("ItemUserid")
@XStreamAlias("ItemUserId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String itemUserId;
@@ -190,7 +190,7 @@ public class WxCpXmlApprovalInfo implements Serializable {
/**
* 分支审批人userid
*/
@XStreamAlias("ItemUserid")
@XStreamAlias("ItemUserId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String itemUserId;

View File

@@ -155,6 +155,10 @@ public class WxCpXmlMessage implements Serializable {
@XStreamConverter(value = XStreamCDataConverter.class)
private String memChangeCnt;
@XStreamAlias("MemChangeList")
@XStreamConverter(value = XStreamCDataConverter.class)
private String MemChangeList;
@XStreamAlias("Source")
@XStreamConverter(value = XStreamCDataConverter.class)
private String source;
@@ -198,6 +202,13 @@ public class WxCpXmlMessage implements Serializable {
@XStreamAlias("SelectedItems")
private List<SelectedItem> selectedItems;
/**
* <a href="https://developer.work.weixin.qq.com/document/path/96488#%E5%9B%9E%E8%B0%83%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E7%BB%93%E6%9E%9C">异步任务id</a>
*/
@XStreamAlias("JobId")
@XStreamConverter(value = XStreamCDataConverter.class)
private String jobId;
/**
* 微信客服
* 调用拉取消息接口时需要传此token用于校验请求的合法性

View File

@@ -603,7 +603,7 @@ public class WxCpChatModel implements Serializable {
private String sdkFileId;
@SerializedName("filesize")
private Integer fileSize;
private Long fileSize;
/**
* From json file.

View File

@@ -6,6 +6,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.chanjar.weixin.cp.bean.oa.templatedata.TemplateTips;
import me.chanjar.weixin.cp.bean.oa.templatedata.TemplateTitle;
import me.chanjar.weixin.cp.bean.oa.templatedata.control.*;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
@@ -94,6 +95,9 @@ public class WxCpOaApprovalTemplateResult implements Serializable {
@SerializedName("vacation_list")
private TemplateVacation vacationList;
@SerializedName("tips")
private TemplateTips tips;
}
@Data

View File

@@ -37,4 +37,6 @@ public class TemplateConfig implements Serializable {
@SerializedName("vacation_list")
private TemplateVacation vacationList;
private TemplateTips tips;
}

View File

@@ -0,0 +1,18 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
/**
* @author mrsiu@msn.com
* @version 1.0
* @date 2025/1/16 09:40
*/
@Data
public class TemplateTips {
@SerializedName("tips_content")
private List<TemplateTipsContent> tipsContent;
}

View File

@@ -0,0 +1,15 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import lombok.Data;
/**
* @author mrsiu@msn.com
* @version 1.0
* @date 2025/1/16 09:42
*/
@Data
public class TemplateTipsContent {
private TemplateTipsText text;
private String lang;
}

View File

@@ -0,0 +1,14 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import lombok.Data;
/**
* @author mrsiu@msn.com
* @version 1.0
* @date 2025/1/16 09:45
*/
@Data
public class TemplateTipsSubText {
private Integer type;
private TemplateTipsSubTextContent content;
}

View File

@@ -0,0 +1,16 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
/**
* @author mrsiu@msn.com
* @version 1.0
* @date 2025/1/16 09:46
*/
@Data
public class TemplateTipsSubTextContent {
@SerializedName("plain_text")
private TemplateTipsSubTextContentPlainText plainText;
private TemplateTipsSubTextContentLink link;
}

View File

@@ -0,0 +1,14 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import lombok.Data;
/**
* @author mrsiu@msn.com
* @version 1.0
* @date 2025/1/16 09:49
*/
@Data
public class TemplateTipsSubTextContentLink {
private String title;
private String url;
}

View File

@@ -0,0 +1,13 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import lombok.Data;
/**
* @author mrsiu@msn.com
* @date 2025/1/16 09:47
* @version 1.0
*/
@Data
public class TemplateTipsSubTextContentPlainText {
private String content;
}

View File

@@ -0,0 +1,17 @@
package me.chanjar.weixin.cp.bean.oa.templatedata;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.util.List;
/**
* @author mrsiu@msn.com
* @date 2025/1/16 09:43
* @version 1.0
*/
@Data
public class TemplateTipsText {
@SerializedName("sub_text")
private List<TemplateTipsSubText> subText;
}

View File

@@ -130,6 +130,10 @@ public interface WxCpApiPathConsts {
* The constant WORKBENCH_DATA_SET.
*/
String WORKBENCH_DATA_SET = "/cgi-bin/agent/set_workbench_data";
/**
* The constant WORKBENCH_BATCH_DATA_SET.
*/
String WORKBENCH_BATCH_DATA_SET = "/cgi-bin/agent/batch_set_workbench_data";
}
/**
@@ -234,6 +238,12 @@ public interface WxCpApiPathConsts {
* The constant JSSDK_MEDIA_GET.
*/
String JSSDK_MEDIA_GET = "/cgi-bin/media/get/jssdk";
/** The constant GET_UPLOAD_BY_URL_RESULT. */
String GET_UPLOAD_BY_URL_RESULT = "/cgi-bin/media/get_upload_by_url_result";
/** The constant UPLOAD_BY_URL. */
String UPLOAD_BY_URL = "/cgi-bin/media/upload_by_url";
}
/**
@@ -691,7 +701,7 @@ public interface WxCpApiPathConsts {
/**
* The constant DEPARTMENT_LIST.
*/
String DEPARTMENT_LIST = "/cgi-bin/school/department/list?id=";
String DEPARTMENT_LIST = "/cgi-bin/school/department/list";
/**
* The constant GET_PAYMENT_RESULT.
@@ -1085,6 +1095,10 @@ public interface WxCpApiPathConsts {
* The constant GET_CONTACT_WAY.
*/
String GET_CONTACT_WAY = "/cgi-bin/externalcontact/get_contact_way";
/**
* The constant LIST_CONTACT_WAY.
*/
String LIST_CONTACT_WAY = "/cgi-bin/externalcontact/list_contact_way";
/**
* The constant UPDATE_CONTACT_WAY.
*/

View File

@@ -219,6 +219,11 @@ public class WxCpConsts {
*/
public static final String CUSTOMER_ACQUISITION = "customer_acquisition";
/**
* <a href="https://developer.work.weixin.qq.com/document/path/96488#%E5%9B%9E%E8%B0%83%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1%E7%BB%93%E6%9E%9C">异步上传临时素材结果回调通知</a>
*/
public static final String UPLOAD_MEDIA_JOB_FINISH = "upload_media_job_finish";
}
/**

View File

@@ -4,6 +4,9 @@ import static org.testng.Assert.assertNotNull;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@@ -90,6 +93,20 @@ public class WxCpExternalContactServiceImplTest {
assertNotNull(contactWayInfo);
}
/**
* Test list contact way.
*
* @throws WxErrorException the wx error exception
*/
@Test
public void testListContactWay() throws WxErrorException {
long startTime = LocalDateTime.now().minusDays(1).toEpochSecond(ZoneOffset.of("+8"));
long endTime = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
WxCpContactWayList wxCpContactWayList = this.wxCpService.getExternalContactService().listContactWay(startTime, endTime, null, 100L);
System.out.println(wxCpContactWayList.toJson());
assertNotNull(wxCpContactWayList);
}
/**
* Test update contact way.
*

View File

@@ -7,6 +7,8 @@ import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.ApiTestModule;
import me.chanjar.weixin.cp.api.TestConstants;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.media.MediaUploadByUrlReq;
import me.chanjar.weixin.cp.bean.media.MediaUploadByUrlResult;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
@@ -127,4 +129,38 @@ public class WxCpMediaServiceImplTest {
assertThat(file).isNotNull();
System.out.println(file);
}
/**
* Test upload media by url.
*
* @throws WxErrorException the wx error exception
*/
@Test
public void testUploadMediaByUrl() throws WxErrorException {
MediaUploadByUrlReq req = new MediaUploadByUrlReq();
req.setScene(1);
req.setType("video");
req.setFilename("mov_bbb");
req.setUrl("https://www.w3school.com.cn/example/html5/mov_bbb.mp4");
req.setMd5("198918f40ecc7cab0fc4231adaf67c96");
String jobId = this.wxService.getMediaService().uploadByUrl(req);
System.out.println(jobId);
}
/**
* Test upload media by url.
*
* @throws WxErrorException the wx error exception
*/
@Test
public void testUploadMediaByUrlResult() throws WxErrorException, InterruptedException {
String jobId = "job1745801375_5GIKWuFF3M7hcIkeSNMqs_W26xy5VeSWjLaLFTEdSfQ";
MediaUploadByUrlResult result = this.wxService.getMediaService().uploadByUrl(jobId);
System.out.println(result);
}
@Test
public void testUploadMediaJobFinishEvent() throws WxErrorException {
File file = this.wxService.getMediaService().getJssdkFile("....");
}
}

View File

@@ -162,8 +162,6 @@ public class WxCpOaServiceImplTest {
*/
@Test
public void testGetCropCheckinOption() throws WxErrorException {
Date now = new Date();
List<WxCpCropCheckinOption> results = wxService.getOaService().getCropCheckinOption();
assertThat(results).isNotNull();
System.out.println("results ");

View File

@@ -0,0 +1,139 @@
package me.chanjar.weixin.cp.api.impl;
import com.google.gson.Gson;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.school.user.WxCpDepartmentList;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.mockito.Mockito;
import org.testng.annotations.Test;
import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.School.DEPARTMENT_LIST;
import static org.testng.Assert.assertEquals;
public class WxCpSchoolUserServiceImplTest {
String allDeptListJson = "{\n" +
"\t\"errcode\": 0,\n" +
"\t\"errmsg\": \"ok\",\n" +
"\t\"departments\": [\n" +
"\t\t{\n" +
"\t\t\t\"name\": \"一年级\",\n" +
"\t\t\t\"parentid\": 1,\n" +
"\t\t\t\"id\": 2,\n" +
"\t\t\t\"type\":2,\n" +
"\t\t\t\"register_year\":2018,\n" +
"\t\t\t\"standard_grade\":1,\n" +
"\t\t\t\"order\":1,\n" +
"\t\t\t\"department_admins\": [\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\t\"userid\": \"zhangsan\",\n" +
"\t\t\t\t\t\"type\": 1\n" +
"\t\t\t\t},\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\t\"userid\": \"lisi\",\n" +
"\t\t\t\t\t\"type\": 2\n" +
"\t\t\t\t}\n" +
"\t\t\t],\n" +
" \"is_graduated\": 0\n" +
"\t\t},\n" +
"\t\t{\n" +
"\t\t\t\"name\": \"一年级一班\",\n" +
"\t\t\t\"parentid\": 1,\n" +
"\t\t\t\"id\": 3,\n" +
"\t\t\t\"type\": 1,\n" +
"\t\t\t\"department_admins\": [\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\t\"userid\": \"zhangsan\",\n" +
"\t\t\t\t\t\"type\": 3,\n" +
"\t\t\t\t\t\"subject\":\"语文\"\n" +
"\t\t\t\t},\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\t\"userid\": \"lisi\",\n" +
"\t\t\t\t\t\"type\": 4,\n" +
"\t\t\t\t\t\"subject\":\"数学\"\n" +
"\t\t\t\t}\n" +
"\t\t\t],\n" +
"\t\t\t\"open_group_chat\": 1,\n" +
" \"group_chat_id\": \"group_chat_id\"\n" +
"\t\t}\n" +
"\t]\n" +
"}\n";
String deptId3Json = "{\n" +
" \"errcode\": 0,\n" +
" \"errmsg\": \"ok\",\n" +
" \"departments\": [\n" +
" {\n" +
" \"name\": \"一年级一班\",\n" +
" \"parentid\": 1,\n" +
" \"id\": 3,\n" +
" \"type\": 1,\n" +
" \"department_admins\": [\n" +
" {\n" +
" \"userid\": \"zhangsan\",\n" +
" \"type\": 3,\n" +
" \"subject\":\"语文\"\n" +
" },\n" +
" {\n" +
" \"userid\": \"lisi\",\n" +
" \"type\": 4,\n" +
" \"subject\":\"数学\"\n" +
" }\n" +
" ],\n" +
" \"open_group_chat\": 1,\n" +
" \"group_chat_id\": \"group_chat_id\"\n" +
" }\n" +
" ]\n" +
"}";
String deptId2Json = "{\n" +
" \"errcode\": 0,\n" +
" \"errmsg\": \"ok\",\n" +
" \"departments\": []\n" +
"}\n";
@Test
public void testListDepartmentWhenIdIsNull() throws WxErrorException {
WxCpService mockCpService = Mockito.mock(WxCpService.class);
WxCpSchoolUserServiceImpl wxCpSchoolUserService = new WxCpSchoolUserServiceImpl(mockCpService);
Mockito.when(mockCpService.getWxCpConfigStorage()).thenReturn(new WxCpDefaultConfigImpl());
Mockito.when(mockCpService.get(mockCpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST), null)).thenReturn(allDeptListJson);
WxCpDepartmentList wxCpDepartmentList = wxCpSchoolUserService.listDepartment(null);
//WxCpDepartmentList没有重写Equals和Hashcode,不能直接比较
Gson gson = new Gson();
assertEquals(gson.toJson(wxCpDepartmentList), gson.toJson(gson.fromJson(allDeptListJson, WxCpDepartmentList.class)), "should be equal");
}
@Test
public void testListDepartmentWhenIdIs2() throws WxErrorException {
WxCpService mockCpService = Mockito.mock(WxCpService.class);
WxCpSchoolUserServiceImpl wxCpSchoolUserService = new WxCpSchoolUserServiceImpl(mockCpService);
Mockito.when(mockCpService.getWxCpConfigStorage()).thenReturn(new WxCpDefaultConfigImpl());
Gson gson = new Gson();
int deptId = 2;
Mockito.when(mockCpService.get(String.format("%s?id=%s", mockCpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST), deptId), null)).thenReturn(deptId2Json);
//WxCpDepartmentList没有重写Equals和Hashcode,不能直接比较
assertEquals(gson.toJson(wxCpSchoolUserService.listDepartment(deptId)), gson.toJson(gson.fromJson(deptId2Json, WxCpDepartmentList.class)), "should be equal");
}
@Test
public void testListDepartmentWhenIdIs3() throws WxErrorException {
WxCpService mockCpService = Mockito.mock(WxCpService.class);
WxCpSchoolUserServiceImpl wxCpSchoolUserService = new WxCpSchoolUserServiceImpl(mockCpService);
Mockito.when(mockCpService.getWxCpConfigStorage()).thenReturn(new WxCpDefaultConfigImpl());
Gson gson = new Gson();
int deptId = 3;
Mockito.when(mockCpService.get(String.format("%s?id=%s", mockCpService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST), deptId), null)).thenReturn(deptId3Json);
//WxCpDepartmentList没有重写Equals和Hashcode,不能直接比较
assertEquals(gson.toJson(wxCpSchoolUserService.listDepartment(deptId)), gson.toJson(gson.fromJson(deptId3Json, WxCpDepartmentList.class)), "should be equal");
}
}

View File

@@ -152,7 +152,7 @@ public class WxCpTpXmlMessageTest {
assertEquals(wxXmlMessage.getCreateTime(), Long.valueOf(1408091189));
assertEquals(wxXmlMessage.getEvent(), "enter_agent");
assertEquals(wxXmlMessage.getEventKey(), "");
assertEquals(wxXmlMessage.getAgentID(), Integer.valueOf(1));
assertEquals(wxXmlMessage.getAgentID(), 1);
}
/**

View File

@@ -6,6 +6,7 @@ import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import org.testng.annotations.Test;
import static me.chanjar.weixin.cp.constant.WxCpConsts.EventType.TASKCARD_CLICK;
import static me.chanjar.weixin.cp.constant.WxCpConsts.EventType.UPLOAD_MEDIA_JOB_FINISH;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@@ -421,4 +422,24 @@ public class WxCpXmlMessageTest {
assertThat(wxCpXmlMessage.getApprovalInfo().getApprovalNodes().get(0).getItems().get(0).getItemName()).isNotEmpty();
assertThat(wxCpXmlMessage.getApprovalInfo().getNotifyNodes().get(0).getItemName()).isNotEmpty();
}
/**
* Test open approval change.
*/
public void testUploadMediaJobFinishEvent() {
String xml = "<xml>\n" +
"\t<ToUserName><![CDATA[wx28dbb14e3720FAKE]]></ToUserName>\n" +
"\t<FromUserName><![CDATA[sys]]></FromUserName>\n" +
"\t<CreateTime>1425284517</CreateTime>\n" +
"\t<MsgType><![CDATA[event]]></MsgType>\n" +
"\t<Event><![CDATA[upload_media_job_finish]]></Event>\n" +
"\t<JobId><![CDATA[jobid_S0MrnndvRG5fadSlLwiBqiDDbM143UqTmKP3152FZk4]]></JobId>\n" +
"</xml>";
WxCpXmlMessage wxCpXmlMessage = WxCpXmlMessage.fromXml(xml);
assertThat(wxCpXmlMessage).isNotNull();
assertThat(wxCpXmlMessage.getJobId()).isNotEmpty();
assertThat(wxCpXmlMessage.getJobId()).isEqualTo("jobid_S0MrnndvRG5fadSlLwiBqiDDbM143UqTmKP3152FZk4");
assertThat(wxCpXmlMessage.getEvent()).isEqualTo(UPLOAD_MEDIA_JOB_FINISH);
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-java-miniapp</artifactId>

View File

@@ -0,0 +1,40 @@
package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.order.WxMaOrderManagementGetOrderDetailPath;
import cn.binarywang.wx.miniapp.bean.order.WxMaOrderManagementResult;
import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* @author xzh
* @Description
* @createTime 2025/01/16 15:20
*/
public interface WxMaOrderManagementService {
/**
* 查询订单详情路径
* 注意事项
* 如果没有配置过订单详情路径会返回成功其中path为''。
*
* @return WxMaOrderManagementGetOrderDetailPath
* @throws WxErrorException e
*/
WxMaOrderManagementGetOrderDetailPath getOrderDetailPath()
throws WxErrorException;
/**
* 配置订单详情路径
* 注意事项
* 调用接口前需要先完成订单中心授权协议签署。
* 请确保配置的path可正常跳转到小程序并且path必须包含字符串“${商品订单号}”。
*
* @param path 订单详情路径
* @return WxMaOrderManagementResult
* @throws WxErrorException e
*/
WxMaOrderManagementResult updateOrderDetailPath(String path)
throws WxErrorException;
}

View File

@@ -550,6 +550,12 @@ public interface WxMaService extends WxService {
* @return getWxMaOrderShippingService
*/
WxMaOrderShippingService getWxMaOrderShippingService();
/**
* 小程序订单管理服务
*
* @return WxMaOrderManagementService
*/
WxMaOrderManagementService getWxMaOrderManagementService();
/**
* 小程序openApi管理

View File

@@ -153,6 +153,9 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH
private final WxMaOrderShippingService wxMaOrderShippingService =
new WxMaOrderShippingServiceImpl(this);
private final WxMaOrderManagementService wxMaOrderManagementService =
new WxMaOrderManagementServiceImpl(this);
private final WxMaOpenApiService wxMaOpenApiService = new WxMaOpenApiServiceImpl(this);
private final WxMaVodService wxMaVodService = new WxMaVodServiceImpl(this);
private final WxMaXPayService wxMaXPayService = new WxMaXPayServiceImpl(this);
@@ -817,6 +820,16 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH
return this.wxMaOrderShippingService;
}
/**
* 小程序订单管理服务
*
* @return WxMaOrderManagementService
*/
@Override
public WxMaOrderManagementService getWxMaOrderManagementService() {
return this.wxMaOrderManagementService;
}
@Override
public WxMaOpenApiService getWxMaOpenApiService() {
return this.wxMaOpenApiService;

View File

@@ -207,7 +207,7 @@ public class WxMaImmediateDeliveryServiceImpl implements WxMaImmediateDeliverySe
@Override
public WxMaBaseResponse updateWaybillGoods(UpdateWaybillGoodsRequest request) throws WxErrorException {
String responseContent = this.wxMaService.post(InstantDelivery.GET_DELIVERY_LIST_URL,request);
String responseContent = this.wxMaService.post(InstantDelivery.UPDATE_WAYBILL_GOODS_URL,request);
WxMaBaseResponse response = WxMaGsonBuilder.create().fromJson(responseContent, WxMaBaseResponse.class);
if (response.getErrcode() == -1) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));

View File

@@ -0,0 +1,72 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaOrderManagementService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.order.WxMaOrderManagementGetOrderDetailPath;
import cn.binarywang.wx.miniapp.bean.order.WxMaOrderManagementResult;
import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.common.util.json.GsonParser;
import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.OrderManagement.*;
/**
* @author xzh
* @Description
* @createTime 2025/01/16 15:31
*/
@Slf4j
@RequiredArgsConstructor
public class WxMaOrderManagementServiceImpl implements WxMaOrderManagementService {
private final WxMaService wxMaService;
/**
* 查询订单详情路径
* 注意事项
* 如果没有配置过订单详情路径会返回成功其中path为''。
*
* @return WxMaOrderManagementGetOrderDetailPath
* @throws WxErrorException e
*/
@Override
public WxMaOrderManagementGetOrderDetailPath getOrderDetailPath() throws WxErrorException {
return request(GET_ORDER_DETAIL_PATH, new Object(), WxMaOrderManagementGetOrderDetailPath.class);
}
/**
* 配置订单详情路径
* 注意事项
* 调用接口前需要先完成订单中心授权协议签署。
* 请确保配置的path可正常跳转到小程序并且path必须包含字符串“${商品订单号}”。
*
* @param path 订单详情路径
* @return WxMaOrderManagementResult
* @throws WxErrorException e
*/
@Override
public WxMaOrderManagementResult updateOrderDetailPath(String path) throws WxErrorException {
JsonObject jsonObject = GsonHelper.buildJsonObject("path", path);
return request(UPDATE_ORDER_DETAIL_PATH, jsonObject, WxMaOrderManagementResult.class);
}
private <T> T request(String url, Object request, Class<T> resultT) throws WxErrorException {
String responseContent = this.wxMaService.post(url, request);
JsonObject jsonObject = GsonParser.parse(responseContent);
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) {
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
}
return WxMaGsonBuilder.create().fromJson(responseContent, resultT);
}
}

View File

@@ -31,7 +31,7 @@ public class WxMaMessage implements Serializable {
private static final long serialVersionUID = -3586245291677274914L;
/**
* 使用dom4j解析的存放所有xml属性和值的map.
* 使用dom4j解析的存放所有xml或json属性和值的map.
*/
private Map<String, Object> allFieldsMap;
@@ -287,6 +287,7 @@ public class WxMaMessage implements Serializable {
}
message.setUselessMsg(null);
}
message.setAllFieldsMap(WxMaGsonBuilder.create().fromJson(json, Map.class));
return message;
}

View File

@@ -0,0 +1,24 @@
package cn.binarywang.wx.miniapp.bean.order;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* @author xzh
* @Description
* @createTime 2025/01/16 15:27
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class WxMaOrderManagementGetOrderDetailPath extends WxMaOrderManagementResult {
private static final long serialVersionUID = -5288666524298706169L;
/**
* 订单详情路径
*/
@SerializedName("path")
private String path;
}

View File

@@ -0,0 +1,27 @@
package cn.binarywang.wx.miniapp.bean.order;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.io.Serializable;
/**
* @author xzh
* @Description
* @createTime 2025/01/16 15:27
*/
@Data
public class WxMaOrderManagementResult implements Serializable {
private static final long serialVersionUID = 1468925151935770503L;
/**
* 错误码
*/
@SerializedName("errcode")
private Integer errCode;
/**
* 错误原因
*/
@SerializedName("errmsg")
private String errMsg;
}

View File

@@ -626,7 +626,7 @@ public class WxMaApiUrlConstants {
String GET_DELIVERY_LIST_URL =
"https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/get_delivery_list";
/** 获取运力id列表get_delivery_list 商户使用此接口获取所有运力id的列表 */
/** 物流服务-查询组件-更新物品信息接口 update_waybill_goods 更新物品信息 */
String UPDATE_WAYBILL_GOODS_URL =
"https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/update_waybill_goods";
@@ -751,7 +751,7 @@ public class WxMaApiUrlConstants {
* </pre>
*/
String UPLOAD_COMBINED_SHIPPING_INFO =
"https://api.weixin.qq.com/wxa/sec/order/upload_combined_shipping_info";
"https://api.weixin.qq.com/wxa/sec/order/upload_combined_shipping_info";
/**
* 查询订单发货状态.
@@ -779,7 +779,7 @@ public class WxMaApiUrlConstants {
* </pre>
*/
String NOTIFY_CONFIRM_RECEIVE =
"https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive";
"https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive";
/**
* 消息跳转路径设置接口.
@@ -809,6 +809,35 @@ public class WxMaApiUrlConstants {
}
/**
* 小程序订单管理
*
* <pre>
* 文档地址: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html
* </pre>
*/
public interface OrderManagement {
/**
* 配置订单详情路径.
*
* <pre>
* 文档地址https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html
* </pre>
*/
String UPDATE_ORDER_DETAIL_PATH = "https://api.weixin.qq.com/wxa/sec/order/update_order_detail_path";
/**
* 查询订单详情路径.
*
* <pre>
* 文档地址https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order_center/order_center.html
* </pre>
*/
String GET_ORDER_DETAIL_PATH = "https://api.weixin.qq.com/wxa/sec/order/get_order_detail_path";
}
public interface Vod {
String LIST_MEDIA_URL = "https://api.weixin.qq.com/wxa/sec/vod/listmedia";
String GET_MEDIA_URL = "https://api.weixin.qq.com/wxa/sec/vod/getmedia";

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-java-mp</artifactId>

View File

@@ -50,12 +50,12 @@ public class WxMpServiceOkHttpImpl extends BaseWxMpServiceImpl<OkHttpClient, OkH
clientBuilder.proxy(getRequestHttpProxy().getProxy());
//设置授权
clientBuilder.authenticator(new Authenticator() {
clientBuilder.proxyAuthenticator(new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic(httpProxy.getProxyUsername(), httpProxy.getProxyPassword());
return response.request().newBuilder()
.header("Authorization", credential)
.header("Proxy-Authorization", credential)
.build();
}
});

View File

@@ -186,6 +186,22 @@ public class WxMpXmlMessage implements Serializable {
@JacksonXmlCData
private String unionId;
@XStreamAlias("ret")
@JacksonXmlProperty(localName = "ret")
private Integer ret;
@XStreamAlias("nickname")
@JacksonXmlProperty(localName = "nickname")
private String nickname;
@XStreamAlias("first")
@JacksonXmlProperty(localName = "first")
private String first;
@XStreamAlias("second")
@JacksonXmlProperty(localName = "second")
private String second;
///////////////////////////////////////
// 群发消息返回的结果
///////////////////////////////////////

View File

@@ -17,7 +17,7 @@ import java.util.Map;
@NoArgsConstructor
@Builder
@AllArgsConstructor
public class WxMpSubscribeMessage {
public class WxMpSubscribeMessage implements Serializable {
/**
* 接收者openid.

View File

@@ -15,7 +15,7 @@ public class WxMpMapConfigImpl extends WxMpDefaultConfigImpl {
private static final long serialVersionUID = 5311395137835650104L;
private static final ConcurrentHashMap<String, String> CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(1);
private final ConcurrentHashMap<String, String> CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(1);
private static final String MAP_KEY = "access_token";

View File

@@ -0,0 +1,58 @@
package me.chanjar.weixin.mp.api.impl;
import com.google.inject.Inject;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.test.ApiTestModule;
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
/**
* 测试 ConcurrentHashMap 保存配置信息
* @author jimmyjimmy-sw
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMpMapConfigImplTest {
@Inject
private WxMpService wxService;
/**
* 测试多租户保存 WxMpMapConfigImpl 到 WxMpService切换之后能获取到租户各自AppId对应的token
* @throws WxErrorException
*/
@Test
public void testAppidSwitch() throws WxErrorException {
// 保存租户A的配置信息并获取token
WxMpMapConfigImpl configAppA = new WxMpMapConfigImpl();
String appidA = "APPID_A";
configAppA.setAppId(appidA);
configAppA.setSecret("APP_SECRET_A");
configAppA.useStableAccessToken(true);
String tokenA = "TOKEN_A";
configAppA.updateAccessToken(tokenA,60 * 60 * 1);
wxService.addConfigStorage(appidA, configAppA);
WxMpConfigStorageHolder.set(appidA);
assertEquals(this.wxService.getAccessToken(),tokenA);
// 保存租户B的配置信息并获取token
WxMpMapConfigImpl configAppB = new WxMpMapConfigImpl();
String appidB = "APPID_B";
configAppB.setAppId(appidB);
configAppB.setSecret("APP_SECRET_B");
configAppB.useStableAccessToken(true);
String tokenB = "TOKEN_B";
configAppB.updateAccessToken(tokenB,60 * 60 * 1);
wxService.addConfigStorage(appidB, configAppB);
WxMpConfigStorageHolder.set(appidB);
assertEquals(this.wxService.getAccessToken(),tokenB);
// 上下文切换到租户A 获取租户A的token
WxMpConfigStorageHolder.set(appidA);
assertEquals(this.wxService.getAccessToken(),tokenA);
}
}

View File

@@ -2,6 +2,9 @@ package me.chanjar.weixin.mp.bean.subscribe;
import org.testng.annotations.*;
import java.io.Serializable;
import java.util.Arrays;
import static org.testng.AssertJUnit.*;
/**
@@ -43,4 +46,9 @@ public class WxMpSubscribeMessageTest {
assertEquals(message.toJson(), actual);
}
@Test
void testWxMpSubscribeMessageIsSerializable() {
assertTrue(Arrays.stream(WxMpSubscribeMessage.class.getInterfaces()).anyMatch(anInterface -> anInterface.isInstance(Serializable.class)));
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<artifactId>weixin-java-open</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java</artifactId>
<version>4.7.1.B</version>
<version>4.7.5.B</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -119,8 +119,8 @@ public class ApplySubjectConfirmCreateRequest implements Serializable {
* IDENTIFICATION_TYPE_TAIWAN_RESIDENT台湾居民证
* 示例值IDENTIFICATION_TYPE_IDCARD
*/
@SerializedName("id_doc_type")
private IdTypeEnum idDocType;
@SerializedName("identification_type")
private IdTypeEnum identificationType;
/**
* 法定代表人说明函
@@ -414,13 +414,13 @@ public class ApplySubjectConfirmCreateRequest implements Serializable {
* 若未传入将默认填写false。
* 示例值true
*/
@SerializedName("finance_institution")
@SerializedName("is_finance_institution")
private Boolean financeInstitution;
/**
* 营业执照
*/
@SerializedName("business_license_info")
@SerializedName("business_licence_info")
private ApplySubConfirmBusinessLicenseInfo businessLicenseInfo;
/**
* 登记证书
@@ -736,8 +736,8 @@ public class ApplySubjectConfirmCreateRequest implements Serializable {
* 参看微信支付提供的特殊行业id对照表
* 示例值100
*/
@SerializedName("finance_type")
private Integer financeType;
@SerializedName("category_id")
private Integer categoryId;
/**
* 行业经营许可证资质照片
@@ -791,29 +791,10 @@ public class ApplySubjectConfirmCreateRequest implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 法人开户承诺函
* 待确认商户号列表
*/
@SerializedName("legal_person_commitment")
private String legalPersonCommitment;
/**
* 法人开户意愿视频
*/
@SerializedName("legal_person_video")
private String legalPersonVideo;
/**
* 补充材料
*/
@SerializedName("business_addition_pics")
private List<String> businessAdditionPics;
/**
* 补充说明
*/
@SerializedName("business_addition_msg")
private String businessAdditionMsg;
@SerializedName("confirm_mchid_list")
private List<String> confirmMchidList;
}
}

View File

@@ -327,4 +327,141 @@ public class ComplaintDetailResult implements Serializable {
*/
@SerializedName("user_tag_list")
private String[] userTagList;
/**
* <pre>
* 字段名:补充信息
* 是否必填:否
* 描述: 用在特定行业或场景下返回的补充信息
* </pre>
*/
@SerializedName("additional_info")
private AdditionalInfo additionalInfo;
@Data
public static class AdditionalInfo implements Serializable {
private static final long serialVersionUID = 7917816070738944147L;
/**
* <pre>
* 字段名:补充信息类型
* 是否必填:否
* 描述: 补充信息类型
* 示例值SHARE_POWER_TYPE: 充电宝投诉相关行业
* </pre>
*/
@SerializedName("type")
private String type;
/**
* <pre>
* 字段名:充电宝投诉相关信息
* 是否必填:否
* 描述当type为充电宝投诉相关时有值
* </pre>
*/
@SerializedName("share_power_info")
private SharePowerInfo sharePowerInfo;
/**
* 充电宝投诉相关信息
*/
@Data
public static class SharePowerInfo implements Serializable {
private static final long serialVersionUID = -2878382307459369354L;
/**
* <pre>
* 字段名:归还时间
* 是否必填:否
* 描述遵循rfc3339标准格式格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
* yyyy-MM-DD表示年月日T出现在字符串中表示time元素的开头
* HH:mm:ss表示时分秒
* TIMEZONE表示时区+08:00表示东八区时间领先UTC 8小时即北京时间
* 示例值2015-05-20T13:29:35+08:00表示北京时间2015年5月20日 13点29分35秒
* </pre>
*/
@SerializedName("return_time")
private String returnTime;
/**
* <pre>
* 字段名:归还地点信息
* 是否必填:否
* 描述: 归还地点信息
* </pre>
*/
@SerializedName("return_address_info")
private ReturnAddressInfo returnAddressInfo;
@Data
public static class ReturnAddressInfo implements Serializable {
private static final long serialVersionUID = -7649986542568217256L;
/**
* <pre>
* 字段名:归还地点
* 是否必填:否 string(256)
* 描述:归还地点
* </pre>
*/
@SerializedName("return_address")
private String returnAddress;
/**
* <pre>
* 字段名:归还地点经度
* 是否必填:否 string(32)
* 描述:经度,字符串,范围为-180~180负数表示西经。使用GCJ-02坐标系
* </pre>
*/
@SerializedName("longitude")
private String longitude;
/**
* <pre>
* 字段名:归还地点纬度
* 是否必填:否 string(32)
* 描述:纬度,字符串,范围为-90~90负数表示南纬。使用GCJ-02坐标系
* </pre>
*/
@SerializedName("latitude")
private String latitude;
}
/**
* <pre>
* 字段名:是否归还同一柜机
* 是否必填:否
* 描述:用户声明是否将充电宝归还至与借取时同一柜机
* </pre>
*/
@SerializedName("is_returned_to_same_machine")
private Boolean isReturnedToSameMachine;
}
}
/**
* <pre>
* 字段名:是否在平台协助中
* 是否必填:否
* 描述:标识当前投诉单是否正处在平台协助流程中。
* 注:在协助期间由微信支付客服为用户服务,期间商户向用户发送的留言用户不可见
* </pre>
*/
@SerializedName("in_platform_service")
private Boolean inPlatformService;
/**
* <pre>
* 字段名:是否需即时服务用户
* 是否必填:否
* 描述:因用户诉求紧急度、用户界面差异等因素,部分投诉单建议商户更即时地响应用户诉求。
* 如此处标识为“是”,建议商户提升服务时效,给用户带来更好的体验
* </pre>
*/
@SerializedName("need_immediate_service")
private Boolean needImmediateService;
}

View File

@@ -142,20 +142,30 @@ public class NegotiationHistoryResult implements Serializable {
* 是否必填:是
* 描述:
* 当前投诉协商记录的操作类型,对应枚举:
* USER_CREATE_COMPLAINT用户提交投诉
* USER_CONTINUE_COMPLAINT用户继续投诉
* USER_RESPONSE用户留言
* PLATFORM_RESPONSE平台留言
* MERCHANT_RESPONSE商户留言
* MERCHANT_CONFIRM_COMPLETE商户申请结单
* COMPLAINT_FULL_REFUNDED投诉单全额退款
* USER_CREATE_COMPLAINT_SYSTEM_MESSAGE:用户提交投诉系统通知
* COMPLAINT_FULL_REFUNDED_SYSTEM_MESSAGE:投诉单全额退款系统通知
* USER_CONTINUE_COMPLAINT_SYSTEM_MESSAGE用户继续投诉系统通知
* MERCHANT_CONFIRM_COMPLETE_SYSTEM_MESSAGE商户申请结单系统通知
* USER_REVOKE_COMPLAINT用户主动撤诉只存在于历史投诉单的协商历史中
* PLATFORM_HELP_APPLICATION平台问询
* USER_APPLY_PLATFORM_HELP申请协助
* USER_CREATE_COMPLAINT: 用户提交投诉
* USER_CONTINUE_COMPLAINT: 用户继续投诉
* USER_RESPONSE: 用户留言
* PLATFORM_RESPONSE: 平台留言
* MERCHANT_RESPONSE: 商户留言
* MERCHANT_CONFIRM_COMPLETE: 商户申请结单
* USER_CREATE_COMPLAINT_SYSTEM_MESSAGE: 用户提交投诉系统通知
* COMPLAINT_FULL_REFUNDED_SYSTEM_MESSAGE: 投诉单发起全额退款系统通知
* USER_CONTINUE_COMPLAINT_SYSTEM_MESSAGE: 用户继续投诉系统通知
* USER_REVOKE_COMPLAINT: 用户主动撤诉(只存在于历史投诉单的协商历史中)
* USER_COMFIRM_COMPLAINT: 用户确认投诉解决(只存在于历史投诉单的协商历史中)
* PLATFORM_HELP_APPLICATION: 平台催办
* USER_APPLY_PLATFORM_HELP: 用户申请平台协助
* MERCHANT_APPROVE_REFUND: 商户同意退款申请
* MERCHANT_REFUSE_RERUND: 商户拒绝退款申请, 此时操作内容里展示拒绝原因
* USER_SUBMIT_SATISFACTION: 用户提交满意度调查结果,此时操作内容里会展示满意度分数
* SERVICE_ORDER_CANCEL: 服务订单已取消
* SERVICE_ORDER_COMPLETE: 服务订单已完成
* COMPLAINT_PARTIAL_REFUNDED_SYSTEM_MESSAGE: 投诉单发起部分退款系统通知
* COMPLAINT_REFUND_RECEIVED_SYSTEM_MESSAGE: 投诉单退款到账系统通知
* COMPLAINT_ENTRUSTED_REFUND_SYSTEM_MESSAGE: 投诉单受托退款系统通知
* USER_APPLY_PLATFORM_SERVICE: 用户申请平台协助
* USER_CANCEL_PLATFORM_SERVICE: 用户取消平台协助
* PLATFORM_SERVICE_FINISHED: 客服结束平台协助
* </pre>
*/
@SerializedName("operate_type")
@@ -179,11 +189,32 @@ public class NegotiationHistoryResult implements Serializable {
* 描述:
* 当前投诉协商记录提交的图片凭证url格式最多返回4张图片url有效时间为1小时。如未查询到协商历史图片凭证则返回空数组。
* 注本字段包含商户、微信支付客服在协商解决投诉时上传的图片凭证若希望查看用户图片请使用complaint_media_list字段并联系微信支付客服
* 注此字段不包含用户提交的图片凭证建议统一使用complaint_media_list字段接收和请求资料凭证未来该字段将废弃
* </pre>
*/
@SerializedName("image_list")
private List<String> imageList;
/**
* <pre>
* 字段名:用户申请平台协助原因
* 是否必填:否
* 描述:用户此次申请平台协助时选择的申请协助原因
* </pre>
*/
@SerializedName("user_appy_platform_service_reason")
private String userApplyPlatformServiceReason;
/**
* <pre>
* 字段名:用户申请平台协助原因描述
* 是否必填:否
* 描述:用户此次申请平台协助时填写的具体申请协助原因描述
* </pre>
*/
@SerializedName("user_appy_platform_service_reason_description")
private String userApplyPlatformServiceReasonDescription;
}
}

View File

@@ -94,4 +94,57 @@ public class ResponseRequest implements Serializable {
@SerializedName("jump_url_text")
private String jumpUrlText;
/**
* <pre>
* 字段名:跳转小程序信息
* 是否必填:否
* 描述:商户可在回复中附加小程序信息,引导用户跳转至商户客诉处理小程序。
* 注:配置小程序属于灰度功能,若有需要请联系对接的行业运营进行咨询。
* </pre>
*/
@SerializedName("mini_program_jump_info")
private MiniProgramJumpInfo miniProgramJumpInfo;
/**
* 跳转小程序信息
*/
@Data
public static class MiniProgramJumpInfo implements Serializable {
private static final long serialVersionUID = 1169503275787468380L;
/**
* <pre>
* 字段名跳转小程序APPID
* 是否必填:是
* 描述:商户可在回复中附加小程序页面路径,引导用户跳转至商户服务工具页面。
* 该字段为小程序APPID。
* </pre>
*/
@SerializedName("appid")
private String appId;
/**
* <pre>
* 字段名跳转小程序页面PATH
* 是否必填:是
* 描述:商户可在回复中附加小程序页面路径,引导用户跳转至商户服务工具页面。
* 该字段为小程序路径。
* </pre>
*/
@SerializedName("path")
private String path;
/**
* <pre>
* 字段名:跳转小程序页面名称
* 是否必填:是
* 描述:商户可在回复中附加小程序页面路径,引导用户跳转至商户服务工具页面。
* 该字段为商户可自定义的页面名称。
* </pre>
*/
@SerializedName("text")
private String text;
}
}

View File

@@ -61,7 +61,7 @@ public class UpdateRefundProgressRequest implements Serializable {
/**
* <pre>
* 字段名:拒绝退款原因
* 是否必填:否
* 是否必填:否 string(200)
* 描述:在拒绝退款时返回拒绝退款的原因
* </pre>
*/
@@ -72,7 +72,9 @@ public class UpdateRefundProgressRequest implements Serializable {
* <pre>
* 字段名:拒绝退款的举证图片列表
* 是否必填:否
* 描述:在拒绝退款时,如果有拒绝的图片举证,可以提供 最多上传4张图片, 传入调用“商户上传反馈图片”接口返回的media_id最多上传4张图片凭证
* 描述:在拒绝退款时,如果有拒绝的图片举证,可以提供 最多上传4张图片,
* 传入调用“商户上传反馈图片”接口返回的media_id最多上传4张图片凭证
*
* </pre>
*/
@SerializedName("reject_media_list")
@@ -81,7 +83,7 @@ public class UpdateRefundProgressRequest implements Serializable {
/**
* <pre>
* 字段名:备注
* 是否必填:否
* 是否必填:否 string(200)
* 描述:任何需要向微信支付客服反馈的信息
* </pre>
*/

View File

@@ -47,13 +47,23 @@ public class ComplaintNotifyResult implements Serializable {
* 是否必填:是
* 描述:
* 触发本次投诉通知回调的具体动作类型,枚举如下:
* 常规通知:
* CREATE_COMPLAINT用户提交投诉
* CONTINUE_COMPLAINT用户继续投诉
* USER_RESPONSE用户新留言
* RESPONSE_BY_PLATFORM平台新留言
* SELLER_REFUND收款方全额退款
* SELLER_REFUND商户发起全额退款
* MERCHANT_RESPONSE商户新回复
* MERCHANT_CONFIRM_COMPLETE商户反馈处理完成
* USER_APPLY_PLATFORM_SERVICE用户申请平台协助
* USER_CANCEL_PLATFORM_SERVICE用户取消平台协助
* PLATFORM_SERVICE_FINISHED客服结束平台协助
*
* 申请退款单的附加通知:
* 以下通知会更新投诉单状态,建议收到后查询投诉单详情。
* MERCHANT_APPROVE_REFUND商户同意退款
* MERCHANT_REJECT_REFUND商户驳回退款
* REFUND_SUCCESS退款到账
* </pre>
*/
@SerializedName(value = "action_type")

View File

@@ -250,6 +250,12 @@ public class WxPayUnifiedOrderV3Request implements Serializable {
*/
@SerializedName(value = "openid")
private String openid;
/**
* 实名支付用户身份标识
*/
@SerializedName(value = "identity")
private Identity identity;
}
@Data
@@ -572,4 +578,36 @@ public class WxPayUnifiedOrderV3Request implements Serializable {
@SerializedName(value = "profit_sharing")
private Boolean profitSharing;
}
@Data
@NoArgsConstructor
public static class Identity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 证件类型
* IDCARD:身份证
* HONGKONG_MACAO:港澳回乡证
* HONGKONG_MACAO_RESIDENT:港澳居住证
* TAIWAN_RESIDENT:台湾居住证
* FOREIGN_RESIDENT:外国人永居证
* OVERSEA_PASSPORT:护照
*/
@SerializedName(value = "type")
private String type;
/**
* 证件号
* 证件号,如身份证号。
* 示例值43102119910910512X
*/
@SerializedName(value = "number")
private String number;
/**
* 证件姓名。
* 示例值:周星星
*/
@SerializedName(value = "name")
private String name;
}
}

Some files were not shown because too many files have changed in this diff Show More