mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2026-03-10 00:13:40 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e48dc7f83 | ||
|
|
f3c1422354 | ||
|
|
d65e2f27a9 | ||
|
|
c3b16228c0 | ||
|
|
24ebc91dca | ||
|
|
1e003ee571 | ||
|
|
8e5ee97378 | ||
|
|
704fba4d85 | ||
|
|
b0daf8428e | ||
|
|
ab1c150feb | ||
|
|
b4b73ad40a | ||
|
|
be0dd8b692 | ||
|
|
83bd92d260 | ||
|
|
6d9fadf86d | ||
|
|
9730e9a387 | ||
|
|
6decd2839b | ||
|
|
a29e00f00f |
@@ -59,7 +59,7 @@
|
||||
### 重要信息
|
||||
1. [`WxJava` 荣获 `GitCode` 2024年度十大开源社区奖项](https://mp.weixin.qq.com/s/wM_UlMsDm3IZ1CPPDvcvQw)。
|
||||
2. 项目合作洽谈请联系微信`binary0000`(在微信里自行搜索并添加好友,请注明来意,如有关于SDK问题需讨论请参考下文入群讨论,不要加此微信)。
|
||||
3. **2023-12-28 发布 [【4.6.0正式版】](https://mp.weixin.qq.com/s/9Hhc_8w-v7ogS_TEAsqfAg)**!
|
||||
3. **2024-12-30 发布 [【4.7.0正式版】](https://mp.weixin.qq.com/s/_7k-XLYBqeJJhvHWCsdT0A)**!
|
||||
4. 贡献源码可以参考视频:[【贡献源码全过程(上集)】](https://mp.weixin.qq.com/s/3xUZSATWwHR_gZZm207h7Q)、[【贡献源码全过程(下集)】](https://mp.weixin.qq.com/s/nyzJwVVoYSJ4hSbwyvTx9A) ,友情提供:[程序员小山与Bug](https://space.bilibili.com/473631007)
|
||||
5. 新手重要提示:本项目仅是一个SDK开发工具包,未提供Web实现,建议使用 `maven` 或 `gradle` 引用本项目即可使用本SDK提供的各种功能,详情可参考 **[【Demo项目】](demo.md)** 或本项目中的部分单元测试代码;
|
||||
6. 微信开发新手请务必阅读【开发文档】([Gitee Wiki](https://gitee.com/binary/weixin-java-tools/wikis/Home) 或者 [Github Wiki](https://github.com/binarywang/WxJava/wiki))的常见问题部分,可以少走很多弯路,节省不少时间。
|
||||
@@ -90,7 +90,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>(不同模块参考下文)</artifactId>
|
||||
<version>4.6.0</version>
|
||||
<version>4.7.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>WxJava - Weixin/Wechat Java SDK</name>
|
||||
<description>微信开发Java SDK</description>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ public abstract class AbstractWxMaConfigStorageConfiguration {
|
||||
config.setToken(StringUtils.trimToNull(properties.getToken()));
|
||||
config.setAesKey(StringUtils.trimToNull(properties.getAesKey()));
|
||||
config.setMsgDataFormat(StringUtils.trimToNull(properties.getMsgDataFormat()));
|
||||
config.useStableAccessToken(properties.isUseStableAccessToken());
|
||||
|
||||
WxMaProperties.ConfigStorage configStorageProperties = properties.getConfigStorage();
|
||||
config.setHttpProxyHost(configStorageProperties.getHttpProxyHost());
|
||||
|
||||
@@ -45,6 +45,11 @@ public class WxMaProperties {
|
||||
*/
|
||||
private String msgDataFormat;
|
||||
|
||||
/**
|
||||
* 是否使用稳定版 Access Token
|
||||
*/
|
||||
private boolean useStableAccessToken = false;
|
||||
|
||||
/**
|
||||
* 存储策略
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-solon-plugins</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
```
|
||||
2. 添加配置(application.properties)
|
||||
```properties
|
||||
# 公众号配置(必填)
|
||||
# 小程序配置(必填)
|
||||
wx.miniapp.appid = appId
|
||||
wx.miniapp.secret = @secret
|
||||
wx.miniapp.token = @token
|
||||
wx.miniapp.aesKey = @aesKey
|
||||
wx.miniapp.msgDataFormat = @msgDataFormat # 消息格式,XML或者JSON.
|
||||
wx.miniapp.use-stable-access-token=@useStableAccessToken
|
||||
# 存储配置redis(可选)
|
||||
# 注意: 指定redis.host值后不会使用容器注入的redis连接(JedisPool)
|
||||
wx.miniapp.config-storage.type = Jedis # 配置类型: Memory(默认), Jedis, RedisTemplate
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ public abstract class AbstractWxMaConfigStorageConfiguration {
|
||||
config.setToken(StringUtils.trimToNull(properties.getToken()));
|
||||
config.setAesKey(StringUtils.trimToNull(properties.getAesKey()));
|
||||
config.setMsgDataFormat(StringUtils.trimToNull(properties.getMsgDataFormat()));
|
||||
config.useStableAccessToken(properties.isUseStableAccessToken());
|
||||
|
||||
WxMaProperties.ConfigStorage configStorageProperties = properties.getConfigStorage();
|
||||
config.setHttpProxyHost(configStorageProperties.getHttpProxyHost());
|
||||
|
||||
@@ -44,6 +44,11 @@ public class WxMaProperties {
|
||||
*/
|
||||
private String msgDataFormat;
|
||||
|
||||
/**
|
||||
* 是否使用稳定版 Access Token
|
||||
*/
|
||||
private boolean useStableAccessToken = false;
|
||||
|
||||
/**
|
||||
* 存储策略
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* 微信支付是否使用仿真测试环境.
|
||||
* 默认不使用
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>wx-java-spring-boot-starters</artifactId>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-graal</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-channel</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-common</artifactId>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-cp</artifactId>
|
||||
|
||||
@@ -334,7 +334,7 @@ public interface WxCpSchoolUserService {
|
||||
* 请求方式:GET(HTTPS)
|
||||
* 请求地址: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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -25,9 +25,6 @@ public class WxCpChatModel implements Serializable {
|
||||
@SerializedName("action")
|
||||
private String action;
|
||||
|
||||
@SerializedName("send")
|
||||
private String send;
|
||||
|
||||
@SerializedName("from")
|
||||
private String from;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,4 +37,6 @@ public class TemplateConfig implements Serializable {
|
||||
@SerializedName("vacation_list")
|
||||
private TemplateVacation vacationList;
|
||||
|
||||
private TemplateTips tips;
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -691,7 +691,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.
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-miniapp</artifactId>
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -550,6 +550,12 @@ public interface WxMaService extends WxService {
|
||||
* @return getWxMaOrderShippingService
|
||||
*/
|
||||
WxMaOrderShippingService getWxMaOrderShippingService();
|
||||
/**
|
||||
* 小程序订单管理服务
|
||||
*
|
||||
* @return WxMaOrderManagementService
|
||||
*/
|
||||
WxMaOrderManagementService getWxMaOrderManagementService();
|
||||
|
||||
/**
|
||||
* 小程序openApi管理
|
||||
|
||||
@@ -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);
|
||||
@@ -499,7 +502,10 @@ public abstract class BaseWxMaServiceImpl<H, P> implements WxMaService, RequestH
|
||||
@Override
|
||||
public void setWxMaConfig(WxMaConfig maConfig) {
|
||||
final String appid = maConfig.getAppid();
|
||||
this.setMultiConfigs(ImmutableMap.of(appid, maConfig), appid);
|
||||
Map<String, WxMaConfig> map = new HashMap<>();
|
||||
map.put(appid, maConfig);
|
||||
Map<String, WxMaConfig> configMap = Collections.unmodifiableMap(map);
|
||||
this.setMultiConfigs(configMap, appid);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -814,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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.util.Map;
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class WxMpSubscribeMessage {
|
||||
public class WxMpSubscribeMessage implements Serializable {
|
||||
|
||||
/**
|
||||
* 接收者openid.
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-open</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商家转账到零钱撤销转账接口
|
||||
* 文档地址:https://pay.weixin.qq.com/doc/v3/merchant/4012716458
|
||||
* </pre>
|
||||
*
|
||||
* @author Nor
|
||||
* @date 2025/1/17
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class TransferBillsCancelResult implements Serializable {
|
||||
private static final long serialVersionUID = -4935840810530008418L;
|
||||
|
||||
/**
|
||||
* 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 【微信转账单号】 微信转账单号,微信商家转账系统返回的唯一标识
|
||||
*/
|
||||
@SerializedName("transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
|
||||
/**
|
||||
* 【单据状态】 商家转账订单状态
|
||||
* 可选取值
|
||||
* CANCELING: 商户撤销请求受理成功,该笔转账正在撤销中
|
||||
* CANCELLED: 转账撤销完成
|
||||
*/
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 【最后一次单据状态变更时间】 按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("update_time")
|
||||
private String updateTime;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商家转账到零钱查询转账单接口
|
||||
* 文档地址:https://pay.weixin.qq.com/doc/v3/merchant/4012716457 https://pay.weixin.qq.com/doc/v3/merchant/4012716437
|
||||
* </pre>
|
||||
*
|
||||
* @author Nor
|
||||
* @date 2025/1/17
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class TransferBillsGetResult implements Serializable {
|
||||
private static final long serialVersionUID = -6376955113492371763L;
|
||||
|
||||
/**
|
||||
* 【商户号】 微信支付分配的商户号
|
||||
*/
|
||||
@SerializedName("mch_id")
|
||||
private String mchId;
|
||||
|
||||
/**
|
||||
* 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 【商家转账订单号】 商家转账订单的主键,唯一定义此资源的标识
|
||||
*/
|
||||
@SerializedName("transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
|
||||
/**
|
||||
* 【商户AppID】 申请商户号的AppID或商户号绑定的AppID(企业号corpid即为此AppID)
|
||||
*/
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 【单据状态】
|
||||
* 可选取值
|
||||
* ACCEPTED: 转账已受理
|
||||
* PROCESSING: 转账处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
|
||||
* WAIT_USER_CONFIRM: 待收款用户确认,可拉起微信收款确认页面进行收款确认
|
||||
* TRANSFERING: 转账结果尚未明确,可拉起微信收款确认页面再次重试确认收款
|
||||
* SUCCESS: 转账成功
|
||||
* FAIL: 转账失败
|
||||
* CANCELING: 商户撤销请求受理成功,该笔转账正在撤销中
|
||||
* CANCELLED: 转账撤销完成
|
||||
*
|
||||
* @see WxPayConstants.TransformBillState
|
||||
*/
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 【转账金额】 转账金额单位为“分”。
|
||||
*/
|
||||
@SerializedName("transfer_amount")
|
||||
private String transferAmount;
|
||||
|
||||
/**
|
||||
* 【转账备注】 单条转账备注(微信用户会收到该备注),UTF8编码,最多允许32个字符
|
||||
*/
|
||||
@SerializedName("transfer_remark")
|
||||
private String transferRemark;
|
||||
|
||||
/**
|
||||
* 【失败原因】 订单已失败或者已退资金时,返回失败原因
|
||||
*/
|
||||
@SerializedName("fail_reason")
|
||||
private String failReason;
|
||||
|
||||
/**
|
||||
* 【收款用户OpenID】 商户AppID下,某用户的OpenID
|
||||
*/
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 【收款用户姓名】 收款方真实姓名。支持标准RSA算法和国密算法,公钥由微信侧提供转账金额 >= 2,000元时,该笔明细必须填写若商户传入收款用户姓名,微信支付会校验用户OpenID与姓名是否一致,并提供电子回单
|
||||
*/
|
||||
@SerializedName("user_name")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 【单据创建时间】 单据受理成功时返回,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("create_time")
|
||||
private String createTime;
|
||||
|
||||
/**
|
||||
* 【最后一次状态变更时间】 单据最后更新时间,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE
|
||||
*/
|
||||
@SerializedName("update_time")
|
||||
private String updateTime;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.notify.OriginNotifyResponse;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayBaseNotifyV3Result;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 商家转账到零钱接口将转账结果通知用户
|
||||
* 文档地址:https://pay.weixin.qq.com/doc/v3/merchant/4012716434
|
||||
* </pre>
|
||||
*/
|
||||
@Data
|
||||
public class TransferBillsNotifyResult implements Serializable, WxPayBaseNotifyV3Result<TransferBillsNotifyResult.DecryptNotifyResult> {
|
||||
/**
|
||||
* 源数据
|
||||
*/
|
||||
private OriginNotifyResponse rawData;
|
||||
/**
|
||||
* 解密后的数据
|
||||
*/
|
||||
private TransferBillsNotifyResult.DecryptNotifyResult result;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class DecryptNotifyResult implements Serializable {
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
@SerializedName(value = "mch_id")
|
||||
private String mchId;
|
||||
/**
|
||||
* 商家批次单号
|
||||
*/
|
||||
@SerializedName(value = "out_bill_no")
|
||||
private String outBillNo;
|
||||
/**
|
||||
* 微信批次单号
|
||||
*/
|
||||
@SerializedName(value = "transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
/**
|
||||
* 批次状态
|
||||
*/
|
||||
@SerializedName(value = "state")
|
||||
private String state;
|
||||
/**
|
||||
* 转账金额
|
||||
*/
|
||||
@SerializedName(value = "transfer_amount")
|
||||
private Integer transferAmount;
|
||||
|
||||
/**
|
||||
* 批次状态
|
||||
*/
|
||||
@SerializedName(value = "openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 单据创建时间
|
||||
*/
|
||||
@SerializedName(value = "create_time")
|
||||
private String createTime;
|
||||
/**
|
||||
* 最后一次状态变更时间
|
||||
*/
|
||||
@SerializedName(value = "update_time")
|
||||
private String updateTime;
|
||||
/**
|
||||
* 错误原因
|
||||
*/
|
||||
@SerializedName(value = "fail_reason")
|
||||
private String failReason;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.v3.SpecEncrypt;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发起商家转账API参数
|
||||
*
|
||||
* @author allovine
|
||||
* created on 2025/1/15
|
||||
**/
|
||||
@Data
|
||||
@Builder(builderMethodName = "newBuilder")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TransferBillsRequest implements Serializable {
|
||||
private static final long serialVersionUID = -2175582517588397437L;
|
||||
|
||||
/**
|
||||
* 直连商户的appid
|
||||
*/
|
||||
@SerializedName("appid")
|
||||
private String appid;
|
||||
|
||||
/**
|
||||
* 商户系统内部的商家单号
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 转账场景ID
|
||||
* 商户平台-产品中心-商家转账 申请
|
||||
* 佣金报酬 ID:1005
|
||||
*/
|
||||
@SerializedName("transfer_scene_id")
|
||||
private String transferSceneId;
|
||||
|
||||
/**
|
||||
* 用户在直连商户应用下的用户标示
|
||||
*/
|
||||
@SerializedName("openid")
|
||||
private String openid;
|
||||
|
||||
/**
|
||||
* 收款用户姓名
|
||||
*/
|
||||
@SpecEncrypt
|
||||
@SerializedName("user_name")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 转账金额
|
||||
*/
|
||||
@SerializedName("transfer_amount")
|
||||
private Integer transferAmount;
|
||||
|
||||
/**
|
||||
* 转账备注
|
||||
*/
|
||||
@SerializedName("transfer_remark")
|
||||
private String transferRemark;
|
||||
|
||||
/**
|
||||
* 异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的url,必须为https,不能携带参数
|
||||
*/
|
||||
@SerializedName("notify_url")
|
||||
private String notifyUrl;
|
||||
|
||||
/**
|
||||
* 用户收款感知
|
||||
*/
|
||||
@SerializedName("user_recv_perception")
|
||||
private String userRecvPerception;
|
||||
|
||||
|
||||
/**
|
||||
* 转账场景报备信息
|
||||
*/
|
||||
@SerializedName("transfer_scene_report_infos")
|
||||
private List<TransferSceneReportInfo> transferSceneReportInfos;
|
||||
|
||||
|
||||
@Data
|
||||
@Builder(builderMethodName = "newBuilder")
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class TransferSceneReportInfo {
|
||||
/**
|
||||
* 信息类型
|
||||
*/
|
||||
@SerializedName("info_type")
|
||||
private String infoType;
|
||||
|
||||
/**
|
||||
* 信息内容
|
||||
*/
|
||||
@SerializedName("info_content")
|
||||
private String infoContent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.github.binarywang.wxpay.bean.transfer;
|
||||
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 商家转账结果
|
||||
*
|
||||
* @author allovine
|
||||
* created on 2025/1/15
|
||||
**/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class TransferBillsResult implements Serializable {
|
||||
private static final long serialVersionUID = -2175582517588397437L;
|
||||
|
||||
/**
|
||||
* 商户单号
|
||||
*/
|
||||
@SerializedName("out_bill_no")
|
||||
private String outBillNo;
|
||||
|
||||
/**
|
||||
* 微信转账单号
|
||||
*/
|
||||
@SerializedName("transfer_bill_no")
|
||||
private String transferBillNo;
|
||||
|
||||
/**
|
||||
* 单据创建时间
|
||||
*/
|
||||
@SerializedName("create_time")
|
||||
private String createTime;
|
||||
|
||||
/**
|
||||
* 单据状态
|
||||
*
|
||||
* @see WxPayConstants.TransformBillState
|
||||
*/
|
||||
@SerializedName("state")
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 失败原因
|
||||
*/
|
||||
@SerializedName("fail_reason")
|
||||
private String failReason;
|
||||
|
||||
/**
|
||||
* 跳转领取页面的package信息
|
||||
*/
|
||||
@SerializedName("package_info")
|
||||
private String packageInfo;
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
import java.util.Optional;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import lombok.Data;
|
||||
@@ -371,7 +372,7 @@ public class WxPayConfig {
|
||||
if (configContent != null) {
|
||||
inputStream = new ByteArrayInputStream(configContent);
|
||||
} else if (StringUtils.isNotEmpty(configString)) {
|
||||
configContent = configString.getBytes(StandardCharsets.UTF_8);
|
||||
configContent = Base64.getDecoder().decode(configString);
|
||||
inputStream = new ByteArrayInputStream(configContent);
|
||||
} else {
|
||||
if (StringUtils.isBlank(configPath)) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
|
||||
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.lang3.time.FastDateFormat;
|
||||
|
||||
import java.text.Format;
|
||||
@@ -353,4 +354,86 @@ public class WxPayConstants {
|
||||
public static final String PERSONAL_SUB_OPENID = "PERSONAL_SUB_OPENID";
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信商户转账订单状态
|
||||
*/
|
||||
@UtilityClass
|
||||
public static class TransformBillState {
|
||||
/**
|
||||
* 转账已受理
|
||||
*/
|
||||
public static final String ACCEPTED = "ACCEPTED";
|
||||
|
||||
/**
|
||||
* 转账处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
|
||||
*/
|
||||
public static final String PROCESSING = "PROCESSING";
|
||||
|
||||
/**
|
||||
* 待收款用户确认,可拉起微信收款确认页面进行收款确认
|
||||
*/
|
||||
public static final String WAIT_USER_CONFIRM = "WAIT_USER_CONFIRM";
|
||||
|
||||
/**
|
||||
* 转账结果尚未明确,可拉起微信收款确认页面再次重试确认收款
|
||||
*/
|
||||
public static final String TRANSFERING = "TRANSFERING";
|
||||
|
||||
/**
|
||||
* 转账成功
|
||||
*/
|
||||
public static final String SUCCESS = "SUCCESS";
|
||||
|
||||
/**
|
||||
* 转账失败
|
||||
*/
|
||||
public static final String FAIL = "FAIL";
|
||||
|
||||
/**
|
||||
* 商户撤销请求受理成功,该笔转账正在撤销中
|
||||
*/
|
||||
public static final String CANCELING = "CANCELING";
|
||||
|
||||
/**
|
||||
* 转账撤销完成
|
||||
*/
|
||||
public static final String CANCELLED = "CANCELLED";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。
|
||||
*/
|
||||
@UtilityClass
|
||||
public static class TransformSceneId {
|
||||
/**
|
||||
* 现金营销
|
||||
*/
|
||||
public static final String CASH_MARKETING = "1001";
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户收款感知
|
||||
*
|
||||
* @see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012711988#3.3-%E5%8F%91%E8%B5%B7%E8%BD%AC%E8%B4%A6">官方文档</a>
|
||||
*/
|
||||
@UtilityClass
|
||||
public static class UserRecvPerception {
|
||||
/**
|
||||
* 转账场景 现金营销
|
||||
* 场景介绍 向参与营销活动的用户发放现金奖励
|
||||
*/
|
||||
public static class CASH_MARKETING {
|
||||
/**
|
||||
* 默认展示
|
||||
*/
|
||||
public static final String ACTIVITY = "活动奖励";
|
||||
|
||||
/**
|
||||
* 需在发起转账时,“用户收款感知”字段主动传入“现金奖励”才可展示
|
||||
*/
|
||||
public static final String CASH = "现金奖励";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,4 +111,82 @@ public interface TransferService {
|
||||
*/
|
||||
TransferBatchDetailResult transferBatchesOutBatchNoDetail(String outBatchNo, String outDetailNo) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
*
|
||||
* 2025.1.15 开始新接口 发起商家转账API
|
||||
*
|
||||
* 请求方式:POST(HTTPS)
|
||||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills">请求地址</a>
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716434">发起商家转账API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param request 转账请求参数
|
||||
* @return TransferBillsResult 转账结果
|
||||
* @throws WxPayException .
|
||||
*/
|
||||
TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
*
|
||||
* 2025.1.15 开始新接口 撤销转账API
|
||||
*
|
||||
* 请求方式:POST(HTTPS)
|
||||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}/cancel">请求地址</a>
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716458">商户撤销转账API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param outBillNo 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
|
||||
* @return TransformBillsGetResult 转账单
|
||||
* @throws WxPayException .
|
||||
*/
|
||||
TransferBillsCancelResult transformBillsCancel(String outBillNo) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
*
|
||||
* 2025.1.15 开始新接口 发起商家转账API
|
||||
*
|
||||
* 请求方式:GET(HTTPS)
|
||||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}">请求地址</a>
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716437">商户单号查询转账单API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param outBillNo 【商户单号】 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
|
||||
* @return TransformBillsGetResult 转账单
|
||||
* @throws WxPayException .
|
||||
*/
|
||||
TransferBillsGetResult getBillsByOutBillNo(String outBillNo) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
*
|
||||
* 2025.1.15 开始新接口 微信单号查询转账单API
|
||||
*
|
||||
* 请求方式:GET(HTTPS)
|
||||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/transfer-bill-no/{transfer_bill_no}">请求地址</a>
|
||||
*
|
||||
* 文档地址:<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012716437">商户单号查询转账单API</a>
|
||||
* </pre>
|
||||
*
|
||||
* @param transferBillNo 【微信转账单号】 微信转账单号,微信商家转账系统返回的唯一标识
|
||||
* @return TransformBillsGetResult 转账单
|
||||
* @throws WxPayException .
|
||||
*/
|
||||
TransferBillsGetResult getBillsByTransferBillNo(String transferBillNo) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 2025.1.15 开始新接口 解析商家转账结果
|
||||
* 详见<a href="https://pay.weixin.qq.com/doc/v3/merchant/4012712115"></a>
|
||||
*
|
||||
* @param notifyData 通知数据
|
||||
* @param header 通知头部数据,不传则表示不校验头
|
||||
* @return the wx transfer notify result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.github.binarywang.wxpay.bean.notify.*;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
@@ -38,16 +39,18 @@ public interface WxPayService {
|
||||
* Map里 加入新的 {@link WxPayConfig},适用于动态添加新的微信商户配置.
|
||||
*
|
||||
* @param mchId 商户id
|
||||
* @param appId 微信应用id
|
||||
* @param wxPayConfig 新的微信配置
|
||||
*/
|
||||
void addConfig(String mchId, WxPayConfig wxPayConfig);
|
||||
void addConfig(String mchId, String appId, WxPayConfig wxPayConfig);
|
||||
|
||||
/**
|
||||
* 从 Map中 移除 {@link String mchId} 所对应的 {@link WxPayConfig},适用于动态移除微信商户配置.
|
||||
* 从 Map中 移除 {@link String mchId} 和 {@link String appId} 所对应的 {@link WxPayConfig},适用于动态移除微信商户配置.
|
||||
*
|
||||
* @param mchId 对应商户的标识
|
||||
* @param appId 微信应用id
|
||||
*/
|
||||
void removeConfig(String mchId);
|
||||
void removeConfig(String mchId, String appId);
|
||||
|
||||
/**
|
||||
* 注入多个 {@link WxPayConfig} 的实现. 并为每个 {@link WxPayConfig} 赋予不同的 {@link String mchId} 值
|
||||
@@ -69,17 +72,19 @@ public interface WxPayService {
|
||||
* 进行相应的商户切换.
|
||||
*
|
||||
* @param mchId 商户标识
|
||||
* @param appId 微信应用id
|
||||
* @return 切换是否成功 boolean
|
||||
*/
|
||||
boolean switchover(String mchId);
|
||||
boolean switchover(String mchId, String appId);
|
||||
|
||||
/**
|
||||
* 进行相应的商户切换.
|
||||
*
|
||||
* @param mchId 商户标识
|
||||
* @param appId 微信应用id
|
||||
* @return 切换成功 ,则返回当前对象,方便链式调用,否则抛出异常
|
||||
*/
|
||||
WxPayService switchoverTo(String mchId);
|
||||
WxPayService switchoverTo(String mchId, String appId);
|
||||
|
||||
/**
|
||||
* 发送post请求,得到响应字节数组.
|
||||
@@ -616,10 +621,10 @@ public interface WxPayService {
|
||||
/**
|
||||
* 调用统一下单接口,并组装生成支付所需参数对象.
|
||||
*
|
||||
* @param <T> 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @param <T> 请使用{@link WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @param tradeType the trade type
|
||||
* @param request 统一下单请求参数
|
||||
* @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @return 返回 {@link WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
<T> T createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException;
|
||||
@@ -627,10 +632,10 @@ public interface WxPayService {
|
||||
/**
|
||||
* 服务商模式调用统一下单接口,并组装生成支付所需参数对象.
|
||||
*
|
||||
* @param <T> 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @param <T> 请使用{@link WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @param tradeType the trade type
|
||||
* @param request 统一下单请求参数
|
||||
* @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @return 返回 {@link WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
<T> T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
|
||||
@@ -991,6 +996,17 @@ public interface WxPayService {
|
||||
*/
|
||||
WxPayTransferBatchesNotifyV3Result parseTransferBatchesNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 解析商家转账批次回调通知
|
||||
* https://pay.weixin.qq.com/doc/v3/merchant/4012712115
|
||||
*
|
||||
* @param notifyData
|
||||
* @param header
|
||||
* @return
|
||||
* @throws WxPayException
|
||||
*/
|
||||
TransferBillsNotifyResult parseTransferBillsNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 解析服务商模式退款结果通知
|
||||
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_11.shtml
|
||||
@@ -1603,7 +1619,8 @@ public interface WxPayService {
|
||||
|
||||
/**
|
||||
* 获取服务商直股份签约计划服务类
|
||||
* @return the partner pay score sign plan service
|
||||
*
|
||||
* @return the partner pay score sign plan service
|
||||
*/
|
||||
PartnerPayScoreSignPlanService getPartnerPayScoreSignPlanService();
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfigHolder;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
@@ -45,6 +45,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_DATE_FORMAT;
|
||||
@@ -121,7 +122,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
private final PartnerPayScoreService partnerPayScoreService = new PartnerPayScoreServiceImpl(this);
|
||||
|
||||
@Getter
|
||||
private final PartnerPayScoreSignPlanService partnerPayScoreSignPlanService=new PartnerPayScoreSignPlanServiceImpl(this);
|
||||
private final PartnerPayScoreSignPlanService partnerPayScoreSignPlanService = new PartnerPayScoreSignPlanServiceImpl(this);
|
||||
|
||||
@Getter
|
||||
private final MerchantTransferService merchantTransferService = new MerchantTransferServiceImpl(this);
|
||||
@@ -129,7 +130,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
@Getter
|
||||
private final BrandMerchantTransferService brandMerchantTransferService = new BrandMerchantTransferServiceImpl(this);
|
||||
|
||||
protected Map<String, WxPayConfig> configMap = new HashMap<>();
|
||||
protected Map<String, WxPayConfig> configMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public WxPayConfig getConfig() {
|
||||
@@ -142,38 +143,37 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
|
||||
@Override
|
||||
public void setConfig(WxPayConfig config) {
|
||||
final String defaultMchId = config.getMchId();
|
||||
this.setMultiConfig(ImmutableMap.of(defaultMchId, config), defaultMchId);
|
||||
final String defaultKey = this.getConfigKey(config.getMchId(), config.getAppId());
|
||||
this.setMultiConfig(ImmutableMap.of(defaultKey, config), defaultKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConfig(String mchId, WxPayConfig wxPayConfig) {
|
||||
public void addConfig(String mchId, String appId, WxPayConfig wxPayConfig) {
|
||||
synchronized (this) {
|
||||
if (this.configMap == null) {
|
||||
this.setConfig(wxPayConfig);
|
||||
} else {
|
||||
WxPayConfigHolder.set(mchId);
|
||||
this.configMap.put(mchId, wxPayConfig);
|
||||
String configKey = this.getConfigKey(mchId, appId);
|
||||
WxPayConfigHolder.set(configKey);
|
||||
this.configMap.put(configKey, wxPayConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConfig(String mchId) {
|
||||
public void removeConfig(String mchId, String appId) {
|
||||
synchronized (this) {
|
||||
if (this.configMap.size() == 1) {
|
||||
this.configMap.remove(mchId);
|
||||
log.warn("已删除最后一个商户号配置:{},须立即使用setConfig或setMultiConfig添加配置", mchId);
|
||||
String configKey = this.getConfigKey(mchId, appId);
|
||||
this.configMap.remove(configKey);
|
||||
if (this.configMap.isEmpty()) {
|
||||
log.warn("已删除最后一个商户号配置:mchId[{}],appid[{}],须立即使用setConfig或setMultiConfig添加配置", mchId, appId);
|
||||
return;
|
||||
}
|
||||
if (WxPayConfigHolder.get().equals(mchId)) {
|
||||
this.configMap.remove(mchId);
|
||||
final String defaultMpId = this.configMap.keySet().iterator().next();
|
||||
WxPayConfigHolder.set(defaultMpId);
|
||||
log.warn("已删除默认商户号配置,商户号【{}】被设为默认配置", defaultMpId);
|
||||
return;
|
||||
if (WxPayConfigHolder.get().equals(configKey)) {
|
||||
final String nextConfigKey = this.configMap.keySet().iterator().next();
|
||||
WxPayConfigHolder.set(nextConfigKey);
|
||||
log.warn("已删除默认商户号配置,商户号【{}】被设为默认配置", nextConfigKey);
|
||||
}
|
||||
this.configMap.remove(mchId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,28 +183,34 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMultiConfig(Map<String, WxPayConfig> wxPayConfigs, String defaultMchId) {
|
||||
public void setMultiConfig(Map<String, WxPayConfig> wxPayConfigs, String defaultConfigKey) {
|
||||
this.configMap = Maps.newHashMap(wxPayConfigs);
|
||||
WxPayConfigHolder.set(defaultMchId);
|
||||
WxPayConfigHolder.set(defaultConfigKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean switchover(String mchId) {
|
||||
if (this.configMap.containsKey(mchId)) {
|
||||
WxPayConfigHolder.set(mchId);
|
||||
public boolean switchover(String mchId, String appId) {
|
||||
String configKey = this.getConfigKey(mchId, appId);
|
||||
if (this.configMap.containsKey(configKey)) {
|
||||
WxPayConfigHolder.set(configKey);
|
||||
return true;
|
||||
}
|
||||
log.error("无法找到对应【{}】的商户号配置信息,请核实!", mchId);
|
||||
log.error("无法找到对应mchId=【{}】,appId=【{}】的商户号配置信息,请核实!", mchId, appId);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayService switchoverTo(String mchId) {
|
||||
if (this.configMap.containsKey(mchId)) {
|
||||
WxPayConfigHolder.set(mchId);
|
||||
public WxPayService switchoverTo(String mchId, String appId) {
|
||||
String configKey = this.getConfigKey(mchId, appId);
|
||||
if (this.configMap.containsKey(configKey)) {
|
||||
WxPayConfigHolder.set(configKey);
|
||||
return this;
|
||||
}
|
||||
throw new WxRuntimeException(String.format("无法找到对应【%s】的商户号配置信息,请核实!", mchId));
|
||||
throw new WxRuntimeException(String.format("无法找到对应mchId=【%s】,appId=【%s】的商户号配置信息,请核实!", mchId, appId));
|
||||
}
|
||||
|
||||
private String getConfigKey(String mchId, String appId) {
|
||||
return mchId + "_" + appId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -301,7 +307,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
|
||||
@Override
|
||||
public WxPayRefundQueryV3Result refundPartnerQueryV3(WxPayRefundQueryV3Request request) throws WxPayException {
|
||||
String url = String.format("%s/v3/refund/domestic/refunds/%s?sub_mchid=%s", this.getPayBaseUrl(), request.getOutRefundNo(),request.getSubMchid());
|
||||
String url = String.format("%s/v3/refund/domestic/refunds/%s?sub_mchid=%s", this.getPayBaseUrl(), request.getOutRefundNo(), request.getSubMchid());
|
||||
String response = this.getV3(url);
|
||||
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
|
||||
}
|
||||
@@ -323,7 +329,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
} else if (configMap.get(result.getMchId()).getSignType() != null) {
|
||||
// 如果配置中signType有值,则使用它进行验签
|
||||
signType = configMap.get(result.getMchId()).getSignType();
|
||||
this.switchover(result.getMchId());
|
||||
this.switchover(result.getMchId(), result.getAppid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +352,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
*/
|
||||
private boolean verifyNotifySign(SignatureHeader header, String data) throws WxSignTestException {
|
||||
String wxPaySign = header.getSignature();
|
||||
if(wxPaySign.startsWith("WECHATPAY/SIGNTEST/")){
|
||||
if (wxPaySign.startsWith("WECHATPAY/SIGNTEST/")) {
|
||||
throw new WxSignTestException("微信支付签名探测流量");
|
||||
}
|
||||
String beforeSign = String.format("%s\n%s\n%s\n",
|
||||
@@ -420,7 +426,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
WxPayRefundNotifyResult result;
|
||||
if (XmlConfig.fastMode) {
|
||||
result = BaseWxPayResult.fromXML(xmlData, WxPayRefundNotifyResult.class);
|
||||
this.switchover(result.getMchId());
|
||||
this.switchover(result.getMchId(), result.getAppid());
|
||||
result.decryptReqInfo(this.getConfig().getMchKey());
|
||||
} else {
|
||||
result = WxPayRefundNotifyResult.fromXML(xmlData, this.getConfig().getMchKey());
|
||||
@@ -442,6 +448,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayTransferBatchesNotifyV3Result.class, WxPayTransferBatchesNotifyV3Result.DecryptNotifyResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransferBillsNotifyResult parseTransferBillsNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
|
||||
return this.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayPartnerRefundNotifyV3Result parsePartnerRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
|
||||
return this.baseParseOrderNotifyV3Result(notifyData, header, WxPayPartnerRefundNotifyV3Result.class, WxPayPartnerRefundNotifyV3Result.DecryptNotifyResult.class);
|
||||
@@ -452,7 +463,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
try {
|
||||
log.debug("扫码支付回调通知请求参数:{}", xmlData);
|
||||
WxScanPayNotifyResult result = BaseWxPayResult.fromXML(xmlData, WxScanPayNotifyResult.class);
|
||||
this.switchover(result.getMchId());
|
||||
this.switchover(result.getMchId(), result.getAppid());
|
||||
log.debug("扫码支付回调通知解析后的对象:{}", result);
|
||||
result.checkResult(this, this.getConfig().getSignType(), false);
|
||||
return result;
|
||||
@@ -1300,7 +1311,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
@Override
|
||||
public WxPayFaceAuthInfoResult getWxPayFaceAuthInfo(WxPayFaceAuthInfoRequest request) throws WxPayException {
|
||||
if (StringUtils.isEmpty(request.getSignType())) {
|
||||
request.setSignType(WxPayConstants.SignType.MD5);
|
||||
request.setSignType(SignType.MD5);
|
||||
}
|
||||
|
||||
request.checkAndSign(this.getConfig());
|
||||
|
||||
@@ -48,8 +48,7 @@ public class TransferServiceImpl implements TransferService {
|
||||
if (request.getNeedQueryDetail()) {
|
||||
url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=true&offset=%s&limit=%s&detail_status=%s",
|
||||
this.payService.getPayBaseUrl(), request.getBatchId(), request.getOffset(), request.getLimit(), request.getDetailStatus());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
url = String.format("%s/v3/transfer/batches/batch-id/%s?need_query_detail=false",
|
||||
this.payService.getPayBaseUrl(), request.getBatchId());
|
||||
}
|
||||
@@ -70,8 +69,7 @@ public class TransferServiceImpl implements TransferService {
|
||||
if (request.getNeedQueryDetail()) {
|
||||
url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=true&offset=%s&limit=%s&detail_status=%s",
|
||||
this.payService.getPayBaseUrl(), request.getOutBatchNo(), request.getOffset(), request.getLimit(), request.getDetailStatus());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
url = String.format("%s/v3/transfer/batches/out-batch-no/%s?need_query_detail=false",
|
||||
this.payService.getPayBaseUrl(), request.getOutBatchNo());
|
||||
}
|
||||
@@ -85,4 +83,45 @@ public class TransferServiceImpl implements TransferService {
|
||||
String result = this.payService.getV3(url);
|
||||
return GSON.fromJson(result, TransferBatchDetailResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransferBillsResult transferBills(TransferBillsRequest request) throws WxPayException {
|
||||
String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills", this.payService.getPayBaseUrl());
|
||||
if (request.getUserName() != null && request.getUserName().length() > 0) {
|
||||
X509Certificate validCertificate = this.payService.getConfig().getVerifier().getValidCertificate();
|
||||
RsaCryptoUtil.encryptFields(request, validCertificate);
|
||||
}
|
||||
String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
|
||||
return GSON.fromJson(result, TransferBillsResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransferBillsCancelResult transformBillsCancel(String outBillNo) throws WxPayException {
|
||||
String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/%s/cancel",
|
||||
this.payService.getPayBaseUrl(), outBillNo);
|
||||
String result = this.payService.postV3(url, "");
|
||||
|
||||
return GSON.fromJson(result, TransferBillsCancelResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransferBillsGetResult getBillsByOutBillNo(String outBillNo) throws WxPayException {
|
||||
String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/%s",
|
||||
this.payService.getPayBaseUrl(), outBillNo);
|
||||
String result = this.payService.getV3(url);
|
||||
return GSON.fromJson(result, TransferBillsGetResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransferBillsGetResult getBillsByTransferBillNo(String transferBillNo) throws WxPayException {
|
||||
String url = String.format("%s/v3/fund-app/mch-transfer/transfer-bills/transfer-bill-no/%s",
|
||||
this.payService.getPayBaseUrl(), transferBillNo);
|
||||
String result = this.payService.getV3(url);
|
||||
return GSON.fromJson(result, TransferBillsGetResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransferBillsNotifyResult parseTransferBillsNotifyResult(String notifyData, SignatureHeader header) throws WxPayException {
|
||||
return this.payService.baseParseOrderNotifyV3Result(notifyData, header, TransferBillsNotifyResult.class, TransferBillsNotifyResult.DecryptNotifyResult.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.WxPayApiData;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.v3.WxPayV3DownloadHttpGet;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -171,7 +172,7 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
|
||||
HttpPost httpPost = this.createHttpPost(url, requestStr);
|
||||
httpPost.addHeader(ACCEPT, APPLICATION_JSON);
|
||||
httpPost.addHeader(CONTENT_TYPE, APPLICATION_JSON);
|
||||
String serialNumber = getConfig().getVerifier().getValidCertificate().getSerialNumber().toString(16).toUpperCase();
|
||||
String serialNumber = getWechatpaySerial(getConfig());
|
||||
httpPost.addHeader("Wechatpay-Serial", serialNumber);
|
||||
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
|
||||
//v3已经改为通过状态码判断200 204 成功
|
||||
@@ -251,7 +252,7 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
httpGet.addHeader(ACCEPT, APPLICATION_JSON);
|
||||
httpGet.addHeader(CONTENT_TYPE, APPLICATION_JSON);
|
||||
String serialNumber = getConfig().getVerifier().getValidCertificate().getSerialNumber().toString(16).toUpperCase();
|
||||
String serialNumber = getWechatpaySerial(getConfig());
|
||||
httpGet.addHeader("Wechatpay-Serial", serialNumber);
|
||||
return this.requestV3(url, httpGet);
|
||||
}
|
||||
@@ -380,4 +381,16 @@ public class WxPayServiceApacheHttpImpl extends BaseWxPayServiceImpl {
|
||||
return wxPayException;
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容微信支付公钥模式
|
||||
* @param wxPayConfig
|
||||
* @return
|
||||
*/
|
||||
private String getWechatpaySerial(WxPayConfig wxPayConfig) {
|
||||
String serialNumber = wxPayConfig.getVerifier().getValidCertificate().getSerialNumber().toString(16).toUpperCase();
|
||||
if (StringUtils.isNotBlank(wxPayConfig.getPublicKeyId())) {
|
||||
serialNumber = wxPayConfig.getPublicKeyId();
|
||||
}
|
||||
return serialNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBillsRequest;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.testbase.ApiTestModule;
|
||||
@@ -73,4 +74,32 @@ public class TransferServiceImplTest {
|
||||
public void testTransferBatchesOutBatchNoDetail() throws WxPayException {
|
||||
log.info("商家明细单号查询明细单:{}", this.payService.getTransferService().transferBatchesOutBatchNoDetail("1655447999520", "1655447989156"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransferBills() throws WxPayException {
|
||||
TransferBillsRequest transferBillsRequest = TransferBillsRequest.newBuilder()
|
||||
.appid("wxf636efh5xxxxx")
|
||||
.outBillNo("1655447989156")
|
||||
.transferSceneId("1005")
|
||||
.transferAmount(100)
|
||||
.transferRemark("测试转账")
|
||||
.openid("oX_7Jzr9gSZz4X_Xc9-_7HGf8XzI")
|
||||
.userName("测试用户").build();
|
||||
log.info("发起商家转账:{}", this.payService.getTransferService().transferBills(transferBillsRequest));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransformBillsCancel() throws WxPayException {
|
||||
log.info("撤销商家转账:{}", this.payService.getTransferService().transformBillsCancel("123456"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBillsByOutBillNo() throws WxPayException {
|
||||
log.info("商户单号查询转账单:{}", this.payService.getTransferService().getBillsByOutBillNo("123456"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBillsByTransferBillNo() throws WxPayException {
|
||||
log.info("微信单号查询转账单:{}", this.payService.getTransferService().getBillsByTransferBillNo("123456"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.7.2.B</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-qidian</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user