mirror of
https://github.com/dromara/payment-spring-boot.git
synced 2026-03-27 14:33:43 +08:00
Compare commits
49 Commits
1.0.18.REL
...
1.0.21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46b7047674 | ||
|
|
095a1e4a4a | ||
|
|
8470286af6 | ||
|
|
e20e19e66a | ||
|
|
c43a91a2de | ||
|
|
dedde9515d | ||
|
|
f0e2495bfd | ||
|
|
b4ff87b80b | ||
|
|
62eaf468fb | ||
|
|
a4fa017cec | ||
|
|
20f80c16db | ||
|
|
7be5971ae3 | ||
|
|
7388a75455 | ||
|
|
6d321273be | ||
|
|
f2f544be9d | ||
|
|
7f2591b3c4 | ||
|
|
8bf83662fb | ||
|
|
9ceeabd9e3 | ||
|
|
d95d9de0f1 | ||
|
|
5b8850b980 | ||
|
|
85621edace | ||
|
|
56995088d1 | ||
|
|
6e2b6decf4 | ||
|
|
d068734422 | ||
|
|
57e794280f | ||
|
|
56bf43f04f | ||
|
|
87257fc8b1 | ||
|
|
616ea0cede | ||
|
|
f4615b02b3 | ||
|
|
4e27958ace | ||
|
|
aaad20b78a | ||
|
|
10b09ac4bb | ||
|
|
62ecc5b700 | ||
|
|
8168097427 | ||
|
|
9645d20b33 | ||
|
|
c42f6d9d5e | ||
|
|
0635d59666 | ||
|
|
5941907d7c | ||
|
|
348fe9b5f1 | ||
|
|
fa0cc541de | ||
|
|
85fde9bb68 | ||
|
|
da0fe928eb | ||
|
|
1c27375d93 | ||
|
|
4271491bc3 | ||
|
|
36259fc8ac | ||
|
|
d7cdebc731 | ||
|
|
97d87ce6f0 | ||
|
|
99136f9bd6 | ||
|
|
571bd2e563 |
27
.github/ISSUE_TEMPLATE/issues.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/issues.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: issues
|
||||||
|
about: 向维护者提问以帮助改进
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**提问前的思考**
|
||||||
|
1. 我是否已经认真阅读了文档和相关操作说明
|
||||||
|
2. 其它ISSUES是否已经有了解决方案
|
||||||
|
|
||||||
|
**描述问题**
|
||||||
|
提问时应该按照以下要点清晰地描述问题,才能得到可靠的答复
|
||||||
|
|
||||||
|
**环境版本信息**
|
||||||
|
问题发生的环境,不限于软件版本、运行时环境、操作系统等
|
||||||
|
|
||||||
|
**操作行为**
|
||||||
|
产生问题的操作行为
|
||||||
|
|
||||||
|
**期望的结果**
|
||||||
|
清晰地描述期望达成的结果
|
||||||
|
|
||||||
|
**代码与截图**
|
||||||
|
通常不建议使用代码截图,这样不太方便维护者进行Preview。代码应该使用Markdown代码块进行格式化。因交互导致的问题才建议使用截图辅助排查。
|
||||||
53
README.md
53
README.md
@@ -16,14 +16,17 @@
|
|||||||
<a target="_blank" href="https://github.com/dromara/payment-spring-boot">
|
<a target="_blank" href="https://github.com/dromara/payment-spring-boot">
|
||||||
<img alt="" src="https://img.shields.io/github/stars/dromara/payment-spring-boot?style=social"/>
|
<img alt="" src="https://img.shields.io/github/stars/dromara/payment-spring-boot?style=social"/>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://gitee.com/felord/payment-spring-boot/stargazers">
|
<a target="_blank" href="https://gitee.com/dromara/payment-spring-boot/stargazers">
|
||||||
<img alt="" src="https://gitee.com/felord/payment-spring-boot/badge/star.svg?theme=white"/>
|
<img alt="" src="https://gitee.com/felord/payment-spring-boot/badge/star.svg?theme=white"/>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://work.weixin.qq.com/kfid/kfc9d9d759f27f087e1">
|
<a target="_blank" href="https://work.weixin.qq.com/kfid/kfc9d9d759f27f087e1">
|
||||||
<img alt="点击立即微信咨询" src="https://img.shields.io/badge/%E7%82%B9%E5%87%BB-%E5%BE%AE%E4%BF%A1%E5%92%A8%E8%AF%A2-brightgreen"/>
|
<img alt="点击立即微信咨询" src="https://img.shields.io/badge/%E7%82%B9%E5%87%BB-%E5%BE%AE%E4%BF%A1%E5%92%A8%E8%AF%A2-brightgreen"/>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://jq.qq.com/?_wv=1027&k=qRTKHWY0">
|
<a target="_blank" href="#">
|
||||||
<img alt="点击加入QQ交流群" src="https://img.shields.io/badge/QQ%E4%BA%A4%E6%B5%81%E7%BE%A4-945342113-ff69b4"/>
|
<img alt="点击加入QQ交流①群(满)" src="https://img.shields.io/badge/QQ%E4%BA%A4%E6%B5%81%E7%BE%A4-945342113(满)-ff69b4"/>
|
||||||
|
</a>
|
||||||
|
<a target="_blank" href="https://jq.qq.com/?_wv=1027&k=cCiv8Vlv">
|
||||||
|
<img alt="点击加入QQ交流②群" src="https://img.shields.io/badge/QQ%E4%BA%A4%E6%B5%81%E7%BE%A4-549174561-ff69b4"/>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ Starter,支持微信优惠券,代金券、商家券、智慧商圈、商家
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.felord</groupId>
|
<groupId>cn.felord</groupId>
|
||||||
<artifactId>payment-spring-boot-starter</artifactId>
|
<artifactId>payment-spring-boot-starter</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -52,24 +55,47 @@ Starter,支持微信优惠券,代金券、商家券、智慧商圈、商家
|
|||||||
|
|
||||||
## 文档地址
|
## 文档地址
|
||||||
|
|
||||||
- [payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot)
|
- ~~[payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot) (暂时不可用)~~
|
||||||
|
|
||||||
## API清单
|
## API清单
|
||||||
|
|
||||||
目前已经实现绝大部分微信支付直连商户和服务商的接口,具体的API明细可查看[API清单](https://dromara.github.io/payment-spring-boot/#/wechat_v3_api)
|
目前已经实现绝大部分微信支付直连商户和服务商的接口,具体的API明细可查看[API清单(暂时不可用)](https://dromara.github.io/payment-spring-boot/#/wechat_v3_api)
|
||||||
> 随着版本迭代功能会增加,也可通过API注册表类`WechatPayV3Type`进行API接口检索。
|
> 随着版本迭代功能会增加,也可通过API注册表类`WechatPayV3Type`进行API接口检索。
|
||||||
|
|
||||||
## CHANGELOG
|
## CHANGELOG
|
||||||
|
|
||||||
更新日志[CHANGELOG](https://dromara.github.io/payment-spring-boot/#/changelog)
|
~~更新日志[CHANGELOG](https://dromara.github.io/payment-spring-boot/#/changelog) (暂时不可用)~~
|
||||||
|
|
||||||
## 使用入门
|
## 使用入门
|
||||||
|
|
||||||
### 集成配置
|
### 集成配置
|
||||||
|
|
||||||
关于集成配置请详细阅读[payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot)
|
~~关于集成配置请详细阅读[payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot)
|
||||||
中[快速接入](https://dromara.github.io/payment-spring-boot/#/quick_start)章节
|
中[快速接入](https://dromara.github.io/payment-spring-boot/#/quick_start)章节 (暂时不可用)~~
|
||||||
|
|
||||||
|
[关于微信支付公钥](https://pay.weixin.qq.com/doc/v3/merchant/4012153196)
|
||||||
|
微信官方推出了微信支付公钥产品以替代原来的微信平台证书,我们对此进行了适配
|
||||||
|
相关配置如下
|
||||||
|
```yaml
|
||||||
|
wechat:
|
||||||
|
pay:
|
||||||
|
v3:
|
||||||
|
# 租户id
|
||||||
|
<tentantId>:
|
||||||
|
# 是否使用微信支付公钥验签 默认false
|
||||||
|
enable-wechat-pay-public: true
|
||||||
|
# 微信支付公钥id
|
||||||
|
wechat-pay-public-key-id: PUB_KEY_ID_1111213
|
||||||
|
# 微信支付公钥路径
|
||||||
|
wechat-pay-public-key-path: 'pub_key.pem'
|
||||||
|
|
||||||
|
wechat-pay-public-key-absolute-path: ''
|
||||||
|
# 是否启用签名验签方法切换 默认false
|
||||||
|
switch-verify-sign-method: true
|
||||||
|
```
|
||||||
|
- 对于旧版本商户,若不使用微信支付公钥,则不需要配置上述对应参数,则默认使用微信平台证书验签。
|
||||||
|
- 对于新进件的商户,微信官方默认启用支付公钥,需要配置上述参数。其中 `switch-verify-sign-method` 参数不需要配置
|
||||||
|
- 若旧版版商户使用微信支付公钥,则需要配置上述参数,并启用 `switch-verify-sign-method : true` [原理参考](https://pay.weixin.qq.com/doc/v3/merchant/4012154180)。<font color=red>当完成从平台证书切换到微信支付公钥后,请务必将`switch-verify-sign-method`参数设置为false 或删除该字段</font>
|
||||||
### 调用示例
|
### 调用示例
|
||||||
|
|
||||||
#### 开启支付
|
#### 开启支付
|
||||||
@@ -348,10 +374,5 @@ public class CallbackController {
|
|||||||
## 仓库地址
|
## 仓库地址
|
||||||
|
|
||||||
- [GitHub](https://github.com/dromara/payment-spring-boot)
|
- [GitHub](https://github.com/dromara/payment-spring-boot)
|
||||||
- [Gitee](https://gitee.com/felord/payment-spring-boot)
|
- [Gitee](https://gitee.com/dromara/payment-spring-boot)
|
||||||
|
|
||||||
## QQ交流群
|
|
||||||
|
|
||||||
为了交流解惑,新建QQ群,可通过扫码进入。
|
|
||||||
|
|
||||||

|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.felord</groupId>
|
<groupId>cn.felord</groupId>
|
||||||
<artifactId>payment-spring-boot-starter</artifactId>
|
<artifactId>payment-spring-boot-starter</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
## 采用技术
|
## 采用技术
|
||||||
@@ -51,4 +51,4 @@
|
|||||||
|
|
||||||
## **免责声明**
|
## **免责声明**
|
||||||
|
|
||||||
**<span style="color:red;">本项目涉及到资金交易开发,开发者需要经严格测试后方能用于生产环境,本项目不对使用者的行为负责。</span>**
|
**<span style="color:red;">本项目涉及到资金交易开发,开发者需要经严格测试后方能用于生产环境,本项目不对使用者的行为负责。</span>**
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
## 1.0.21.RELEASE
|
||||||
|
### 微信支付
|
||||||
|
|
||||||
|
- enhance: 增加了通过微信公钥对微信支付相关接口的响应内容或微信回调通知的参数进行验签的支持。
|
||||||
|
- 微信配置项增加了:```enable-wechat-pay-public: 是否启用微信支付公钥验签、 wechat-pay-public-key-id: 微信支付公钥的ID、 wechat-pay-public-key-path:微信支付公钥的路径、wechat-pay-public-key-absolute-path: 微信支付公钥的绝对路径、 switch-verify-sign-method: 是否启用从平台证书切换到微信支公钥```
|
||||||
|
- `enable-wechat-pay-public` 与 `wechat-pay-public-key-id ` 、`wechat-pay-public-key-path或wechat-pay-public-key-absolute-path`<font color=red>同时正确配置</font>,才会启用微信支付公钥验签,否则默认使用平台证书进行验签。
|
||||||
|
-
|
||||||
|
- 如果需要[从平台证书切换成微信支付公钥](https://pay.weixin.qq.com/doc/v3/merchant/4012154180#5.-%E6%B2%A1%E6%9C%89%E4%BD%BF%E7%94%A8%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98SDK%E7%9A%84%E5%95%86%E6%88%B7%E5%A6%82%E4%BD%95%E5%B0%86%E5%B9%B3%E5%8F%B0%E8%AF%81%E4%B9%A6%E5%88%87%E6%8D%A2%E6%88%90%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%85%AC%E9%92%A5),请启用`switch-verify-sign-method`参数
|
||||||
|
- enhance: 增加了微信支付V3版本的付款码支付``codePay``与撤销API``reverse``(仅支持普通商户模式,服务商模式暂不支持)
|
||||||
|
- factor: 升级了spring-boot-parent版本从 2.7.7 到2.7.18
|
||||||
|
- factor: 升级了Alipay SDK版本从4.31.7.ALL到4.40.251.ALL
|
||||||
|
## 1.0.18.RELEASE
|
||||||
|
### 微信支付
|
||||||
|
|
||||||
|
- enhance: 使用`ResourceLoader`加载资源以改善Docker容器环境下的文件挂载问题
|
||||||
|
- enhance: 修改了微信支付配置加载机制,现在可以借助于`WechatTenantService`实现不停机维护微信支付参数的能力
|
||||||
|
- factor: 移除过时的V2退款API相关参数`RefundModel`和`RefundQueryModel`
|
||||||
|
- docs: 更新文档地址到[dromara.org](https://gitee.com/dromara),现在你可以通过[https://dromara.org/payment-spring-boot/](https://dromara.org/payment-spring-boot/)访问项目文档
|
||||||
|
- docs: 修正文档描述错误
|
||||||
|
|
||||||
## 1.0.17.RELEASE
|
## 1.0.17.RELEASE
|
||||||
### 微信支付
|
### 微信支付
|
||||||
- feat: 直连商户合单支付增加查询单笔退款
|
- feat: 直连商户合单支付增加查询单笔退款
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.felord</groupId>
|
<groupId>cn.felord</groupId>
|
||||||
<artifactId>payment-spring-boot-starter</artifactId>
|
<artifactId>payment-spring-boot-starter</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
> 基于 **Spring Boot 2.x**
|
> 基于 **Spring Boot 2.x**
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
```xml
|
```xml
|
||||||
<properties>
|
<properties>
|
||||||
<!-- 修改为你对应的Spring Boot版本号 -->
|
<!-- 修改为你对应的Spring Boot版本号 -->
|
||||||
<spring-boot.version>2.4.0</spring-boot.version>
|
<spring-boot.version>2.7.18</spring-boot.version>
|
||||||
</properties>
|
</properties>
|
||||||
```
|
```
|
||||||
然后安装使用
|
然后安装使用
|
||||||
@@ -86,6 +86,15 @@ wechat:
|
|||||||
mch-id: 1603337223
|
mch-id: 1603337223
|
||||||
domain: https://felord.cn/miniapp
|
domain: https://felord.cn/miniapp
|
||||||
cert-path: miniapp/apiclient_cert.p12
|
cert-path: miniapp/apiclient_cert.p12
|
||||||
|
# 是否启用微信支付公钥
|
||||||
|
enable-wechat-pay-public: true
|
||||||
|
#微信公钥ID
|
||||||
|
wechat-pay-public-key-id: PUB_KEY_ID_0116278111111115222222501
|
||||||
|
#微信公钥
|
||||||
|
wechat-pay-public-key-path: pub_key.pem
|
||||||
|
wechat-pay-public-key-absolute-path: D:\\felord\\wechat\\cert\\pub_key.pem
|
||||||
|
#是否启用从平台证书切换成微信支付公钥 不填默认为false,
|
||||||
|
switch-verify-sign-method: true
|
||||||
```
|
```
|
||||||
|
|
||||||
> ❗注意:在一套系统中需要开发者保证`tentanID`唯一。
|
> ❗注意:在一套系统中需要开发者保证`tentanID`唯一。
|
||||||
@@ -174,4 +183,4 @@ public class PayConfig {
|
|||||||
|
|
||||||
System.out.println("execute = " + execute.getBody());
|
System.out.println("execute = " + execute.getBody());
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
## 入口类
|
## 入口类
|
||||||
|
|
||||||
`WechatApiProvider`是本项目微信支付的入口类,已被注入**Spring IoC**,由它来初始化微信支付相关的**API**,具体分为**直连商户**和**服务商**两个体系。
|
`WechatApiProvider`是本项目微信支付的入口类,已被注入**Spring IoC**,由它来初始化微信支付相关的**API**,具体分为**直连商户
|
||||||
|
**和**服务商**两个体系。
|
||||||
|
|
||||||
> 以下清单请搭配微信支付文档使用。
|
> 以下清单请搭配微信支付文档使用。
|
||||||
|
|
||||||
@@ -152,7 +153,15 @@
|
|||||||
|
|
||||||
##### 支付有礼
|
##### 支付有礼
|
||||||
|
|
||||||
- [ ] 功能实现中……
|
- [x] `WechatMarketingPayGiftActivityApi` 支付有礼,通过`WechatApiProvider#marketingPayGiftActivityApi`初始化
|
||||||
|
- [x] `create` 创建全场满额送活动
|
||||||
|
- [x] `details` 查询活动详情接口
|
||||||
|
- [x] `merchants` 查询活动发券商户号
|
||||||
|
- [x] `goods` 查询活动指定商品列表
|
||||||
|
- [x] `terminate` 终止活动
|
||||||
|
- [x] `addMches` 新增活动发券商户号
|
||||||
|
- [x] `page` 获取支付有礼活动列表
|
||||||
|
- [x] `deleteMch` 删除活动发券商户号
|
||||||
|
|
||||||
##### 图片上传(营销专用)
|
##### 图片上传(营销专用)
|
||||||
|
|
||||||
@@ -221,5 +230,7 @@
|
|||||||
- [x] `marketingImageUpload` 营销图片上传
|
- [x] `marketingImageUpload` 营销图片上传
|
||||||
|
|
||||||
> 通过营销**图片上传API**上传图片后可获得图片url地址。图片url可在微信支付营销相关的API使用,包括商家券、代金券、支付有礼等。
|
> 通过营销**图片上传API**上传图片后可获得图片url地址。图片url可在微信支付营销相关的API使用,包括商家券、代金券、支付有礼等。
|
||||||
|
|
||||||
### 服务商
|
### 服务商
|
||||||
|
|
||||||
施工中……
|
施工中……
|
||||||
@@ -22,11 +22,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.felord</groupId>
|
<groupId>cn.felord</groupId>
|
||||||
<artifactId>payment-spring-boot</artifactId>
|
<artifactId>payment-spring-boot</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>payment-spring-boot-autoconfigure</artifactId>
|
<artifactId>payment-spring-boot-autoconfigure</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -92,4 +92,4 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -17,14 +17,24 @@
|
|||||||
|
|
||||||
package cn.felord.payment.wechat;
|
package cn.felord.payment.wechat;
|
||||||
|
|
||||||
import cn.felord.payment.wechat.v3.KeyPairFactory;
|
import cn.felord.payment.PayException;
|
||||||
import cn.felord.payment.wechat.v3.WechatMetaBean;
|
import cn.felord.payment.wechat.v3.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.bouncycastle.util.io.pem.PemObject;
|
||||||
|
import org.bouncycastle.util.io.pem.PemReader;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -32,34 +42,65 @@ import java.util.stream.Collectors;
|
|||||||
/**
|
/**
|
||||||
* 从配置文件中加载租户信息,默认实现,可被覆盖
|
* 从配置文件中加载租户信息,默认实现,可被覆盖
|
||||||
*
|
*
|
||||||
* @author xiafang
|
* @author dax
|
||||||
* @since 2023/2/3 11:40
|
* @since 2023/2/3 11:40
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class InMemoryWechatTenantService implements WechatTenantService {
|
public class InMemoryWechatTenantService implements WechatTenantService {
|
||||||
private final WechatPayProperties wechatPayProperties;
|
private final WechatPayProperties wechatPayProperties;
|
||||||
private final ResourceLoader resourceLoader;
|
private final ResourceLoader resourceLoader;
|
||||||
|
private final Set<WechatMetaBean> cache = new HashSet<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<WechatMetaBean> loadTenants() {
|
public Set<WechatMetaBean> loadTenants() {
|
||||||
Map<String, WechatPayProperties.V3> v3Map = wechatPayProperties.getV3();
|
if (CollectionUtils.isEmpty(cache)) {
|
||||||
KeyPairFactory keyPairFactory = new KeyPairFactory();
|
Map<String, WechatPayProperties.V3> v3Map = wechatPayProperties.getV3();
|
||||||
return v3Map.entrySet()
|
KeyPairFactory keyPairFactory = new KeyPairFactory();
|
||||||
.stream()
|
Set<WechatMetaBean> beans = v3Map.entrySet()
|
||||||
.map(entry -> {
|
.stream()
|
||||||
WechatPayProperties.V3 v3 = entry.getValue();
|
.map(entry -> {
|
||||||
String tenantId = entry.getKey();
|
WechatPayProperties.V3 v3 = entry.getValue();
|
||||||
String certPath = v3.getCertPath();
|
String tenantId = entry.getKey();
|
||||||
String certAbsolutePath = v3.getCertAbsolutePath();
|
String certPath = v3.getCertPath();
|
||||||
String mchId = v3.getMchId();
|
String certAbsolutePath = v3.getCertAbsolutePath();
|
||||||
Resource resource = certAbsolutePath != null ? new FileSystemResource(certAbsolutePath) :
|
String mchId = v3.getMchId();
|
||||||
resourceLoader.getResource(certPath == null ? "classpath:wechat/apiclient_cert.p12" :
|
Resource resource = certAbsolutePath != null ? new FileSystemResource(certAbsolutePath) :
|
||||||
certPath.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) ? certPath : ResourceUtils.CLASSPATH_URL_PREFIX + certPath);
|
resourceLoader.getResource(certPath == null ? "classpath:wechat/apiclient_cert.p12" :
|
||||||
WechatMetaBean wechatMetaBean = keyPairFactory.initWechatMetaBean(resource, mchId);
|
certPath.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) ? certPath : ResourceUtils.CLASSPATH_URL_PREFIX + certPath);
|
||||||
wechatMetaBean.setV3(v3);
|
WechatMetaBean wechatMetaBean = keyPairFactory.initWechatMetaBean(resource, mchId);
|
||||||
wechatMetaBean.setTenantId(tenantId);
|
wechatMetaBean.setV3(v3);
|
||||||
return wechatMetaBean;
|
wechatMetaBean.setTenantId(tenantId);
|
||||||
})
|
SignatureProvider.addWeChatPublicKey(initWeChatPublicKeyInfo(wechatMetaBean));
|
||||||
.collect(Collectors.toSet());
|
return wechatMetaBean;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
cache.addAll(beans);
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WeChatPublicKeyInfo initWeChatPublicKeyInfo(WechatMetaBean meta) {
|
||||||
|
boolean enablePublicKey=StringUtils.hasLength(meta.getV3().getWechatPayPublicKeyId()) &&
|
||||||
|
(StringUtils.hasLength(meta.getV3().getWechatPayPublicKeyPath())||StringUtils.hasLength(meta.getV3().getWechatPayPublicKeyAbsolutePath()));
|
||||||
|
if (!enablePublicKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String certPath=meta.getV3().getWechatPayPublicKeyPath();
|
||||||
|
String certAbsolutePath = meta.getV3().getWechatPayPublicKeyAbsolutePath();
|
||||||
|
Resource resource =
|
||||||
|
StringUtils.hasLength(certAbsolutePath) ? new FileSystemResource(certAbsolutePath) :
|
||||||
|
resourceLoader.getResource(!StringUtils.hasLength(certPath) ? "classpath:wechat/pub_key.pem" :
|
||||||
|
certPath.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) ? certPath : ResourceUtils.CLASSPATH_URL_PREFIX + certPath);
|
||||||
|
PemReader pemReader = new PemReader(new InputStreamReader(resource.getInputStream()));
|
||||||
|
PemObject pemObject = pemReader.readPemObject();
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pemObject.getContent());
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
|
||||||
|
// 生成公钥
|
||||||
|
return new WeChatPublicKeyInfo(publicKey, meta.getV3().getWechatPayPublicKeyId(), meta.getTenantId());
|
||||||
|
}catch (Exception e){
|
||||||
|
throw new PayException("An error occurred while generating the public key,Please check the format and content of the configured public key");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,5 +76,31 @@ public class WechatPayProperties {
|
|||||||
* your pay server domain
|
* your pay server domain
|
||||||
*/
|
*/
|
||||||
private String domain;
|
private String domain;
|
||||||
|
|
||||||
|
|
||||||
|
private Boolean enableWechatPayPublic=false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wechat pay public key id
|
||||||
|
*/
|
||||||
|
private String wechatPayPublicKeyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012154180#4.1-%E8%8E%B7%E5%8F%96%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%85%AC%E9%92%A5">
|
||||||
|
* </a>
|
||||||
|
* wechat pay public key
|
||||||
|
*/
|
||||||
|
private String wechatPayPublicKeyPath;
|
||||||
|
|
||||||
|
private String wechatPayPublicKeyAbsolutePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* see <a href="https://pay.weixin.qq.com/doc/v3/merchant/4012154180">
|
||||||
|
* Indicate whether to switch from the platform certificate to the WeChat Pay public key
|
||||||
|
* </a>
|
||||||
|
*/
|
||||||
|
private Boolean switchVerifySignMethod = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum Activity status.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public enum ActivityStatus {
|
||||||
|
/**
|
||||||
|
* 状态未知
|
||||||
|
*/
|
||||||
|
ACT_STATUS_UNKNOWN,
|
||||||
|
/**
|
||||||
|
* 已创建
|
||||||
|
*/
|
||||||
|
CREATE_ACT_STATUS,
|
||||||
|
/**
|
||||||
|
* 运行中
|
||||||
|
*/
|
||||||
|
ONGOING_ACT_STATUS,
|
||||||
|
/**
|
||||||
|
* 已终止
|
||||||
|
*/
|
||||||
|
TERMINATE_ACT_STATUS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已暂停
|
||||||
|
*/
|
||||||
|
STOP_ACT_STATUS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已过期
|
||||||
|
*/
|
||||||
|
OVER_TIME_ACT_STATUS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建活动失败
|
||||||
|
*/
|
||||||
|
CREATE_ACT_FAILED
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum Award type.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public enum AwardType {
|
||||||
|
/**
|
||||||
|
* 商家券
|
||||||
|
*/
|
||||||
|
BUSIFAVOR
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum Business cert type.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 2023 /7/1 8:34
|
||||||
|
*/
|
||||||
|
public enum BusinessCertType {
|
||||||
|
/**
|
||||||
|
* 事业单位法人证书
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2388,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一社会信用代码证书
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2389,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 社会团体法人登记证书
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2394,
|
||||||
|
/**
|
||||||
|
* 民办非企业单位登记证书
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2395,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基金会法人登记证书
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2396,
|
||||||
|
/**
|
||||||
|
* 宗教活动场所登记证
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2399,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 政府部门下发的其他有效证明文件
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2400,
|
||||||
|
/**
|
||||||
|
* 执业许可证/执业证
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2520,
|
||||||
|
/**
|
||||||
|
* 基层群众性自治组织特别法人统一社会信用代码证
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2521,
|
||||||
|
/**
|
||||||
|
* 农村集体经济组织登记证
|
||||||
|
*/
|
||||||
|
CERTIFICATE_TYPE_2522
|
||||||
|
}
|
||||||
@@ -28,41 +28,57 @@ public enum CouponBgColor {
|
|||||||
/**
|
/**
|
||||||
* Color 010 coupon bg color.
|
* Color 010 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR010,
|
COLOR010("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 020 coupon bg color.
|
* COLOR 020 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR020,
|
COLOR020("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 030 coupon bg color.
|
* COLOR 030 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR030,
|
COLOR030("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 040 coupon bg color.
|
* COLOR 040 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR040,
|
COLOR040("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 050 coupon bg color.
|
* COLOR 050 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR050,
|
COLOR050("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 060 coupon bg color.
|
* COLOR 060 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR060,
|
COLOR060("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 070 coupon bg color.
|
* COLOR 070 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR070,
|
COLOR070("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 080 coupon bg color.
|
* COLOR 080 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR080,
|
COLOR080("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 090 coupon bg color.
|
* COLOR 090 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR090,
|
COLOR090("Color010"),
|
||||||
/**
|
/**
|
||||||
* COLOR 100 coupon bg color.
|
* COLOR 100 coupon bg color.
|
||||||
*/
|
*/
|
||||||
COLOR100
|
COLOR100("Color010");
|
||||||
|
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
CouponBgColor(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets value.
|
||||||
|
*
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum Delivery purpose.
|
||||||
|
*
|
||||||
|
* @author felord.cn
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public enum DeliveryPurpose {
|
||||||
|
/**
|
||||||
|
* 拉用户回店消费
|
||||||
|
*/
|
||||||
|
OFF_LINE_PAY,
|
||||||
|
/**
|
||||||
|
* 引导用户前往小程序消费
|
||||||
|
*/
|
||||||
|
JUMP_MINI_APP
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public enum DeliveryUserCategory {
|
||||||
|
/**
|
||||||
|
* 所有用户
|
||||||
|
*/
|
||||||
|
DELIVERY_ALL_PERSON,
|
||||||
|
/**
|
||||||
|
* 会员用户
|
||||||
|
*/
|
||||||
|
DELIVERY_MEMBER_PERSON
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum Send content.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public enum SendContent {
|
||||||
|
/**
|
||||||
|
* 单张券
|
||||||
|
*/
|
||||||
|
SINGLE_COUPON,
|
||||||
|
/**
|
||||||
|
* 礼包
|
||||||
|
*/
|
||||||
|
GIFT_PACKAGE
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ package cn.felord.payment.wechat.enumeration;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiafang
|
* @author dax
|
||||||
* @since 2023/2/1 8:59
|
* @since 2023/2/1 8:59
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ public enum WechatPayV3Type {
|
|||||||
MERCHANT_MEDIA_VIDEO(HttpMethod.POST, "%s/v3/merchant/media/video_upload"),
|
MERCHANT_MEDIA_VIDEO(HttpMethod.POST, "%s/v3/merchant/media/video_upload"),
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 付款码支付
|
||||||
|
*
|
||||||
|
* @since 1.0.0.RELEASE
|
||||||
|
*/
|
||||||
|
CODE(HttpMethod.POST, "%s/v3/pay/transactions/codepay"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信公众号支付或者小程序支付.
|
* 微信公众号支付或者小程序支付.
|
||||||
*
|
*
|
||||||
@@ -99,6 +106,13 @@ public enum WechatPayV3Type {
|
|||||||
* @since 1.0.0.RELEASE
|
* @since 1.0.0.RELEASE
|
||||||
*/
|
*/
|
||||||
CLOSE(HttpMethod.POST, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}/close"),
|
CLOSE(HttpMethod.POST, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}/close"),
|
||||||
|
/**
|
||||||
|
* 关闭订单.
|
||||||
|
*
|
||||||
|
* @since 1.0.0.RELEASE
|
||||||
|
*/
|
||||||
|
REVERSE(HttpMethod.POST, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}/reverse"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付订单号查询API.
|
* 微信支付订单号查询API.
|
||||||
*
|
*
|
||||||
@@ -507,6 +521,55 @@ public enum WechatPayV3Type {
|
|||||||
*/
|
*/
|
||||||
MARKETING_PARTNERSHIPS_GET(HttpMethod.GET, "%s/v3/marketing/partnerships"),
|
MARKETING_PARTNERSHIPS_GET(HttpMethod.GET, "%s/v3/marketing/partnerships"),
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
/**
|
||||||
|
* 创建全场满额送活动API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY(HttpMethod.POST, "%s/v3/marketing/paygiftactivity/unique-threshold-activity"),
|
||||||
|
/**
|
||||||
|
* 查询活动详情接口API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_DETAIL(HttpMethod.GET, "%s/v3/marketing/paygiftactivity/activities/{activity_id}"),
|
||||||
|
/**
|
||||||
|
* 查询活动发券商户号API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_MCH(HttpMethod.GET, "%s/v3/marketing/paygiftactivity/activities/{activity_id}/merchants"),
|
||||||
|
/**
|
||||||
|
* 查询活动指定商品列表API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_GOODS(HttpMethod.GET, "%s/v3/marketing/paygiftactivity/activities/{activity_id}/goods"),
|
||||||
|
/**
|
||||||
|
* 终止活动API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_TERMINATE(HttpMethod.POST, "%s/v3/marketing/paygiftactivity/activities/{activity_id}/terminate"),
|
||||||
|
/**
|
||||||
|
* 新增活动发券商户号API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_MCH_ADD(HttpMethod.POST, "%s/v3/marketing/paygiftactivity/activities/{activity_id}/merchants/add"),
|
||||||
|
/**
|
||||||
|
* 获取支付有礼活动列表API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_ACTIVITIES(HttpMethod.GET, "%s/v3/marketing/paygiftactivity/activities"),
|
||||||
|
/**
|
||||||
|
* 删除活动发券商户号API
|
||||||
|
*
|
||||||
|
* @since 1.0.19.RELEASES
|
||||||
|
*/
|
||||||
|
MARKETING_PAYGIFTACTIVITY_MCH_DEL(HttpMethod.POST, "%s/v3/marketing/paygiftactivity/activities/{activity_id}/merchants/delete"),
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
/**
|
/**
|
||||||
* 发起批量转账API.
|
* 发起批量转账API.
|
||||||
@@ -584,6 +647,7 @@ public enum WechatPayV3Type {
|
|||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务商APP下单API.
|
* 服务商APP下单API.
|
||||||
*
|
*
|
||||||
@@ -655,7 +719,7 @@ public enum WechatPayV3Type {
|
|||||||
*
|
*
|
||||||
* @since 1.0.11.RELEASE
|
* @since 1.0.11.RELEASE
|
||||||
*/
|
*/
|
||||||
PROFITSHARING_RETURN_ORDERS_RESULT(HttpMethod.GET, "%s/v3/profitsharing/return-orders"),
|
PROFITSHARING_RETURN_ORDERS_RESULT(HttpMethod.GET, "%s/v3/profitsharing/return-orders/{out_return_no}"),
|
||||||
/**
|
/**
|
||||||
* 解冻剩余资金API.
|
* 解冻剩余资金API.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.ContentDisposition;
|
import org.springframework.http.ContentDisposition;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
@@ -44,6 +47,8 @@ import org.springframework.web.util.UriComponentsBuilder;
|
|||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -92,12 +97,16 @@ public abstract class AbstractApi {
|
|||||||
* @param mapper the mapper
|
* @param mapper the mapper
|
||||||
*/
|
*/
|
||||||
private void applyObjectMapper(ObjectMapper mapper) {
|
private void applyObjectMapper(ObjectMapper mapper) {
|
||||||
|
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
|
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
|
||||||
|
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||||
|
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
|
||||||
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
|
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
// empty string error
|
// empty string error
|
||||||
.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
|
.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
|
||||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
.registerModule(new JavaTimeModule());
|
.registerModule(javaTimeModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,17 +27,15 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.bouncycastle.util.io.pem.PemObject;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.bouncycastle.util.io.pem.PemReader;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.http.RequestEntity;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.http.*;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
||||||
import org.springframework.util.AlternativeJdkIdGenerator;
|
import org.springframework.util.*;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.Base64Utils;
|
|
||||||
import org.springframework.util.IdGenerator;
|
|
||||||
import org.springframework.web.client.RestOperations;
|
import org.springframework.web.client.RestOperations;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
import org.springframework.web.util.UriComponents;
|
import org.springframework.web.util.UriComponents;
|
||||||
@@ -48,14 +46,17 @@ import javax.crypto.NoSuchPaddingException;
|
|||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.LocalDateTime;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.time.ZoneOffset;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -90,6 +91,11 @@ public class SignatureProvider {
|
|||||||
* 微信平台证书容器 key = 序列号 value = 证书对象
|
* 微信平台证书容器 key = 序列号 value = 证书对象
|
||||||
*/
|
*/
|
||||||
private static final Set<X509WechatCertificateInfo> CERTIFICATE_SET = Collections.synchronizedSet(new HashSet<>());
|
private static final Set<X509WechatCertificateInfo> CERTIFICATE_SET = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
|
private static final Set<WeChatPublicKeyInfo> PUBLIC_KEY_SET = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
|
private static final String PUBLIC_KYE_ID_PREFIX = "PUB_KEY_ID";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密算法提供方 - BouncyCastle
|
* 加密算法提供方 - BouncyCastle
|
||||||
*/
|
*/
|
||||||
@@ -122,6 +128,10 @@ public class SignatureProvider {
|
|||||||
wechatMetaContainer.getTenantIds().forEach(this::refreshCertificate);
|
wechatMetaContainer.getTenantIds().forEach(this::refreshCertificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addWeChatPublicKey(WeChatPublicKeyInfo weChatPublicKeyInfo) {
|
||||||
|
PUBLIC_KEY_SET.add(weChatPublicKeyInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 我方请求前用 SHA256withRSA 加签,使用API证书.
|
* 我方请求前用 SHA256withRSA 加签,使用API证书.
|
||||||
@@ -135,7 +145,7 @@ public class SignatureProvider {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String requestSign(String tenantId, String method, String canonicalUrl, String body) {
|
public String requestSign(String tenantId, String method, String canonicalUrl, String body) {
|
||||||
|
|
||||||
long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
|
long timestamp = Instant.now().getEpochSecond();
|
||||||
String nonceStr = nonceStrGenerator.generateId()
|
String nonceStr = nonceStrGenerator.generateId()
|
||||||
.toString()
|
.toString()
|
||||||
.replaceAll("-", "");
|
.replaceAll("-", "");
|
||||||
@@ -175,9 +185,20 @@ public class SignatureProvider {
|
|||||||
* @param params the params
|
* @param params the params
|
||||||
* @return the boolean
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
|
||||||
public boolean responseSignVerify(ResponseSignVerifyParams params) {
|
public boolean responseSignVerify(ResponseSignVerifyParams params) {
|
||||||
|
log.debug("wechatpaySerial: {}", params.getWechatpaySerial());
|
||||||
|
boolean verifyResult= params.getWechatpaySerial().startsWith(PUBLIC_KYE_ID_PREFIX)?
|
||||||
|
responseSignVerifyWithWeChatPublicKeyInfo(params):
|
||||||
|
responseSignVerifyWithX509WechatCertificate(params);
|
||||||
|
log.debug("responseSignVerify: {}", verifyResult);
|
||||||
|
return verifyResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
*通过平台证书进行验签
|
||||||
|
*/
|
||||||
|
private boolean responseSignVerifyWithX509WechatCertificate(ResponseSignVerifyParams params){
|
||||||
|
log.debug("responseSignVerifyWithX509WechatCertificate: {}", params);
|
||||||
String wechatpaySerial = params.getWechatpaySerial();
|
String wechatpaySerial = params.getWechatpaySerial();
|
||||||
X509WechatCertificateInfo certificate = CERTIFICATE_SET.stream()
|
X509WechatCertificateInfo certificate = CERTIFICATE_SET.stream()
|
||||||
.filter(cert -> Objects.equals(wechatpaySerial, cert.getWechatPaySerial()))
|
.filter(cert -> Objects.equals(wechatpaySerial, cert.getWechatPaySerial()))
|
||||||
@@ -190,15 +211,41 @@ public class SignatureProvider {
|
|||||||
.orElseThrow(() -> new PayException("cannot obtain the certificate"));
|
.orElseThrow(() -> new PayException("cannot obtain the certificate"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody());
|
final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody());
|
||||||
Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER);
|
Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER);
|
||||||
signer.initVerify(certificate.getX509Certificate());
|
signer.initVerify(certificate.getX509Certificate());
|
||||||
signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
|
signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return signer.verify(Base64Utils.decodeFromString(params.getWechatpaySignature()));
|
||||||
return signer.verify(Base64Utils.decodeFromString(params.getWechatpaySignature()));
|
} catch (Exception e) {
|
||||||
|
throw new PayException("An exception occurred during the response verification, the cause: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
*通过微信支付公钥进行验签
|
||||||
|
*/
|
||||||
|
private boolean responseSignVerifyWithWeChatPublicKeyInfo(ResponseSignVerifyParams params){
|
||||||
|
log.debug("responseSignVerifyWithWeChatPublicKeyInfo: {}", params);
|
||||||
|
String wechatpaySerial = params.getWechatpaySerial();
|
||||||
|
if (wechatpaySerial.startsWith(PUBLIC_KYE_ID_PREFIX)){
|
||||||
|
WeChatPublicKeyInfo info = PUBLIC_KEY_SET.stream()
|
||||||
|
.filter(key -> Objects.equals(wechatpaySerial, key.getPublicKeyId()))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow(() -> new PayException("cannot obtain the public key"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody());
|
||||||
|
Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER);
|
||||||
|
signer.initVerify(info.getPublicKey());
|
||||||
|
signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return signer.verify(Base64Utils.decodeFromString(params.getWechatpaySignature()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PayException("An exception occurred during the response verification, the cause: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当我方服务器不存在平台证书或者证书同当前响应报文中的证书序列号不一致时应当刷新 调用/v3/certificates
|
* 当我方服务器不存在平台证书或者证书同当前响应报文中的证书序列号不一致时应当刷新 调用/v3/certificates
|
||||||
@@ -207,8 +254,12 @@ public class SignatureProvider {
|
|||||||
*/
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private synchronized void refreshCertificate(String tenantId) {
|
private synchronized void refreshCertificate(String tenantId) {
|
||||||
String url = WechatPayV3Type.CERT.uri(WeChatServer.CHINA);
|
|
||||||
|
|
||||||
|
WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId);
|
||||||
|
if (wechatMetaBean.getV3().getEnableWechatPayPublic() && !wechatMetaBean.getV3().getSwitchVerifySignMethod()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String url = WechatPayV3Type.CERT.uri(WeChatServer.CHINA);
|
||||||
UriComponents uri = UriComponentsBuilder.fromHttpUrl(url).build();
|
UriComponents uri = UriComponentsBuilder.fromHttpUrl(url).build();
|
||||||
|
|
||||||
String canonicalUrl = uri.getPath();
|
String canonicalUrl = uri.getPath();
|
||||||
@@ -234,12 +285,9 @@ public class SignatureProvider {
|
|||||||
throw new PayException("cant obtain the response body");
|
throw new PayException("cant obtain the response body");
|
||||||
}
|
}
|
||||||
ArrayNode certificates = bodyObjectNode.withArray("data");
|
ArrayNode certificates = bodyObjectNode.withArray("data");
|
||||||
if (certificates.isArray() && certificates.size() > 0) {
|
if (certificates.isArray() && !certificates.isEmpty()) {
|
||||||
CERTIFICATE_SET.forEach(x509WechatCertificateInfo -> {
|
CERTIFICATE_SET.removeIf(x509WechatCertificateInfo ->
|
||||||
if (Objects.equals(tenantId, x509WechatCertificateInfo.getTenantId())) {
|
Objects.equals(tenantId, x509WechatCertificateInfo.getTenantId()));
|
||||||
CERTIFICATE_SET.remove(x509WechatCertificateInfo);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", BC_PROVIDER);
|
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", BC_PROVIDER);
|
||||||
certificates.forEach(objectNode -> {
|
certificates.forEach(objectNode -> {
|
||||||
JsonNode encryptCertificate = objectNode.get("encrypt_certificate");
|
JsonNode encryptCertificate = objectNode.get("encrypt_certificate");
|
||||||
@@ -306,18 +354,42 @@ public class SignatureProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String encryptRequestMessage(String message, WechatMetaBean wechatMetaBean) {
|
||||||
|
PublicKey publicKey;
|
||||||
|
if (wechatMetaBean.getEnableWechatPayPublicEncrypt()){
|
||||||
|
WeChatPublicKeyInfo info=this.getWechatPublicKeyInfo(wechatMetaBean.getTenantId());
|
||||||
|
publicKey=info.getPublicKey();
|
||||||
|
}else {
|
||||||
|
X509WechatCertificateInfo certificate = getCertificate(wechatMetaBean.getTenantId());
|
||||||
|
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
||||||
|
publicKey=x509Certificate.getPublicKey();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", BC_PROVIDER);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
byte[] data = message.getBytes(StandardCharsets.UTF_8);
|
||||||
|
byte[] cipherData = cipher.doFinal(data);
|
||||||
|
return Base64Utils.encodeToString(cipherData);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PayException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对请求敏感字段进行加密
|
* 对请求敏感字段进行加密
|
||||||
*
|
* 只有使用平台证书进行验签与签名的商户使用该方法
|
||||||
* @param message the message
|
* @param message the message
|
||||||
* @param certificate the certificate
|
* @param publicKey the wechatPubicKey certificate
|
||||||
* @return encrypt message
|
* @return encrypt message
|
||||||
* @since 1.0.6.RELEASE
|
* @since 1.0.6.RELEASE
|
||||||
*/
|
*/
|
||||||
public String encryptRequestMessage(String message, Certificate certificate) {
|
@Deprecated
|
||||||
|
public String encryptRequestMessage(String message, RSAPublicKey publicKey) {
|
||||||
try {
|
try {
|
||||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", BC_PROVIDER);
|
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", BC_PROVIDER);
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
|
||||||
byte[] data = message.getBytes(StandardCharsets.UTF_8);
|
byte[] data = message.getBytes(StandardCharsets.UTF_8);
|
||||||
byte[] cipherData = cipher.doFinal(data);
|
byte[] cipherData = cipher.doFinal(data);
|
||||||
@@ -357,7 +429,7 @@ public class SignatureProvider {
|
|||||||
* @param tenantId the tenant id
|
* @param tenantId the tenant id
|
||||||
* @return the x 509 wechat certificate info
|
* @return the x 509 wechat certificate info
|
||||||
*/
|
*/
|
||||||
public X509WechatCertificateInfo getCertificate(String tenantId) {
|
private X509WechatCertificateInfo getCertificate(String tenantId) {
|
||||||
|
|
||||||
return CERTIFICATE_SET.stream()
|
return CERTIFICATE_SET.stream()
|
||||||
.filter(cert -> Objects.equals(tenantId, cert.getTenantId()))
|
.filter(cert -> Objects.equals(tenantId, cert.getTenantId()))
|
||||||
@@ -371,6 +443,15 @@ public class SignatureProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WeChatPublicKeyInfo getWechatPublicKeyInfo(String tenantId) {
|
||||||
|
return PUBLIC_KEY_SET.stream()
|
||||||
|
.filter(publicKeyInfo -> Objects.equals(tenantId, publicKeyInfo.getTenantId()))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new PayException("cannot obtain the public key")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wechat meta container.
|
* Wechat meta container.
|
||||||
@@ -402,4 +483,21 @@ public class SignatureProvider {
|
|||||||
.collect(Collectors.joining("\n", "", "\n"));
|
.collect(Collectors.joining("\n", "", "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSwitchVerifySignMethod(String tenantId) {
|
||||||
|
|
||||||
|
return wechatMetaContainer.getWechatMeta(tenantId).getV3().getSwitchVerifySignMethod()
|
||||||
|
&& wechatMetaContainer.getWechatMeta(tenantId).getV3().getEnableWechatPayPublic();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWechatPublicKeyId(String tenantId) {
|
||||||
|
return wechatMetaContainer.getWechatMeta(tenantId).getV3().getWechatPayPublicKeyId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWechatPaySerial(WechatMetaBean wechatMetaBean) {
|
||||||
|
if (wechatMetaBean.getEnableWechatPayPublicEncrypt()){
|
||||||
|
return this.getWechatPublicKeyInfo(wechatMetaBean.getTenantId()).getPublicKeyId();
|
||||||
|
}else {
|
||||||
|
return this.getCertificate(wechatMetaBean.getTenantId()).getWechatPaySerial();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package cn.felord.payment.wechat.v3;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WeChatPublicKeyInfo {
|
||||||
|
|
||||||
|
private RSAPublicKey publicKey;
|
||||||
|
|
||||||
|
private String publicKeyId;
|
||||||
|
|
||||||
|
private String tenantId;
|
||||||
|
|
||||||
|
public WeChatPublicKeyInfo(RSAPublicKey publicKey, String publicKeyId, String tenantId) {
|
||||||
|
this.publicKeyId = publicKeyId;
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeChatPublicKeyInfo() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -140,6 +140,17 @@ public class WechatApiProvider {
|
|||||||
return new WechatMarketingPartnershipApi(this.wechatPayClient, tenantId);
|
return new WechatMarketingPartnershipApi(this.wechatPayClient, tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付有礼-直连商户
|
||||||
|
*
|
||||||
|
* @param tenantId the tenant id
|
||||||
|
* @return the wechat marketing pay gift activity api
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public WechatMarketingPayGiftActivityApi marketingPayGiftActivityApi(String tenantId) {
|
||||||
|
return new WechatMarketingPayGiftActivityApi(this.wechatPayClient, tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量转账到零钱.
|
* 批量转账到零钱.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -77,18 +77,16 @@ public class WechatBatchTransferApi extends AbstractApi {
|
|||||||
List<CreateBatchTransferParams.TransferDetailListItem> transferDetailList = createBatchTransferParams.getTransferDetailList();
|
List<CreateBatchTransferParams.TransferDetailListItem> transferDetailList = createBatchTransferParams.getTransferDetailList();
|
||||||
|
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
List<CreateBatchTransferParams.TransferDetailListItem> encrypted = transferDetailList.stream()
|
List<CreateBatchTransferParams.TransferDetailListItem> encrypted = transferDetailList.stream()
|
||||||
.peek(transferDetailListItem -> {
|
.peek(transferDetailListItem -> {
|
||||||
String userName = transferDetailListItem.getUserName();
|
String userName = transferDetailListItem.getUserName();
|
||||||
if (StringUtils.hasText(userName)) {
|
if (StringUtils.hasText(userName)) {
|
||||||
String encryptedUserName = signatureProvider.encryptRequestMessage(userName, x509Certificate);
|
String encryptedUserName = signatureProvider.encryptRequestMessage(userName, this.wechatMetaBean());
|
||||||
transferDetailListItem.setUserName(encryptedUserName);
|
transferDetailListItem.setUserName(encryptedUserName);
|
||||||
}
|
}
|
||||||
String userIdCard = transferDetailListItem.getUserIdCard();
|
String userIdCard = transferDetailListItem.getUserIdCard();
|
||||||
if (StringUtils.hasText(userIdCard)) {
|
if (StringUtils.hasText(userIdCard)) {
|
||||||
String encryptedUserIdCard = signatureProvider.encryptRequestMessage(userIdCard, x509Certificate);
|
String encryptedUserIdCard = signatureProvider.encryptRequestMessage(userIdCard, this.wechatMetaBean());
|
||||||
transferDetailListItem.setUserIdCard(encryptedUserIdCard);
|
transferDetailListItem.setUserIdCard(encryptedUserIdCard);
|
||||||
}
|
}
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
@@ -98,7 +96,7 @@ public class WechatBatchTransferApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, createBatchTransferParams, httpHeaders);
|
return Post(uri, createBatchTransferParams, httpHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,11 +56,8 @@ public class WechatCapitalApi extends AbstractApi{
|
|||||||
this.client().withType(WechatPayV3Type.CAPITAL_SEARCH, accountNumber)
|
this.client().withType(WechatPayV3Type.CAPITAL_SEARCH, accountNumber)
|
||||||
.function((type, param) -> {
|
.function((type, param) -> {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
.queryParam("account_number", signatureProvider.encryptRequestMessage(param,x509Certificate))
|
.queryParam("account_number", signatureProvider.encryptRequestMessage(param,this.wechatMetaBean()))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
return Get(uri);
|
return Get(uri);
|
||||||
|
|||||||
@@ -57,11 +57,34 @@ public class WechatDirectPayApi extends AbstractApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* APP下单API
|
* 付款码支付API
|
||||||
*
|
*
|
||||||
* @param payParams the pay params
|
* @param payParams the pay params
|
||||||
* @return the wechat response entity
|
* @return the wechat response entity
|
||||||
*/
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> codePay(PayParams payParams) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.CODE, payParams)
|
||||||
|
.function(this::payFunction)
|
||||||
|
.consumer(responseEntity -> {
|
||||||
|
ObjectNode body = responseEntity.getBody();
|
||||||
|
if (Objects.isNull(body)) {
|
||||||
|
throw new PayException("response body cannot be resolved");
|
||||||
|
}
|
||||||
|
wechatResponseEntity.setHttpStatus(responseEntity.getStatusCodeValue());
|
||||||
|
wechatResponseEntity.setBody(body);
|
||||||
|
})
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP下单API
|
||||||
|
*
|
||||||
|
* @param payParams the pay params
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
public WechatResponseEntity<ObjectNode> appPay(PayParams payParams) {
|
public WechatResponseEntity<ObjectNode> appPay(PayParams payParams) {
|
||||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
this.client().withType(WechatPayV3Type.APP, payParams)
|
this.client().withType(WechatPayV3Type.APP, payParams)
|
||||||
@@ -185,8 +208,10 @@ public class WechatDirectPayApi extends AbstractApi {
|
|||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
payParams.setAppid(v3.getAppId());
|
payParams.setAppid(v3.getAppId());
|
||||||
payParams.setMchid(v3.getMchId());
|
payParams.setMchid(v3.getMchId());
|
||||||
String notifyUrl = v3.getDomain().concat(payParams.getNotifyUrl());
|
if (!type.equals(WechatPayV3Type.CODE)){
|
||||||
payParams.setNotifyUrl(notifyUrl);
|
String notifyUrl = v3.getDomain().concat(payParams.getNotifyUrl());
|
||||||
|
payParams.setNotifyUrl(notifyUrl);
|
||||||
|
}
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
@@ -252,6 +277,21 @@ public class WechatDirectPayApi extends AbstractApi {
|
|||||||
return wechatResponseEntity;
|
return wechatResponseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销API
|
||||||
|
*
|
||||||
|
* @param outTradeNo the out trade no
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> reverse(String outTradeNo) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.REVERSE, outTradeNo)
|
||||||
|
.function(this::reverseOutTradeNoFunction)
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
private RequestEntity<?> closeByOutTradeNoFunction(WechatPayV3Type type, String outTradeNo) {
|
private RequestEntity<?> closeByOutTradeNoFunction(WechatPayV3Type type, String outTradeNo) {
|
||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
|
|
||||||
@@ -265,6 +305,20 @@ public class WechatDirectPayApi extends AbstractApi {
|
|||||||
return Post(uri, queryParams);
|
return Post(uri, queryParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RequestEntity<?> reverseOutTradeNoFunction(WechatPayV3Type type, String outTradeNo) {
|
||||||
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
|
|
||||||
|
Map<String, String> queryParams = new HashMap<>(1);
|
||||||
|
queryParams.put("mchid", v3.getMchId());
|
||||||
|
queryParams.put("appid", v3.getAppId());
|
||||||
|
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.build()
|
||||||
|
.expand(outTradeNo)
|
||||||
|
.toUri();
|
||||||
|
return Post(uri, queryParams);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请退款API
|
* 申请退款API
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -158,7 +158,9 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
|||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
|
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
params.setStockCreatorMchid(v3.getMchId());
|
if (StringUtils.hasText(params.getStockCreatorMchid())){
|
||||||
|
params.setStockCreatorMchid(v3.getMchId());
|
||||||
|
}
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.expand(params.getOpenid())
|
.expand(params.getOpenid())
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.WeChatServer;
|
||||||
|
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
|
||||||
|
import cn.felord.payment.wechat.v3.model.paygiftactivity.ActivitiesListPageRequest;
|
||||||
|
import cn.felord.payment.wechat.v3.model.paygiftactivity.ActivitiesPageRequest;
|
||||||
|
import cn.felord.payment.wechat.v3.model.paygiftactivity.DeleteActivityMchRequest;
|
||||||
|
import cn.felord.payment.wechat.v3.model.paygiftactivity.GiftActivityParams;
|
||||||
|
import cn.felord.payment.wechat.v3.model.paygiftactivity.NewActivityMchRequest;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付有礼
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
public class WechatMarketingPayGiftActivityApi extends AbstractApi {
|
||||||
|
/**
|
||||||
|
* Instantiates a new Abstract api.
|
||||||
|
*
|
||||||
|
* @param wechatPayClient the wechat pay client
|
||||||
|
* @param tenantId the tenant id
|
||||||
|
*/
|
||||||
|
public WechatMarketingPayGiftActivityApi(WechatPayClient wechatPayClient, String tenantId) {
|
||||||
|
super(wechatPayClient, tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建全场满额送活动API
|
||||||
|
*
|
||||||
|
* @param params the params
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> create(GiftActivityParams params) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY, params)
|
||||||
|
.function((type, activityParams) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.build()
|
||||||
|
.toUri();
|
||||||
|
return Post(uri, activityParams);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询活动详情接口API
|
||||||
|
*
|
||||||
|
* @param activityId the activity id
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> details(String activityId) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_DETAIL, activityId)
|
||||||
|
.function((type, param) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.build()
|
||||||
|
.expand(param)
|
||||||
|
.toUri();
|
||||||
|
return Get(uri);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询活动发券商户号API
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> merchants(ActivitiesPageRequest request) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_MCH, request)
|
||||||
|
.function((type, params) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.queryParam("offset", params.getOffset())
|
||||||
|
.queryParam("limit", params.getLimit())
|
||||||
|
.build()
|
||||||
|
.expand(params.getActivityId())
|
||||||
|
.toUri();
|
||||||
|
return Get(uri);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询活动指定商品列表API
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> goods(ActivitiesPageRequest request) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_GOODS, request)
|
||||||
|
.function((type, params) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.queryParam("offset", params.getOffset())
|
||||||
|
.queryParam("limit", params.getLimit())
|
||||||
|
.build()
|
||||||
|
.expand(params.getActivityId())
|
||||||
|
.toUri();
|
||||||
|
return Get(uri);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 终止活动API
|
||||||
|
*
|
||||||
|
* @param activityId the activity id
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> terminate(String activityId) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_TERMINATE, activityId)
|
||||||
|
.function((type, param) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.build()
|
||||||
|
.expand(param)
|
||||||
|
.toUri();
|
||||||
|
return Post(uri, Collections.emptyMap());
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增活动发券商户号API
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> addMches(NewActivityMchRequest request) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_MCH_ADD, request)
|
||||||
|
.function((type, params) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.build()
|
||||||
|
.expand(params.getActivityId())
|
||||||
|
.toUri();
|
||||||
|
Map<String, Object> body = new HashMap<>();
|
||||||
|
body.put("merchant_id_list", params.getMerchantIdList());
|
||||||
|
body.put("add_request_no", params.getAddRequestNo());
|
||||||
|
return Post(uri, body);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付有礼活动列表API
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> page(ActivitiesListPageRequest request) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_ACTIVITIES, request)
|
||||||
|
.function((type, params) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.queryParam("offset", params.getOffset())
|
||||||
|
.queryParam("limit", params.getLimit())
|
||||||
|
.queryParam("activity_name", params.getActivityName())
|
||||||
|
.queryParam("activity_status", params.getActivityStatus())
|
||||||
|
.queryParam("award_type", params.getAwardType())
|
||||||
|
.build()
|
||||||
|
.toUri();
|
||||||
|
return Get(uri);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除活动发券商户号API
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @return the wechat response entity
|
||||||
|
*/
|
||||||
|
public WechatResponseEntity<ObjectNode> deleteMch(DeleteActivityMchRequest request) {
|
||||||
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
|
this.client().withType(WechatPayV3Type.MARKETING_PAYGIFTACTIVITY_MCH_DEL, request)
|
||||||
|
.function((type, params) -> {
|
||||||
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
|
.build()
|
||||||
|
.expand(params.getActivityId())
|
||||||
|
.toUri();
|
||||||
|
Map<String, Object> body = new HashMap<>();
|
||||||
|
body.put("merchant_id_list", params.getMerchantIdList());
|
||||||
|
body.put("delete_request_no", params.getDeleteRequestNo());
|
||||||
|
return Post(uri, body);
|
||||||
|
})
|
||||||
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
.request();
|
||||||
|
return wechatResponseEntity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,5 +46,9 @@ public class WechatMetaBean {
|
|||||||
* The V3.
|
* The V3.
|
||||||
*/
|
*/
|
||||||
private WechatPayProperties.V3 v3;
|
private WechatPayProperties.V3 v3;
|
||||||
|
|
||||||
|
|
||||||
|
public Boolean getEnableWechatPayPublicEncrypt() {
|
||||||
|
return v3.getEnableWechatPayPublic();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ package cn.felord.payment.wechat.v3;
|
|||||||
import cn.felord.payment.wechat.WechatTenantService;
|
import cn.felord.payment.wechat.WechatTenantService;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentSkipListSet;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置容器
|
* 配置容器
|
||||||
@@ -33,7 +36,6 @@ import java.util.concurrent.ConcurrentSkipListSet;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class WechatMetaContainer {
|
public class WechatMetaContainer {
|
||||||
private final Map<String, WechatMetaBean> wechatMetaBeanMap = new ConcurrentHashMap<>();
|
private final Map<String, WechatMetaBean> wechatMetaBeanMap = new ConcurrentHashMap<>();
|
||||||
private final Set<String> tenantIds = new ConcurrentSkipListSet<>();
|
|
||||||
private final WechatTenantService wechatTenantService;
|
private final WechatTenantService wechatTenantService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,22 +49,9 @@ public class WechatMetaContainer {
|
|||||||
|
|
||||||
private void addMeta(WechatMetaBean wechatMetaBean) {
|
private void addMeta(WechatMetaBean wechatMetaBean) {
|
||||||
String tenantId = wechatMetaBean.getTenantId();
|
String tenantId = wechatMetaBean.getTenantId();
|
||||||
tenantIds.add(tenantId);
|
|
||||||
wechatMetaBeanMap.put(tenantId, wechatMetaBean);
|
wechatMetaBeanMap.put(tenantId, wechatMetaBean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove wechat meta wechat meta bean.
|
|
||||||
*
|
|
||||||
* @param tenantId the tenantId
|
|
||||||
* @return the wechat meta bean
|
|
||||||
*/
|
|
||||||
public WechatMetaBean removeWechatMeta(String tenantId) {
|
|
||||||
tenantIds.remove(tenantId);
|
|
||||||
return this.wechatMetaBeanMap.remove(tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets wechat meta.
|
* Gets wechat meta.
|
||||||
*
|
*
|
||||||
@@ -86,6 +75,9 @@ public class WechatMetaContainer {
|
|||||||
* @return the properties keys
|
* @return the properties keys
|
||||||
*/
|
*/
|
||||||
public Set<String> getTenantIds() {
|
public Set<String> getTenantIds() {
|
||||||
return tenantIds;
|
return wechatTenantService.loadTenants()
|
||||||
|
.stream()
|
||||||
|
.map(WechatMetaBean::getTenantId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class WechatPartnerPayApi extends AbstractApi {
|
|||||||
WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId());
|
WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId());
|
||||||
PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate();
|
PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate();
|
||||||
|
|
||||||
String subAppid = partnerPayParams.getSubAppid();
|
String spAppid = partnerPayParams.getSpAppid();
|
||||||
long epochSecond = LocalDateTime.now()
|
long epochSecond = LocalDateTime.now()
|
||||||
.toEpochSecond(ZoneOffset.of("+8"));
|
.toEpochSecond(ZoneOffset.of("+8"));
|
||||||
String timestamp = String.valueOf(epochSecond);
|
String timestamp = String.valueOf(epochSecond);
|
||||||
@@ -89,9 +89,8 @@ public class WechatPartnerPayApi extends AbstractApi {
|
|||||||
.toString()
|
.toString()
|
||||||
.replaceAll("-", "");
|
.replaceAll("-", "");
|
||||||
String prepayId = body.get("prepay_id").asText();
|
String prepayId = body.get("prepay_id").asText();
|
||||||
String paySign = signatureProvider.doRequestSign(privateKey, subAppid, timestamp, nonceStr, prepayId);
|
String paySign = signatureProvider.doRequestSign(privateKey, spAppid, timestamp, nonceStr, prepayId);
|
||||||
|
body.put("appid", spAppid);
|
||||||
body.put("appid", subAppid);
|
|
||||||
body.put("partnerid", partnerPayParams.getSubMchid());
|
body.put("partnerid", partnerPayParams.getSubMchid());
|
||||||
body.put("prepayid", prepayId);
|
body.put("prepayid", prepayId);
|
||||||
body.put("package", "Sign=WXPay");
|
body.put("package", "Sign=WXPay");
|
||||||
@@ -129,7 +128,7 @@ public class WechatPartnerPayApi extends AbstractApi {
|
|||||||
WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId());
|
WechatMetaBean wechatMetaBean = wechatMetaContainer.getWechatMeta(tenantId());
|
||||||
PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate();
|
PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate();
|
||||||
|
|
||||||
String subAppid = partnerPayParams.getSubAppid();
|
String spAppid = partnerPayParams.getSpAppid();
|
||||||
long epochSecond = LocalDateTime.now()
|
long epochSecond = LocalDateTime.now()
|
||||||
.toEpochSecond(ZoneOffset.of("+8"));
|
.toEpochSecond(ZoneOffset.of("+8"));
|
||||||
String timestamp = String.valueOf(epochSecond);
|
String timestamp = String.valueOf(epochSecond);
|
||||||
@@ -138,9 +137,8 @@ public class WechatPartnerPayApi extends AbstractApi {
|
|||||||
.toString()
|
.toString()
|
||||||
.replaceAll("-", "");
|
.replaceAll("-", "");
|
||||||
String packageStr = "prepay_id=" + body.get("prepay_id").asText();
|
String packageStr = "prepay_id=" + body.get("prepay_id").asText();
|
||||||
String paySign = signatureProvider.doRequestSign(privateKey, subAppid, timestamp, nonceStr, packageStr);
|
String paySign = signatureProvider.doRequestSign(privateKey, spAppid, timestamp, nonceStr, packageStr);
|
||||||
|
body.put("appid", spAppid);
|
||||||
body.put("appId", subAppid);
|
|
||||||
body.put("timeStamp", timestamp);
|
body.put("timeStamp", timestamp);
|
||||||
body.put("nonceStr", nonceStr);
|
body.put("nonceStr", nonceStr);
|
||||||
body.put("package", packageStr);
|
body.put("package", packageStr);
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
|
|||||||
.function((wechatPayV3Type, params) -> {
|
.function((wechatPayV3Type, params) -> {
|
||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
List<Receiver> receivers = params.getReceivers();
|
List<Receiver> receivers = params.getReceivers();
|
||||||
if (!CollectionUtils.isEmpty(receivers)) {
|
if (!CollectionUtils.isEmpty(receivers)) {
|
||||||
@@ -88,7 +86,7 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
|
|||||||
.peek(receiversItem -> {
|
.peek(receiversItem -> {
|
||||||
String name = receiversItem.getName();
|
String name = receiversItem.getName();
|
||||||
if (StringUtils.hasText(name)) {
|
if (StringUtils.hasText(name)) {
|
||||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
String encryptedName = signatureProvider.encryptRequestMessage(name,this.wechatMetaBean());
|
||||||
receiversItem.setName(encryptedName);
|
receiversItem.setName(encryptedName);
|
||||||
}
|
}
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
@@ -98,7 +96,7 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, params, httpHeaders);
|
return Post(uri, params, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
@@ -294,19 +292,17 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
|
|||||||
.function((wechatPayV3Type, params) -> {
|
.function((wechatPayV3Type, params) -> {
|
||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
|
|
||||||
if (ReceiverType.MERCHANT_ID.equals(params.getType())) {
|
if (ReceiverType.MERCHANT_ID.equals(params.getType())) {
|
||||||
String encryptedName = signatureProvider.encryptRequestMessage(params.getName(), x509Certificate);
|
String encryptedName = signatureProvider.encryptRequestMessage(params.getName(), this.wechatMetaBean());
|
||||||
params.setName(encryptedName);
|
params.setName(encryptedName);
|
||||||
}
|
}
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, params, httpHeaders);
|
return Post(uri, params, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
|||||||
@@ -63,14 +63,12 @@ public class WechatPartnerSpecialMchApi extends AbstractApi {
|
|||||||
this.client().withType(WechatPayV3Type.SPEC_MCH_APPLY_PARTNER, params)
|
this.client().withType(WechatPayV3Type.SPEC_MCH_APPLY_PARTNER, params)
|
||||||
.function((wechatPayV3Type, applymentParams) -> {
|
.function((wechatPayV3Type, applymentParams) -> {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
ApplymentParams applyRequestParams = this.convert(applymentParams, signatureProvider);
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
ApplymentParams applyRequestParams = this.convert(applymentParams, signatureProvider, x509Certificate);
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, applyRequestParams, httpHeaders);
|
return Post(uri, applyRequestParams, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
@@ -133,17 +131,15 @@ public class WechatPartnerSpecialMchApi extends AbstractApi {
|
|||||||
this.client().withType(WechatPayV3Type.SPEC_MCH_SUB_MODIFY, params)
|
this.client().withType(WechatPayV3Type.SPEC_MCH_SUB_MODIFY, params)
|
||||||
.function((type, subMchModifyParams) -> {
|
.function((type, subMchModifyParams) -> {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.expand(subMchModifyParams.getSubMchid())
|
.expand(subMchModifyParams.getSubMchid())
|
||||||
.toUri();
|
.toUri();
|
||||||
|
|
||||||
subMchModifyParams.setSubMchid(null);
|
subMchModifyParams.setSubMchid(null);
|
||||||
subMchModifyParams.setAccountNumber(signatureProvider.encryptRequestMessage(subMchModifyParams.getAccountNumber(), x509Certificate));
|
subMchModifyParams.setAccountNumber(signatureProvider.encryptRequestMessage(subMchModifyParams.getAccountNumber(), this.wechatMetaBean()));
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, subMchModifyParams, httpHeaders);
|
return Post(uri, subMchModifyParams, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
@@ -175,55 +171,55 @@ public class WechatPartnerSpecialMchApi extends AbstractApi {
|
|||||||
return wechatResponseEntity;
|
return wechatResponseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApplymentParams convert(ApplymentParams applymentParams, SignatureProvider signatureProvider, final X509Certificate x509Certificate) {
|
private ApplymentParams convert(ApplymentParams applymentParams, SignatureProvider signatureProvider) {
|
||||||
|
|
||||||
ContactInfo contactInfo = applymentParams.getContactInfo();
|
ContactInfo contactInfo = applymentParams.getContactInfo();
|
||||||
contactInfo.setContactName(signatureProvider.encryptRequestMessage(contactInfo.getContactName(), x509Certificate));
|
contactInfo.setContactName(signatureProvider.encryptRequestMessage(contactInfo.getContactName(), this.wechatMetaBean()));
|
||||||
String contactIdNumber = contactInfo.getContactIdNumber();
|
String contactIdNumber = contactInfo.getContactIdNumber();
|
||||||
if (contactIdNumber != null) {
|
if (contactIdNumber != null) {
|
||||||
contactInfo.setContactIdNumber(signatureProvider.encryptRequestMessage(contactIdNumber, x509Certificate));
|
contactInfo.setContactIdNumber(signatureProvider.encryptRequestMessage(contactIdNumber,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
String openid = contactInfo.getOpenid();
|
String openid = contactInfo.getOpenid();
|
||||||
if (openid != null) {
|
if (openid != null) {
|
||||||
contactInfo.setOpenid(signatureProvider.encryptRequestMessage(openid, x509Certificate));
|
contactInfo.setOpenid(signatureProvider.encryptRequestMessage(openid,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
contactInfo.setMobilePhone(signatureProvider.encryptRequestMessage(contactInfo.getMobilePhone(), x509Certificate));
|
contactInfo.setMobilePhone(signatureProvider.encryptRequestMessage(contactInfo.getMobilePhone(), this.wechatMetaBean()));
|
||||||
contactInfo.setContactEmail(signatureProvider.encryptRequestMessage(contactInfo.getContactEmail(), x509Certificate));
|
contactInfo.setContactEmail(signatureProvider.encryptRequestMessage(contactInfo.getContactEmail(), this.wechatMetaBean()));
|
||||||
|
|
||||||
SubjectInfo subjectInfo = applymentParams.getSubjectInfo();
|
SubjectInfo subjectInfo = applymentParams.getSubjectInfo();
|
||||||
IdentityInfo identityInfo = subjectInfo.getIdentityInfo();
|
IdentityInfo identityInfo = subjectInfo.getIdentityInfo();
|
||||||
|
|
||||||
IdCardInfo idCardInfo = identityInfo.getIdCardInfo();
|
IdCardInfo idCardInfo = identityInfo.getIdCardInfo();
|
||||||
if (idCardInfo != null) {
|
if (idCardInfo != null) {
|
||||||
idCardInfo.setIdCardName(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardName(), x509Certificate));
|
idCardInfo.setIdCardName(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardName(), this.wechatMetaBean()));
|
||||||
idCardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardNumber(), x509Certificate));
|
idCardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardNumber(), this.wechatMetaBean()));
|
||||||
String idCardAddress = idCardInfo.getIdCardAddress();
|
String idCardAddress = idCardInfo.getIdCardAddress();
|
||||||
if (StringUtils.hasText(idCardAddress)){
|
if (StringUtils.hasText(idCardAddress)){
|
||||||
idCardInfo.setIdCardAddress(signatureProvider.encryptRequestMessage(idCardAddress, x509Certificate));
|
idCardInfo.setIdCardAddress(signatureProvider.encryptRequestMessage(idCardAddress,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IdDocInfo idDocInfo = identityInfo.getIdDocInfo();
|
IdDocInfo idDocInfo = identityInfo.getIdDocInfo();
|
||||||
if (idDocInfo != null) {
|
if (idDocInfo != null) {
|
||||||
idDocInfo.setIdDocName(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocName(), x509Certificate));
|
idDocInfo.setIdDocName(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocName(), this.wechatMetaBean()));
|
||||||
idDocInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocNumber(), x509Certificate));
|
idDocInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocNumber(), this.wechatMetaBean()));
|
||||||
String idDocAddress = idDocInfo.getIdDocAddress();
|
String idDocAddress = idDocInfo.getIdDocAddress();
|
||||||
if (StringUtils.hasText(idDocAddress)){
|
if (StringUtils.hasText(idDocAddress)){
|
||||||
idDocInfo.setIdDocAddress(signatureProvider.encryptRequestMessage(idDocAddress, x509Certificate));
|
idDocInfo.setIdDocAddress(signatureProvider.encryptRequestMessage(idDocAddress,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<UboInfoListItem> uboInfoList = subjectInfo.getUboInfoList();
|
List<UboInfoListItem> uboInfoList = subjectInfo.getUboInfoList();
|
||||||
if (!CollectionUtils.isEmpty(uboInfoList)) {
|
if (!CollectionUtils.isEmpty(uboInfoList)) {
|
||||||
uboInfoList.forEach(uboInfoListItem -> {
|
uboInfoList.forEach(uboInfoListItem -> {
|
||||||
uboInfoListItem.setUboIdDocName(signatureProvider.encryptRequestMessage(uboInfoListItem.getUboIdDocName(), x509Certificate));
|
uboInfoListItem.setUboIdDocName(signatureProvider.encryptRequestMessage(uboInfoListItem.getUboIdDocName(), this.wechatMetaBean()));
|
||||||
uboInfoListItem.setUboIdDocNumber(signatureProvider.encryptRequestMessage(uboInfoListItem.getUboIdDocNumber(), x509Certificate));
|
uboInfoListItem.setUboIdDocNumber(signatureProvider.encryptRequestMessage(uboInfoListItem.getUboIdDocNumber(), this.wechatMetaBean()));
|
||||||
uboInfoListItem.setUboIdDocAddress(signatureProvider.encryptRequestMessage(uboInfoListItem.getUboIdDocAddress(), x509Certificate));
|
uboInfoListItem.setUboIdDocAddress(signatureProvider.encryptRequestMessage(uboInfoListItem.getUboIdDocAddress(), this.wechatMetaBean()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
BankAccountInfo bankAccountInfo = applymentParams.getBankAccountInfo();
|
BankAccountInfo bankAccountInfo = applymentParams.getBankAccountInfo();
|
||||||
|
|
||||||
bankAccountInfo.setAccountName(signatureProvider.encryptRequestMessage(bankAccountInfo.getAccountName(), x509Certificate));
|
bankAccountInfo.setAccountName(signatureProvider.encryptRequestMessage(bankAccountInfo.getAccountName(), this.wechatMetaBean()));
|
||||||
bankAccountInfo.setAccountNumber(signatureProvider.encryptRequestMessage(bankAccountInfo.getAccountNumber(), x509Certificate));
|
bankAccountInfo.setAccountNumber(signatureProvider.encryptRequestMessage(bankAccountInfo.getAccountNumber(), this.wechatMetaBean()));
|
||||||
|
|
||||||
return applymentParams;
|
return applymentParams;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,11 @@ public class WechatPayClient {
|
|||||||
// 避免出现因为中文导致的 HttpRetryException
|
// 避免出现因为中文导致的 HttpRetryException
|
||||||
httpHeaders.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
httpHeaders.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signatureProvider.isSwitchVerifySignMethod(tenantId)){
|
||||||
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPublicKeyId(tenantId));
|
||||||
|
}
|
||||||
|
|
||||||
httpHeaders.add("Authorization", authorization);
|
httpHeaders.add("Authorization", authorization);
|
||||||
httpHeaders.add("User-Agent", "X-Pay-Service");
|
httpHeaders.add("User-Agent", "X-Pay-Service");
|
||||||
httpHeaders.remove("Meta-Info");
|
httpHeaders.remove("Meta-Info");
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public class WechatPayScoreParkingApi extends AbstractApi {
|
|||||||
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.queryParams(queryParams)
|
.queryParams(queryParams)
|
||||||
|
.encode()
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
return Get(uri);
|
return Get(uri);
|
||||||
|
|||||||
@@ -77,8 +77,6 @@ public class WechatProfitsharingApi extends AbstractApi {
|
|||||||
.function((wechatPayV3Type, params) -> {
|
.function((wechatPayV3Type, params) -> {
|
||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
List<Receiver> receivers = params.getReceivers();
|
List<Receiver> receivers = params.getReceivers();
|
||||||
if (!CollectionUtils.isEmpty(receivers)) {
|
if (!CollectionUtils.isEmpty(receivers)) {
|
||||||
@@ -86,7 +84,7 @@ public class WechatProfitsharingApi extends AbstractApi {
|
|||||||
.peek(receiversItem -> {
|
.peek(receiversItem -> {
|
||||||
String name = receiversItem.getName();
|
String name = receiversItem.getName();
|
||||||
if (StringUtils.hasText(name)) {
|
if (StringUtils.hasText(name)) {
|
||||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
String encryptedName = signatureProvider.encryptRequestMessage(name,this.wechatMetaBean());
|
||||||
receiversItem.setName(encryptedName);
|
receiversItem.setName(encryptedName);
|
||||||
}
|
}
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
@@ -96,7 +94,7 @@ public class WechatProfitsharingApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, params, httpHeaders);
|
return Post(uri, params, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
@@ -263,19 +261,17 @@ public class WechatProfitsharingApi extends AbstractApi {
|
|||||||
.function((wechatPayV3Type, params) -> {
|
.function((wechatPayV3Type, params) -> {
|
||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
String name = params.getName();
|
String name = params.getName();
|
||||||
if (StringUtils.hasText(name)) {
|
if (StringUtils.hasText(name)) {
|
||||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
String encryptedName = signatureProvider.encryptRequestMessage(name,this.wechatMetaBean());
|
||||||
params.setName(encryptedName);
|
params.setName(encryptedName);
|
||||||
}
|
}
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, params, httpHeaders);
|
return Post(uri, params, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
|||||||
@@ -65,15 +65,13 @@ public class WechatSmartGuideApi extends AbstractApi {
|
|||||||
this.client().withType(WechatPayV3Type.SMART_GUIDES, params)
|
this.client().withType(WechatPayV3Type.SMART_GUIDES, params)
|
||||||
.function((wechatPayV3Type, smartGuidesParams) -> {
|
.function((wechatPayV3Type, smartGuidesParams) -> {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
smartGuidesParams.setName(signatureProvider.encryptRequestMessage(smartGuidesParams.getName(), this.wechatMetaBean()));
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
smartGuidesParams.setMobile(signatureProvider.encryptRequestMessage(smartGuidesParams.getMobile(), this.wechatMetaBean()));
|
||||||
smartGuidesParams.setName(signatureProvider.encryptRequestMessage(smartGuidesParams.getName(), x509Certificate));
|
|
||||||
smartGuidesParams.setMobile(signatureProvider.encryptRequestMessage(smartGuidesParams.getMobile(), x509Certificate));
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, smartGuidesParams, httpHeaders);
|
return Post(uri, smartGuidesParams, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
@@ -137,10 +135,8 @@ public class WechatSmartGuideApi extends AbstractApi {
|
|||||||
String mobile = smartGuidesQueryParams.getMobile();
|
String mobile = smartGuidesQueryParams.getMobile();
|
||||||
if (mobile != null) {
|
if (mobile != null) {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
queryParams.add("mobile", signatureProvider.encryptRequestMessage(mobile,this.wechatMetaBean()));
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
queryParams.add("mobile", signatureProvider.encryptRequestMessage(mobile, x509Certificate));
|
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
|
||||||
}
|
}
|
||||||
String workId = smartGuidesQueryParams.getWorkId();
|
String workId = smartGuidesQueryParams.getWorkId();
|
||||||
if (workId != null) {
|
if (workId != null) {
|
||||||
@@ -177,15 +173,13 @@ public class WechatSmartGuideApi extends AbstractApi {
|
|||||||
this.client().withType(WechatPayV3Type.SMART_GUIDES_MODIFY, params)
|
this.client().withType(WechatPayV3Type.SMART_GUIDES_MODIFY, params)
|
||||||
.function((wechatPayV3Type, smartGuidesParams) -> {
|
.function((wechatPayV3Type, smartGuidesParams) -> {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
smartGuidesParams.setName(signatureProvider.encryptRequestMessage(smartGuidesParams.getName(), this.wechatMetaBean()));
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
smartGuidesParams.setMobile(signatureProvider.encryptRequestMessage(smartGuidesParams.getMobile(), this.wechatMetaBean()));
|
||||||
smartGuidesParams.setName(signatureProvider.encryptRequestMessage(smartGuidesParams.getName(), x509Certificate));
|
|
||||||
smartGuidesParams.setMobile(signatureProvider.encryptRequestMessage(smartGuidesParams.getMobile(), x509Certificate));
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Patch(uri, smartGuidesParams, httpHeaders);
|
return Patch(uri, smartGuidesParams, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
|||||||
@@ -71,12 +71,10 @@ public class ApplymentApi extends AbstractApi {
|
|||||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||||
this.client().withType(WechatPayV3Type.ECOMMERCE_APPLYMENT, params).function((wechatPayV3Type, applymentParams) -> {
|
this.client().withType(WechatPayV3Type.ECOMMERCE_APPLYMENT, params).function((wechatPayV3Type, applymentParams) -> {
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
EcommerceApplymentParams applyRequestParams = this.convert(applymentParams, signatureProvider);
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
EcommerceApplymentParams applyRequestParams = this.convert(applymentParams, signatureProvider, x509Certificate);
|
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA)).build().toUri();
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA)).build().toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, applyRequestParams, httpHeaders);
|
return Post(uri, applyRequestParams, httpHeaders);
|
||||||
}).consumer(wechatResponseEntity::convert).request();
|
}).consumer(wechatResponseEntity::convert).request();
|
||||||
return wechatResponseEntity;
|
return wechatResponseEntity;
|
||||||
@@ -138,49 +136,50 @@ public class ApplymentApi extends AbstractApi {
|
|||||||
return this.wechatPartnerSpecialMchApi.querySettlement(subMchid);
|
return this.wechatPartnerSpecialMchApi.querySettlement(subMchid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EcommerceApplymentParams convert(EcommerceApplymentParams applymentParams, SignatureProvider signatureProvider, X509Certificate x509Certificate) {
|
private EcommerceApplymentParams convert(EcommerceApplymentParams applymentParams, SignatureProvider signatureProvider) {
|
||||||
EcommerceIdCardInfo idCardInfo = applymentParams.getIdCardInfo();
|
EcommerceIdCardInfo idCardInfo = applymentParams.getIdCardInfo();
|
||||||
if (idCardInfo != null) {
|
if (idCardInfo != null) {
|
||||||
idCardInfo.setIdCardName(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardName(), x509Certificate));
|
idCardInfo.setIdCardName(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardName(), this.wechatMetaBean()));
|
||||||
idCardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardNumber(), x509Certificate));
|
idCardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardNumber(), this.wechatMetaBean()));
|
||||||
String idCardAddress = idCardInfo.getIdCardAddress();
|
String idCardAddress = idCardInfo.getIdCardAddress();
|
||||||
if (StringUtils.hasText(idCardAddress)) {
|
if (StringUtils.hasText(idCardAddress)) {
|
||||||
idCardInfo.setIdCardAddress(signatureProvider.encryptRequestMessage(idCardAddress, x509Certificate));
|
idCardInfo.setIdCardAddress(signatureProvider.encryptRequestMessage(idCardAddress,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EcommerceIdDocInfo idDocInfo = applymentParams.getIdDocInfo();
|
EcommerceIdDocInfo idDocInfo = applymentParams.getIdDocInfo();
|
||||||
if (idDocInfo != null) {
|
if (idDocInfo != null) {
|
||||||
idDocInfo.setIdDocName(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocName(), x509Certificate));
|
idDocInfo.setIdDocName(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocName(), this.wechatMetaBean()));
|
||||||
idDocInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocNumber(), x509Certificate));
|
idDocInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocNumber(), this.wechatMetaBean()));
|
||||||
String idDocAddress = idDocInfo.getIdDocAddress();
|
String idDocAddress = idDocInfo.getIdDocAddress();
|
||||||
if (StringUtils.hasText(idDocAddress)) {
|
if (StringUtils.hasText(idDocAddress)) {
|
||||||
idDocInfo.setIdDocAddress(signatureProvider.encryptRequestMessage(idDocAddress, x509Certificate));
|
idDocInfo.setIdDocAddress(signatureProvider.encryptRequestMessage(idDocAddress,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UboInfo uboInfo = applymentParams.getUboInfo();
|
UboInfo uboInfo = applymentParams.getUboInfo();
|
||||||
if (uboInfo != null) {
|
if (uboInfo != null) {
|
||||||
UboInfo.IdCardInfo cardInfo = uboInfo.getIdCardInfo();
|
UboInfo.IdCardInfo cardInfo = uboInfo.getIdCardInfo();
|
||||||
if (cardInfo != null) {
|
if (cardInfo != null) {
|
||||||
cardInfo.setIdCardName(signatureProvider.encryptRequestMessage(cardInfo.getIdCardName(), x509Certificate));
|
cardInfo.setIdCardName(signatureProvider.encryptRequestMessage(cardInfo.getIdCardName(), this.wechatMetaBean()));
|
||||||
cardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(cardInfo.getIdCardNumber(), x509Certificate));
|
cardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(cardInfo.getIdCardNumber(), this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
UboInfo.IdDocInfo docInfo = uboInfo.getIdDocInfo();
|
UboInfo.IdDocInfo docInfo = uboInfo.getIdDocInfo();
|
||||||
if (docInfo != null) {
|
if (docInfo != null) {
|
||||||
docInfo.setIdDocName(signatureProvider.encryptRequestMessage(docInfo.getIdDocName(), x509Certificate));
|
docInfo.setIdDocName(signatureProvider.encryptRequestMessage(docInfo.getIdDocName(), this.wechatMetaBean()));
|
||||||
docInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(docInfo.getIdDocNumber(), x509Certificate));
|
docInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(docInfo.getIdDocNumber(), this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EcommerceAccountInfo accountInfo = applymentParams.getAccountInfo();
|
EcommerceAccountInfo accountInfo = applymentParams.getAccountInfo();
|
||||||
if (accountInfo != null) {
|
if (accountInfo != null) {
|
||||||
accountInfo.setAccountName(signatureProvider.encryptRequestMessage(accountInfo.getAccountName(), x509Certificate));
|
accountInfo.setAccountName(signatureProvider.encryptRequestMessage(accountInfo.getAccountName(), this.wechatMetaBean()));
|
||||||
accountInfo.setAccountNumber(signatureProvider.encryptRequestMessage(accountInfo.getAccountNumber(), x509Certificate));
|
accountInfo.setAccountNumber(signatureProvider.encryptRequestMessage(accountInfo.getAccountNumber(), this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
EcommerceContactInfo contactInfo = applymentParams.getContactInfo();
|
EcommerceContactInfo contactInfo = applymentParams.getContactInfo();
|
||||||
contactInfo.setContactName(signatureProvider.encryptRequestMessage(contactInfo.getContactName(), x509Certificate));
|
contactInfo.setContactName(signatureProvider.encryptRequestMessage(contactInfo.getContactName(), this.wechatMetaBean()));
|
||||||
contactInfo.setContactIdCardNumber(signatureProvider.encryptRequestMessage(contactInfo.getContactIdCardNumber(), x509Certificate));
|
contactInfo.setContactIdCardNumber(signatureProvider.encryptRequestMessage(contactInfo.getContactIdCardNumber(), this.wechatMetaBean()));
|
||||||
|
contactInfo.setMobilePhone(signatureProvider.encryptRequestMessage(contactInfo.getMobilePhone(), this.wechatMetaBean()));
|
||||||
String contactEmail = contactInfo.getContactEmail();
|
String contactEmail = contactInfo.getContactEmail();
|
||||||
if (contactEmail != null) {
|
if (contactEmail != null) {
|
||||||
contactInfo.setContactEmail(signatureProvider.encryptRequestMessage(contactEmail, x509Certificate));
|
contactInfo.setContactEmail(signatureProvider.encryptRequestMessage(contactEmail,this.wechatMetaBean()));
|
||||||
}
|
}
|
||||||
return applymentParams;
|
return applymentParams;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,15 +77,13 @@ public class ProfitsharingApi extends AbstractApi {
|
|||||||
.function((wechatPayV3Type, params) -> {
|
.function((wechatPayV3Type, params) -> {
|
||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
List<Receiver> receivers = params.getReceivers();
|
List<Receiver> receivers = params.getReceivers();
|
||||||
if (!CollectionUtils.isEmpty(receivers)) {
|
if (!CollectionUtils.isEmpty(receivers)) {
|
||||||
receivers.forEach(receiversItem -> {
|
receivers.forEach(receiversItem -> {
|
||||||
String name = receiversItem.getReceiverName();
|
String name = receiversItem.getReceiverName();
|
||||||
if (StringUtils.hasText(name)) {
|
if (StringUtils.hasText(name)) {
|
||||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
String encryptedName = signatureProvider.encryptRequestMessage(name,this.wechatMetaBean());
|
||||||
receiversItem.setReceiverName(encryptedName);
|
receiversItem.setReceiverName(encryptedName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -94,7 +92,7 @@ public class ProfitsharingApi extends AbstractApi {
|
|||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, params, httpHeaders);
|
return Post(uri, params, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
@@ -256,20 +254,17 @@ public class ProfitsharingApi extends AbstractApi {
|
|||||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||||
params.setAppid(v3.getAppId());
|
params.setAppid(v3.getAppId());
|
||||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
|
|
||||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
|
||||||
|
|
||||||
String name = params.getName();
|
String name = params.getName();
|
||||||
if (ReceiverType.PERSONAL_OPENID.equals(params.getType()) && StringUtils.hasText(name)) {
|
if (ReceiverType.PERSONAL_OPENID.equals(params.getType()) && StringUtils.hasText(name)) {
|
||||||
// 个人应该必传
|
// 个人应该必传
|
||||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
String encryptedName = signatureProvider.encryptRequestMessage(name,this.wechatMetaBean());
|
||||||
params.setEncryptedName(encryptedName);
|
params.setEncryptedName(encryptedName);
|
||||||
}
|
}
|
||||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||||
.build()
|
.build()
|
||||||
.toUri();
|
.toUri();
|
||||||
HttpHeaders httpHeaders = new HttpHeaders();
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPaySerial(this.wechatMetaBean()));
|
||||||
return Post(uri, params, httpHeaders);
|
return Post(uri, params, httpHeaders);
|
||||||
})
|
})
|
||||||
.consumer(wechatResponseEntity::convert)
|
.consumer(wechatResponseEntity::convert)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class PatternInfo {
|
|||||||
/**
|
/**
|
||||||
* 背景色
|
* 背景色
|
||||||
*/
|
*/
|
||||||
private CouponBgColor backgroundColor;
|
private String backgroundColor;
|
||||||
/**
|
/**
|
||||||
* 券详情图片
|
* 券详情图片
|
||||||
*/
|
*/
|
||||||
@@ -49,4 +49,16 @@ public class PatternInfo {
|
|||||||
*/
|
*/
|
||||||
private String merchantName;
|
private String merchantName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets background color.
|
||||||
|
*
|
||||||
|
* @param backgroundColor the background color
|
||||||
|
*/
|
||||||
|
public void setBackgroundColor(CouponBgColor backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBackgroundColor(String backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,4 +38,6 @@ public class Payer {
|
|||||||
* 用户子标识
|
* 用户子标识
|
||||||
*/
|
*/
|
||||||
private String subOpenid;
|
private String subOpenid;
|
||||||
|
|
||||||
|
private String authCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ public class CreateBatchTransferParams {
|
|||||||
* 指定该笔转账使用的转账场景ID
|
* 指定该笔转账使用的转账场景ID
|
||||||
*/
|
*/
|
||||||
private String transferSceneId;
|
private String transferSceneId;
|
||||||
|
/**
|
||||||
|
* 回调通知
|
||||||
|
* @since 1.0.20
|
||||||
|
*/
|
||||||
|
private String notifyUrl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转账明细.
|
* 转账明细.
|
||||||
@@ -96,4 +101,4 @@ public class CreateBatchTransferParams {
|
|||||||
*/
|
*/
|
||||||
private String userIdCard;
|
private String userIdCard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
package cn.felord.payment.wechat.v3.model.busifavor;
|
package cn.felord.payment.wechat.v3.model.busifavor;
|
||||||
|
|
||||||
import cn.felord.payment.wechat.enumeration.CouponBgColor;
|
import cn.felord.payment.wechat.enumeration.CouponBgColor;
|
||||||
import cn.felord.payment.wechat.v3.WechatMarketingFavorApi;
|
import cn.felord.payment.wechat.v3.WechatMediaApi;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ public class DisplayPatternInfo {
|
|||||||
/**
|
/**
|
||||||
* 背景颜色
|
* 背景颜色
|
||||||
*/
|
*/
|
||||||
private CouponBgColor backgroundColor;
|
private String backgroundColor;
|
||||||
/**
|
/**
|
||||||
* 商户logo
|
* 商户logo
|
||||||
* <ol>
|
* <ol>
|
||||||
@@ -42,7 +42,7 @@ public class DisplayPatternInfo {
|
|||||||
* </ol>
|
* </ol>
|
||||||
* 仅支持通过 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/chapter3_1.shtml">图片上传API</a> 接口获取的图片URL地址。
|
* 仅支持通过 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/chapter3_1.shtml">图片上传API</a> 接口获取的图片URL地址。
|
||||||
*
|
*
|
||||||
* @see WechatMarketingFavorApi#marketingImageUpload(MultipartFile)
|
* @see WechatMediaApi#marketingImageUpload(MultipartFile)
|
||||||
*/
|
*/
|
||||||
private String merchantLogoUrl;
|
private String merchantLogoUrl;
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +54,7 @@ public class DisplayPatternInfo {
|
|||||||
* </ol>
|
* </ol>
|
||||||
* 仅支持通过 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/chapter3_1.shtml">图片上传API</a> 接口获取的图片URL地址。
|
* 仅支持通过 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/chapter3_1.shtml">图片上传API</a> 接口获取的图片URL地址。
|
||||||
*
|
*
|
||||||
* @see WechatMarketingFavorApi#marketingImageUpload(MultipartFile)
|
* @see WechatMediaApi#marketingImageUpload(MultipartFile)
|
||||||
*/
|
*/
|
||||||
private String couponImageUrl;
|
private String couponImageUrl;
|
||||||
/**
|
/**
|
||||||
@@ -69,4 +69,17 @@ public class DisplayPatternInfo {
|
|||||||
* 商户名称,字数上限为16个
|
* 商户名称,字数上限为16个
|
||||||
*/
|
*/
|
||||||
private String merchantName;
|
private String merchantName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets background color.
|
||||||
|
*
|
||||||
|
* @param backgroundColor the background color
|
||||||
|
*/
|
||||||
|
public void setBackgroundColor(CouponBgColor backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBackgroundColor(String backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package cn.felord.payment.wechat.v3.model.ecommerce;
|
package cn.felord.payment.wechat.v3.model.ecommerce;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.BusinessCertType;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,6 +26,7 @@ import lombok.Data;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class EcommerceBusinessLicenseInfo {
|
public class EcommerceBusinessLicenseInfo {
|
||||||
|
private BusinessCertType certType;
|
||||||
private String businessLicenseCopy;
|
private String businessLicenseCopy;
|
||||||
private String businessLicenseNumber;
|
private String businessLicenseNumber;
|
||||||
private String merchantName;
|
private String merchantName;
|
||||||
|
|||||||
@@ -17,13 +17,20 @@
|
|||||||
|
|
||||||
package cn.felord.payment.wechat.v3.model.ecommerce;
|
package cn.felord.payment.wechat.v3.model.ecommerce;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.IdDocType;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class EcommerceContactInfo {
|
public class EcommerceContactInfo {
|
||||||
private String contactType;
|
private String contactType;
|
||||||
private String contactName;
|
private String contactName;
|
||||||
|
private IdDocType contactIdDocType;
|
||||||
private String contactIdCardNumber;
|
private String contactIdCardNumber;
|
||||||
|
private String contactIdDocCopy;
|
||||||
|
private String contactIdDocCopyBack;
|
||||||
|
private String contactIdDocPeriodEnd;
|
||||||
|
private String businessAuthorizationLetter;
|
||||||
|
private String contactIdDocPeriodBegin;
|
||||||
private String mobilePhone;
|
private String mobilePhone;
|
||||||
private String contactEmail;
|
private String contactEmail;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.ecommerce;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.IdDocType;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UboInfoListItem {
|
||||||
|
private IdDocType uboIdDocType;
|
||||||
|
private String uboIdDocCopy;
|
||||||
|
private String uboIdDocCopyBack;
|
||||||
|
private String uboIdDocName;
|
||||||
|
private String uboIdDocNumber;
|
||||||
|
private String uboIdDocAddress;
|
||||||
|
private LocalDate uboIdDocPeriodBegin;
|
||||||
|
private String uboIdDocPeriodEnd;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.ActivityStatus;
|
||||||
|
import cn.felord.payment.wechat.enumeration.AwardType;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ActivitiesListPageRequest {
|
||||||
|
private final long offset;
|
||||||
|
private final long limit;
|
||||||
|
private String activityName;
|
||||||
|
private ActivityStatus activityStatus;
|
||||||
|
private AwardType awardType;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ActivitiesPageRequest {
|
||||||
|
private final String activityId;
|
||||||
|
private Long offset;
|
||||||
|
private Long limit;
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.CouponBgColor;
|
||||||
|
import cn.felord.payment.wechat.enumeration.DeliveryPurpose;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Activity base info.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ActivityBaseInfo {
|
||||||
|
private String activityName;
|
||||||
|
private String activitySecondTitle;
|
||||||
|
private String merchantLogoUrl;
|
||||||
|
private String backgroundColor;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
|
private OffsetDateTime beginTime;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
|
private OffsetDateTime endTime;
|
||||||
|
private AvailablePeriods availablePeriods;
|
||||||
|
private String outRequestNo;
|
||||||
|
private DeliveryPurpose deliveryPurpose;
|
||||||
|
private String miniProgramsPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets background color.
|
||||||
|
*
|
||||||
|
* @param backgroundColor the background color
|
||||||
|
*/
|
||||||
|
void setBackgroundColor(String backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets background color.
|
||||||
|
*
|
||||||
|
* @param backgroundColor the background color
|
||||||
|
*/
|
||||||
|
public void setBackgroundColor(CouponBgColor backgroundColor) {
|
||||||
|
this.backgroundColor = backgroundColor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.DeliveryUserCategory;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AdvancedSetting {
|
||||||
|
private DeliveryUserCategory deliveryUserCategory;
|
||||||
|
private String merchantMemberAppid;
|
||||||
|
private Set<String> goodsTags;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Available periods.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AvailablePeriods {
|
||||||
|
private List<OffsetDateTimePeriods> availableTime;
|
||||||
|
private List<LocalTimePeriods> availableDayTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AwardItem {
|
||||||
|
private final String stock_id;
|
||||||
|
private final String original_image_url;
|
||||||
|
private String thumbnail_url;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import cn.felord.payment.wechat.enumeration.AwardType;
|
||||||
|
import cn.felord.payment.wechat.enumeration.SendContent;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 满送活动规则
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AwardSendRule {
|
||||||
|
private final int transactionAmountMinimum;
|
||||||
|
private final SendContent sendContent;
|
||||||
|
private final AwardType awardType;
|
||||||
|
private final List<AwardItem> awardList;
|
||||||
|
private final String merchantOption;
|
||||||
|
private final List<String> merchantIdList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DeleteActivityMchRequest {
|
||||||
|
private final String activityId;
|
||||||
|
private String deleteRequestNo;
|
||||||
|
private List<String> merchantIdList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class GiftActivityParams {
|
||||||
|
private final ActivityBaseInfo activityBaseInfo;
|
||||||
|
private final AwardSendRule awardSendRule;
|
||||||
|
private AdvancedSetting advancedSetting;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LocalTimePeriods {
|
||||||
|
@JsonFormat(pattern = "HHmmss")
|
||||||
|
private final OffsetDateTime beginDayTime;
|
||||||
|
@JsonFormat(pattern = "HHmmss")
|
||||||
|
private final OffsetDateTime endDayTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class NewActivityMchRequest {
|
||||||
|
private final String activityId;
|
||||||
|
private final String addRequestNo;
|
||||||
|
private List<String> merchantIdList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.felord.payment.wechat.v3.model.paygiftactivity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Time periods.
|
||||||
|
*
|
||||||
|
* @author dax
|
||||||
|
* @since 1.0.19.RELEASE
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OffsetDateTimePeriods {
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
|
private final OffsetDateTime beginTime;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
|
||||||
|
private final OffsetDateTime endTime;
|
||||||
|
}
|
||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2022 felord.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Website:
|
||||||
|
* https://felord.cn
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -5,7 +22,7 @@ import lombok.Data;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiafang
|
* @author dax
|
||||||
* @since 2023/1/3 10:27
|
* @since 2023/1/3 10:27
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
|||||||
@@ -22,11 +22,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.felord</groupId>
|
<groupId>cn.felord</groupId>
|
||||||
<artifactId>payment-spring-boot</artifactId>
|
<artifactId>payment-spring-boot</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.20.RELEASE</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>payment-spring-boot-starter</artifactId>
|
<artifactId>payment-spring-boot-starter</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -62,4 +62,4 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
10
pom.xml
10
pom.xml
@@ -21,7 +21,7 @@
|
|||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<groupId>cn.felord</groupId>
|
<groupId>cn.felord</groupId>
|
||||||
<artifactId>payment-spring-boot</artifactId>
|
<artifactId>payment-spring-boot</artifactId>
|
||||||
<version>1.0.18.RELEASE</version>
|
<version>1.0.21.RELEASE</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
@@ -88,9 +88,9 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<spring-boot.version>2.7.7</spring-boot.version>
|
<spring-boot.version>2.7.18</spring-boot.version>
|
||||||
<alipay-sdk.version>4.31.7.ALL</alipay-sdk.version>
|
<alipay-sdk.version>4.40.251.ALL</alipay-sdk.version>
|
||||||
<bcprov.version>1.69</bcprov.version>
|
<bcprov.version>1.78</bcprov.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
@@ -212,4 +212,4 @@
|
|||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
Reference in New Issue
Block a user