diff --git a/_doc/Task.md b/_doc/Task.md index 75bd47a2..894536e8 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -5,12 +5,17 @@ - [ ] 分账功能 - [x] 分账接收方配置 - [ ] 分账单管理 + - [ ] 分账接口开发 - [ ] 网关配套移动端开发 - [ ] 同步回调页 -- [ ] 商户应用增加启停用状态 -- [ ] 商户应用应该要有一个类似删除的功能, 实现停用冻结, 但不影响数据的关联 - [x] 微信通道添加单独的认证跳转地址, 处理它的特殊情况 +## bugs +- [ ] 修复 BigDecimal 类型数据序列化和签名异常问题 + + ## 任务池 - [ ] 定时同步任务频次不要太高, 预防产生过多的数据 - [ ] 退款支持以撤销的方式进行退款 +- [ ] 商户应用增加启停用状态 +- [ ] 商户应用应该要有一个类似删除的功能, 实现停用冻结, 但不影响数据的关联 diff --git a/daxpay-single-sdk/src/main/java/cn/daxpay/single/sdk/util/JsonUtil.java b/daxpay-single-sdk/src/main/java/cn/daxpay/single/sdk/util/JsonUtil.java index 7ac733c7..ba63746d 100644 --- a/daxpay-single-sdk/src/main/java/cn/daxpay/single/sdk/util/JsonUtil.java +++ b/daxpay-single-sdk/src/main/java/cn/daxpay/single/sdk/util/JsonUtil.java @@ -17,7 +17,6 @@ import lombok.experimental.UtilityClass; public class JsonUtil { private final JSONConfig JSON_CONFIG = JSONConfig.create() .setDateFormat(DatePattern.NORM_DATETIME_PATTERN); -// .setStripTrailingZeros(false); /** * 转换为实体 diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocOrderResultEnum.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocTransactionResultEnum.java similarity index 91% rename from daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocOrderResultEnum.java rename to daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocTransactionResultEnum.java index 9b754105..df3b7fa1 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocOrderResultEnum.java +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocTransactionResultEnum.java @@ -10,7 +10,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum AllocOrderResultEnum { +public enum AllocTransactionResultEnum { ALL_PENDING("all_pending", "处理中"), ALL_SUCCESS("all_success", "全部成功"), diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocOrderStatusEnum.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocTransactionStatusEnum.java similarity index 86% rename from daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocOrderStatusEnum.java rename to daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocTransactionStatusEnum.java index 2e9f18c4..f69e0241 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocOrderStatusEnum.java +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/enums/AllocTransactionStatusEnum.java @@ -10,13 +10,14 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum AllocOrderStatusEnum { +public enum AllocTransactionStatusEnum { ALLOC_PROCESSING("alloc_processing", "分账处理中"), ALLOC_END("alloc_end", "分账完成"), ALLOC_FAILED("alloc_failed", "分账失败"), FINISH("finish", "完结"), FINISH_FAILED("finish_failed", "完结失败"), + IGNORE("ignore", "忽略"), ; final String code; diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/AllocFinishParam.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/AllocFinishParam.java new file mode 100644 index 00000000..c6ce985e --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/AllocFinishParam.java @@ -0,0 +1,23 @@ +package org.dromara.daxpay.core.param.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.daxpay.core.param.PaymentCommonParam; + +/** + * 分账完结参数 + * @author xxm + * @since 2024/4/7 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Schema(title = "分账请求参数") +public class AllocFinishParam extends PaymentCommonParam { + + @Schema(description = "商户分账单号") + private String bizAllocNo; + + @Schema(description = "分账单号") + private String allocNo; +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/AllocationParam.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/AllocationParam.java new file mode 100644 index 00000000..f195314e --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/AllocationParam.java @@ -0,0 +1,67 @@ +package org.dromara.daxpay.core.param.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.dromara.daxpay.core.param.PaymentCommonParam; + +import java.util.List; + +/** + * 分账请求参数 + * @author xxm + * @since 2024/11/14 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@Schema(title = "分账请求参数") +public class AllocationParam extends PaymentCommonParam { + /** 商户分账单号 */ + @NotBlank(message = "商户分账单号不可为空") + @Size(max = 100, message = "商户分账单号不可超过100位") + @Schema(description = "商户分账单号") + private String bizAllocNo; + + /** 支付订单号 */ + @Size(max = 32, message = "支付订单号不可超过32位") + @Schema(description = "支付订单号") + private String orderNo; + + /** 商户支付订单号 */ + @Size(max = 100, message = "商户支付订单号不可超过100位") + @Schema(description = "商户支付订单号") + private String bizOrderNo; + + /** 分账描述 */ + @Size(max = 150, message = "分账描述不可超过150位") + @Schema(description = "分账描述") + private String description; + + /** + * 优先级 分账接收方列表 > 分账组编号 > 默认分账组 + */ + @Size(max = 20, message = "分账组编号不可超过20位") + @Schema(description = "分账组编号") + private String groupNo; + + /** 分账接收方列表 */ + @Schema(description = "分账接收方列表") + @Valid + private List receivers; + + /** 回调通知地址 */ + @Size(max = 200, message = "回调通知地址不可超过200位") + @Schema(description = "回调通知地址") + private String notifyUrl; + + /** 商户扩展参数,回调时会原样返回 */ + @Size(max = 500, message = "商户扩展参数不可超过500位") + @Schema(description = "商户扩展参数") + private String attach; + +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/QueryAllocTransactionParam.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/QueryAllocTransactionParam.java new file mode 100644 index 00000000..b3a8387e --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/QueryAllocTransactionParam.java @@ -0,0 +1,23 @@ +package org.dromara.daxpay.core.param.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.daxpay.core.param.PaymentCommonParam; + +/** + * 分账订单查询参数 + * @author xxm + * @since 2024/4/7 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Schema(title = "支付订单查询参数") +public class QueryAllocTransactionParam extends PaymentCommonParam { + + @Schema(description = "分账单号") + private String allocNo; + + @Schema(description = "商户分账单号") + private String bizAllocNo; +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/ReceiverParam.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/ReceiverParam.java new file mode 100644 index 00000000..70510480 --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/param/allocation/transaction/ReceiverParam.java @@ -0,0 +1,34 @@ +package org.dromara.daxpay.core.param.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +/** + * 分账接收方列表 + * @author xxm + * @since 2024/5/21 + */ +@Data +@Accessors(chain = true) +@Schema(title = "分账接收方列表") +public class ReceiverParam { + + /** 分账接收方编号 */ + @Schema(description = "分账接收方编号") + @NotBlank(message = "分账接收方编号必填") + @Size(max = 32, message = "分账接收方编号不可超过32位") + private String receiverNo; + + /** 分账金额 */ + @Schema(description = "分账金额") + @NotNull(message = "分账金额必填") + @Min(value = 1,message = "分账金额至少为0.01元") + private BigDecimal amount; +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/receiver/AllocReceiverResult.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/receiver/AllocReceiverResult.java index 8fa58918..0eff8d81 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/receiver/AllocReceiverResult.java +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/receiver/AllocReceiverResult.java @@ -2,10 +2,8 @@ package org.dromara.daxpay.core.result.allocation.receiver; 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; import java.util.List; @@ -14,11 +12,10 @@ import java.util.List; * @author xxm * @since 2024/3/28 */ -@EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) @Schema(title = "分账接收方") -public class AllocReceiverResult extends MchAppResult { +public class AllocReceiverResult { @Schema(description = "接收方列表") private List receivers; diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocDetailResult.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocDetailResult.java new file mode 100644 index 00000000..bba0c56f --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocDetailResult.java @@ -0,0 +1,65 @@ +package org.dromara.daxpay.core.result.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; +import org.dromara.daxpay.core.enums.AllocDetailResultEnum; +import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum; + +import java.time.LocalDateTime; + +/** + * 分账订单明细 + * @author xxm + * @since 2024/5/21 + */ +@Data +@Accessors(chain = true) +@Schema(title = "分账订单明细") +public class AllocDetailResult { + + @Schema(description = "分账接收方编号") + private String receiverNo; + + /** 分账金额 */ + @Schema(description = "分账金额") + private Integer amount; + + /** 分账比例 */ + @Schema(description = "分账比例(万分之多少)") + private Integer rate; + + /** + * 分账接收方类型 + * @see AllocReceiverTypeEnum + */ + @Schema(description = "分账接收方类型") + private String receiverType; + + /** 接收方账号 */ + @Schema(description = "接收方账号") + private String receiverAccount; + + /** 接收方姓名 */ + @Schema(description = "接收方姓名") + private String receiverName; + + /** + * 分账结果 + * @see AllocDetailResultEnum + */ + @Schema(description = "分账结果") + private String result; + + /** 错误代码 */ + @Schema(description = "错误代码") + private String errorCode; + + /** 错误原因 */ + @Schema(description = "错误原因") + private String errorMsg; + + /** 分账完成时间 */ + @Schema(description = "分账完成时间") + private LocalDateTime finishTime; +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocResult.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocResult.java new file mode 100644 index 00000000..4ce8b5be --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocResult.java @@ -0,0 +1,31 @@ +package org.dromara.daxpay.core.result.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; +import org.dromara.daxpay.core.enums.AllocTransactionStatusEnum; + +/** + * 分账请求结果 + * @author xxm + * @since 2024/4/7 + */ +@Data +@Accessors(chain = true) +@Schema(title = "分账请求结果") +public class AllocResult { + /** 分账订单号 */ + @Schema(description = "分账订单号") + private String allocNo; + + /** 商户分账订单号 */ + @Schema(description = "商户分账订单号") + private String bizAllocNo; + + /** + * 分账状态 + * @see AllocTransactionStatusEnum + */ + @Schema(description = "分账状态") + private String status; +} diff --git a/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocTransactionResult.java b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocTransactionResult.java new file mode 100644 index 00000000..a16bb7b9 --- /dev/null +++ b/daxpay-single/daxpay-single-core/src/main/java/org/dromara/daxpay/core/result/allocation/transaction/AllocTransactionResult.java @@ -0,0 +1,108 @@ +package org.dromara.daxpay.core.result.allocation.transaction; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; +import org.dromara.daxpay.core.enums.AllocTransactionResultEnum; +import org.dromara.daxpay.core.enums.AllocTransactionStatusEnum; +import org.dromara.daxpay.core.enums.ChannelEnum; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 分账订单返回结果 + * @author xxm + * @since 2024/5/21 + */ +@Data +@Accessors(chain = true) +@Schema(title = "分账订单返回结果") +public class AllocTransactionResult { + + /** 分账单号 */ + @Schema(description = "分账单号") + private String allocNo; + + /** 商户分账单号 */ + @Schema(description = "商户分账单号") + private String bizAllocNo; + + /** 通道分账号 */ + @Schema(description = "通道分账号") + private String outAllocNo; + + /** + * 支付订单号 + */ + @Schema(description = "支付订单号") + private String orderNo; + + /** 商户支付订单号 */ + @Schema(description = "商户支付订单号") + private String bizOrderNo; + + /** 通道支付订单号 */ + @Schema(description = "通道支付订单号") + private String outOrderNo; + + /** + * 支付订单标题 + */ + @Schema(description = "支付订单标题") + private String title; + + /** + * 所属通道 + * @see ChannelEnum + */ + @Schema(description = "所属通道") + private String channel; + + /** + * 总分账金额 + */ + @Schema(description = "总分账金额") + private Integer amount; + + /** + * 分账描述 + */ + @Schema(description = "分账描述") + private String description; + + /** + * 状态 + * @see AllocTransactionStatusEnum + */ + @Schema(description = "状态") + private String status; + + /** + * 处理结果 + * @see AllocTransactionResultEnum + */ + @Schema(description = "处理结果") + private String result; + + /** + * 错误码 + */ + @Schema(description = "错误码") + private String errorCode; + + /** + * 错误信息 + */ + @Schema(description = "错误原因") + private String errorMsg; + + /** 分账订单完成时间 */ + @Schema(description = "分账订单完成时间") + private LocalDateTime finishTime; + + /** 分账明细 */ + @Schema(description = "分账明细") + private List details; + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocGroupReceiverResultBo.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocGroupReceiverResultBo.java similarity index 96% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocGroupReceiverResultBo.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocGroupReceiverResultBo.java index 757c129c..a4b7414c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocGroupReceiverResultBo.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocGroupReceiverResultBo.java @@ -1,4 +1,4 @@ -package org.dromara.daxpay.service.bo.allocation; +package org.dromara.daxpay.service.bo.allocation.receiver; import cn.bootx.platform.common.jackson.sensitive.SensitiveInfo; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocGroupResultBo.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocGroupResultBo.java similarity index 93% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocGroupResultBo.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocGroupResultBo.java index 8a855080..e9dff491 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocGroupResultBo.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocGroupResultBo.java @@ -1,4 +1,4 @@ -package org.dromara.daxpay.service.bo.allocation; +package org.dromara.daxpay.service.bo.allocation.receiver; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocReceiverResultBo.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocReceiverResultBo.java similarity index 96% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocReceiverResultBo.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocReceiverResultBo.java index a8ad179e..679a4d05 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/AllocReceiverResultBo.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocReceiverResultBo.java @@ -1,4 +1,4 @@ -package org.dromara.daxpay.service.bo.allocation; +package org.dromara.daxpay.service.bo.allocation.receiver; import cn.bootx.platform.common.jackson.sensitive.SensitiveInfo; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocStartResultBo.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocStartResultBo.java new file mode 100644 index 00000000..cb74da3a --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/bo/allocation/receiver/AllocStartResultBo.java @@ -0,0 +1,17 @@ +package org.dromara.daxpay.service.bo.allocation.receiver; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 分账操作结果 + * @author xxm + * @since 2024/11/15 + */ +@Data +@Accessors(chain = true) +public class AllocStartResultBo { + + /** 通道分账号 */ + private String outAllocNo; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocGroupController.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocGroupController.java index 3a0570b4..7d45270d 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocGroupController.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocGroupController.java @@ -10,13 +10,13 @@ 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.bo.allocation.AllocGroupResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupResultBo; 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.bo.allocation.AllocGroupReceiverResultBo; -import org.dromara.daxpay.service.service.allocation.AllocGroupService; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupReceiverResultBo; +import org.dromara.daxpay.service.service.allocation.receiver.AllocGroupService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java index c6562cb0..1e4e29e1 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java @@ -13,9 +13,9 @@ import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverAddParam; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverRemoveParam; -import org.dromara.daxpay.service.bo.allocation.AllocReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocReceiverResultBo; import org.dromara.daxpay.service.param.allocation.receiver.AllocReceiverQuery; -import org.dromara.daxpay.service.service.allocation.AllocReceiverService; +import org.dromara.daxpay.service.service.allocation.receiver.AllocReceiverService; import org.dromara.daxpay.service.service.assist.PaymentAssistService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/unipay/UniAllocationController.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/unipay/UniAllocationController.java index 0c88f458..817903cf 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/unipay/UniAllocationController.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/unipay/UniAllocationController.java @@ -7,11 +7,17 @@ import lombok.RequiredArgsConstructor; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverAddParam; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverQueryParam; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverRemoveParam; +import org.dromara.daxpay.core.param.allocation.transaction.AllocFinishParam; +import org.dromara.daxpay.core.param.allocation.transaction.AllocationParam; +import org.dromara.daxpay.core.param.allocation.transaction.QueryAllocTransactionParam; import org.dromara.daxpay.core.result.DaxResult; import org.dromara.daxpay.core.result.allocation.receiver.AllocReceiverResult; +import org.dromara.daxpay.core.result.allocation.transaction.AllocResult; +import org.dromara.daxpay.core.result.allocation.transaction.AllocTransactionResult; import org.dromara.daxpay.core.util.DaxRes; import org.dromara.daxpay.service.common.anno.PaymentVerify; -import org.dromara.daxpay.service.service.allocation.AllocReceiverService; +import org.dromara.daxpay.service.service.allocation.AllocationService; +import org.dromara.daxpay.service.service.allocation.receiver.AllocReceiverService; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,17 +36,24 @@ import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor public class UniAllocationController { private final AllocReceiverService allocReceiverService; + private final AllocationService allocationService; @Operation(summary = "发起分账接口") @PostMapping("/start") - public DaxResult start(){ - return DaxRes.ok(); + public DaxResult start(@RequestBody AllocationParam param){ + return DaxRes.ok(allocationService.allocation(param)); } @Operation(summary = "分账完结接口") @PostMapping("/finish") - public DaxResult finish(){ - return DaxRes.ok(); + public DaxResult finish(AllocFinishParam param){ + return DaxRes.ok(allocationService.finish(param)); + } + + @Operation(summary = "分账写你查询接口") + @PostMapping("/query") + public DaxResult query(@RequestBody QueryAllocTransactionParam param){ + return DaxRes.ok(allocationService.queryAllocTransaction(param)); } @Operation(summary = "分账接收方查询接口") diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupConvert.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupConvert.java index 3d827ed9..c597b059 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupConvert.java @@ -2,7 +2,7 @@ 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.bo.allocation.AllocGroupResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupResultBo; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupReceiverConvert.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupReceiverConvert.java index e4c9d713..9ea0e4a4 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupReceiverConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocGroupReceiverConvert.java @@ -1,6 +1,6 @@ package org.dromara.daxpay.service.convert.allocation; -import org.dromara.daxpay.service.bo.allocation.AllocGroupReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupReceiverResultBo; import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroupReceiver; import org.dromara.daxpay.service.param.allocation.group.AllocGroupReceiverParam; import org.mapstruct.Mapper; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocReceiverConvert.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocReceiverConvert.java index 65d2f348..fa1fb673 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocReceiverConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocReceiverConvert.java @@ -2,7 +2,7 @@ package org.dromara.daxpay.service.convert.allocation; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverAddParam; import org.dromara.daxpay.core.result.allocation.receiver.AllocReceiverResult; -import org.dromara.daxpay.service.bo.allocation.AllocReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocReceiverResultBo; import org.dromara.daxpay.service.entity.allocation.receiver.AllocReceiver; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocTransactionConvert.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocTransactionConvert.java new file mode 100644 index 00000000..098d4afd --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/convert/allocation/AllocTransactionConvert.java @@ -0,0 +1,22 @@ +package org.dromara.daxpay.service.convert.allocation; + +import org.dromara.daxpay.core.result.allocation.transaction.AllocDetailResult; +import org.dromara.daxpay.core.result.allocation.transaction.AllocTransactionResult; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author xxm + * @since 2024/11/15 + */ +@Mapper +public interface AllocTransactionConvert { + AllocTransactionConvert CONVERT = Mappers.getMapper(AllocTransactionConvert.class); + + AllocTransactionResult toResult(AllocTransaction in); + + AllocDetailResult toResult(AllocDetail in); +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocDetailManager.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocDetailManager.java new file mode 100644 index 00000000..dbe41338 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocDetailManager.java @@ -0,0 +1,23 @@ +package org.dromara.daxpay.service.dao.allocation.transaction; + +import cn.bootx.platform.common.mybatisplus.impl.BaseManager; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 分账明细 + * @author xxm + * @since 2024/11/14 + */ +@Slf4j +@Repository +@RequiredArgsConstructor +public class AllocDetailManager extends BaseManager { + public List findAllByOrderId(Long id) { + return findAllByField(AllocDetail::getAllocationId, id); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocDetailMapper.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocDetailMapper.java new file mode 100644 index 00000000..881f9738 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocDetailMapper.java @@ -0,0 +1,14 @@ +package org.dromara.daxpay.service.dao.allocation.transaction; + +import com.github.yulichang.base.MPJBaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; + +/** + * + * @author xxm + * @since 2024/11/14 + */ +@Mapper +public interface AllocDetailMapper extends MPJBaseMapper { +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocTransactionManager.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocTransactionManager.java new file mode 100644 index 00000000..4a8f3225 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocTransactionManager.java @@ -0,0 +1,40 @@ +package org.dromara.daxpay.service.dao.allocation.transaction; + +import cn.bootx.platform.common.mybatisplus.impl.BaseManager; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +/** + * 分账交易 + * @author xxm + * @since 2024/11/14 + */ +@Slf4j +@Repository +@RequiredArgsConstructor +public class AllocTransactionManager extends BaseManager { + /** + * 根据商户分账单号查询数据 + */ + public Optional findByBizAllocNo(String bizAllocNo, String appId) { + return lambdaQuery() + .eq(AllocTransaction::getBizAllocNo, bizAllocNo) + .eq(MchAppBaseEntity::getAppId, appId) + .oneOpt(); + } + + /** + * 根据分账单号查询数据 + */ + public Optional findByAllocNo(String allocNo, String appId) { + return lambdaQuery() + .eq(AllocTransaction::getAllocNo, allocNo) + .eq(MchAppBaseEntity::getAppId, appId) + .oneOpt(); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocTransactionMapper.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocTransactionMapper.java new file mode 100644 index 00000000..4878b9c7 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/allocation/transaction/AllocTransactionMapper.java @@ -0,0 +1,14 @@ +package org.dromara.daxpay.service.dao.allocation.transaction; + +import com.github.yulichang.base.MPJBaseMapper; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.mapstruct.Mapper; + +/** + * + * @author xxm + * @since 2024/11/14 + */ +@Mapper +public interface AllocTransactionMapper extends MPJBaseMapper { +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderDetailManager.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderDetailManager.java deleted file mode 100644 index f78b636a..00000000 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderDetailManager.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.dromara.daxpay.service.dao.order.allocation; - -import cn.bootx.platform.common.mybatisplus.impl.BaseManager; -import org.dromara.daxpay.service.entity.order.allocation.AllocOrderDetail; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * - * @author xxm - * @since 2024/4/7 - */ -@Slf4j -@Repository -@RequiredArgsConstructor -public class AllocOrderDetailManager extends BaseManager { - - /** - * 根据订单ID查询 - */ - public List findAllByOrderId(Long orderId) { - return findAllByField(AllocOrderDetail::getAllocId, orderId); - } -} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderDetailMapper.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderDetailMapper.java deleted file mode 100644 index f97fb820..00000000 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderDetailMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.dromara.daxpay.service.dao.order.allocation; - -import org.dromara.daxpay.service.entity.order.allocation.AllocOrderDetail; -import com.github.yulichang.base.MPJBaseMapper; -import org.apache.ibatis.annotations.Mapper; - -/** - * - * @author xxm - * @since 2024/4/7 - */ -@Mapper -public interface AllocOrderDetailMapper extends MPJBaseMapper { -} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderManager.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderManager.java deleted file mode 100644 index e19f7069..00000000 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderManager.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.daxpay.service.dao.order.allocation; - -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 org.dromara.daxpay.core.enums.AllocOrderStatusEnum; -import org.dromara.daxpay.service.entity.order.allocation.AllocOrder; -import org.dromara.daxpay.service.param.order.allocation.AllocOrderQuery; -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; - -import java.util.List; -import java.util.Optional; - -/** - * - * @author xxm - * @since 2024/4/7 - */ -@Slf4j -@Repository -@RequiredArgsConstructor -public class AllocOrderManager extends BaseManager { - - /** - * 根据分账单号查询 - */ - public Optional findByAllocNo(String allocNo){ - return findByField(AllocOrder::getAllocNo, allocNo); - } - - /** - * 根据商户分账号查询 - */ - public Optional findByBizAllocNo(String bizAllocNo){ - return findByField(AllocOrder::getBizAllocNo, bizAllocNo); - } - - /** - * 分页 - */ - public Page page(PageParam pageParam, AllocOrderQuery param){ - Page mpPage = MpUtil.getMpPage(pageParam); - QueryWrapper generator = QueryGenerator.generator(param); - return this.page(mpPage, generator); - } - - /** - * 查询待同步的分账单 - */ - public List findSyncOrder(){ - List statusList = List.of(AllocOrderStatusEnum.ALLOC_PROCESSING.getCode(), AllocOrderStatusEnum.ALLOC_END.getCode()); - return lambdaQuery() - .in(AllocOrder::getStatus, statusList) - .list(); - } -} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderMapper.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderMapper.java deleted file mode 100644 index 534a6d84..00000000 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/order/allocation/AllocOrderMapper.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.dromara.daxpay.service.dao.order.allocation; - -import org.dromara.daxpay.service.entity.order.allocation.AllocOrder; -import com.github.yulichang.base.MPJBaseMapper; -import org.apache.ibatis.annotations.Mapper; - -/** - * - * @author xxm - * @since 2024/4/7 - */ -@Mapper -public interface AllocOrderMapper extends MPJBaseMapper { -} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroup.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroup.java index 8cbcce15..ac1ef380 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroup.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroup.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; -import org.dromara.daxpay.service.bo.allocation.AllocGroupResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupResultBo; import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; import org.dromara.daxpay.service.convert.allocation.AllocGroupConvert; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroupReceiver.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroupReceiver.java index a59901eb..f4e0143a 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroupReceiver.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocGroupReceiver.java @@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; -import org.dromara.daxpay.service.bo.allocation.AllocGroupReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupReceiverResultBo; import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; import org.dromara.daxpay.service.convert.allocation.AllocGroupReceiverConvert; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocReceiver.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocReceiver.java index 71d43583..9c58f534 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocReceiver.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/receiver/AllocReceiver.java @@ -12,7 +12,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import org.dromara.daxpay.service.convert.allocation.AllocReceiverConvert; -import org.dromara.daxpay.service.bo.allocation.AllocReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocReceiverResultBo; /** * 分账接收方 diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/order/allocation/AllocOrderDetail.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java similarity index 78% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/order/allocation/AllocOrderDetail.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java index 3b78b1ca..27367cef 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/order/allocation/AllocOrderDetail.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java @@ -1,29 +1,27 @@ -package org.dromara.daxpay.service.entity.order.allocation; +package org.dromara.daxpay.service.entity.allocation.transaction; -import org.dromara.daxpay.core.enums.AllocDetailResultEnum; -import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum; -import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; -import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import org.dromara.daxpay.core.enums.AllocDetailResultEnum; +import org.dromara.daxpay.core.enums.AllocReceiverTypeEnum; +import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; import java.math.BigDecimal; import java.time.LocalDateTime; /** - * 分账订单明细 + * 分账明细 * @author xxm - * @since 2024/6/1 + * @since 2024/11/14 */ @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) -@TableName("pay_alloc_order_detail") -public class AllocOrderDetail extends MchAppBaseEntity { +public class AllocDetail extends MchAppBaseEntity { /** 分账订单ID */ - private Long allocId; + private Long allocationId; /** 接收者ID */ private Long receiverId; @@ -31,7 +29,7 @@ public class AllocOrderDetail extends MchAppBaseEntity { /** 分账接收方编号 */ private String receiverNo; - /** 分账比例(百分之多少) */ + /** 分账比例 */ private BigDecimal rate; /** 分账金额 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/order/allocation/AllocOrder.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocTransaction.java similarity index 63% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/order/allocation/AllocOrder.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocTransaction.java index 742423da..3e2e5d69 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/order/allocation/AllocOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocTransaction.java @@ -1,66 +1,52 @@ -package org.dromara.daxpay.service.entity.order.allocation; +package org.dromara.daxpay.service.entity.allocation.transaction; -import org.dromara.daxpay.core.enums.AllocOrderResultEnum; -import org.dromara.daxpay.core.enums.AllocOrderStatusEnum; -import org.dromara.daxpay.core.enums.ChannelEnum; -import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; 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.core.enums.AllocTransactionResultEnum; +import org.dromara.daxpay.core.enums.AllocTransactionStatusEnum; +import org.dromara.daxpay.core.enums.ChannelEnum; +import org.dromara.daxpay.service.common.entity.MchAppBaseEntity; import java.math.BigDecimal; import java.time.LocalDateTime; /** - * 分账订单 + * 分账交易记录 * @author xxm - * @since 2024/6/1 + * @since 2024/11/14 */ @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) -@TableName("pay_alloc_order") -public class AllocOrder extends MchAppBaseEntity { +@TableName("pay_alloc_transaction") +public class AllocTransaction extends MchAppBaseEntity { - /** - * 分账单号 - */ + /** 分账单号 */ private String allocNo; - /** - * 商户分账单号 - */ + /** 商户分账单号 */ private String bizAllocNo; - /** - * 通道分账号 - */ + /** 通道分账号 */ private String outAllocNo; /** 支付订单ID */ private Long orderId; - /** - * 支付订单号 - */ + /** 支付订单号 */ private String orderNo; - /** - * 商户支付订单号 - */ + /** 商户支付订单号 */ private String bizOrderNo; - /** - * 通道系统支付订单号 - */ + /** 通道支付订单号 */ private String outOrderNo; - /** - * 支付订单标题 - */ + /** 支付标题 */ private String title; /** @@ -81,33 +67,35 @@ public class AllocOrder extends MchAppBaseEntity { /** * 状态 - * @see AllocOrderStatusEnum + * @see AllocTransactionStatusEnum */ private String status; /** * 处理结果 - * @see AllocOrderResultEnum + * @see AllocTransactionResultEnum */ private String result; /** 分账完成时间 */ private LocalDateTime finishTime; - /** 商户扩展参数,回调时会原样返回, 以最后一次为准 */ + /** 异步通知地址 */ @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String notifyUrl; + + /** 商户扩展参数,回调时会原样返回, 以最后一次为准 */ private String attach; - /** 支付终端ip 以最后一次为准 */ - @TableField(updateStrategy = FieldStrategy.ALWAYS) + /** 请求时间,时间戳转时间 */ + private LocalDateTime reqTime; + + /** 终端ip */ private String clientIp; /** 错误码 */ - @TableField(updateStrategy = FieldStrategy.ALWAYS) private String errorCode; /** 错误信息 */ - @TableField(updateStrategy = FieldStrategy.ALWAYS) private String errorMsg; - } diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/TransactionAndDetail.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/TransactionAndDetail.java new file mode 100644 index 00000000..ce2d6e2a --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/TransactionAndDetail.java @@ -0,0 +1,11 @@ +package org.dromara.daxpay.service.entity.allocation.transaction; + +import java.util.List; + +/** + * 分账订单和分账明细 + * @author xxm + * @since 2024/11/14 + */ +public record TransactionAndDetail(AllocTransaction transaction, +List details) {} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocationService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocationService.java new file mode 100644 index 00000000..baf14f91 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocationService.java @@ -0,0 +1,240 @@ +package org.dromara.daxpay.service.service.allocation; + +import cn.bootx.platform.core.exception.DataNotExistException; +import cn.bootx.platform.core.exception.RepetitiveOperationException; +import com.baomidou.lock.LockInfo; +import com.baomidou.lock.LockTemplate; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.core.enums.AllocTransactionResultEnum; +import org.dromara.daxpay.core.enums.AllocTransactionStatusEnum; +import org.dromara.daxpay.core.exception.DataErrorException; +import org.dromara.daxpay.core.exception.TradeStatusErrorException; +import org.dromara.daxpay.core.param.allocation.transaction.AllocFinishParam; +import org.dromara.daxpay.core.param.allocation.transaction.AllocationParam; +import org.dromara.daxpay.core.param.allocation.transaction.QueryAllocTransactionParam; +import org.dromara.daxpay.core.result.allocation.transaction.AllocResult; +import org.dromara.daxpay.core.result.allocation.transaction.AllocTransactionResult; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocStartResultBo; +import org.dromara.daxpay.service.convert.allocation.AllocTransactionConvert; +import org.dromara.daxpay.service.dao.allocation.transaction.AllocDetailManager; +import org.dromara.daxpay.service.dao.allocation.transaction.AllocTransactionManager; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.dromara.daxpay.service.entity.allocation.transaction.TransactionAndDetail; +import org.dromara.daxpay.service.entity.order.pay.PayOrder; +import org.dromara.daxpay.service.service.allocation.transaction.AllocAssistService; +import org.dromara.daxpay.service.strategy.AbsAllocationStrategy; +import org.dromara.daxpay.service.util.PaymentStrategyFactory; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static org.dromara.daxpay.core.enums.AllocTransactionStatusEnum.ALLOC_END; +import static org.dromara.daxpay.core.enums.AllocTransactionStatusEnum.FINISH_FAILED; + +/** + * 分账处理 + * @author xxm + * @since 2024/11/14 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AllocationService { + + private final AllocTransactionManager allocationOrderManager; + + private final AllocDetailManager allocOrderDetailManager; + + private final AllocAssistService allocationAssistService; + + private final LockTemplate lockTemplate; + + /** + * 开启分账 多次请求只会分账一次 + * 优先级 分账接收方列表 > 分账组编号 > 默认分账组 + */ + public AllocResult allocation(AllocationParam param) { + // 判断是否已经有分账订单 + var allocOrder = allocationOrderManager.findByBizAllocNo(param.getBizAllocNo(), param.getAppId()).orElse(null); + if (Objects.nonNull(allocOrder)){ + // 重复分账 + return this.retryAlloc(param, allocOrder); + } else { + // 首次分账 + PayOrder payOrder = allocationAssistService.getAndCheckPayOrder(param); + return this.allocation(param, payOrder); + } + } + + /** + * 开启分账 优先级 分账接收方列表 > 分账组编号 > 默认分账组 + */ + public AllocResult allocation(AllocationParam param, PayOrder payOrder) { + LockInfo lock = lockTemplate.lock("payment:allocation:" + payOrder.getId(),10000,200); + if (Objects.isNull(lock)){ + throw new RepetitiveOperationException("分账发起处理中,请勿重复操作"); + } + try { + // 构建分账订单相关信息 + TransactionAndDetail orderAndDetail = allocationAssistService.checkAndCreateAlloc(param, payOrder); + // 检查是否需要进行分账 + var order = orderAndDetail.transaction(); + List details = orderAndDetail.details(); + // 无需进行分账, + if (Objects.equals(order.getStatus(), AllocTransactionStatusEnum.IGNORE.getCode())){ + return new AllocResult() + .setAllocNo(order.getAllocNo()) + .setBizAllocNo(order.getBizAllocNo()) + .setStatus(order.getStatus()); + } + // 创建分账策略并初始化 + var allocationStrategy = PaymentStrategyFactory.create(payOrder.getChannel(),AbsAllocationStrategy.class); + allocationStrategy.initParam(order, details); + try { + // 分账预处理 + allocationStrategy.doBeforeHandler(); + // 分账处理 + AllocStartResultBo result = allocationStrategy.start(); + // 执行中 + order.setStatus(AllocTransactionStatusEnum.ALLOC_PROCESSING.getCode()) + .setResult(AllocTransactionResultEnum.ALL_PENDING.getCode()) + .setOutAllocNo(result.getOutAllocNo()) + .setErrorMsg(null); + } catch (Exception e) { + log.error("分账出现错误:", e); + // 失败 + order.setStatus(AllocTransactionStatusEnum.ALLOC_FAILED.getCode()) + .setErrorMsg(e.getMessage()); + // TODO 返回异常处理 + } + allocationOrderManager.updateById(order); + return new AllocResult() + .setAllocNo(order.getAllocNo()) + .setBizAllocNo(order.getBizAllocNo()) + .setStatus(order.getStatus()); + } finally { + lockTemplate.releaseLock(lock); + } + } + + /** + * 重新分账 + */ + private AllocResult retryAlloc(AllocationParam param, AllocTransaction order){ + LockInfo lock = lockTemplate.lock("payment:allocation:" + order.getOrderId(),10000,200); + if (Objects.isNull(lock)){ + throw new RepetitiveOperationException("分账发起处理中,请勿重复操作"); + } + try { + // 需要是分账中分账中或者完成状态才能重新分账 + List list = Arrays.asList(ALLOC_END.getCode(), + AllocTransactionStatusEnum.ALLOC_FAILED.getCode(), + AllocTransactionStatusEnum.ALLOC_PROCESSING.getCode()); + if (!list.contains(order.getStatus())){ + throw new TradeStatusErrorException("分账单状态错误,无法重试"); + } + List details = allocationAssistService.getDetails(order.getId()); + // 创建分账策略并初始化 + var allocationStrategy = PaymentStrategyFactory.create(order.getChannel(),AbsAllocationStrategy.class); + allocationStrategy.initParam(order, details); + // 分账预处理 + allocationStrategy.doBeforeHandler(); + // 更新分账单信息 + allocationAssistService.updateOrder(param, order); + try { + // 重复分账处理 + allocationStrategy.start(); + order.setStatus(AllocTransactionStatusEnum.ALLOC_PROCESSING.getCode()) + .setErrorMsg(null); + + } catch (Exception e) { + log.error("重新分账出现错误:", e); + order.setStatus(AllocTransactionStatusEnum.ALLOC_FAILED.getCode()) + .setErrorMsg(e.getMessage()); + } + allocationOrderManager.updateById(order); + return new AllocResult() + .setAllocNo(order.getAllocNo()) + .setBizAllocNo(order.getBizAllocNo()) + .setStatus(order.getStatus()); + } finally { + lockTemplate.releaseLock(lock); + } + } + + /** + * 分账完结 + */ + public AllocResult finish(AllocFinishParam param) { + AllocTransaction allocOrder; + if (Objects.nonNull(param.getAllocNo())){ + allocOrder = allocationOrderManager.findByAllocNo(param.getAllocNo(), param.getAppId()) + .orElseThrow(() -> new DataNotExistException("未查询到分账单信息")); + } else { + allocOrder = allocationOrderManager.findByBizAllocNo(param.getBizAllocNo(), param.getAppId()) + .orElseThrow(() -> new DataNotExistException("未查询到分账单信息")); + } + return this.finish(allocOrder); + } + + /** + * 分账完结 + */ + public AllocResult finish(AllocTransaction allocOrder) { + // 只有分账结束后才可以完结 + if (!Arrays.asList(ALLOC_END.getCode(),FINISH_FAILED.getCode()).contains(allocOrder.getStatus())) { + throw new TradeStatusErrorException("分账单状态错误"); + } + List details = allocationAssistService.getDetails(allocOrder.getId()); + + // 创建分账策略并初始化 + AbsAllocationStrategy allocationStrategy = PaymentStrategyFactory.create(allocOrder.getChannel(),AbsAllocationStrategy.class); + allocationStrategy.initParam(allocOrder, details); + + // 分账完结预处理 + allocationStrategy.doBeforeHandler(); + try { + // 完结处理 + allocationStrategy.finish(); + // 完结状态 + allocOrder.setStatus(AllocTransactionStatusEnum.FINISH.getCode()) + .setFinishTime(LocalDateTime.now()) + .setErrorMsg(null); + } catch (Exception e) { + log.error("分账完结错误:", e); + // 失败 + allocOrder.setStatus(FINISH_FAILED.getCode()) + .setErrorMsg(e.getMessage()); + } + allocationOrderManager.updateById(allocOrder); + return new AllocResult() + .setAllocNo(allocOrder.getAllocNo()) + .setBizAllocNo(allocOrder.getBizAllocNo()) + .setStatus(allocOrder.getStatus()); + } + + + /** + * 查询分账结果 + */ + public AllocTransactionResult queryAllocTransaction(QueryAllocTransactionParam param) { + // 查询分账单 + var allocOrder = allocationOrderManager.findByAllocNo(param.getAllocNo(), param.getAppId()) + .orElseThrow(() -> new DataErrorException("分账单不存在")); + var result = AllocTransactionConvert.CONVERT.toResult(allocOrder); + // 查询分账单明细 + var details = allocOrderDetailManager.findAllByOrderId(allocOrder.getId()).stream() + .map(AllocTransactionConvert.CONVERT::toResult) + .collect(Collectors.toList()); + result.setDetails(details); + return result; + } + + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocGroupService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/receiver/AllocGroupService.java similarity index 97% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocGroupService.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/receiver/AllocGroupService.java index 87d93a8b..6575d671 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocGroupService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/receiver/AllocGroupService.java @@ -1,4 +1,4 @@ -package org.dromara.daxpay.service.service.allocation; +package org.dromara.daxpay.service.service.allocation.receiver; import cn.bootx.platform.common.mybatisplus.function.CollectorsFunction; import cn.bootx.platform.common.mybatisplus.util.MpUtil; @@ -10,7 +10,7 @@ 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.bo.allocation.AllocGroupReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupReceiverResultBo; 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; @@ -19,7 +19,7 @@ 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.bo.allocation.AllocGroupResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupResultBo; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocReceiverService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/receiver/AllocReceiverService.java similarity index 98% rename from daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocReceiverService.java rename to daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/receiver/AllocReceiverService.java index 120e8e51..aee595fd 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/AllocReceiverService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/receiver/AllocReceiverService.java @@ -1,4 +1,4 @@ -package org.dromara.daxpay.service.service.allocation; +package org.dromara.daxpay.service.service.allocation.receiver; import cn.bootx.platform.baseapi.service.dict.DictionaryItemService; import cn.bootx.platform.common.mybatisplus.util.MpUtil; @@ -20,7 +20,7 @@ import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverAddParam; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverQueryParam; import org.dromara.daxpay.core.param.allocation.receiver.AllocReceiverRemoveParam; import org.dromara.daxpay.core.result.allocation.receiver.AllocReceiverResult; -import org.dromara.daxpay.service.bo.allocation.AllocReceiverResultBo; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocReceiverResultBo; 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; diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/transaction/AllocAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/transaction/AllocAssistService.java new file mode 100644 index 00000000..da8a1f73 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/transaction/AllocAssistService.java @@ -0,0 +1,124 @@ +package org.dromara.daxpay.service.service.allocation.transaction; + +import cn.bootx.platform.core.exception.ValidationFailedException; +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.core.enums.AllocDetailResultEnum; +import org.dromara.daxpay.core.enums.PayAllocStatusEnum; +import org.dromara.daxpay.core.exception.DataErrorException; +import org.dromara.daxpay.core.exception.OperationUnsupportedException; +import org.dromara.daxpay.core.exception.TradeNotExistException; +import org.dromara.daxpay.core.exception.TradeStatusErrorException; +import org.dromara.daxpay.core.param.allocation.transaction.AllocationParam; +import org.dromara.daxpay.service.dao.allocation.receiver.AllocGroupManager; +import org.dromara.daxpay.service.dao.allocation.transaction.AllocDetailManager; +import org.dromara.daxpay.service.dao.allocation.transaction.AllocTransactionManager; +import org.dromara.daxpay.service.entity.allocation.receiver.AllocGroup; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.dromara.daxpay.service.entity.allocation.transaction.TransactionAndDetail; +import org.dromara.daxpay.service.entity.order.pay.PayOrder; +import org.dromara.daxpay.service.service.allocation.receiver.AllocGroupService; +import org.dromara.daxpay.service.service.order.pay.PayOrderQueryService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 分账支撑方法 + * @author xxm + * @since 2024/5/22 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AllocAssistService { + + private final AllocTransactionManager transactionManager; + + private final PayOrderQueryService payOrderQueryService; + + private final AllocGroupManager groupManager; + + private final AllocGroupService allocationGroupService; + + private final AllocTransactionService allocOrderService; + + private final AllocDetailManager allocOrderDetailManager; + + + /** + * 根据新传入的分账订单更新订单信息 + */ + @Transactional(rollbackFor = Exception.class) + public void updateOrder(AllocationParam allocationParam, AllocTransaction orderExtra) { + // 扩展信息 + orderExtra.setClientIp(allocationParam.getClientIp()) + .setNotifyUrl(allocationParam.getNotifyUrl()) + .setAttach(allocationParam.getAttach()) + .setReqTime(allocationParam.getReqTime()); + transactionManager.updateById(orderExtra); + } + + /** + * 获取并检查支付订单 + */ + public PayOrder getAndCheckPayOrder(AllocationParam param) { + // 查询支付单 + PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getOrderNo(), param.getBizOrderNo(), param.getAppId()) + .orElseThrow(() -> new TradeNotExistException("支付单不存在")); + // 判断订单是否可以分账 + if (!payOrder.getAllocation()){ + throw new OperationUnsupportedException("该订单不允许分账"); + } + // 判断分账状态 + if (Objects.equals(PayAllocStatusEnum.ALLOCATION.getCode(), payOrder.getAllocStatus())){ + throw new TradeStatusErrorException("该订单已分账完成"); + } + return payOrder; + } + + /** + * 构建分账订单相关信息 + */ + public TransactionAndDetail checkAndCreateAlloc(AllocationParam param, PayOrder payOrder){ + // 创建分账单和明细并保存, 同时更新支付订单状态 使用事务 + TransactionAndDetail orderAndDetail; + // 判断是否传输了分账接收方列表 + if (CollUtil.isNotEmpty(param.getReceivers())) { + orderAndDetail = allocOrderService.createAndUpdate(param, payOrder); + } else { + AllocGroup allocationGroup; + if (Objects.nonNull(param.getGroupNo())){ + // 指定分账组 + allocationGroup = groupManager.findByGroupNo(param.getGroupNo(),param.getAppId()).orElseThrow(() -> new DataErrorException("未查询到分账组")); + } else { + // 默认分账组 + allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel(),param.getAppId()).orElseThrow(() -> new DataErrorException("未查询到默认分账组")); + } + // 判断通道类型是否一致 + if (!Objects.equals(allocationGroup.getChannel(), payOrder.getChannel())){ + throw new ValidationFailedException("分账接收方列表存在非本通道的数据"); + } + + var receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId()); + orderAndDetail = allocOrderService.createAndUpdate(param ,payOrder, receiversByGroups); + } + return orderAndDetail; + } + + /** + * 获取发起分账或完结的明细 + */ + public List getDetails(Long allocOrderId){ + List details = allocOrderDetailManager.findAllByOrderId(allocOrderId); + // 过滤掉忽略的条目 + return details.stream() + .filter(detail -> !Objects.equals(detail.getResult(), AllocDetailResultEnum.IGNORE.getCode())) + .collect(Collectors.toList()); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/transaction/AllocTransactionService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/transaction/AllocTransactionService.java new file mode 100644 index 00000000..ad5cce38 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/allocation/transaction/AllocTransactionService.java @@ -0,0 +1,185 @@ +package org.dromara.daxpay.service.service.allocation.transaction; + +import cn.bootx.platform.core.exception.ValidationFailedException; +import cn.bootx.platform.core.util.BigDecimalUtil; +import cn.hutool.core.util.IdUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.core.enums.AllocDetailResultEnum; +import org.dromara.daxpay.core.enums.AllocTransactionResultEnum; +import org.dromara.daxpay.core.enums.AllocTransactionStatusEnum; +import org.dromara.daxpay.core.enums.PayAllocStatusEnum; +import org.dromara.daxpay.core.param.allocation.transaction.ReceiverParam; +import org.dromara.daxpay.core.param.allocation.transaction.AllocationParam; +import org.dromara.daxpay.core.util.TradeNoGenerateUtil; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocGroupReceiverResultBo; +import org.dromara.daxpay.service.dao.allocation.receiver.AllocReceiverManager; +import org.dromara.daxpay.service.dao.allocation.transaction.AllocDetailManager; +import org.dromara.daxpay.service.dao.allocation.transaction.AllocTransactionManager; +import org.dromara.daxpay.service.dao.order.pay.PayOrderManager; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; +import org.dromara.daxpay.service.entity.allocation.transaction.TransactionAndDetail; +import org.dromara.daxpay.service.entity.order.pay.PayOrder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 分账交易记录服务 + * @author xxm + * @since 2024/11/14 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AllocTransactionService { + + private final AllocReceiverManager receiverManager; + + private final AllocTransactionManager transactionManager; + + private final AllocDetailManager transactionDetailManager; + + private final PayOrderManager payOrderManager; + + /** + * 生成分账订单, 根据分账组创建 + */ + @Transactional(rollbackFor = Exception.class) + public TransactionAndDetail createAndUpdate(AllocationParam param, PayOrder payOrder, List receiversByGroups) { + // 订单明细 + List details = receiversByGroups.stream() + .map(o -> { + // 计算分账金额, 小数部分直接舍弃, 防止分账金额超过上限 + // 等同于 payOrder.getAmount() * rate / 100; + var amount = payOrder.getAmount() + .multiply(o.getRate()) + .divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN); + + AllocDetail detail = new AllocDetail() + .setReceiverNo(o.getReceiverNo()) + .setReceiverId(o.getId()) + .setAmount(amount) + .setResult(AllocDetailResultEnum.PENDING.getCode()) + .setRate(amount) + .setReceiverType(o.getReceiverType()) + .setReceiverName(o.getReceiverName()) + .setReceiverAccount(o.getReceiverAccount()); + // 如果金额为0, 设置为分账失败, 不参与分账 + if (BigDecimalUtil.isEqual(amount, BigDecimal.ZERO)) { + detail.setResult(AllocDetailResultEnum.IGNORE.getCode()) + .setErrorMsg("分账比例有误或金额太小, 无法进行分账") + .setFinishTime(LocalDateTime.now()); + } + return detail; + }) + .collect(Collectors.toList()); + return this.saveAllocOrder(param, payOrder, details); + } + + /** + * 生成分账订单, 通过传入的分账方创建 + */ + @Transactional(rollbackFor = Exception.class) + public TransactionAndDetail createAndUpdate(AllocationParam param, PayOrder payOrder) { + List receiverNos = param.getReceivers() + .stream() + .map(ReceiverParam::getReceiverNo) + .distinct() + .collect(Collectors.toList()); + if (receiverNos.size() != param.getReceivers() + .size()) { + throw new ValidationFailedException("分账接收方编号重复"); + } + var receiverNoMap = param.getReceivers() + .stream() + .collect(Collectors.toMap(ReceiverParam::getReceiverNo, ReceiverParam::getAmount)); + // 查询分账接收方信息 + var receivers = receiverManager.findAllByReceiverNos(receiverNos, payOrder.getAppId()); + if (receivers.size() != receiverNos.size()) { + throw new ValidationFailedException("分账接收方列表存在重复或无效的数据"); + } + // 判断分账接收方类型是否都与分账订单类型匹配 + boolean anyMatch = receivers.stream() + .anyMatch(o -> !Objects.equals(o.getChannel(), payOrder.getChannel())); + if (anyMatch) { + throw new ValidationFailedException("分账接收方列表存在非本通道的数据"); + } + long allocId = IdUtil.getSnowflakeNextId(); + // 订单明细 + List details = receivers.stream() + .map(o -> { + // 计算分账比例, 不是很精确 + var amount = receiverNoMap.get(o.getReceiverNo()); + var rate = amount + .divide(payOrder.getAmount(), 2, RoundingMode.DOWN) + .multiply(BigDecimal.valueOf(100)); + AllocDetail detail = new AllocDetail(); + detail.setAllocationId(allocId) + .setReceiverId(o.getId()) + .setReceiverNo(o.getReceiverNo()) + .setAmount(amount) + .setResult(AllocDetailResultEnum.PENDING.getCode()) + .setRate(rate) + .setReceiverType(o.getReceiverType()) + .setReceiverName(o.getReceiverName()) + .setReceiverAccount(o.getReceiverAccount()); + return detail; + }) + .collect(Collectors.toList()); + return this.saveAllocOrder(param, payOrder, details); + } + + /** + * 保存分账相关订单信息 + */ + private TransactionAndDetail saveAllocOrder(AllocationParam param, PayOrder payOrder, List details) { + long allocId = IdUtil.getSnowflakeNextId(); + // 分账明细设置ID + details.forEach(o -> o.setAllocationId(allocId)); + // 求分账的总额 + var sumAmount = details.stream() + .map(AllocDetail::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + // 分账订单 + var allocOrder = new AllocTransaction() + .setOrderId(payOrder.getId()) + .setOrderNo(payOrder.getOrderNo()) + .setBizOrderNo(payOrder.getBizOrderNo()) + .setOutOrderNo(payOrder.getOutOrderNo()) + .setTitle(payOrder.getTitle()) + .setAllocNo(TradeNoGenerateUtil.allocation()) + .setBizAllocNo(param.getBizAllocNo()) + .setChannel(payOrder.getChannel()) + .setDescription(param.getDescription()) + .setStatus(AllocTransactionStatusEnum.ALLOC_PROCESSING.getCode()) + .setResult(AllocTransactionResultEnum.ALL_PENDING.getCode()) + .setAmount(sumAmount) + .setNotifyUrl(param.getNotifyUrl()) + .setAttach(param.getAttach()) + .setClientIp(param.getClientIp()); + // 如果分账订单金额为0, 设置为忽略状态 + if (BigDecimalUtil.isEqual(sumAmount, BigDecimal.ZERO)) { + allocOrder.setStatus(AllocTransactionStatusEnum.IGNORE.getCode()) + .setFinishTime(LocalDateTime.now()) + .setResult(AllocTransactionStatusEnum.ALLOC_FAILED.getCode()) + .setErrorMsg("分账比例有误或金额太小, 无法进行分账"); + } + + allocOrder.setId(allocId); + // 更新支付订单分账状态 + payOrder.setAllocStatus(PayAllocStatusEnum.ALLOCATION.getCode()); + payOrderManager.updateById(payOrder); + transactionDetailManager.saveAll(details); + transactionManager.save(allocOrder); + return new TransactionAndDetail(allocOrder,details); + } +} + diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/strategy/AbsAllocationStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/strategy/AbsAllocationStrategy.java new file mode 100644 index 00000000..0f3d2ce1 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/strategy/AbsAllocationStrategy.java @@ -0,0 +1,48 @@ +package org.dromara.daxpay.service.strategy; + +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.service.bo.allocation.receiver.AllocStartResultBo; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocTransaction; +import org.dromara.daxpay.service.entity.allocation.transaction.AllocDetail; + +import java.util.List; + +/** + * 分账接收方管理抽象策略 + * @author xxm + * @since 2024/4/1 + */ +@Slf4j +@Getter +@Setter +public abstract class AbsAllocationStrategy implements PaymentStrategy{ + private AllocTransaction transaction; + + private List details; + + /** + * 初始化参数 + */ + public void initParam(AllocTransaction transaction, List details) { + this.transaction = transaction; + this.details = details; + } + + /** + * 操作前处理, 校验和初始化支付配置 + */ + public abstract void doBeforeHandler(); + + /** + * 分账启动 + */ + public abstract AllocStartResultBo start(); + + /** + * 分账完结 + */ + public abstract void finish(); + +}