mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-11-29 01:05:12 +08:00
feat 分账接收方功能
This commit is contained in:
69
README.md
69
README.md
@@ -5,36 +5,32 @@
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/stars/dromara/dax-pay?style=flat&label=Github">
|
||||
<img src='https://gitee.com/bootx/dax-pay/badge/star.svg?theme=dark' alt='star'/>
|
||||
<img src="https://img.shields.io/badge/Dax%20Pay-2.0.8-success.svg" alt="Build Status"/>
|
||||
<img src="https://img.shields.io/badge/Dax%20Pay-3.0.0-success.svg" alt="Build Status"/>
|
||||
<img src="https://img.shields.io/badge/Author-Daxpay-orange.svg" alt="Build Status"/>
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-2.7.18-blue.svg" alt="Downloads"/>
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-3.3.4-blue.svg" alt="Downloads"/>
|
||||
<img src="https://img.shields.io/badge/license-Apache%20License%202.0-green.svg"/>
|
||||
</p>
|
||||
|
||||
# Dromara Dax-Pay(开源支付系统-单商户版)
|
||||
> **`multi-xxx` 相关分支为多商户版本, `single-xxx` 相关分支为单商户版本**
|
||||
|
||||
## ❗使用须知
|
||||
|
||||
`DaxPay`是一款基于`Apache License 2.0`协议分发的开源软件,受中华人民共和国相关法律法规的保护和限制,可以在符合[《用户授权使用协议》](用户授权使用协议.txt)和
|
||||
[《Apache License 2.0》](LICENSE)开源协议情况下进行免费使用、学习和交流。**在使用前请阅读上述协议,如果不同意请勿进行使用。**
|
||||
|
||||
## ⚠️多商户版本开发中
|
||||
> 当前单商户各种BUG问题将不会做特意的修复,使用者可以自行进行debug进行修改,后续新版单商户将基于多商户相同架构进行实现。
|
||||
|
||||
目前多商户版本已经进入开发中状态,为了更好的听取大家的建议,特建立一个征集需求建议的issues,欢迎提出各种功能需求和建议,填写地址:[功能和建议填写](https://gitee.com/dromara/dax-pay/issues/I9F3EO)
|
||||
|
||||
|
||||
## 🍈项目介绍
|
||||
|
||||
> DaxPay是一套开源支付网关系统,已经对接支付宝、微信支付、云闪付相关的接口。可以独立部署,提供接口供业务系统进行调用,不对原有系统产生影响
|
||||
> DaxPay是一套开源支付网关系统,已经对接支付宝、微信支付、云闪付相关的接口。可以独立部署,提供接口供业务系统进行调用,不对原有系统产生影响。
|
||||
>
|
||||
|
||||
## 🧭 特色功能
|
||||
- 封装各类支付通道的接口为统一的接口,方便业务系统进行调用,简化对接多种支付方式的复杂度
|
||||
- 已对接`微信支付`、`支付宝`和`云闪付`相关的接口,后续版本将支持`V3`版本的接口
|
||||
- 已对接`微信支付`、`支付宝`和`云闪付`相关的接口,并以扩展包的方式支持更多类型的通道
|
||||
- 支持支付、退款、对账、分账等支付相关的能力
|
||||
- 提供`HTTP`方式接口调用能力,和`Java`版本的`SDK`,方便业务系统进行对接
|
||||
- 接口请求和响应数据支持启用签名机制,保证交易安全可靠
|
||||
- 提供管理平台,方便运营人员进行管理和操作,不需要懂IT技术也可以轻松使用
|
||||
- 提供`聚合支付`、`电脑收银台`和`手机收银台`的演示模块,供开发者参考其实现支付功能的逻辑
|
||||
- 提供管理端,方便运营人员进行管理和操作,不需要懂IT技术也可以轻松使用
|
||||
|
||||
## 📃 文档和源码地址
|
||||
### 文档地址
|
||||
@@ -45,47 +41,30 @@
|
||||
|
||||
### 项目地址
|
||||
|
||||
| 项目 | GITEE | GITHUB |GITCODE |
|
||||
|---------|---------------------------------------------|-------------------------------------------------|---------------------------------------------|
|
||||
| 后端地址 | [GITEE](https://gitee.com/dromara/dax-pay) | [GITHUB](https://github.com/dromara/dax-pay) | [GITCODE](https://gitcode.com/dromara/dax-pay) |
|
||||
| Web前端地址 | [GITEE](https://gitee.com/bootx/dax-pay-ui) | [GITHUB](https://github.com/xxm1995/dax-pay-ui) | [GITCODE](https://github.com/daxpay/dax-pay-ui) |
|
||||
| H5前端地址 | [GITEE](https://gitee.com/bootx/dax-pay-h5) | [GITHUB](https://github.com/xxm1995/dax-pay-h5) | [GITCODE](https://github.com/daxpay/dax-pay-h5) |
|
||||
| 项目 | GITEE | GITHUB | GITCODE |
|
||||
|---------|---------------------------------------------|-------------------------------------------------|------------------------------------------------|
|
||||
| 后端地址 | [GITEE](https://gitee.com/dromara/dax-pay) | [GITHUB](https://github.com/dromara/dax-pay) | [GITCODE](https://gitcode.com/dromara/dax-pay) |
|
||||
| Web前端地址 | [GITEE](https://gitee.com/bootx/dax-pay-ui) | [GITHUB](https://github.com/xxm1995/dax-pay-ui) | |
|
||||
| H5前端地址 | [GITEE](https://gitee.com/bootx/dax-pay-h5) | [GITHUB](https://github.com/xxm1995/dax-pay-h5) | |
|
||||
|
||||
|
||||
## 🏬 系统演示
|
||||
### 管理平台:
|
||||
> 注:演示账号部分功能修改删除权限未开放。
|
||||
|
||||
地址:https://daxpay.demo.bootx.cn
|
||||
地址:https://single.web.daxpay.cn
|
||||
|
||||
账号:daxpay
|
||||
|
||||
密码:123456
|
||||
|
||||
### 网关接口
|
||||
> 注:接口平台只开放支付网关相关的接口,不开放系统其他接口。
|
||||
|
||||
地址: https://daxpay.server.bootx.cn/doc.html
|
||||
|
||||
账号: daxpay
|
||||
|
||||
密码: 123456
|
||||
|
||||
### 收银台演示
|
||||
> 请勿大额支付,可以通过后台管理端进行退款
|
||||
|
||||
电脑收银台地址: https://daxpay.demo.bootx.cn/#/cashier
|
||||
|
||||
手机收银台地址: https://daxpay.demo.bootx.cn/h5/#/cashier/uniCashier
|
||||
|
||||
## 🥞 核心技术栈
|
||||
| 名称 | 描述 | 版本要求 |
|
||||
|-------------|----------|----------------------------|
|
||||
| Jdk | Java环境 | 1.8+,11版本可以正常使用,但17+版本暂不支持 |
|
||||
| Spring Boot | 开发框架 | 2.7.x |
|
||||
| Redis | 分布式缓存 | 5.x版本及以上 |
|
||||
| MySQL | 数据库 | 基于5.7.X版本开发,基本支持8.x版本 |
|
||||
| Vue | 前端框架 | 3.x |
|
||||
| 名称 | 描述 | 版本要求 |
|
||||
|-------------|----------|-----------------------|
|
||||
| Jdk | Java环境 | 21+ |
|
||||
| Spring Boot | 开发框架 | 3.3.x |
|
||||
| Redis | 分布式缓存 | 5.x版本及以上 |
|
||||
| Vue | 前端框架 | 3.x |
|
||||
|
||||
## 🛠️ 业务系统接入
|
||||
> 业务系统想接入支付网关的话,不需要集成到业务系统里,只需要单独部署一份支付系统,然后业务系统通过接口调用即可拥有对应的支付能力,
|
||||
@@ -152,14 +131,6 @@ public class PayOrderTest {
|
||||
### 支付通道配置
|
||||

|
||||
## 🛣️ 路线图
|
||||
> dev为开发分支,本地运行请使用master或dev分支进行测试,当前正在进行整个系统的优化重构工作,各种功能都会有可能调整,
|
||||
`V2.1.0`时将作为正式生产可用版本进行发布,之后会保证系统版本非大版本升级时,API接口和数据接口向前兼容。
|
||||
**请勿在生产环境中使用,请等待生产可用的版本发布。如在使用,需要自己来保证应用的安全**
|
||||
|
||||
- 支持支付宝和微信V3版本接口
|
||||
- 支持撤销、转账等更多支付接口
|
||||
- 增加微信通知、钉钉通知、飞书通知能力
|
||||
- 支持服务商模式,以及一些间连通道,如通联支付、易宝支付等,更好适应小微收单场景
|
||||
|
||||
[**当前开发进度和任务池**](/_doc/Task.md)
|
||||
|
||||
|
||||
54
_doc/Task.md
54
_doc/Task.md
@@ -1,39 +1,17 @@
|
||||
## 单商户
|
||||
|
||||
2.0.9: 消息通知改版和系统优化
|
||||
- [ ] 增加类似支付宝应用通知的方式, 首先支持http方式通信
|
||||
- [ ] ~~修复功能优化, 更改为交易调整单, 并按交易类型进行拆分~~ 去除修复记录, 放到各支付方式中进行实现
|
||||
- [x] 支付订单调整
|
||||
- [x] 退款订单调整
|
||||
- [ ] 分账订单调整
|
||||
- [ ] 转账订单调整
|
||||
- [ ] 增加分账回调处理(支付宝)
|
||||
- [ ] 转账同步接口
|
||||
- [ ] 支持微信V3版本支付接口
|
||||
- [ ] 平台配置拆分出接口地址配置项
|
||||
|
||||
2.1.0.0: 多商户系统统一改造
|
||||
|
||||
- 脚手架同步为多商户脚手架的jdk8实现
|
||||
|
||||
**任务池**
|
||||
- [ ] 优化前端各种状态颜色展示
|
||||
- [ ] 增加验签调试等功能的页面
|
||||
- [ ] 聚合支付UA在前端判断, 提高响应速度
|
||||
- [ ] 记录异常交易信息: 存储到订单金额与网关不一致
|
||||
- [ ] 升级新版脚手架
|
||||
- [ ] 请求权限改版, 使用专用配置类
|
||||
- [ ] 增加收单收银台功能
|
||||
- [ ] 增加资金对账单功能
|
||||
- [ ] 新增支付单预警功能, 处理支付单与网关状态不一致且无法自动修复的情况
|
||||
- [ ] 差错单据处理
|
||||
- [ ] 支付成功回调订单已超时
|
||||
- [ ] 对账单据不平
|
||||
- [ ] 特殊退款接口
|
||||
- [ ] 统计报表功能
|
||||
- [ ] 微信新增V3版本接口
|
||||
- [ ] 增加各类日志记录,例如钱包的各项操作
|
||||
- [ ] 针对同步/对账等出现脏数据导致阻塞的问题, 进行优化
|
||||
- [ ] 同步接口
|
||||
- [ ] 对账接口
|
||||
|
||||
## 3.0.0: 功能完善第一阶段
|
||||
- 优化:
|
||||
- [x] 增加延时队列的可视页面
|
||||
- [ ] 增加首页驾驶舱功能
|
||||
- [ ] 定时同步任务频次不要太高, 预防产生过多的数据
|
||||
- [ ] 转账接收方类型优化
|
||||
- [ ] 支付/退款/转账商户订单号根据AppId做隔离
|
||||
- [ ] 云闪付支付通道对接
|
||||
- [ ] 分账功能
|
||||
- [ ] 分账接收方配置
|
||||
- [ ] 分账组管理
|
||||
- [ ] 自动分账管理
|
||||
- [ ] 分账单管理
|
||||
- [ ] 网关配套移动端开发
|
||||
- [x] OpenId获取页
|
||||
- [ ] 同步回调页
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.mapstruct.factory.Mappers;
|
||||
* @since 2022/1/12
|
||||
*/
|
||||
@Mapper
|
||||
public interface FileConvert {
|
||||
public interface FileConvert {
|
||||
|
||||
FileConvert CONVERT = Mappers.getMapper(FileConvert.class);
|
||||
|
||||
@@ -21,7 +21,6 @@ public interface FileConvert {
|
||||
|
||||
FileInfo toFileInfo(UploadFileInfo in);
|
||||
|
||||
UploadFileResult toDto(FileInfo in);
|
||||
|
||||
UploadFileResult toResult(FileInfo in);
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import cn.bootx.platform.starter.file.dao.UploadFileManager;
|
||||
import cn.bootx.platform.starter.file.entity.UploadFileInfo;
|
||||
import cn.bootx.platform.starter.file.param.UploadFileQuery;
|
||||
import cn.bootx.platform.starter.file.result.UploadFileResult;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@@ -99,7 +98,7 @@ public class FileUploadService {
|
||||
uploadPretreatment.setPath(LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy/MM/dd/"));
|
||||
|
||||
FileInfo upload = uploadPretreatment.upload();
|
||||
return FileConvert.CONVERT.toDto(upload);
|
||||
return FileConvert.CONVERT.toResult(upload);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package org.dromara.daxpay.channel.alipay.service.allocation.receiver;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.AlipayResponse;
|
||||
import com.alipay.api.domain.AlipayTradeRoyaltyRelationBindModel;
|
||||
import com.alipay.api.domain.AlipayTradeRoyaltyRelationUnbindModel;
|
||||
import com.alipay.api.domain.RoyaltyEntity;
|
||||
import com.alipay.api.request.AlipayTradeRoyaltyRelationBindRequest;
|
||||
import com.alipay.api.request.AlipayTradeRoyaltyRelationUnbindRequest;
|
||||
import com.alipay.api.response.AlipayTradeRoyaltyRelationBindResponse;
|
||||
import com.alipay.api.response.AlipayTradeRoyaltyRelationUnbindResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.alipay.code.AliPayCode;
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.ConfigErrorException;
|
||||
import org.dromara.daxpay.core.exception.TradeStatusErrorException;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.*;
|
||||
|
||||
|
||||
/**
|
||||
* 支付宝分账
|
||||
* @author xxm
|
||||
* @since 2024/3/28
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayAllocReceiverService {
|
||||
private final AliPayConfigService aliPayConfigService;
|
||||
|
||||
/**
|
||||
* 校验
|
||||
*/
|
||||
public boolean validation(AllocReceiver allocReceiver){
|
||||
List<String> list = Arrays.asList(USER_ID.getCode(), OPEN_ID.getCode(), LOGIN_NAME.getCode());
|
||||
String receiverType = allocReceiver.getReceiverType();
|
||||
return list.contains(receiverType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定关系
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void bind(AllocReceiver allocReceiver){
|
||||
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
|
||||
AlipayTradeRoyaltyRelationBindModel model = new AlipayTradeRoyaltyRelationBindModel();
|
||||
model.setOutRequestNo(String.valueOf(allocReceiver.getId()));
|
||||
|
||||
RoyaltyEntity entity = new RoyaltyEntity();
|
||||
AllocReceiverTypeEnum receiverTypeEnum = AllocReceiverTypeEnum.findByCode(allocReceiver.getReceiverType());
|
||||
entity.setType(this.getReceiverType(receiverTypeEnum));
|
||||
entity.setAccount(allocReceiver.getReceiverAccount());
|
||||
entity.setName(allocReceiver.getReceiverName());
|
||||
entity.setMemo(allocReceiver.getRelationName());
|
||||
|
||||
// 不报错视为同步成功
|
||||
model.setReceiverList(Collections.singletonList(entity));
|
||||
AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest();
|
||||
request.setBizModel(model);
|
||||
AlipayTradeRoyaltyRelationBindResponse response = alipayClient.execute(request);
|
||||
this.verifyErrorMsg(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑关系
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void unbind(AllocReceiver allocReceiver){
|
||||
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
|
||||
AlipayTradeRoyaltyRelationUnbindModel model = new AlipayTradeRoyaltyRelationUnbindModel();
|
||||
model.setOutRequestNo(String.valueOf(allocReceiver.getId()));
|
||||
|
||||
RoyaltyEntity entity = new RoyaltyEntity();
|
||||
AllocReceiverTypeEnum receiverTypeEnum = findByCode(allocReceiver.getReceiverType());
|
||||
entity.setType(this.getReceiverType(receiverTypeEnum));
|
||||
entity.setAccount(allocReceiver.getReceiverAccount());
|
||||
|
||||
model.setReceiverList(Collections.singletonList(entity));
|
||||
AlipayTradeRoyaltyRelationUnbindRequest request = new AlipayTradeRoyaltyRelationUnbindRequest();
|
||||
request.setBizModel(model);
|
||||
AlipayTradeRoyaltyRelationUnbindResponse response = alipayClient.execute(request);
|
||||
System.out.println(response);
|
||||
// 如果出现分账方不存在也视为成功
|
||||
if (Objects.equals(response.getSubCode(), AliPayCode.USER_NOT_EXIST)) {
|
||||
return;
|
||||
}
|
||||
this.verifyErrorMsg(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证错误信息
|
||||
*/
|
||||
private void verifyErrorMsg(AlipayResponse alipayResponse) {
|
||||
if (!Objects.equals(alipayResponse.getCode(), AliPayCode.ResponseCode.SUCCESS)) {
|
||||
String errorMsg = alipayResponse.getSubMsg();
|
||||
if (StrUtil.isBlank(errorMsg)) {
|
||||
errorMsg = alipayResponse.getMsg();
|
||||
}
|
||||
log.error("分账接收方处理失败 {}", errorMsg);
|
||||
throw new TradeStatusErrorException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分账接收方类型编码
|
||||
*/
|
||||
private String getReceiverType(AllocReceiverTypeEnum receiverTypeEnum){
|
||||
if (receiverTypeEnum == USER_ID){
|
||||
return "ali_user_id";
|
||||
}
|
||||
if (receiverTypeEnum == OPEN_ID){
|
||||
return "ali_open_id";
|
||||
}
|
||||
if (receiverTypeEnum == LOGIN_NAME){
|
||||
return "ali_login_name";
|
||||
}
|
||||
throw new ConfigErrorException("分账接收方类型错误");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import cn.bootx.platform.core.exception.ValidationFailedException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.alipay.service.allocation.receiver.AliPayAllocReceiverService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.strategy.AbsAllocReceiverStrategy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 支付宝分账接收者策略
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
|
||||
|
||||
private final AliPayAllocReceiverService receiverService;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.ALI.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AllocReceiverTypeEnum> getSupportReceiverTypes() {
|
||||
return List.of(AllocReceiverTypeEnum.LOGIN_NAME, AllocReceiverTypeEnum.USER_ID, AllocReceiverTypeEnum.OPEN_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验方法
|
||||
*/
|
||||
@Override
|
||||
public boolean validation(){
|
||||
return receiverService.validation(this.getAllocReceiver());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加到支付系统中
|
||||
*/
|
||||
@Override
|
||||
public void bind() {
|
||||
if (!receiverService.validation(this.getAllocReceiver())){
|
||||
throw new ValidationFailedException("分账接收者参数未通过校验");
|
||||
}
|
||||
receiverService.bind(this.getAllocReceiver());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从三方支付系统中删除
|
||||
*/
|
||||
@Override
|
||||
public void unbind() {
|
||||
if (!receiverService.validation(this.getAllocReceiver())){
|
||||
throw new ValidationFailedException("分账参数未通过校验");
|
||||
}
|
||||
receiverService.unbind(this.getAllocReceiver());
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.daxpay.channel.alipay.service.sync.AliPaySyncService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.sync.PaySyncResultBo;
|
||||
import org.dromara.daxpay.service.strategy.AbsSyncPayOrderStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -21,8 +20,6 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
@RequiredArgsConstructor
|
||||
public class AliPaySyncOrderStrategy extends AbsSyncPayOrderStrategy {
|
||||
|
||||
private final AliPayConfigService alipayConfigService;
|
||||
|
||||
private final AliPaySyncService alipaySyncService;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.daxpay.channel.alipay.service.sync.AliPayRefundSyncService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.service.bo.sync.RefundSyncResultBo;
|
||||
import org.dromara.daxpay.service.entity.order.refund.RefundOrder;
|
||||
import org.dromara.daxpay.service.strategy.AbsSyncRefundOrderStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -25,9 +24,6 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
@RequiredArgsConstructor
|
||||
public class AliPaySyncRefundStrategy extends AbsSyncRefundOrderStrategy {
|
||||
|
||||
|
||||
private final AliPayConfigService alipayConfigService;
|
||||
|
||||
private final AliPayRefundSyncService alipaySyncService;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.daxpay.channel.alipay.service.sync.AliPayTransferSyncService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.sync.TransferSyncResultBo;
|
||||
import org.dromara.daxpay.service.strategy.AbsSyncTransferOrderStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -22,7 +21,6 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
public class AliPaySyncTransferStrategy extends AbsSyncTransferOrderStrategy {
|
||||
|
||||
private final AliPayTransferSyncService syncTransferOrderStrategy;
|
||||
private final AliPayConfigService aliPayConfigService;
|
||||
|
||||
/**
|
||||
* 策略标识, 可以自行进行扩展
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy;
|
||||
|
||||
import cn.bootx.platform.core.exception.ValidationFailedException;
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.service.config.AliPayConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.alipay.service.transfer.AliPayTransferService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.core.param.trade.transfer.TransferParam;
|
||||
import org.dromara.daxpay.service.bo.trade.TransferResultBo;
|
||||
import org.dromara.daxpay.service.strategy.AbsTransferStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -29,12 +27,8 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayTransferStrategy extends AbsTransferStrategy {
|
||||
|
||||
private final AliPayConfigService payConfigService;
|
||||
|
||||
private final AliPayTransferService aliPayTransferService;
|
||||
|
||||
private AliPayConfig config;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.Receiver;
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReceiverRequest;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.ProfitSharingService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.ConfigErrorException;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.MERCHANT_NO;
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.OPEN_ID;
|
||||
|
||||
/**
|
||||
* 微信分账接收方服务
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatPayAllocReceiverV2Service {
|
||||
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
|
||||
/**
|
||||
* 绑定
|
||||
*/
|
||||
public void bind(AllocReceiver allocReceiver, WechatPayConfig config){
|
||||
AllocReceiverTypeEnum receiverTypeEnum = AllocReceiverTypeEnum.findByCode(allocReceiver.getReceiverType());
|
||||
String receiverType = this.getReceiverType(receiverTypeEnum);
|
||||
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
ProfitSharingService sharingService = wxPayService.getProfitSharingService();
|
||||
|
||||
ProfitSharingReceiverRequest request = new ProfitSharingReceiverRequest();
|
||||
Receiver receiver = new Receiver(receiverType,allocReceiver.getReceiverAccount(),allocReceiver.getReceiverName(),allocReceiver.getRelationType(),allocReceiver.getRelationName());
|
||||
List<Receiver> receivers = List.of(receiver);
|
||||
request.setReceiver(GSON.toJson(receivers));
|
||||
|
||||
try {
|
||||
sharingService.addReceiver(request);
|
||||
} catch (WxPayException e) {
|
||||
throw new OperationFailException("微信添加分账方V3失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除绑定
|
||||
*/
|
||||
public void unbind(AllocReceiver allocReceiver, WechatPayConfig config){
|
||||
AllocReceiverTypeEnum receiverTypeEnum = AllocReceiverTypeEnum.findByCode(allocReceiver.getReceiverType());
|
||||
String receiverType = this.getReceiverType(receiverTypeEnum);
|
||||
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
ProfitSharingService sharingService = wxPayService.getProfitSharingService();
|
||||
|
||||
ProfitSharingReceiverRequest request = new ProfitSharingReceiverRequest();
|
||||
Receiver receiver = new Receiver(receiverType,allocReceiver.getReceiverAccount());
|
||||
List<Receiver> receivers = List.of(receiver);
|
||||
request.setReceiver(GSON.toJson(receivers));
|
||||
try {
|
||||
sharingService.removeReceiver(request);
|
||||
} catch (WxPayException e) {
|
||||
throw new OperationFailException("微信添加分账方V3失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取分账接收方类型编码
|
||||
*/
|
||||
private String getReceiverType(AllocReceiverTypeEnum receiverTypeEnum){
|
||||
if (receiverTypeEnum == OPEN_ID){
|
||||
return "PERSONAL_OPENID";
|
||||
}
|
||||
if (receiverTypeEnum == MERCHANT_NO){
|
||||
return "MERCHANT_ID";
|
||||
}
|
||||
throw new ConfigErrorException("分账接收方类型错误");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.allocation;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReceiverV3Request;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.ProfitSharingService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.ConfigErrorException;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.MERCHANT_NO;
|
||||
import static org.dromara.daxpay.core.enums.AllocReceiverTypeEnum.OPEN_ID;
|
||||
|
||||
/**
|
||||
* 微信分账接收方服务
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatPayAllocReceiverV3Service {
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
/**
|
||||
* 校验参数是否合法
|
||||
*/
|
||||
public boolean validation(AllocReceiver allocReceiver){
|
||||
List<String> list = Arrays.asList(AllocReceiverTypeEnum.OPEN_ID.getCode(), AllocReceiverTypeEnum.MERCHANT_NO.getCode());
|
||||
String receiverType = allocReceiver.getReceiverType();
|
||||
return list.contains(receiverType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定
|
||||
*/
|
||||
public void bind(AllocReceiver allocReceiver, WechatPayConfig config){
|
||||
AllocReceiverTypeEnum receiverTypeEnum = AllocReceiverTypeEnum.findByCode(allocReceiver.getReceiverType());
|
||||
String receiverType = this.getReceiverType(receiverTypeEnum);
|
||||
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
ProfitSharingService sharingService = wxPayService.getProfitSharingService();
|
||||
|
||||
ProfitSharingReceiverV3Request request = new ProfitSharingReceiverV3Request();
|
||||
request.setType(receiverType);
|
||||
request.setAccount(allocReceiver.getReceiverAccount());
|
||||
request.setName(allocReceiver.getReceiverName());
|
||||
request.setRelationType(allocReceiver.getRelationType());
|
||||
request.setCustomRelation(allocReceiver.getRelationName());
|
||||
try {
|
||||
sharingService.addReceiverV3(request);
|
||||
} catch (WxPayException e) {
|
||||
throw new OperationFailException("微信添加分账方V3失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除绑定
|
||||
*/
|
||||
public void unbind(AllocReceiver allocReceiver, WechatPayConfig config){
|
||||
AllocReceiverTypeEnum receiverTypeEnum = AllocReceiverTypeEnum.findByCode(allocReceiver.getReceiverType());
|
||||
String receiverType = this.getReceiverType(receiverTypeEnum);
|
||||
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
ProfitSharingService sharingService = wxPayService.getProfitSharingService();
|
||||
|
||||
ProfitSharingReceiverV3Request request = new ProfitSharingReceiverV3Request();
|
||||
request.setType(receiverType);
|
||||
request.setAccount(allocReceiver.getReceiverAccount());
|
||||
request.setName(allocReceiver.getReceiverName());
|
||||
request.setRelationType(allocReceiver.getRelationType());
|
||||
request.setCustomRelation(allocReceiver.getRelationName());
|
||||
try {
|
||||
sharingService.removeReceiverV3(request);
|
||||
} catch (WxPayException e) {
|
||||
throw new OperationFailException("微信添加分账方V3失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分账接收方类型编码
|
||||
*/
|
||||
private String getReceiverType(AllocReceiverTypeEnum receiverTypeEnum){
|
||||
if (receiverTypeEnum == OPEN_ID){
|
||||
return "PERSONAL_OPENID";
|
||||
}
|
||||
if (receiverTypeEnum == MERCHANT_NO){
|
||||
return "MERCHANT_ID";
|
||||
}
|
||||
throw new ConfigErrorException("分账接收方类型错误");
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import org.springframework.stereotype.Service;
|
||||
@RequiredArgsConstructor
|
||||
public class WechatAuthService {
|
||||
|
||||
private final WechatPayConfigService weChatPayConfigService;
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
private final PlatformConfigService platformsConfigService;
|
||||
|
||||
@@ -80,7 +80,7 @@ public class WechatAuthService {
|
||||
* 获取微信公众号API的Service
|
||||
*/
|
||||
private WxMpService getWxMpService() {
|
||||
WechatPayConfig config = weChatPayConfigService.getWechatPayConfig();
|
||||
WechatPayConfig config = wechatPayConfigService.getWechatPayConfig();
|
||||
WxMpService wxMpService = new WxMpServiceImpl();
|
||||
WxMpDefaultConfigImpl wxMpConfig = new WxMpDefaultConfigImpl();
|
||||
wxMpConfig.setAppId(config.getWxAppId()); // 设置微信公众号的appid
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.close;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 微信支付关闭和退款
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2021/6/21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatPayCloseService {
|
||||
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import org.springframework.stereotype.Service;
|
||||
@RequiredArgsConstructor
|
||||
public class WechatPayCashierService {
|
||||
|
||||
private final WechatPayConfigService weChatPayConfigService;
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
private final PlatformConfigService platformConfigService;
|
||||
|
||||
@@ -86,7 +86,7 @@ public class WechatPayCashierService {
|
||||
* 获取微信公众号API的Service
|
||||
*/
|
||||
private WxMpService getWxMpService() {
|
||||
WechatPayConfig config = weChatPayConfigService.getWechatPayConfig();
|
||||
WechatPayConfig config = wechatPayConfigService.getWechatPayConfig();
|
||||
WxMpService wxMpService = new WxMpServiceImpl();
|
||||
WxMpDefaultConfigImpl wxMpConfig = new WxMpDefaultConfigImpl();
|
||||
wxMpConfig.setAppId(config.getWxAppId()); // 设置微信公众号的appid
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.dromara.daxpay.channel.wechat.strategy;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.code.WechatPayCode;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.service.allocation.WechatPayAllocReceiverV2Service;
|
||||
import org.dromara.daxpay.channel.wechat.service.allocation.WechatPayAllocReceiverV3Service;
|
||||
import org.dromara.daxpay.channel.wechat.service.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.strategy.AbsAllocReceiverStrategy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 微信分账接收策略
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@RequiredArgsConstructor
|
||||
public class WechatPayAllocReceiverStrategy extends AbsAllocReceiverStrategy {
|
||||
|
||||
private final WechatPayAllocReceiverV2Service receiverV2Service;
|
||||
|
||||
private final WechatPayAllocReceiverV3Service receiverV3Service;
|
||||
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
private WechatPayConfig config;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.WECHAT.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AllocReceiverTypeEnum> getSupportReceiverTypes() {
|
||||
return List.of(AllocReceiverTypeEnum.OPEN_ID, AllocReceiverTypeEnum.MERCHANT_NO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验方法
|
||||
*/
|
||||
@Override
|
||||
public boolean validation(){
|
||||
List<String> list = Arrays.asList(AllocReceiverTypeEnum.OPEN_ID.getCode(), AllocReceiverTypeEnum.MERCHANT_NO.getCode());
|
||||
String receiverType = this.getAllocReceiver().getReceiverType();
|
||||
return list.contains(receiverType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBeforeHandler(){
|
||||
this.config = wechatPayConfigService.getWechatPayConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加到支付系统中
|
||||
*/
|
||||
@Override
|
||||
public void bind() {
|
||||
if (Objects.equals(config.getApiVersion(), WechatPayCode.API_V2)){
|
||||
receiverV2Service.bind(getAllocReceiver(), this.config);
|
||||
} else {
|
||||
receiverV3Service.bind(getAllocReceiver(), this.config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从三方支付系统中删除
|
||||
*/
|
||||
@Override
|
||||
public void unbind() {
|
||||
if (Objects.equals(config.getApiVersion(), WechatPayCode.API_V2)){
|
||||
receiverV2Service.unbind(getAllocReceiver(), this.config);
|
||||
} else {
|
||||
receiverV3Service.unbind(getAllocReceiver(), this.config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,6 @@ public class WechatPayCashierStrategy extends AbsChannelCashierStrategy {
|
||||
|
||||
/**
|
||||
* 获取认证结果
|
||||
*
|
||||
* @param param
|
||||
*/
|
||||
@Override
|
||||
public AuthResult doAuth(CashierAuthCodeParam param) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT
|
||||
@RequiredArgsConstructor
|
||||
public class WechatRefundStrategy extends AbsRefundStrategy {
|
||||
|
||||
private final WechatPayConfigService weChatPayConfigService;
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
private final WechatRefundV2Service wechatRefundV2Service;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class WechatRefundStrategy extends AbsRefundStrategy {
|
||||
*/
|
||||
@Override
|
||||
public void doBeforeRefundHandler() {
|
||||
this.config = weChatPayConfigService.getWechatPayConfig();
|
||||
this.config = wechatPayConfigService.getWechatPayConfig();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.dromara.daxpay;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
package org.dromara.daxpay;
|
||||
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
/**
|
||||
* 移动端前端转发
|
||||
* 移动端前端转发
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@@ -23,7 +22,6 @@ public class FrontH5Interceptor implements HandlerInterceptor {
|
||||
// 对于静态资源,继续处理
|
||||
return true;
|
||||
}
|
||||
|
||||
// 不包含后缀的路径,转发到 index.html
|
||||
request.getRequestDispatcher("/h5/index.html").forward(request, response);
|
||||
// 阻止继续处理请求
|
||||
|
||||
@@ -38,4 +38,4 @@ easy-trans:
|
||||
# 平台配置
|
||||
bootx-platform:
|
||||
config:
|
||||
client-code: dax-pay-server
|
||||
client-code: dax-pay
|
||||
|
||||
@@ -12,9 +12,9 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
public enum AllocOrderStatusEnum {
|
||||
|
||||
ALLOCATION_PROCESSING("allocation_processing", "分账处理中"),
|
||||
ALLOCATION_END("allocation_end", "分账完成"),
|
||||
ALLOCATION_FAILED("allocation_failed", "分账失败"),
|
||||
ALLOC_PROCESSING("alloc_processing", "分账处理中"),
|
||||
ALLOC_END("alloc_end", "分账完成"),
|
||||
ALLOC_FAILED("alloc_failed", "分账失败"),
|
||||
FINISH("finish", "完结"),
|
||||
FINISH_FAILED("finish_failed", "完结失败"),
|
||||
;
|
||||
|
||||
@@ -4,7 +4,6 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账接收方类型
|
||||
@@ -14,17 +13,14 @@ import java.util.List;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AllocReceiverTypeEnum {
|
||||
/** 个人 */
|
||||
WX_PERSONAL("wx_personal", "个人"),
|
||||
/** 商户 */
|
||||
WX_MERCHANT("wx_merchant", "商户"),
|
||||
|
||||
/** userId 以2088开头的纯16位数字 */
|
||||
ALI_USER_ID("ali_user_id", "用户ID"),
|
||||
/** 商户号 */
|
||||
MERCHANT_NO("merchant_no", "商户号"),
|
||||
/** userId */
|
||||
USER_ID("user_id", "用户ID"),
|
||||
/** openId */
|
||||
ALI_OPEN_ID("ali_open_id", "openId"),
|
||||
OPEN_ID("open_id", "openId"),
|
||||
/** 账号 */
|
||||
ALI_LOGIN_NAME("ali_login_name", "账号");
|
||||
LOGIN_NAME("login_name", "账号");
|
||||
|
||||
/** 编码 */
|
||||
private final String code;
|
||||
@@ -41,9 +37,4 @@ public enum AllocReceiverTypeEnum {
|
||||
.orElseThrow(() -> new IllegalArgumentException("未找到对应的分账接收方类型"));
|
||||
}
|
||||
|
||||
/** 微信支持类型 */
|
||||
public static final List<AllocReceiverTypeEnum> WECHAT_LIST = List.of(WX_PERSONAL, WX_MERCHANT);
|
||||
/** 支付宝支持类型 */
|
||||
public static final List<AllocReceiverTypeEnum> ALI_LIST = List.of(ALI_OPEN_ID, ALI_USER_ID, ALI_LOGIN_NAME);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import lombok.Getter;
|
||||
public enum PayAllocStatusEnum {
|
||||
WAITING("waiting", "待分账"),
|
||||
ALLOCATION("allocation", "已分账"),
|
||||
/** 部分通道不支持分账 */
|
||||
IGNORE("ignore", "忽略分账"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
package org.dromara.daxpay.service.controller.allocation;
|
||||
|
||||
import cn.bootx.platform.core.rest.Res;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.core.rest.result.PageResult;
|
||||
import cn.bootx.platform.core.rest.result.Result;
|
||||
import cn.bootx.platform.core.util.ValidationUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupBindParam;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupParam;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupQuery;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupUnbindParam;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupReceiverResult;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupResult;
|
||||
import org.dromara.daxpay.service.service.allocation.AllocGroupService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账组
|
||||
* @author xxm
|
||||
* @since 2024/4/2
|
||||
*/
|
||||
@Tag(name = "分账组")
|
||||
@RestController
|
||||
@RequestMapping("/allocation/group")
|
||||
@RequiredArgsConstructor
|
||||
public class AllocGroupController {
|
||||
private final AllocGroupService allocGroupService;
|
||||
|
||||
@Operation(summary = "分页")
|
||||
@GetMapping("/page")
|
||||
public Result<PageResult<AllocGroupResult>> page(PageParam pageParam, AllocGroupQuery query){
|
||||
return Res.ok(allocGroupService.page(pageParam,query));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询详情")
|
||||
@GetMapping("/findById")
|
||||
public Result<AllocGroupResult> findById(Long id){
|
||||
return Res.ok(allocGroupService.findById(id));
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "编码是否存在")
|
||||
@GetMapping("/existsByGroupNo")
|
||||
public Result<Boolean> existsByGroupNo(String groupNo, String appId){
|
||||
return Res.ok(allocGroupService.existsByGroupNo(groupNo, appId));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询分账接收方信息")
|
||||
@GetMapping("/findReceiversByGroups")
|
||||
public Result<List<AllocGroupReceiverResult>> findReceiversByGroups(Long groupId){
|
||||
return Res.ok(allocGroupService.findReceiversByGroups(groupId));
|
||||
}
|
||||
|
||||
@Operation(summary = "创建")
|
||||
@PostMapping("/create")
|
||||
public Result<Void> create(@RequestBody AllocGroupParam param){
|
||||
allocGroupService.create(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改")
|
||||
@PostMapping("/update")
|
||||
public Result<Void> update(@RequestBody AllocGroupParam param){
|
||||
allocGroupService.update(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除")
|
||||
@PostMapping("/delete")
|
||||
public Result<Void> delete(Long id){
|
||||
allocGroupService.delete(id);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "批量绑定接收者")
|
||||
@PostMapping("/bindReceivers")
|
||||
public Result<Void> bindReceivers(@RequestBody AllocGroupBindParam param){
|
||||
ValidationUtil.validateParam(param);
|
||||
allocGroupService.bindReceivers(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "批量取消绑定接收者")
|
||||
@PostMapping("/unbindReceivers")
|
||||
public Result<Void> unbindReceivers(@RequestBody AllocGroupUnbindParam param){
|
||||
allocGroupService.unbindReceivers(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "取消绑定接收者")
|
||||
@PostMapping("/unbindReceiver")
|
||||
public Result<Void> unbindReceiver(Long receiverId){
|
||||
allocGroupService.unbindReceiver(receiverId);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改分账比例")
|
||||
@PostMapping("/updateRate")
|
||||
public Result<Void> updateRate(Long receiverId, BigDecimal rate){
|
||||
allocGroupService.updateRate(receiverId,rate);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "设置默认分账组")
|
||||
@PostMapping("/setDefault")
|
||||
public Result<Void> setDefault(Long id){
|
||||
allocGroupService.setUpDefault(id);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "清除默认分账组")
|
||||
@PostMapping("/clearDefault")
|
||||
public Result<Void> clearDefault(Long id){
|
||||
allocGroupService.clearDefault(id);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.dromara.daxpay.service.controller.allocation;
|
||||
|
||||
import cn.bootx.platform.core.rest.Res;
|
||||
import cn.bootx.platform.core.rest.dto.LabelValue;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.core.rest.result.PageResult;
|
||||
import cn.bootx.platform.core.rest.result.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverAddParam;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverQuery;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverRemoveParam;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocReceiverResult;
|
||||
import org.dromara.daxpay.service.service.allocation.AllocReceiverService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账接收方控制器
|
||||
* @author xxm
|
||||
* @since 2024/3/28
|
||||
*/
|
||||
@Validated
|
||||
@Tag(name = "分账接收方控制器")
|
||||
@RestController
|
||||
@RequestMapping("/allocation/receiver")
|
||||
@RequiredArgsConstructor
|
||||
public class AllocReceiverController {
|
||||
|
||||
private final AllocReceiverService receiverService;
|
||||
|
||||
@Operation(summary = "分页")
|
||||
@GetMapping("/page")
|
||||
public Result<PageResult<AllocReceiverResult>> page(PageParam pageParam, AllocReceiverQuery query){
|
||||
return Res.ok(receiverService.page(pageParam, query));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询详情")
|
||||
@GetMapping("/findById")
|
||||
public Result<AllocReceiverResult> findById(Long id){
|
||||
return Res.ok(receiverService.findById(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "编码是否存在")
|
||||
@GetMapping("/existsByReceiverNo")
|
||||
public Result<Boolean> existsByReceiverNo(@NotBlank(message = "接收者编号必填") String receiverNo,@NotBlank(message = "商户应用ID必填") String appId){
|
||||
return Res.ok(receiverService.existsByReceiverNo(receiverNo, appId));
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "添加")
|
||||
@PostMapping("/add")
|
||||
public Result<Void> add(@RequestBody @Validated AllocReceiverAddParam param){
|
||||
receiverService.addAndSync(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除")
|
||||
@PostMapping("/delete")
|
||||
public Result<Void> delete(@RequestBody @Validated AllocReceiverRemoveParam param){
|
||||
receiverService.removeAndSync(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "可分账的通道列表")
|
||||
@GetMapping("/findChannels")
|
||||
public Result<List<LabelValue>> findChannels(){
|
||||
return Res.ok(receiverService.findChannels());
|
||||
}
|
||||
|
||||
@Operation(summary = "根据通道获取分账接收方类型")
|
||||
@GetMapping("/findReceiverTypeByChannel")
|
||||
public Result<List<LabelValue>> findReceiverTypeByChannel(String channel){
|
||||
return Res.ok(receiverService.findReceiverTypeByChannel(channel));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.dromara.daxpay.service.convert.allocation;
|
||||
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroup;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupParam;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupResult;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocGroupConvert {
|
||||
AllocGroupConvert CONVERT = Mappers.getMapper(AllocGroupConvert.class);
|
||||
|
||||
AllocGroupResult convert(AllocGroup in);
|
||||
|
||||
AllocGroup convert(AllocGroupParam in);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.dromara.daxpay.service.convert.allocation;
|
||||
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroupReceiver;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupReceiverParam;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupReceiverResult;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocGroupReceiverConvert {
|
||||
AllocGroupReceiverConvert CONVERT = Mappers.getMapper(AllocGroupReceiverConvert.class);
|
||||
|
||||
AllocGroupReceiverResult convert(AllocGroupReceiver in);
|
||||
|
||||
AllocGroupReceiver convert(AllocGroupReceiverParam in);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.dromara.daxpay.service.convert.allocation;
|
||||
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverAddParam;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocReceiverResult;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/3/28
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocReceiverConvert {
|
||||
AllocReceiverConvert CONVERT = Mappers.getMapper(AllocReceiverConvert.class);
|
||||
|
||||
AllocReceiver convert(AllocReceiverAddParam in);
|
||||
|
||||
AllocReceiverResult toResult(AllocReceiver in);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.dromara.daxpay.service.dao.allocation.receiver;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.query.generator.QueryGenerator;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroup;
|
||||
import org.dromara.daxpay.service.param.allocation.group.AllocGroupQuery;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class AllocGroupManager extends BaseManager<AllocGroupMapper, AllocGroup> {
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<AllocGroup> page(PageParam pageParam, AllocGroupQuery query) {
|
||||
Page<AllocGroup> mpPage = MpUtil.getMpPage(pageParam, AllocGroup.class);
|
||||
QueryWrapper<AllocGroup> generator = QueryGenerator.generator(query);
|
||||
return page(mpPage,generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分账组编号查询
|
||||
*/
|
||||
public Optional<AllocGroup> findByGroupNo(String groupNo, String appId) {
|
||||
return this.lambdaQuery()
|
||||
.eq(AllocGroup::getGroupNo,groupNo)
|
||||
.eq(AllocGroup::getAppId,appId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除默认分账组
|
||||
*/
|
||||
public void clearDefault(String channel, String appId) {
|
||||
lambdaUpdate()
|
||||
.set(AllocGroup::isDefaultGroup,false)
|
||||
.eq(AllocGroup::getChannel,channel)
|
||||
.eq(AllocGroup::getAppId,appId)
|
||||
.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认分账组
|
||||
*/
|
||||
public Optional<AllocGroup> findDefaultGroup(String channel, String appId) {
|
||||
return this.lambdaQuery()
|
||||
.eq(AllocGroup::getChannel,channel)
|
||||
.eq(AllocGroup::isDefaultGroup,true)
|
||||
.eq(AllocGroup::getAppId,appId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账组编号是否存在
|
||||
*/
|
||||
public boolean existedByGroupNo(String groupNo, String appId) {
|
||||
return this.lambdaQuery()
|
||||
.eq(AllocGroup::getGroupNo,groupNo)
|
||||
.eq(AllocGroup::getAppId,appId)
|
||||
.exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.daxpay.service.dao.allocation.receiver;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroup;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocGroupMapper extends MPJBaseMapper<AllocGroup> {
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.dromara.daxpay.service.dao.allocation.receiver;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroupReceiver;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class AllocGroupReceiverManager extends BaseManager<AllocGroupReceiverMapper, AllocGroupReceiver> {
|
||||
|
||||
|
||||
/**
|
||||
* 判断接收者是否已经被使用
|
||||
*/
|
||||
public boolean isUsed(Long receiverId){
|
||||
return existedByField(AllocGroupReceiver::getReceiverId, receiverId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分组ID进行查询
|
||||
*/
|
||||
public List<AllocGroupReceiver> findByGroupId(Long groupId){
|
||||
return findAllByField(AllocGroupReceiver::getGroupId, groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分组ID进行批量删除
|
||||
*/
|
||||
public void deleteByGroupId(Long groupId){
|
||||
deleteByField(AllocGroupReceiver::getGroupId, groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在分账接收者
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.daxpay.service.dao.allocation.receiver;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroupReceiver;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocGroupReceiverMapper extends MPJBaseMapper<AllocGroupReceiver> {
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.dromara.daxpay.service.dao.allocation.receiver;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.query.generator.QueryGenerator;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverQuery;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 分账接收方
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class AllocReceiverManager extends BaseManager<AllocReceiverMapper, AllocReceiver> {
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public Page<AllocReceiver> page(PageParam pageParam, AllocReceiverQuery param){
|
||||
Page<AllocReceiver> mpPage = MpUtil.getMpPage(pageParam, AllocReceiver.class);
|
||||
QueryWrapper<AllocReceiver> generator = QueryGenerator.generator(param);
|
||||
return this.page(mpPage, generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据接收方编号查询
|
||||
*/
|
||||
public Optional<AllocReceiver> findByReceiverNo(String receiverNo, String appId) {
|
||||
return lambdaQuery()
|
||||
.eq(AllocReceiver::getReceiverNo, receiverNo)
|
||||
.eq(MchAppBaseEntity::getAppId, appId)
|
||||
.oneOpt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分账方编号查询列表
|
||||
*/
|
||||
public List<AllocReceiver> findAllByReceiverNos(List<String> receiverNos, String appId) {
|
||||
return lambdaQuery()
|
||||
.eq(AllocReceiver::getReceiverNo, receiverNos)
|
||||
.eq(MchAppBaseEntity::getAppId, appId)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据所属通道查询
|
||||
*/
|
||||
public List<AllocReceiver> findAllByChannel(String channel, String appId) {
|
||||
return lambdaQuery()
|
||||
.eq(AllocReceiver::getChannel, channel)
|
||||
.eq(MchAppBaseEntity::getAppId, appId)
|
||||
.list();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断是否存在
|
||||
*/
|
||||
public boolean existedByReceiverNo(String receiverNo, String appId) {
|
||||
return lambdaQuery()
|
||||
.eq(AllocReceiver::getReceiverNo, receiverNo)
|
||||
.eq(MchAppBaseEntity::getAppId, appId)
|
||||
.exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.daxpay.service.dao.allocation.receiver;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocReceiverMapper extends MPJBaseMapper<AllocReceiver> {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.dromara.daxpay.service.dao.config;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.service.entity.config.AllocConfig;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class AllocConfigManger extends BaseManager<AllocConfigMapper, AllocConfig> {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.dromara.daxpay.service.dao.config;
|
||||
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.dromara.daxpay.service.entity.config.AllocConfig;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@Mapper
|
||||
public interface AllocConfigMapper extends MPJBaseMapper<AllocConfig> {
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,15 @@ import java.util.Optional;
|
||||
@RequiredArgsConstructor
|
||||
public class ChannelCashierConfigManage extends BaseManager<ChannelCashierConfigMapper, ChannelCashierConfig> {
|
||||
|
||||
/**
|
||||
* 根据AppId查询列表
|
||||
*/
|
||||
public List<ChannelCashierConfig> findAllByAppId(String appId) {
|
||||
return this.lambdaQuery()
|
||||
.eq(ChannelCashierConfig::getAppId, appId)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断类型是否存在
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -54,7 +53,7 @@ public class AllocOrderManager extends BaseManager<AllocOrderMapper, AllocOrder>
|
||||
* 查询待同步的分账单
|
||||
*/
|
||||
public List<AllocOrder> findSyncOrder(){
|
||||
List<String> statusList = List.of(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode(), AllocOrderStatusEnum.ALLOCATION_END.getCode());
|
||||
List<String> statusList = List.of(AllocOrderStatusEnum.ALLOC_PROCESSING.getCode(), AllocOrderStatusEnum.ALLOC_END.getCode());
|
||||
return lambdaQuery()
|
||||
.in(AllocOrder::getStatus, statusList)
|
||||
.list();
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package org.dromara.daxpay.service.entity.allocation.receiver;
|
||||
|
||||
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
import cn.bootx.platform.common.mybatisplus.function.ToResult;
|
||||
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
import org.dromara.daxpay.service.convert.allocation.AllocGroupConvert;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupResult;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -17,7 +21,8 @@ import java.math.BigDecimal;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AllocGroup extends MchAppBaseEntity {
|
||||
@TableName("pay_alloc_group")
|
||||
public class AllocGroup extends MchAppBaseEntity implements ToResult<AllocGroupResult> {
|
||||
|
||||
/** 分账组编码 */
|
||||
private String groupNo;
|
||||
@@ -37,4 +42,9 @@ public class AllocGroup extends MchAppBaseEntity {
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
@Override
|
||||
public AllocGroupResult toResult() {
|
||||
return AllocGroupConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package org.dromara.daxpay.service.entity.allocation.receiver;
|
||||
|
||||
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
import cn.bootx.platform.common.mybatisplus.function.ToResult;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
import org.dromara.daxpay.service.convert.allocation.AllocGroupReceiverConvert;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupReceiverResult;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -15,7 +19,8 @@ import java.math.BigDecimal;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AllocGroupReceiver extends MchAppBaseEntity {
|
||||
@TableName("pay_alloc_group_receiver")
|
||||
public class AllocGroupReceiver extends MchAppBaseEntity implements ToResult<AllocGroupReceiverResult> {
|
||||
|
||||
/** 分账组ID */
|
||||
private Long groupId;
|
||||
@@ -25,4 +30,9 @@ public class AllocGroupReceiver extends MchAppBaseEntity {
|
||||
|
||||
/** 分账比例(百分之多少) */
|
||||
private BigDecimal rate;
|
||||
|
||||
@Override
|
||||
public AllocGroupReceiverResult toResult() {
|
||||
return AllocGroupReceiverConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.dromara.daxpay.service.entity.allocation.receiver;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.function.ToResult;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.AllocRelationTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
@@ -9,6 +11,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.service.convert.allocation.AllocReceiverConvert;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocReceiverResult;
|
||||
|
||||
/**
|
||||
* 分账接收方
|
||||
@@ -18,7 +22,8 @@ import lombok.experimental.Accessors;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AllocReceiver extends MchAppBaseEntity {
|
||||
@TableName("pay_alloc_receiver")
|
||||
public class AllocReceiver extends MchAppBaseEntity implements ToResult<AllocReceiverResult> {
|
||||
|
||||
/** 分账接收方编号, 需要保证唯一 */
|
||||
private String receiverNo;
|
||||
@@ -51,4 +56,9 @@ public class AllocReceiver extends MchAppBaseEntity {
|
||||
|
||||
/** 关系名称 */
|
||||
private String relationName;
|
||||
|
||||
@Override
|
||||
public AllocReceiverResult toResult() {
|
||||
return AllocReceiverConvert.CONVERT.toResult(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.dromara.daxpay.service.entity.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分账配置
|
||||
* @author xxm
|
||||
* @since 2024/10/6
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("pay_alloc_config")
|
||||
public class AllocConfig extends MchAppBaseEntity {
|
||||
|
||||
/** 是否自动分账 */
|
||||
private Boolean autoAlloc;
|
||||
|
||||
/** 开启分账最低额 */
|
||||
private Boolean enableAllocLimit;
|
||||
|
||||
/** 大于多少开启分账 */
|
||||
private BigDecimal minAmount;
|
||||
|
||||
/** 分账时机类型 立即/定期/延时 */
|
||||
private String allocTimeType;
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package org.dromara.daxpay.service.entity.config;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.function.ToResult;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.core.enums.CashierTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.core.enums.PayMethodEnum;
|
||||
@@ -8,11 +12,6 @@ import org.dromara.daxpay.service.common.entity.MchAppBaseEntity;
|
||||
import org.dromara.daxpay.service.convert.config.ChannelCashierConfigConvert;
|
||||
import org.dromara.daxpay.service.param.config.ChannelCashierConfigParam;
|
||||
import org.dromara.daxpay.service.result.config.ChannelCashierConfigResult;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 通道收银台配置
|
||||
@@ -55,7 +54,6 @@ public class ChannelCashierConfig extends MchAppBaseEntity implements ToResult<C
|
||||
private Boolean autoAllocation;
|
||||
|
||||
/** 备注 */
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
public static ChannelCashierConfig init(ChannelCashierConfigParam param){
|
||||
|
||||
@@ -31,8 +31,8 @@ public class AllocOrderDetail extends MchAppBaseEntity {
|
||||
/** 分账接收方编号 */
|
||||
private String receiverNo;
|
||||
|
||||
/** 分账比例 */
|
||||
private Integer rate;
|
||||
/** 分账比例(百分之多少) */
|
||||
private BigDecimal rate;
|
||||
|
||||
/** 分账金额 */
|
||||
private BigDecimal amount;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.dromara.daxpay.service.param.allocation.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账组绑定参数
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组绑定参数")
|
||||
public class AllocGroupBindParam {
|
||||
|
||||
@NotNull(message = "分账组ID不可为空")
|
||||
@Schema(description = "分账组ID")
|
||||
private Long groupId;
|
||||
|
||||
@Valid
|
||||
@NotEmpty(message = "分账接收方不可为空")
|
||||
@Schema(description = "分账接收方集合")
|
||||
private List<AllocGroupReceiverParam> receivers;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.dromara.daxpay.service.param.allocation.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 分账组参数
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组参数")
|
||||
public class AllocGroupParam {
|
||||
|
||||
@Schema(description = "主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分账组编号")
|
||||
private String groupNo;
|
||||
|
||||
@Schema(description = "分组名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "通道")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "商户应用ID")
|
||||
private String appId;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.dromara.daxpay.service.param.allocation.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.service.common.param.MchAppQuery;
|
||||
|
||||
/**
|
||||
* 分账组参数
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组参数")
|
||||
public class AllocGroupQuery extends MchAppQuery {
|
||||
|
||||
@Schema(description = "分账组编号")
|
||||
private String groupNo;
|
||||
|
||||
@Schema(description = "分组名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "通道")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "商户应用ID")
|
||||
private String appId;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.dromara.daxpay.service.param.allocation.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.DecimalMax;
|
||||
import javax.validation.constraints.Min;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分账组接收者参数
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组接收者参数")
|
||||
public class AllocGroupReceiverParam {
|
||||
|
||||
@NotNull(message = "接收者ID不可为空")
|
||||
@Schema(description = "接收者ID")
|
||||
private Long receiverId;
|
||||
|
||||
@Schema(description = "分账比例(百分之多少)")
|
||||
@NotNull(message = "分账比例不可为空")
|
||||
@Min(value = 0,message = "分账比例不可为负数")
|
||||
@DecimalMax(value = "100",message = "分账比例不可大于100%")
|
||||
@DecimalMin(value = "0.01", message = "分账比例不可小于0.01%")
|
||||
@Digits(integer = 3, fraction = 2, message = "分账比例最多只允许两位小数")
|
||||
private BigDecimal rate;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.dromara.daxpay.service.param.allocation.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账组接收者解除绑定
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组取消接收者绑定")
|
||||
public class AllocGroupUnbindParam {
|
||||
|
||||
@NotNull(message = "分账组ID不可为空")
|
||||
@Schema(description = "分账组ID")
|
||||
private Long groupId;
|
||||
|
||||
@NotBlank(message = "分账接收方不可为空")
|
||||
@Schema(description = "分账接收方集合")
|
||||
List<Long> receiverIds;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.dromara.daxpay.service.param.allocation.receiver;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.AllocRelationTypeEnum;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 分账接收者添加参数
|
||||
* @author xxm
|
||||
* @since 2024/5/20
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账接收者添加参数")
|
||||
public class AllocReceiverAddParam{
|
||||
|
||||
@Schema(description = "接收者编号, 需要保证唯一")
|
||||
@NotBlank(message = "接收者编号必填")
|
||||
@Size(max = 32, message = "接收者编号不可超过32位")
|
||||
private String receiverNo;
|
||||
|
||||
/**
|
||||
* 所属通道
|
||||
* @see ChannelEnum
|
||||
*/
|
||||
@Schema(description = "所属通道")
|
||||
@NotBlank(message = "所属通道必填")
|
||||
@Size(max = 20, message = "所属通道不可超过20位")
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 分账接收方类型 根据不同类型的通道进行传输
|
||||
* @see AllocReceiverTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账接收方类型")
|
||||
@NotBlank(message = "分账接收方类型必填")
|
||||
@Size(max = 20, message = "分账接收方类型不可超过20位")
|
||||
private String receiverType;
|
||||
|
||||
/** 接收方账号 */
|
||||
@Schema(description = "接收方账号")
|
||||
@NotBlank(message = "接收方账号必填")
|
||||
@Size(max = 100, message = "接收方账号不可超过100位")
|
||||
private String receiverAccount;
|
||||
|
||||
/** 接收方姓名 */
|
||||
@Schema(description = "接收方姓名")
|
||||
@Size(max = 100, message = "接收方姓名不可超过50位")
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 分账关系类型
|
||||
* @see AllocRelationTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账关系类型")
|
||||
@NotBlank(message = "分账关系类型必填")
|
||||
@Size(max = 20, message = "分账关系类型不可超过20位")
|
||||
private String relationType;
|
||||
|
||||
/** 关系名称 关系类型为自定义是填写 */
|
||||
@Schema(description = "关系名称")
|
||||
@Size(max = 50, message = "关系名称不可超过50位")
|
||||
private String relationName;
|
||||
|
||||
@Schema(description = "商户应用ID")
|
||||
@NotBlank(message = "商户应用ID必填")
|
||||
@Size(max = 32, message = "商户应用ID不可超过32位")
|
||||
private String appId;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.dromara.daxpay.service.param.allocation.receiver;
|
||||
|
||||
import cn.bootx.platform.core.annotation.QueryParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.dromara.daxpay.core.enums.AllocRelationTypeEnum;
|
||||
import org.dromara.daxpay.service.common.param.MchAppQuery;
|
||||
|
||||
/**
|
||||
* 分账接收方查询条件
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class AllocReceiverQuery extends MchAppQuery {
|
||||
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
|
||||
@Schema(description = "接收方编号")
|
||||
private String receiverNo;
|
||||
|
||||
/**
|
||||
* @see org.dromara.daxpay.core.enums.ChannelEnum
|
||||
*/
|
||||
@Schema(description = "所属通道")
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 分账接收方类型 个人/商户
|
||||
*/
|
||||
@Schema(description = "分账接收方类型")
|
||||
private String receiverType;
|
||||
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
|
||||
@Schema(description = "接收方账号")
|
||||
private String receiverAccount;
|
||||
|
||||
/** 接收方姓名 */
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
|
||||
@Schema(description = "接收方姓名")
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 分账关系类型
|
||||
* @see AllocRelationTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账关系类型")
|
||||
private String relationType;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.dromara.daxpay.service.param.allocation.receiver;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 分账接收者删除参数
|
||||
* @author xxm
|
||||
* @since 2024/5/20
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账接收者删除参数")
|
||||
public class AllocReceiverRemoveParam {
|
||||
|
||||
@Schema(description = "接收者编号")
|
||||
@NotBlank(message = "接收者编号必填")
|
||||
@Size(max = 32, message = "接收者编号不可超过32位")
|
||||
private String receiverNo;
|
||||
|
||||
@Schema(description = "商户应用ID")
|
||||
@NotBlank(message = "商户应用ID必填")
|
||||
@Size(max = 32, message = "商户应用ID不可超过32位")
|
||||
private String appId;
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
|
||||
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "商户应用查询参数")
|
||||
public class MchAppQuery {
|
||||
public final class MchAppQuery {
|
||||
|
||||
/** 应用名称 */
|
||||
@Schema(description = "应用号")
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.dromara.daxpay.service.result.allocation;
|
||||
|
||||
import cn.bootx.platform.common.jackson.sensitive.SensitiveInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.core.enums.AllocRelationTypeEnum;
|
||||
import org.dromara.daxpay.core.result.MchAppResult;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分账组接收方信息
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组接收方信息")
|
||||
public class AllocGroupReceiverResult extends MchAppResult {
|
||||
|
||||
@Schema(description = "接收方ID")
|
||||
private Long receiverId;
|
||||
|
||||
@Schema(description = "接收方编号")
|
||||
private String receiverNo;
|
||||
|
||||
@Schema(description = "分账比例(百分之多少)")
|
||||
private BigDecimal rate;
|
||||
|
||||
/**
|
||||
* 分账接收方类型
|
||||
* @see org.dromara.daxpay.core.enums.AllocReceiverTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账接收方类型")
|
||||
private String receiverType;
|
||||
|
||||
@Schema(description = "接收方账号")
|
||||
@SensitiveInfo
|
||||
private String receiverAccount;
|
||||
|
||||
/** 接收方姓名 */
|
||||
@Schema(description = "接收方姓名")
|
||||
@SensitiveInfo(SensitiveInfo.SensitiveType.CHINESE_NAME)
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 分账关系类型
|
||||
* @see AllocRelationTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账关系类型")
|
||||
private String relationType;
|
||||
|
||||
@Schema(description = "关系名称")
|
||||
private String relationName;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.dromara.daxpay.service.result.allocation;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.core.result.MchAppResult;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 分账组
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账组")
|
||||
public class AllocGroupResult extends MchAppResult {
|
||||
|
||||
@Schema(description = "分账组编号")
|
||||
private String groupNo;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "通道")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "默认分账组")
|
||||
private Boolean defaultGroup;
|
||||
|
||||
@Schema(description = "分账比例(百分之多少)")
|
||||
private BigDecimal totalRate;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.dromara.daxpay.service.result.allocation;
|
||||
|
||||
import cn.bootx.platform.common.jackson.sensitive.SensitiveInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.core.result.MchAppResult;
|
||||
|
||||
/**
|
||||
* 分账接收方
|
||||
* @author xxm
|
||||
* @since 2024/3/28
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账接收方")
|
||||
public class AllocReceiverResult extends MchAppResult {
|
||||
|
||||
@Schema(description = "账号别名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "接收方编号")
|
||||
private String receiverNo;
|
||||
|
||||
/**
|
||||
* @see ChannelEnum
|
||||
*/
|
||||
@Schema(description = "所属通道")
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 分账接收方类型 个人/商户
|
||||
* @see org.dromara.daxpay.core.enums.AllocReceiverTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账接收方类型")
|
||||
private String receiverType;
|
||||
|
||||
|
||||
@Schema(description = "接收方账号")
|
||||
@SensitiveInfo
|
||||
private String receiverAccount;
|
||||
|
||||
/** 接收方姓名 */
|
||||
@Schema(description = "接收方姓名")
|
||||
@SensitiveInfo(SensitiveInfo.SensitiveType.CHINESE_NAME)
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 分账关系类型
|
||||
* @see org.dromara.daxpay.core.enums.AllocRelationTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账关系类型")
|
||||
private String relationType;
|
||||
|
||||
@Schema(description = "关系名称")
|
||||
private String relationName;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import java.math.BigDecimal;
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "商户应用")
|
||||
public class MchAppResult extends BaseResult {
|
||||
public final class MchAppResult extends BaseResult {
|
||||
|
||||
/** 应用号 */
|
||||
@Schema(description = "应用号")
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
package org.dromara.daxpay.service.service.allocation;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.function.CollectorsFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.core.exception.BizException;
|
||||
import cn.bootx.platform.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.core.rest.result.PageResult;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.service.convert.allocation.AllocGroupConvert;
|
||||
import org.dromara.daxpay.service.dao.allocation.receiver.AllocGroupManager;
|
||||
import org.dromara.daxpay.service.dao.allocation.receiver.AllocGroupReceiverManager;
|
||||
import org.dromara.daxpay.service.dao.allocation.receiver.AllocReceiverManager;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroup;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroupReceiver;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.dromara.daxpay.service.param.allocation.group.*;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupReceiverResult;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocGroupResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 分账组服务
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AllocGroupService {
|
||||
private final AllocGroupManager groupManager;
|
||||
private final AllocGroupReceiverManager groupReceiverManager;
|
||||
private final AllocReceiverManager receiverManager;
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public PageResult<AllocGroupResult> page(PageParam pageParam, AllocGroupQuery query){
|
||||
return MpUtil.toPageResult(groupManager.page(pageParam, query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
*/
|
||||
public AllocGroupResult findById(Long id){
|
||||
return groupManager.findById(id).map(AllocGroup::toResult).orElseThrow(()->new DataNotExistException("分账组不存在"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分账接收方
|
||||
*/
|
||||
public List<AllocGroupReceiverResult> findReceiversByGroups(Long groupId){
|
||||
List<AllocGroupReceiver> groupReceivers = groupReceiverManager.findByGroupId(groupId);
|
||||
List<Long> receiverIds = groupReceivers.stream()
|
||||
.map(AllocGroupReceiver::getReceiverId)
|
||||
.collect(Collectors.toList());
|
||||
// 查询关联接收方信息
|
||||
Map<Long, AllocReceiver> receiverMap = receiverManager.findAllByIds(receiverIds)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(AllocReceiver::getId, Function.identity(), CollectorsFunction::retainLatest));
|
||||
// 组装信息
|
||||
return groupReceivers.stream()
|
||||
.map(o -> {
|
||||
AllocReceiver receiver = receiverMap.get(o.getReceiverId());
|
||||
AllocGroupReceiverResult result = new AllocGroupReceiverResult()
|
||||
.setReceiverId(receiver.getId())
|
||||
.setReceiverNo(receiver.getReceiverNo())
|
||||
.setReceiverAccount(receiver.getReceiverAccount())
|
||||
.setReceiverName(receiver.getReceiverName())
|
||||
.setRate(o.getRate())
|
||||
.setReceiverType(receiver.getReceiverType())
|
||||
.setRelationName(receiver.getRelationName())
|
||||
.setRelationType(receiver.getRelationType());
|
||||
result.setId(o.getId());
|
||||
return result;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建分账组
|
||||
*/
|
||||
public void create(AllocGroupParam param){
|
||||
AllocGroup group = AllocGroupConvert.CONVERT.convert(param);
|
||||
group.setTotalRate(BigDecimal.ZERO);
|
||||
groupManager.save(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认分账组
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void setUpDefault(Long id){
|
||||
// 分账组
|
||||
AllocGroup group = groupManager.findById(id).orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
groupManager.clearDefault(group.getChannel(), group.getAppId());
|
||||
group.setDefaultGroup(true);
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除默认分账组
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void clearDefault(Long id){
|
||||
AllocGroup group = groupManager.findById(id).orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
group.setDefaultGroup(false);
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新分账组
|
||||
*/
|
||||
public void update(AllocGroupParam param){
|
||||
AllocGroup group = groupManager.findById(param.getId()).orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
BeanUtil.copyProperties(param,group, CopyOptions.create().ignoreNullValue());
|
||||
group.setTotalRate(null);
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分账组
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(Long id){
|
||||
groupManager.deleteById(id);
|
||||
groupReceiverManager.deleteByGroupId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定分账接收方
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void bindReceivers(AllocGroupBindParam param) {
|
||||
// 分账组
|
||||
AllocGroup group = groupManager.findById(param.getGroupId()).orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
// 查询接收方
|
||||
List<AllocGroupReceiverParam> receiverParams = param.getReceivers();
|
||||
List<Long> receiverIds = receiverParams.stream()
|
||||
.map(AllocGroupReceiverParam::getReceiverId)
|
||||
.collect(Collectors.toList());
|
||||
List<AllocReceiver> receivers = receiverManager.findAllByIds(receiverIds);
|
||||
if (receivers.size() != receiverIds.size()){
|
||||
throw new DataNotExistException("传入的分账接收房数量与查询到的不一致");
|
||||
}
|
||||
// 接收方只能为一个支付通道
|
||||
long count = receivers.stream()
|
||||
.map(AllocReceiver::getChannel)
|
||||
.distinct()
|
||||
.count();
|
||||
if (count > 1){
|
||||
throw new BizException("接收方只能为一个支付通道");
|
||||
}
|
||||
// 检查接收方和传入的通道是否是不一致
|
||||
if (!Objects.equals(group.getChannel(), receivers.getFirst().getChannel())){
|
||||
throw new BizException("接收方和传入的通道不一致");
|
||||
}
|
||||
|
||||
// 保存分账接收者
|
||||
List<AllocGroupReceiver> groupReceivers = receivers.stream()
|
||||
.map(receiver -> new AllocGroupReceiver().setGroupId(group.getId())
|
||||
.setReceiverId(receiver.getId())
|
||||
.setRate(receiverParams.get(receivers.indexOf(receiver))
|
||||
.getRate()))
|
||||
.collect(Collectors.toList());
|
||||
groupReceiverManager.saveAll(groupReceivers);
|
||||
// 计算分账比例
|
||||
var sum = receiverParams.stream()
|
||||
.map(AllocGroupReceiverParam::getRate)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
group.setTotalRate(group.getTotalRate().add(sum));
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除分账接收方
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void unbindReceivers(AllocGroupUnbindParam param){
|
||||
// 分账组
|
||||
AllocGroup group = groupManager.findById(param.getGroupId())
|
||||
.orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
// 删除接收方
|
||||
List<AllocGroupReceiver> receivers = groupReceiverManager.findAllByIds(param.getReceiverIds());
|
||||
if (receivers.size() != param.getReceiverIds().size()){
|
||||
throw new DataNotExistException("传入的分账接收房数量与查询到的不一致");
|
||||
}
|
||||
groupReceiverManager.deleteByIds(param.getReceiverIds());
|
||||
// 计算分账比例
|
||||
var sum = receivers.stream()
|
||||
.map(AllocGroupReceiver::getRate)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
group.setTotalRate(group.getTotalRate().subtract(sum));
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个分账接收方
|
||||
*/
|
||||
@Transactional
|
||||
public void unbindReceiver(Long receiverId){
|
||||
AllocGroupReceiver groupReceiver = groupReceiverManager.findById(receiverId)
|
||||
.orElseThrow(() -> new DataNotExistException("未找到分账接收方"));
|
||||
AllocGroup group = groupManager.findById(groupReceiver.getGroupId())
|
||||
.orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
// 更新分账比例
|
||||
group.setTotalRate(group.getTotalRate().subtract(groupReceiver.getRate()));
|
||||
// 更新接收比例
|
||||
groupReceiverManager.deleteById(receiverId);
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改分账比例
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateRate(Long receiverId, BigDecimal rate){
|
||||
AllocGroupReceiver groupReceiver = groupReceiverManager.findById(receiverId)
|
||||
.orElseThrow(() -> new DataNotExistException("未找到分账接收方"));
|
||||
AllocGroup group = groupManager.findById(groupReceiver.getGroupId())
|
||||
.orElseThrow(() -> new DataNotExistException("未找到分账组"));
|
||||
// 更新分账比例
|
||||
group.setTotalRate(group.getTotalRate().subtract(groupReceiver.getRate()).add(rate));
|
||||
// 更新接收比例
|
||||
groupReceiver.setRate(rate);
|
||||
groupReceiverManager.updateById(groupReceiver);
|
||||
groupManager.updateById(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断分账组编号是否存在
|
||||
*/
|
||||
public boolean existsByGroupNo(String groupNo, String appId) {
|
||||
return groupManager.existedByGroupNo(groupNo, appId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package org.dromara.daxpay.service.service.allocation;
|
||||
|
||||
import cn.bootx.platform.baseapi.service.dict.DictionaryItemService;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.core.exception.ValidationFailedException;
|
||||
import cn.bootx.platform.core.rest.dto.LabelValue;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.core.rest.result.PageResult;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.core.exception.DataErrorException;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.core.exception.OperationProcessingException;
|
||||
import org.dromara.daxpay.service.convert.allocation.AllocReceiverConvert;
|
||||
import org.dromara.daxpay.service.dao.allocation.receiver.AllocGroupReceiverManager;
|
||||
import org.dromara.daxpay.service.dao.allocation.receiver.AllocReceiverManager;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverAddParam;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverQuery;
|
||||
import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverRemoveParam;
|
||||
import org.dromara.daxpay.service.result.allocation.AllocReceiverResult;
|
||||
import org.dromara.daxpay.service.strategy.AbsAllocReceiverStrategy;
|
||||
import org.dromara.daxpay.service.strategy.PaymentStrategy;
|
||||
import org.dromara.daxpay.service.util.PaymentStrategyFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 分账接收方服务类
|
||||
* @author xxm
|
||||
* @since 2024/3/27
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AllocReceiverService {
|
||||
|
||||
private final AllocGroupReceiverManager groupReceiverManager;
|
||||
|
||||
private final AllocReceiverManager allocReceiverManager;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final DictionaryItemService dictionaryItemService;
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public PageResult<AllocReceiverResult> page(PageParam pageParam, AllocReceiverQuery query) {
|
||||
return MpUtil.toPageResult(allocReceiverManager.page(pageParam, query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
*/
|
||||
public AllocReceiverResult findById(Long id) {
|
||||
return allocReceiverManager.findById(id)
|
||||
.map(AllocReceiver::toResult)
|
||||
.orElseThrow(() -> new DataNotExistException("分账接收方不存在"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码是否存在
|
||||
*/
|
||||
public boolean existsByReceiverNo(String receiverNo, String appId) {
|
||||
return allocReceiverManager.existedByReceiverNo(receiverNo, appId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分账接收方并同步到三方支付系统中
|
||||
*/
|
||||
public void addAndSync(AllocReceiverAddParam param) {
|
||||
// 判断是否已经添加
|
||||
LockInfo lock = lockTemplate.lock("payment:receiver:" + param.getReceiverNo(), 10000, 200);
|
||||
if (Objects.isNull(lock)) {
|
||||
throw new OperationProcessingException("分账方处理中,请勿重复操作");
|
||||
}
|
||||
try {
|
||||
Optional<AllocReceiver> receiverOptional = allocReceiverManager.findByReceiverNo(param.getReceiverNo(),param.getAppId());
|
||||
if (receiverOptional.isPresent()) {
|
||||
throw new OperationFailException("该接收方已存在");
|
||||
}
|
||||
AllocReceiver receiver = AllocReceiverConvert.CONVERT.convert(param);
|
||||
// 获取策略
|
||||
AbsAllocReceiverStrategy receiverStrategy = PaymentStrategyFactory.create(param.getChannel(), AbsAllocReceiverStrategy.class);
|
||||
// 校验
|
||||
receiverStrategy.setAllocReceiver(receiver);
|
||||
if (!receiverStrategy.validation()) {
|
||||
throw new ValidationFailedException("接收方信息校验失败");
|
||||
}
|
||||
// 先添加到三方支付系统中, 然后保存到本地
|
||||
receiverStrategy.doBeforeHandler();
|
||||
receiverStrategy.bind();
|
||||
allocReceiverManager.save(receiver);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账方删除
|
||||
*/
|
||||
public void removeAndSync(AllocReceiverRemoveParam param) {
|
||||
// 判断是否存在
|
||||
AllocReceiver receiver = allocReceiverManager.findByReceiverNo(param.getReceiverNo(), param.getAppId())
|
||||
.orElseThrow(() -> new DataErrorException("该接收方不存在"));
|
||||
if (groupReceiverManager.isUsed(receiver.getId())) {
|
||||
throw new OperationFailException("该接收方已被使用,无法被删除");
|
||||
}
|
||||
// 获取策略
|
||||
var receiverStrategy = PaymentStrategyFactory.create(receiver.getChannel(), AbsAllocReceiverStrategy.class);
|
||||
LockInfo lock = lockTemplate.lock("payment:receiver:" + param.getReceiverNo(), 10000, 200);
|
||||
if (Objects.isNull(lock)) {
|
||||
throw new OperationProcessingException("分账方处理中,请勿重复操作");
|
||||
}
|
||||
try {
|
||||
receiverStrategy.setAllocReceiver(receiver);
|
||||
// 校验
|
||||
receiverStrategy.validation();
|
||||
// 预处理
|
||||
receiverStrategy.doBeforeHandler();
|
||||
// 取消绑定
|
||||
receiverStrategy.unbind();
|
||||
allocReceiverManager.deleteById(receiver.getId());
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 可分账的通道列表
|
||||
*/
|
||||
public List<LabelValue> findChannels() {
|
||||
// 先查询策略, 然后查询通道并进行过滤
|
||||
List<String> channelCodes = SpringUtil.getBeansOfType(AbsAllocReceiverStrategy.class)
|
||||
.values()
|
||||
.stream()
|
||||
.map(PaymentStrategy::getChannel)
|
||||
.toList();
|
||||
return dictionaryItemService.findEnableByDictCode("channel").stream()
|
||||
.filter(item -> channelCodes.contains(item.getCode()))
|
||||
.map(item -> new LabelValue(item.getName(), item.getCode()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据通道获取分账接收方类型
|
||||
*/
|
||||
public List<LabelValue> findReceiverTypeByChannel(String channel) {
|
||||
var receiverStrategy = PaymentStrategyFactory.create(channel, AbsAllocReceiverStrategy.class);
|
||||
return receiverStrategy.getSupportReceiverTypes().stream()
|
||||
.map(o-> new LabelValue(o.getName(), o.getCode()))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -27,17 +27,17 @@ import java.util.List;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ChannelCashierConfigService {
|
||||
private final ChannelCashierConfigManage cashierConfigManage;
|
||||
|
||||
private final MchAppManager mchAppManager;
|
||||
|
||||
private final ChannelCashierConfigManage cashierConfigManage;
|
||||
|
||||
private final PlatformConfigService platformConfigService;
|
||||
|
||||
/**
|
||||
* 分页
|
||||
* 列表
|
||||
*/
|
||||
public List<ChannelCashierConfigResult> findByAppId(String appId) {
|
||||
return MpUtil.toListResult(cashierConfigManage.findAll());
|
||||
return MpUtil.toListResult(cashierConfigManage.findAllByAppId(appId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.dromara.daxpay.service.strategy;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum;
|
||||
import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账抽象策略
|
||||
* @author xxm
|
||||
* @since 2024/4/1
|
||||
*/
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class AbsAllocReceiverStrategy implements PaymentStrategy{
|
||||
|
||||
private AllocReceiver allocReceiver;
|
||||
|
||||
/**
|
||||
* 支持的接收者类型
|
||||
*/
|
||||
public abstract List<AllocReceiverTypeEnum> getSupportReceiverTypes();
|
||||
|
||||
/**
|
||||
* 操作前校验
|
||||
*/
|
||||
public boolean validation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作前处理, 校验和初始化支付配置
|
||||
*/
|
||||
public void doBeforeHandler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加到三方支付系统中
|
||||
*/
|
||||
public abstract void bind();
|
||||
|
||||
/**
|
||||
* 从三方支付系统中删除
|
||||
*/
|
||||
public abstract void unbind();
|
||||
}
|
||||
@@ -27,4 +27,6 @@ public class PaymentStrategyFactory {
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new UnsupportedAbilityException("不支持的能力"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user