diff --git a/README.md b/README.md index 7c0981e4b..c5c0928be 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ -# Dromara Dax-Pay(开源支付系统) -

+

+ +

+ +

+ star Build Status Build Status @@ -9,6 +13,7 @@

+# Dromara Dax-Pay(开源支付系统) ## ❗使用须知 `DaxPay`是一款基于`Apache License 2.0`协议分发的开源软件,受中华人民共和国相关法律法规的保护和限制,可以在符合[《用户授权使用协议》](用户授权使用协议.txt)和 @@ -24,6 +29,7 @@ - 封装各类支付通道的接口为统一的接口,方便业务系统进行调用,简化对接多种支付方式的复杂度 - 已对接`微信支付`、`支付宝`和云闪付相关的接口,后续版本将支持`V3`版本的接口 - 支持组合支付,满足用户系统需要多种方式同时进行支付的场景。 +- 支持支付、退款、对账、分账等支付相关的能力 - 提供`HTTP`方式接口调用能力,和`Java`版本的`SDK`,方便业务系统进行对接 - 接口请求和响应数据支持启用签名机制,可根据实际需要进行开关,保证交易安全可靠 - 提供管理平台,方便运营人员进行管理和操作,不需要懂IT技术也可以轻松使用 @@ -204,12 +210,9 @@ Apache License Version 2.0 display: flex; flex-wrap: wrap; } - - .member-project a { padding: 10px; } - .member-project a img { height: 40px; } diff --git a/_doc/Task.md b/_doc/Task.md index 5260e9a69..e5a080c25 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -1,12 +1,12 @@ 2.0.5: - [ ] 资金流水优化 -- [ ] 支付通道配置是否支持分账 +- [x] 支付通道配置是否支持分账 - [ ] 分账接收方管理 - [ ] 分账组管理 - [ ] 分账订单管理 - [ ] 统计报表功能 - [x] 修复创建支付订单报错时, 订单保存数据不完整 -- [ ] DEMI增加获取微信OpenID和支付宝OpenId功能 +- [ ] DEMO增加获取微信OpenID和支付宝OpenId功能 2.0.x 版本内容 - [ ] 三方支付外部订单号规则优化: 支付P、退款R、分账A,根据环境加前缀:DEV_、DEMO_、PRE_ @@ -20,6 +20,7 @@ - [ ] 同步接口 - [ ] 对账接口 - [ ] 增加通道开通能力管理,在操作发起前的校验时提前进行拦截 +- [ ] 支付通道两个独立的配置进行合并为一个 **任务池** - [ ] 对账改造: diff --git a/_doc/images/dax-pay.svg b/_doc/images/dax-pay.svg new file mode 100644 index 000000000..f274be717 --- /dev/null +++ b/_doc/images/dax-pay.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationGroupController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationGroupController.java new file mode 100644 index 000000000..c2aa6d38b --- /dev/null +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationGroupController.java @@ -0,0 +1,101 @@ +package cn.bootx.platform.daxpay.admin.controller.allocation; + +import cn.bootx.platform.common.core.rest.PageResult; +import cn.bootx.platform.common.core.rest.Res; +import cn.bootx.platform.common.core.rest.ResResult; +import cn.bootx.platform.common.core.rest.param.PageParam; +import cn.bootx.platform.common.core.util.ValidationUtil; +import cn.bootx.platform.daxpay.service.core.payment.allocation.service.AllocationGroupService; +import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupDto; +import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverResult; +import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupBindParam; +import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupParam; +import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupUnbindParam; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 分账组 + * @author xxm + * @since 2024/4/2 + */ +@Tag(name = "分账组") +@RestController +@RequestMapping("/allocation/group") +@RequiredArgsConstructor +public class AllocationGroupController { + private final AllocationGroupService allocationGroupService; + + @Operation(summary = "分页") + @GetMapping("/page") + public ResResult> page(PageParam pageParam, AllocationGroupParam query){ + return Res.ok(allocationGroupService.page(pageParam,query)); + } + + @Operation(summary = "查询详情") + @GetMapping("/findById") + public ResResult findById(Long id){ + return Res.ok(allocationGroupService.findById(id)); + } + + @Operation(summary = "查询分账接收方信息") + @GetMapping("/findReceiversByGroups") + public ResResult> findReceiversByGroups(Long groupId){ + return Res.ok(allocationGroupService.findReceiversByGroups(groupId)); + } + + @Operation(summary = "创建") + @PostMapping("/create") + public ResResult create(@RequestBody AllocationGroupParam param){ + allocationGroupService.create(param); + return Res.ok(); + } + + @Operation(summary = "修改") + @PostMapping("/update") + public ResResult update(@RequestBody AllocationGroupParam param){ + allocationGroupService.update(param); + return Res.ok(); + } + + @Operation(summary = "删除") + @PostMapping("/delete") + public ResResult delete(Long id){ + allocationGroupService.delete(id); + return Res.ok(); + } + + @Operation(summary = "批量绑定接收者") + @PostMapping("/bindReceivers") + public ResResult bindReceivers(@RequestBody AllocationGroupBindParam param){ + ValidationUtil.validateParam(param); + allocationGroupService.bindReceivers(param); + return Res.ok(); + } + + @Operation(summary = "批量取消绑定接收者") + @PostMapping("/unbindReceivers") + public ResResult unbindReceivers(@RequestBody AllocationGroupUnbindParam param){ + allocationGroupService.unbindReceivers(param); + return Res.ok(); + } + + @Operation(summary = "取消绑定接收者") + @PostMapping("/unbindReceiver") + public ResResult unbindReceiver(Long receiverId){ + allocationGroupService.unbindReceiver(receiverId); + return Res.ok(); + } + + @Operation(summary = "修改分账比例") + @PostMapping("/updateRate") + public ResResult updateRate(Long receiverId, Integer rate){ + allocationGroupService.updateRate(receiverId,rate); + return Res.ok(); + } + +} diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationReceiverController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationReceiverController.java index 072fb62e2..f64180994 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationReceiverController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/allocation/AllocationReceiverController.java @@ -3,6 +3,7 @@ package cn.bootx.platform.daxpay.admin.controller.allocation; import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; +import cn.bootx.platform.common.core.rest.dto.LabelValue; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.daxpay.service.core.payment.allocation.service.AllocationReceiverService; import cn.bootx.platform.daxpay.service.dto.allocation.AllocationReceiverDto; @@ -11,10 +12,9 @@ import cn.bootx.platform.daxpay.service.param.allocation.AllocationReceiverQuery import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; /** * 对账接收方控制器 @@ -41,20 +41,38 @@ public class AllocationReceiverController { return Res.ok(receiverService.findById(id)); } + @Operation(summary = "获取可以分账的通道") + @GetMapping("/findChannels") + public ResResult> findChannels(){ + return Res.ok(receiverService.findChannels()); + } + @Operation(summary = "根据通道获取分账接收方类型") + @GetMapping("/findReceiverTypeByChannel") + public ResResult> findReceiverTypeByChannel(String channel){ + return Res.ok(receiverService.findReceiverTypeByChannel(channel)); + } + @Operation(summary = "新增") - @PostMapping("") - public ResResult add(AllocationReceiverParam param){ + @PostMapping("add") + public ResResult add(@RequestBody AllocationReceiverParam param){ receiverService.add(param); return Res.ok(); } @Operation(summary = "修改") @PostMapping("update") - public ResResult update(AllocationReceiverParam param){ + public ResResult update(@RequestBody AllocationReceiverParam param){ receiverService.update(param); return Res.ok(); } + @Operation(summary = "删除") + @PostMapping("delete") + public ResResult delete(Long id){ + receiverService.remove(id); + return Res.ok(); + } + @Operation(summary = "同步到三方支付系统中") @PostMapping("registerByGateway") public ResResult registerByGateway(Long id){ diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/AllocationReceiverTypeEnum.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/AllocationReceiverTypeEnum.java index 22c7121c4..9db403765 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/AllocationReceiverTypeEnum.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/AllocationReceiverTypeEnum.java @@ -3,8 +3,12 @@ package cn.bootx.platform.daxpay.code; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + /** - * 分账接收方类型枚举 + * 分账接收方类型 * @author xxm * @since 2024/4/1 */ @@ -12,18 +16,27 @@ import lombok.Getter; @AllArgsConstructor public enum AllocationReceiverTypeEnum { /** 个人 */ - WX_PERSONAL("PERSONAL_OPENID", "个人"), + WX_PERSONAL("wx_personal","PERSONAL_OPENID", "个人"), /** 商户 */ - WX_MERCHANT("MERCHANT_ID", "商户"), + WX_MERCHANT("wx_merchant","MERCHANT_ID", "商户"), /** userId 以2088开头的纯16位数字 */ - ALI_USER_ID("userId", "账号ID"), + ALI_USER_ID("ali_user_id","userId", "用户ID"), /** openId */ - ALI_OPEN_ID("openId", "登录号"), + ALI_OPEN_ID("ali_open_id","openId", "openId"), /** 账号 */ - ALI_LOGIN_NAME("loginName", "openId"); + ALI_LOGIN_NAME("ali_login_name","loginName", "账号"); + /** 编码 */ private final String code; + /** 外部编码, 三方支付系统使用的编码 */ + private final String outCode; + /** 名称 */ private final String name; + /** 微信支持类型 */ + public static final List WECHAT_LIST = Collections.unmodifiableList(Arrays.asList(WX_PERSONAL, WX_MERCHANT)); + /** 支付宝支持类型 */ + public static final List ALI_LIST = Collections.unmodifiableList(Arrays.asList(ALI_OPEN_ID, ALI_USER_ID, ALI_LOGIN_NAME)); + } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayChannelEnum.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayChannelEnum.java index 131247596..55da288b1 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayChannelEnum.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/code/PayChannelEnum.java @@ -45,12 +45,6 @@ public enum PayChannelEnum { .orElseThrow(() -> new PayFailureException("不存在的支付通道")); } - /** 支付宝 UA */ - public static final String UA_ALI_PAY = "Alipay"; - - /** 微信 UA */ - public static final String UA_WECHAT_PAY = "MicroMessenger"; - /** 异步支付通道 */ public static final List ASYNC_TYPE = Collections.unmodifiableList(Arrays.asList(ALI, WECHAT, UNION_PAY)); /** 异步支付通道的编码 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayAllocationReceiverService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayAllocationReceiverService.java index 310648795..1402caa96 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayAllocationReceiverService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayAllocationReceiverService.java @@ -32,7 +32,7 @@ public class AliPayAllocationReceiverService { * 校验 */ public boolean validation(AllocationReceiver allocationReceiver){ - List list = Arrays.asList(ALI_USER_ID.getCode(), ALI_OPEN_ID.getCode(), ALI_LOGIN_NAME.getCode()); + List list = Arrays.asList(ALI_USER_ID.getOutCode(), ALI_OPEN_ID.getOutCode(), ALI_LOGIN_NAME.getOutCode()); String receiverType = allocationReceiver.getReceiverType(); return list.contains(receiverType); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayAllocationReceiverService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayAllocationReceiverService.java index 84fcbe3d2..fc19a7bea 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayAllocationReceiverService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayAllocationReceiverService.java @@ -33,7 +33,7 @@ public class WeChatPayAllocationReceiverService { * 校验参数是否合法 */ public boolean validation(AllocationReceiver allocationReceiver){ - List list = Arrays.asList(WX_MERCHANT.getCode(), WX_MERCHANT.getCode()); + List list = Arrays.asList(WX_MERCHANT.getOutCode(), WX_MERCHANT.getOutCode()); String receiverType = allocationReceiver.getReceiverType(); return !list.contains(receiverType); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/convert/AllocationGroupReceiverConvert.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/convert/AllocationGroupReceiverConvert.java index d5644b8e0..dbce8cb24 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/convert/AllocationGroupReceiverConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/convert/AllocationGroupReceiverConvert.java @@ -1,7 +1,7 @@ package cn.bootx.platform.daxpay.service.core.payment.allocation.convert; import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroupReceiver; -import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverDto; +import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverResult; import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupReceiverParam; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -15,7 +15,7 @@ import org.mapstruct.factory.Mappers; public interface AllocationGroupReceiverConvert { AllocationGroupReceiverConvert CONVERT = Mappers.getMapper(AllocationGroupReceiverConvert.class); - AllocationGroupReceiverDto convert(AllocationGroupReceiver in); + AllocationGroupReceiverResult convert(AllocationGroupReceiver in); AllocationGroupReceiver convert(AllocationGroupReceiverParam in); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupManager.java index f684c7a7a..ae9a769bf 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupManager.java @@ -1,7 +1,13 @@ package cn.bootx.platform.daxpay.service.core.payment.allocation.dao; +import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.impl.BaseManager; +import cn.bootx.platform.common.mybatisplus.util.MpUtil; +import cn.bootx.platform.common.query.generator.QueryGenerator; import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroup; +import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupParam; +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.springframework.stereotype.Repository; @@ -15,4 +21,10 @@ import org.springframework.stereotype.Repository; @Repository @RequiredArgsConstructor public class AllocationGroupManager extends BaseManager { + + public Page page(PageParam pageParam, AllocationGroupParam query) { + Page mpPage = MpUtil.getMpPage(pageParam, AllocationGroup.class); + QueryWrapper generator = QueryGenerator.generator(query); + return page(mpPage,generator); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupReceiverManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupReceiverManager.java index 6f6193952..6aa97a683 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupReceiverManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/dao/AllocationGroupReceiverManager.java @@ -6,6 +6,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; +import java.util.List; + /** * 分账组关联接收方 * @author xxm @@ -22,4 +24,18 @@ public class AllocationGroupReceiverManager extends BaseManager findByGroupId(Long groupId){ + return findAllByField(AllocationGroupReceiver::getGroupId, groupId); + } + + /** + * 根据分组ID进行批量删除 + */ + public void deleteByGroupId(Long groupId){ + deleteByField(AllocationGroupReceiver::getGroupId, groupId); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroup.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroup.java index f62c3d8be..069a6eb91 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroup.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroup.java @@ -6,6 +6,7 @@ import cn.bootx.platform.daxpay.service.core.payment.allocation.convert.Allocati import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupDto; import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbComment; +import cn.bootx.table.modify.annotation.DbTable; import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -21,6 +22,7 @@ import lombok.experimental.Accessors; @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) +@DbTable(comment = "分账组") @TableName("pay_allocation_receiver_group") public class AllocationGroup extends MpBaseEntity implements EntityBaseFunction { diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroupReceiver.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroupReceiver.java index 12416d6b3..c2a531bbd 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroupReceiver.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationGroupReceiver.java @@ -2,6 +2,8 @@ package cn.bootx.platform.daxpay.service.core.payment.allocation.entity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.table.modify.annotation.DbColumn; +import cn.bootx.table.modify.annotation.DbTable; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -14,9 +16,11 @@ import lombok.experimental.Accessors; @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) +@DbTable(comment = "分账接收组关系") +@TableName("pay_allocation_group_receiver") public class AllocationGroupReceiver extends MpCreateEntity { - @DbColumn(comment = "分账ID") + @DbColumn(comment = "分账组ID") private Long groupId; @DbColumn(comment = "接收者ID") diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationReceiver.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationReceiver.java index 41af87c6e..fbcb6dff6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationReceiver.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/entity/AllocationReceiver.java @@ -8,8 +8,10 @@ import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.service.core.payment.allocation.convert.AllocationReceiverConvert; import cn.bootx.platform.daxpay.service.dto.allocation.AllocationReceiverDto; import cn.bootx.table.modify.annotation.DbColumn; +import cn.bootx.table.modify.annotation.DbTable; 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; @@ -22,6 +24,8 @@ import lombok.experimental.Accessors; @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) +@DbTable(comment = "分账接收方") +@TableName("pay_allocation_receiver") public class AllocationReceiver extends MpBaseEntity implements EntityBaseFunction { @DbColumn(comment = "账号别名") @@ -67,6 +71,9 @@ public class AllocationReceiver extends MpBaseEntity implements EntityBaseFuncti @DbColumn(comment = "是否已经同步到网关") private boolean sync; + @DbColumn(comment = "备注") + private String remark; + /** * 转换 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationGroupService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationGroupService.java index 0e9581554..aa27a9aec 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationGroupService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationGroupService.java @@ -1,6 +1,10 @@ package cn.bootx.platform.daxpay.service.core.payment.allocation.service; import cn.bootx.platform.common.core.exception.DataNotExistException; +import cn.bootx.platform.common.core.function.CollectorsFunction; +import cn.bootx.platform.common.core.rest.PageResult; +import cn.bootx.platform.common.core.rest.param.PageParam; +import cn.bootx.platform.common.mybatisplus.util.MpUtil; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.service.core.payment.allocation.convert.AllocationGroupConvert; import cn.bootx.platform.daxpay.service.core.payment.allocation.dao.AllocationGroupManager; @@ -9,6 +13,8 @@ import cn.bootx.platform.daxpay.service.core.payment.allocation.dao.AllocationRe import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroup; import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationGroupReceiver; import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.AllocationReceiver; +import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupDto; +import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverResult; import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupBindParam; import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupParam; import cn.bootx.platform.daxpay.service.param.allocation.AllocationGroupReceiverParam; @@ -21,6 +27,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -36,13 +44,57 @@ public class AllocationGroupService { private final AllocationGroupReceiverManager groupReceiverManager; private final AllocationReceiverManager receiverManager; + /** + * 分页 + */ + public PageResult page(PageParam pageParam, AllocationGroupParam query){ + return MpUtil.convert2DtoPageResult(groupManager.page(pageParam,query)); + } + + /** + * 查询详情 + */ + public AllocationGroupDto findById(Long id){ + return groupManager.findById(id).map(AllocationGroup::toDto).orElseThrow(()->new DataNotExistException("分账组不存在")); + } + + /** + * 查询分账接收方 + */ + public List findReceiversByGroups(Long groupId){ + List groupReceivers = groupReceiverManager.findByGroupId(groupId); + List receiverIds = groupReceivers.stream() + .map(AllocationGroupReceiver::getReceiverId) + .collect(Collectors.toList()); + // 查询关联接收方信息 + Map receiverMap = receiverManager.findAllByIds(receiverIds) + .stream() + .collect(Collectors.toMap(AllocationReceiver::getId, Function.identity(), CollectorsFunction::retainLatest)); + // 组装信息 + return groupReceivers.stream() + .map(o -> { + AllocationReceiver allocationReceiver = receiverMap.get(o.getReceiverId()); + return new AllocationGroupReceiverResult() + .setId(o.getId()) + .setReceiverId(allocationReceiver.getId()) + .setReceiverAccount(allocationReceiver.getReceiverAccount()) + .setReceiverName(allocationReceiver.getReceiverName()) + .setRate(o.getRate()) + .setReceiverType(allocationReceiver.getReceiverType()) + .setRelationName(allocationReceiver.getRelationName()) + .setRelationType(allocationReceiver.getRelationType()); + }) + .collect(Collectors.toList()); + } + /** * 创建分账组 */ public void create(AllocationGroupParam param){ PayChannelEnum.findByCode(param.getChannel()); - AllocationGroup allocation = AllocationGroupConvert.CONVERT.convert(param); - groupManager.save(allocation); + AllocationGroup group = AllocationGroupConvert.CONVERT.convert(param); + group.setTotalRate(0); + groupManager.save(group); } /** @@ -52,22 +104,24 @@ public class AllocationGroupService { AllocationGroup group = groupManager.findById(param.getId()) .orElseThrow(() -> new DataNotExistException("未找到分账组")); BeanUtil.copyProperties(param,group, CopyOptions.create().ignoreNullValue()); - group.setTotalRate(0); + group.setTotalRate(null); groupManager.updateById(group); } /** * 删除分账组 */ - public void delete(){ - + @Transactional(rollbackFor = Exception.class) + public void delete(Long id){ + groupManager.deleteById(id); + groupReceiverManager.deleteByGroupId(id); } /** * 绑定分账接收方 */ @Transactional(rollbackFor = Exception.class) - public void bind(AllocationGroupBindParam param) { + public void bindReceivers(AllocationGroupBindParam param) { // 分账组 AllocationGroup group = groupManager.findById(param.getGroupId()) .orElseThrow(() -> new DataNotExistException("未找到分账组")); @@ -108,7 +162,7 @@ public class AllocationGroupService { * 批量删除分账接收方 */ @Transactional(rollbackFor = Exception.class) - public void removeReceivers(AllocationGroupUnbindParam param){ + public void unbindReceivers(AllocationGroupUnbindParam param){ // 分账组 AllocationGroup group = groupManager.findById(param.getGroupId()) .orElseThrow(() -> new DataNotExistException("未找到分账组")); @@ -130,7 +184,7 @@ public class AllocationGroupService { * 删除单个分账接收方 */ @Transactional - public void removeReceiver(Long receiverId){ + public void unbindReceiver(Long receiverId){ AllocationGroupReceiver groupReceiver = groupReceiverManager.findById(receiverId) .orElseThrow(() -> new DataNotExistException("未找到分账接收方")); AllocationGroup group = groupManager.findById(groupReceiver.getGroupId()) @@ -145,6 +199,7 @@ public class AllocationGroupService { /** * 修改分账比例 */ + @Transactional(rollbackFor = Exception.class) public void updateRate(Long receiverId, Integer rate){ AllocationGroupReceiver groupReceiver = groupReceiverManager.findById(receiverId) .orElseThrow(() -> new DataNotExistException("未找到分账接收方")); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationReceiverService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationReceiverService.java index b03ec0036..fb4866d08 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationReceiverService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationReceiverService.java @@ -1,9 +1,12 @@ package cn.bootx.platform.daxpay.service.core.payment.allocation.service; +import cn.bootx.platform.common.core.exception.BizException; import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.rest.PageResult; +import cn.bootx.platform.common.core.rest.dto.LabelValue; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; +import cn.bootx.platform.daxpay.code.AllocationReceiverTypeEnum; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.core.payment.allocation.convert.AllocationReceiverConvert; @@ -19,6 +22,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + /** * 分账接收方服务类 * @author xxm @@ -47,6 +54,34 @@ public class AllocationReceiverService { return manager.findById(id).map(AllocationReceiver::toDto).orElseThrow(() -> new DataNotExistException("分账接收方不存在")); } + /** + * 获取可以分账的通道 + */ + public List findChannels(){ + return Arrays.asList( + new LabelValue(PayChannelEnum.ALI.getName(),PayChannelEnum.ALI.getCode()), + new LabelValue(PayChannelEnum.WECHAT.getName(),PayChannelEnum.WECHAT.getCode()) + ); + } + + /** + * 根据通道获取分账接收方类型 + */ + public List findReceiverTypeByChannel(String channel){ + PayChannelEnum channelEnum = PayChannelEnum.findByCode(channel); + List list; + if (channelEnum == PayChannelEnum.ALI){ + list = AllocationReceiverTypeEnum.ALI_LIST; + } else if (channelEnum == PayChannelEnum.WECHAT){ + list = AllocationReceiverTypeEnum.WECHAT_LIST; + } else { + throw new BizException("非法的分账通道类型"); + } + return list.stream() + .map(item -> new LabelValue(item.getName(),item.getCode())) + .collect(Collectors.toList()); + } + /** * 添加分账接收方 */ @@ -69,16 +104,26 @@ public class AllocationReceiverService { * 修改信息 */ public void update(AllocationReceiverParam param){ - // 未同步状态可以修改 - - + AllocationReceiver receiver = manager.findById(param.getId()).orElseThrow(() -> new PayFailureException("未找到分账接收方")); + receiver.setName(param.getName()) + .setRemark(param.getRemark()); + manager.updateById(receiver); } /** * 删除分账接收方 */ public void remove(Long id){ - + // 未同步可以删除 + AllocationReceiver receiver = manager.findById(id).orElseThrow(() -> new PayFailureException("未找到分账接收方")); + if (receiver.isSync()){ + throw new BizException("该接收方已同步到三方支付系统中,无法删除"); + } + // 判断是否绑定了分账组 + if (groupReceiverManager.isUsed(id)){ + throw new PayFailureException("该接收方已被分账组使用,无法删除"); + } + manager.deleteById(id); } /** @@ -120,4 +165,5 @@ public class AllocationReceiverService { receiver.setSync(false); manager.updateById(receiver); } + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationGroupReceiverDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationGroupReceiverDto.java deleted file mode 100644 index d0b875050..000000000 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationGroupReceiverDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.bootx.platform.daxpay.service.dto.allocation; - -import cn.bootx.platform.common.core.rest.dto.BaseDto; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * - * @author xxm - * @since 2024/4/1 - */ -@EqualsAndHashCode(callSuper = true) -@Data -@Accessors(chain = true) -@Schema(title = "") -public class AllocationGroupReceiverDto extends BaseDto { -} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationGroupReceiverResult.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationGroupReceiverResult.java new file mode 100644 index 000000000..2da533e80 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationGroupReceiverResult.java @@ -0,0 +1,52 @@ +package cn.bootx.platform.daxpay.service.dto.allocation; + +import cn.bootx.platform.daxpay.code.AllocationReceiverTypeEnum; +import cn.bootx.platform.daxpay.code.AllocationRelationTypeEnum; +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 AllocationGroupReceiverResult { + + @Schema(description = "主键") + private Long id; + + @Schema(description = "接收者ID") + private Long receiverId; + + @Schema(description = "分账比例(万分之多少)") + private Integer rate; + + /** + * 分账接收方类型 + * @see AllocationReceiverTypeEnum + */ + @Schema(description = "分账接收方类型") + private String receiverType; + + + @Schema(description = "接收方账号") + private String receiverAccount; + + /** 接收方姓名 */ + @Schema(description = "接收方姓名") + private String receiverName; + + /** + * 分账关系类型 + * @see AllocationRelationTypeEnum + */ + @Schema(description = "分账关系类型") + private String relationType; + + @Schema(description = "关系名称") + private String relationName; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationReceiverDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationReceiverDto.java index 7828fc1e7..06ac5f2a8 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationReceiverDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/allocation/AllocationReceiverDto.java @@ -1,6 +1,7 @@ package cn.bootx.platform.daxpay.service.dto.allocation; import cn.bootx.platform.common.core.rest.dto.BaseDto; +import cn.bootx.platform.daxpay.code.AllocationReceiverTypeEnum; import cn.bootx.platform.daxpay.code.AllocationRelationTypeEnum; import cn.bootx.platform.daxpay.code.PayChannelEnum; import io.swagger.v3.oas.annotations.media.Schema; @@ -33,6 +34,7 @@ public class AllocationReceiverDto extends BaseDto { /** * 分账接收方类型 个人/商户 + * @see AllocationReceiverTypeEnum */ @Schema(description = "分账接收方类型") private String receiverType; @@ -57,4 +59,7 @@ public class AllocationReceiverDto extends BaseDto { @Schema(description = "是否已经同步到网关") private boolean sync; + + @Schema(description = "备注") + private String remark; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/allocation/AllocationReceiverParam.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/allocation/AllocationReceiverParam.java index 41437080c..bee954fa1 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/allocation/AllocationReceiverParam.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/allocation/AllocationReceiverParam.java @@ -1,5 +1,6 @@ package cn.bootx.platform.daxpay.service.param.allocation; +import cn.bootx.platform.daxpay.code.AllocationReceiverTypeEnum; import cn.bootx.platform.daxpay.code.AllocationRelationTypeEnum; import cn.bootx.platform.daxpay.code.PayChannelEnum; import io.swagger.v3.oas.annotations.media.Schema; @@ -31,6 +32,7 @@ public class AllocationReceiverParam { /** * 分账接收方类型 个人/商户 + * @see AllocationReceiverTypeEnum */ @Schema(description = "分账接收方类型") private String receiverType; @@ -56,4 +58,7 @@ public class AllocationReceiverParam { @Schema(description = "是否已经同步到网关") private boolean sync; + @Schema(description = "备注") + private String remark; + }