ref 分账开发接口开发和结构调整

This commit is contained in:
DaxPay
2024-05-21 22:41:00 +08:00
parent 6b5513b638
commit 3ac539f277
36 changed files with 688 additions and 242 deletions

View File

@@ -3,21 +3,25 @@
- [x] 新增资金流水
- [x] 增加对超时订单进行处理(数据库同步)
- [x] 支持分账组分账和自己传接收方进行分账
- [ ] 分账组管理提供接口调用
- [ ] 添加分账接收方
- [ ] 查询分账接收方
- [ ] 删除分账接收方
- [ ] 启动分账
- [ ] 分账查询
- [ ] 分账完结
- [x] 分账组管理提供接口调用
- [x] 添加分账接收方
- [x] 查询分账接收方
- [x] 删除分账接收方
- [x] 启动分账
- [x] 自定义比例分账
- [x] 默认分账组分账
- [x] 指定分账组分账
- [x] 分账查询
- [x] 分账完结
- [x] 分账同步
- [ ] SDK支持分账相关接口
- [ ] DEMO增加获取微信OpenID和支付宝OpenId功能
- [ ] 分账回调处理
- [ ] 分账组管理提供接口调用
- [ ] 分账通知发送功能
- [ ] 分账支持手动和自动分账两种
- [x] 分账支持手动和自动分账两种
- [ ] 金额过小不进行分账, 增加新状态, 金额小于0.01元直接忽略
- [ ] 增加收单收银台功能
- [x] 对账差异单, 数据不一致处理异常, 本地待对账订单类型记录错误
- 2.0.7: 对账完善和系统优化
- [ ] 对账提供外部接口调用
- [ ] 下载系统账单

View File

@@ -5,9 +5,10 @@ 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.daxpay.single.param.payment.allocation.AllocReceiverAddParam;
import cn.daxpay.single.param.payment.allocation.AllocReceiverRemoveParam;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationReceiverService;
import cn.daxpay.single.service.dto.allocation.AllocationReceiverDto;
import cn.daxpay.single.service.param.allocation.receiver.AllocationReceiverParam;
import cn.daxpay.single.service.param.allocation.receiver.AllocationReceiverQuery;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -53,39 +54,17 @@ public class AllocationReceiverController {
return Res.ok(receiverService.findReceiverTypeByChannel(channel));
}
@Operation(summary = "新增")
@Operation(summary = "添加")
@PostMapping("add")
public ResResult<Void> add(@RequestBody AllocationReceiverParam param){
receiverService.add(param);
return Res.ok();
}
@Operation(summary = "修改")
@PostMapping("update")
public ResResult<Void> update(@RequestBody AllocationReceiverParam param){
receiverService.update(param);
public ResResult<Void> add(@RequestBody AllocReceiverAddParam param){
receiverService.addAndSync(param);
return Res.ok();
}
@Operation(summary = "删除")
@PostMapping("delete")
public ResResult<Void> delete(Long id){
receiverService.remove(id);
public ResResult<Void> delete(@RequestBody AllocReceiverRemoveParam param){
receiverService.remove(param);
return Res.ok();
}
@Operation(summary = "同步到三方支付系统中")
@PostMapping("registerByGateway")
public ResResult<Void> registerByGateway(Long id){
receiverService.registerByGateway(id);
return Res.ok();
}
@Operation(summary = "从三方支付系统中删除")
@PostMapping("removeByGateway")
public ResResult<Void> removeByGateway(Long id){
receiverService.removeByGateway(id);
return Res.ok();
}
}

View File

@@ -28,6 +28,8 @@ public interface PaymentApiCode {
String QUERY_REFUND_ORDER = "queryRefundOrder";
/** 查询分账订单 */
String QUERY_ALLOCATION_ORDER = "queryAllocationOrder";
/** 查询分账接收方 */
String QUERY_ALLOCATION_RECEIVER = "QueryAllocationReceiver";
/** 获取微信授权链接 */
String GET_WX_AUTH_URL = "getWxAuthUrl";
/** 获取微信AccessToken */
@@ -36,8 +38,6 @@ public interface PaymentApiCode {
String ALLOCATION_RECEIVER_ADD = "allocationReceiverAdd";
/** 删除分账方 */
String ALLOCATION_RECEIVER_REMOVE = "allocationReceiverRemove";
/** 查询分账方 */
String ALLOCATION_RECEIVER_QUERY = "allocationReceiverQuery";

View File

@@ -35,7 +35,7 @@ public class AllocReceiverAddParam extends PaymentCommonParam {
private String channel;
/**
* 分账接收方类型 个人/商户
* 分账接收方类型 根据不同类型的通道进行传输
* @see AllocReceiverTypeEnum
*/
@Schema(description = "分账接收方类型")

View File

@@ -0,0 +1,24 @@
package cn.daxpay.single.param.payment.allocation;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 分账接收方列表
* @author xxm
* @since 2024/5/21
*/
@Data
@Accessors(chain = true)
@Schema(title = "分账接收方列表")
public class AllocReceiverParam {
/** 分账接收方编号 */
@Schema(description = "分账接收方编号")
private String receiverNo;
/** 分账金额 */
@Schema(description = "分账金额")
private Integer amount;
}

View File

@@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 开始分账请求参数
@@ -22,19 +23,26 @@ public class AllocStartParam extends PaymentCommonParam {
@NotBlank(message = "商户分账单号不可为空")
private String bizAllocationNo;
/** 支付订单号 */
@Schema(description = "支付订单号")
private String orderNo;
/** 商户订单号 */
@Schema(description = "商户订单号")
private String bizOrderNo;
/** 分账描述 */
@Schema(description = "分账描述")
private String description;
/**
* 不传输分账组使用默认分账组进行分账
* 优先级 分账接收方列表 > 分账组编号 > 默认分账组
*/
@Schema(description = "分账组ID")
private Long allocationGroupId;
@Schema(description = "分账组编号")
private String groupNo;
/** 分账接收方列表 */
@Schema(description = "分账接收方列表")
private List<AllocReceiverParam> receivers;
}

View File

@@ -16,4 +16,8 @@ import lombok.experimental.Accessors;
@Accessors(chain = true)
@Schema(title = "查询分账接收者参数")
public class QueryAllocReceiverParam extends PaymentCommonParam {
/** 所属通道 */
@Schema(description = "所属通道")
private String channel;
}

View File

@@ -0,0 +1,65 @@
package cn.daxpay.single.result.allocation;
import cn.daxpay.single.code.AllocDetailResultEnum;
import cn.daxpay.single.code.AllocReceiverTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 分账订单明细
* @author xxm
* @since 2024/5/21
*/
@Data
@Accessors(chain = true)
@Schema(title = "分账订单明细")
public class AllocOrderDetailResult {
@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;
}

View File

@@ -0,0 +1,116 @@
package cn.daxpay.single.result.allocation;
import cn.daxpay.single.code.AllocOrderResultEnum;
import cn.daxpay.single.code.AllocOrderStatusEnum;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
/**
* 分账订单返回结果
* @author xxm
* @since 2024/5/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "分账订单返回结果")
public class AllocOrderResult extends PaymentCommonResult {
/**
* 分账单号
*/
@Schema(description = "分账单号")
private String allocationNo;
/**
* 商户分账单号
*/
@Schema(description = "商户分账单号")
private String bizAllocationNo;
/**
* 通道分账号
*/
@Schema(description = "通道分账号")
private String outAllocationNo;
/**
* 支付订单号
*/
@Schema(description = "支付订单号")
private String orderNo;
/**
* 商户支付订单号
*/
@Schema(description = "商户支付订单号")
private String bizOrderNo;
/**
* 支付订单标题
*/
@Schema(description = "支付订单标题")
private String title;
/**
* 所属通道
* @see PayChannelEnum
*/
@Schema(description = "所属通道")
private String channel;
/**
* 总分账金额
*/
@Schema(description = "总分账金额")
private Integer amount;
/**
* 分账描述
*/
@Schema(description = "分账描述")
private String description;
/**
* 状态
* @see AllocOrderStatusEnum
*/
@Schema(description = "状态")
private String status;
/**
* 处理结果
* @see AllocOrderResultEnum
*/
@Schema(description = "处理结果")
private String result;
/**
* 错误码
*/
@Schema(description = "错误码")
private String errorCode;
/**
* 错误信息
*/
@Schema(description = "错误原因")
private String errorMsg;
/** 分账订单完成时间 */
@Schema(description = "分账订单完成时间")
private LocalDateTime finishTime;
/** 分账明细 */
@Schema(description = "分账明细")
private List<AllocOrderDetailResult> details;
}

View File

@@ -0,0 +1,19 @@
package cn.daxpay.single.result.allocation;
import cn.daxpay.single.result.pay.PayCloseResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 分账接收方添加返回结果
* @author xxm
* @since 2024/5/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "分账接收方返回结果")
public class AllocReceiverAddResult extends PayCloseResult {
}

View File

@@ -0,0 +1,19 @@
package cn.daxpay.single.result.allocation;
import cn.daxpay.single.result.pay.PayCloseResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 分账接收方删除返回结果
* @author xxm
* @since 2024/5/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "分账接收方返回结果")
public class AllocReceiverRemoveResult extends PayCloseResult {
}

View File

@@ -0,0 +1,53 @@
package cn.daxpay.single.result.allocation;
import cn.daxpay.single.code.AllocReceiverTypeEnum;
import cn.daxpay.single.code.AllocRelationTypeEnum;
import cn.daxpay.single.code.PayChannelEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 分账接收方
* @author xxm
* @since 2024/5/21
*/
@Data
@Accessors(chain = true)
@Schema(title = "分账接收方")
public class AllocReceiverResult {
/** 分账接收方编号, 需要保证唯一 */
private String receiverNo;
/** 账号别名 */
private String name;
/**
* 所属通道
* @see PayChannelEnum
*/
private String channel;
/**
* 分账接收方类型
* @see AllocReceiverTypeEnum
*/
private String receiverType;
/** 接收方账号 */
private String receiverAccount;
/** 接收方姓名 */
private String receiverName;
/**
* 分账关系类型
* @see AllocRelationTypeEnum
*/
private String relationType;
/** 关系名称 */
private String relationName;
}

View File

@@ -0,0 +1,25 @@
package cn.daxpay.single.result.allocation;
import cn.daxpay.single.result.pay.PayCloseResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 分账接收方返回结果
* @author xxm
* @since 2024/5/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "分账接收方返回结果")
public class AllocReceiversResult extends PayCloseResult {
@Schema(description = "接收方列表")
private List<AllocReceiverResult> receivers;
}

View File

@@ -3,8 +3,7 @@ package cn.daxpay.single.gateway.controller;
import cn.daxpay.single.code.PaymentApiCode;
import cn.daxpay.single.param.payment.allocation.*;
import cn.daxpay.single.result.DaxResult;
import cn.daxpay.single.result.allocation.AllocationResult;
import cn.daxpay.single.result.allocation.AllocationSyncResult;
import cn.daxpay.single.result.allocation.*;
import cn.daxpay.single.service.annotation.PaymentApi;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationReceiverService;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationService;
@@ -53,34 +52,18 @@ public class UniAllocationController {
return DaxRes.ok(allocationService.sync(param));
}
@PaymentApi(PaymentApiCode.QUERY_ALLOCATION_ORDER)
@Operation(summary = "分账查询接口")
@PostMapping("/query")
public DaxResult<Void> query(@RequestBody AllocFinishParam param){
allocationService.query(param);
return DaxRes.ok();
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_ADD)
@Operation(summary = "添加分账接收方接口")
@PostMapping("/receiver/add")
public DaxResult<Void> receiverAdd(@RequestBody AllocReceiverAddParam param){
receiverService.addAndSync(param);
return DaxRes.ok();
public DaxResult<AllocReceiverAddResult> receiverAdd(@RequestBody AllocReceiverAddParam param){
return DaxRes.ok(receiverService.addAndSync(param));
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_REMOVE)
@Operation(summary = "删除分账接收方接口")
@PostMapping("/receiver/remove")
public DaxResult<Void> receiverRemove(@RequestBody AllocReceiverRemoveParam param){
return DaxRes.ok();
}
@PaymentApi(PaymentApiCode.ALLOCATION_RECEIVER_QUERY)
@Operation(summary = "查询分账接收方接口")
@PostMapping("/receiver/query")
public DaxResult<Void> receiveQuery(@RequestBody QueryAllocReceiverParam param){
return DaxRes.ok();
public DaxResult<AllocReceiverRemoveResult> receiverRemove(@RequestBody AllocReceiverRemoveParam param){
return DaxRes.ok(receiverService.remove(param));
}
}

View File

@@ -2,14 +2,20 @@ package cn.daxpay.single.gateway.controller;
import cn.bootx.platform.common.core.annotation.IgnoreAuth;
import cn.daxpay.single.code.PaymentApiCode;
import cn.daxpay.single.param.payment.allocation.QueryAllocOrderParam;
import cn.daxpay.single.param.payment.allocation.QueryAllocReceiverParam;
import cn.daxpay.single.param.payment.pay.QueryPayParam;
import cn.daxpay.single.param.payment.refund.QueryRefundParam;
import cn.daxpay.single.result.DaxResult;
import cn.daxpay.single.result.allocation.AllocOrderResult;
import cn.daxpay.single.result.allocation.AllocReceiversResult;
import cn.daxpay.single.result.order.PayOrderResult;
import cn.daxpay.single.result.order.RefundOrderResult;
import cn.daxpay.single.service.annotation.PaymentApi;
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
import cn.daxpay.single.service.core.order.refund.service.RefundOrderQueryService;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationReceiverService;
import cn.daxpay.single.service.core.payment.allocation.service.AllocationService;
import cn.daxpay.single.util.DaxRes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -33,6 +39,8 @@ public class UniQueryController {
private final PayOrderQueryService payOrderQueryService;
private final RefundOrderQueryService refundOrderQueryService;
private final AllocationReceiverService allocationReceiverService;
private final AllocationService allocationService;
@PaymentApi(PaymentApiCode.QUERY_PAY_ORDER)
@Operation(summary = "支付订单查询接口")
@@ -47,4 +55,20 @@ public class UniQueryController {
public DaxResult<RefundOrderResult> queryRefundOrder(@RequestBody QueryRefundParam param){
return DaxRes.ok(refundOrderQueryService.queryRefundOrder(param));
}
@PaymentApi(PaymentApiCode.QUERY_ALLOCATION_ORDER)
@Operation(summary = "分账订单查询接口")
@PostMapping("/allocationOrder")
public DaxResult<AllocOrderResult> queryAllocationOrder(@RequestBody QueryAllocOrderParam param){
return DaxRes.ok(allocationService.queryAllocationOrder(param));
}
@PaymentApi(PaymentApiCode.QUERY_ALLOCATION_RECEIVER)
@Operation(summary = "分账接收方查询接口")
@PostMapping("/allocReceiver")
public DaxResult<AllocReceiversResult> queryAllocReceive(@RequestBody QueryAllocReceiverParam param){
return DaxRes.ok(allocationReceiverService.queryAllocReceive(param));
}
}

View File

@@ -1,5 +1,7 @@
package cn.daxpay.single.service.core.order.allocation.convert;
import cn.daxpay.single.result.allocation.AllocOrderDetailResult;
import cn.daxpay.single.result.allocation.AllocOrderResult;
import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrder;
import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrderDetail;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDetailDto;
@@ -19,6 +21,10 @@ public interface AllocationConvert {
AllocationOrderDto convert(AllocationOrder in);
AllocOrderResult toResult(AllocationOrder in);
AllocOrderDetailResult toResult(AllocationOrderDetail in);
AllocationOrderDetailDto convert(AllocationOrderDetail in);
}

View File

@@ -2,17 +2,16 @@ package cn.daxpay.single.service.core.order.allocation.entity;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import cn.daxpay.single.code.AllocOrderResultEnum;
import cn.daxpay.single.code.AllocOrderStatusEnum;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.service.core.order.allocation.convert.AllocationConvert;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDto;
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 io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@@ -74,7 +73,7 @@ public class AllocationOrder extends MpBaseEntity implements EntityBaseFunction<
/**
* 支付订单标题
*/
@Schema(description = "支付订单标题")
@DbColumn(comment = "支付订单标题")
private String title;
/**

View File

@@ -2,13 +2,13 @@ package cn.daxpay.single.service.core.order.allocation.entity;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import cn.daxpay.single.code.AllocDetailResultEnum;
import cn.daxpay.single.code.AllocReceiverTypeEnum;
import cn.daxpay.single.service.common.typehandler.DecryptTypeHandler;
import cn.daxpay.single.service.core.order.allocation.convert.AllocationConvert;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDetailDto;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -37,6 +37,10 @@ public class AllocationOrderDetail extends MpBaseEntity implements EntityBaseFun
@DbColumn(comment = "接收者ID")
private Long receiverId;
/** 分账接收方编号 */
@DbColumn(comment = "分账接收方编号")
private String receiverNo;
/** 分账比例 */
@DbColumn(comment = "分账比例(万分之多少)")
private Integer rate;

View File

@@ -10,6 +10,8 @@ import cn.daxpay.single.code.AllocDetailResultEnum;
import cn.daxpay.single.code.AllocOrderStatusEnum;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.code.PayOrderAllocStatusEnum;
import cn.daxpay.single.exception.pay.PayFailureException;
import cn.daxpay.single.param.payment.allocation.AllocReceiverParam;
import cn.daxpay.single.param.payment.allocation.AllocStartParam;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderDetailManager;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderManager;
@@ -18,6 +20,8 @@ import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrderDeta
import cn.daxpay.single.service.core.order.allocation.entity.OrderAndDetail;
import cn.daxpay.single.service.core.order.pay.dao.PayOrderManager;
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
import cn.daxpay.single.service.core.payment.allocation.dao.AllocationReceiverManager;
import cn.daxpay.single.service.core.payment.allocation.entity.AllocationReceiver;
import cn.daxpay.single.service.dto.allocation.AllocationGroupReceiverResult;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDetailDto;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDto;
@@ -29,8 +33,11 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -42,7 +49,10 @@ import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class AllocationOrderService {
private final AllocationReceiverManager receiverManager;
private final AllocationOrderManager allocationOrderManager;
private final AllocationOrderDetailManager allocationOrderDetailManager;
private final PayOrderManager payOrderManager;
@@ -89,10 +99,10 @@ public class AllocationOrderService {
/**
* 生成分账订单
* 生成分账订单, 根据分账组创建
*/
@Transactional(rollbackFor = Exception.class)
public OrderAndDetail createAndUpdate(AllocStartParam param, PayOrder payOrder, int orderAmount, List<AllocationGroupReceiverResult> receiversByGroups){
public OrderAndDetail createAndUpdate(AllocStartParam param, PayOrder payOrder, List<AllocationGroupReceiverResult> receiversByGroups){
long orderId = IdUtil.getSnowflakeNextId();
// 订单明细
@@ -100,9 +110,10 @@ public class AllocationOrderService {
.map(o -> {
// 计算分账金额, 小数不分直接舍弃, 防止分账金额超过上限
Integer rate = o.getRate();
Integer amount = orderAmount * rate / 10000;
Integer amount = payOrder.getAmount() * rate / 10000;
AllocationOrderDetail detail = new AllocationOrderDetail();
detail.setAllocationId(orderId)
.setReceiverNo(o.getReceiverNo())
.setReceiverId(o.getId())
.setAmount(amount)
.setResult(AllocDetailResultEnum.PENDING.getCode())
@@ -134,10 +145,79 @@ public class AllocationOrderService {
// 更新支付订单分账状态
payOrder.setAllocationStatus(PayOrderAllocStatusEnum.ALLOCATION.getCode());
payOrderManager.updateById(payOrder);
// 因为加密后字段值会发生变更, 所以在保存前备份一下
allocationOrderDetailManager.saveAll(details);
allocationOrderManager.save(allocationOrder);
return new OrderAndDetail().setOrder(allocationOrder).setDetails(details);
}
/**
* 生成分账订单, 通过传入的分账方创建
*/
public OrderAndDetail createAndUpdate(AllocStartParam param, PayOrder payOrder) {
List<String> receiverNos = param.getReceivers()
.stream()
.map(AllocReceiverParam::getReceiverNo)
.distinct()
.collect(Collectors.toList());
if (receiverNos.size() != param.getReceivers().size()){
throw new PayFailureException("分账接收方编号重复");
}
Map<String, Integer> receiverNoMap = param.getReceivers()
.stream()
.collect(Collectors.toMap(AllocReceiverParam::getReceiverNo, AllocReceiverParam::getAmount));
// 查询分账接收方信息
List<AllocationReceiver> receivers = receiverManager.findAllByReceiverNos(receiverNos);
if (receivers.size() != receiverNos.size()){
throw new PayFailureException("分账接收方列表存在无效的分账接收方");
}
long orderId = IdUtil.getSnowflakeNextId();
// 订单明细
List<AllocationOrderDetail> details = receivers.stream()
.map(o -> {
// 计算分账比例, 不是很精确
Integer amount = receiverNoMap.get(o.getReceiverNo());
Integer rate = BigDecimal.valueOf(amount)
.divide(BigDecimal.valueOf(payOrder.getAmount()), 4, RoundingMode.DOWN)
.multiply(BigDecimal.valueOf(10000)).intValue();
AllocationOrderDetail detail = new AllocationOrderDetail();
detail.setAllocationId(orderId)
.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());
// 求分账的总额
Integer sumAmount = details.stream()
.map(AllocationOrderDetail::getAmount)
.reduce(0, Integer::sum);
// 分账订单
AllocationOrder allocationOrder = new AllocationOrder()
.setOrderId(payOrder.getId())
.setOrderNo(payOrder.getOrderNo())
.setBizOrderNo(payOrder.getBizOrderNo())
.setOutOrderNo(payOrder.getOutOrderNo())
.setTitle(payOrder.getTitle())
.setAllocationNo(OrderNoGenerateUtil.allocation())
.setBizAllocationNo(param.getBizAllocationNo())
.setChannel(payOrder.getChannel())
.setDescription(param.getDescription())
.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
.setAmount(sumAmount);
allocationOrder.setId(orderId);
// 更新支付订单分账状态
payOrder.setAllocationStatus(PayOrderAllocStatusEnum.ALLOCATION.getCode());
payOrderManager.updateById(payOrder);
allocationOrderDetailManager.saveAll(details);
allocationOrderManager.save(allocationOrder);
return new OrderAndDetail().setOrder(allocationOrder).setDetails(details);
}
}

View File

@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 对账-第三方交易明细, 从三方系统下载的交易记录
* 对账-通道交易明细, 从三方系统下载的交易记录
* @author xxm
* @since 2024/1/18
*/

View File

@@ -1,6 +1,7 @@
package cn.daxpay.single.service.core.payment.allocation.convert;
import cn.daxpay.single.param.payment.allocation.AllocReceiverAddParam;
import cn.daxpay.single.result.allocation.AllocReceiverResult;
import cn.daxpay.single.service.core.payment.allocation.entity.AllocationReceiver;
import cn.daxpay.single.service.dto.allocation.AllocationReceiverDto;
import cn.daxpay.single.service.param.allocation.receiver.AllocationReceiverParam;
@@ -18,6 +19,8 @@ public interface AllocationReceiverConvert {
AllocationReceiverDto convert(AllocationReceiver in);
AllocReceiverResult toResult(AllocationReceiver in);
AllocationReceiver convert(AllocationReceiverParam in);
AllocationReceiver convert(AllocReceiverAddParam in);

View File

@@ -33,6 +33,15 @@ public class AllocationGroupManager extends BaseManager<AllocationGroupMapper, A
return page(mpPage,generator);
}
/**
* 根据分账组编号查询
*/
public Optional<AllocationGroup> findByGroupNo(String groupNo) {
return this.lambdaQuery()
.eq(AllocationGroup::getGroupNo,groupNo)
.oneOpt();
}
/**
* 清除默认分账组
*/

View File

@@ -12,6 +12,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/**
* 分账接收方
* @author xxm
@@ -31,4 +34,24 @@ public class AllocationReceiverManager extends BaseManager<AllocationReceiverMap
return this.page(mpPage, generator);
}
/**
* 根据接收方编号查询
*/
public Optional<AllocationReceiver> findByReceiverNo(String receiverNo) {
return findByField(AllocationReceiver::getReceiverNo, receiverNo);
}
/**
* 根据分账方编号查询列表
*/
public List<AllocationReceiver> findAllByReceiverNos(List<String> receiverNos) {
return findAllByFields(AllocationReceiver::getReceiverNo, receiverNos);
}
/**
* 根据所属通道查询
*/
public List<AllocationReceiver> findAllByChannel(String channel) {
return findAllByField(AllocationReceiver::getChannel, channel);
}
}

View File

@@ -26,19 +26,28 @@ import lombok.experimental.Accessors;
@TableName("pay_allocation_group")
public class AllocationGroup extends MpBaseEntity implements EntityBaseFunction<AllocationGroupDto> {
/** 分账组编码 */
@DbColumn(comment = "分账组编码")
private String groupNo;
/** 名称 */
@DbComment("名称")
private String name;
/** 通道 */
@DbColumn(comment = "通道")
@TableField(updateStrategy = FieldStrategy.NEVER)
private String channel;
/** 是否为默认分账组 */
@DbColumn(comment = "默认分账组")
private boolean defaultGroup;
/** 总分账比例(万分之多少) */
@DbColumn(comment = "总分账比例(万分之多少)")
private Integer totalRate;
/** 备注 */
@DbColumn(comment = "备注")
private String remark;

View File

@@ -33,10 +33,12 @@ public class AllocationReceiver extends MpBaseEntity implements EntityBaseFuncti
@DbColumn(comment = "分账接收方编号")
private String receiverNo;
/** 账号别名 */
@DbColumn(comment = "账号别名")
private String name;
/**
* 所属通道
* @see PayChannelEnum
*/
@DbColumn(comment = "所属通道")
@@ -50,7 +52,7 @@ public class AllocationReceiver extends MpBaseEntity implements EntityBaseFuncti
@DbColumn(comment = "分账接收方类型")
private String receiverType;
/** 接收方账号 */
@DbColumn(comment = "接收方账号")
@TableField(typeHandler = DecryptTypeHandler.class)
private String receiverAccount;
@@ -67,15 +69,10 @@ public class AllocationReceiver extends MpBaseEntity implements EntityBaseFuncti
@DbColumn(comment = "分账关系类型")
private String relationType;
/** 关系名称 */
@DbColumn(comment = "关系名称")
private String relationName;
@DbColumn(comment = "是否已经同步到网关")
private Boolean sync;
@DbColumn(comment = "备注")
private String remark;
/**
* 转换
*/

View File

@@ -75,17 +75,18 @@ public class AllocationGroupService {
// 组装信息
return groupReceivers.stream()
.map(o -> {
AllocationReceiver allocationReceiver = receiverMap.get(o.getReceiverId());
AllocationReceiver receiver = receiverMap.get(o.getReceiverId());
return new AllocationGroupReceiverResult()
.setId(o.getId())
.setName(allocationReceiver.getName())
.setReceiverId(allocationReceiver.getId())
.setReceiverAccount(allocationReceiver.getReceiverAccount())
.setReceiverName(allocationReceiver.getReceiverName())
.setName(receiver.getName())
.setReceiverId(receiver.getId())
.setReceiverNo(receiver.getReceiverNo())
.setReceiverAccount(receiver.getReceiverAccount())
.setReceiverName(receiver.getReceiverName())
.setRate(o.getRate())
.setReceiverType(allocationReceiver.getReceiverType())
.setRelationName(allocationReceiver.getRelationName())
.setRelationType(allocationReceiver.getRelationType());
.setReceiverType(receiver.getReceiverType())
.setRelationName(receiver.getRelationName())
.setRelationType(receiver.getRelationType());
})
.collect(Collectors.toList());
}
@@ -161,13 +162,6 @@ public class AllocationGroupService {
if (receivers.size() != receiverIds.size()){
throw new DataNotExistException("传入的分账接收房数量与查询到的不一致");
}
// 接收方需要已经同步到三方系统中
receivers.stream()
.filter(receiver -> Objects.equals(receiver.getSync(), Boolean.FALSE))
.findAny()
.ifPresent(receiver -> {
throw new BizException("接收方未同步到三方值系统中");
});
// 接收方只能为一个支付通道
long count = receivers.stream()
.map(AllocationReceiver::getChannel)

View File

@@ -10,6 +10,12 @@ import cn.daxpay.single.code.AllocReceiverTypeEnum;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.exception.pay.PayFailureException;
import cn.daxpay.single.param.payment.allocation.AllocReceiverAddParam;
import cn.daxpay.single.param.payment.allocation.AllocReceiverRemoveParam;
import cn.daxpay.single.param.payment.allocation.QueryAllocReceiverParam;
import cn.daxpay.single.result.allocation.AllocReceiverAddResult;
import cn.daxpay.single.result.allocation.AllocReceiverRemoveResult;
import cn.daxpay.single.result.allocation.AllocReceiverResult;
import cn.daxpay.single.result.allocation.AllocReceiversResult;
import cn.daxpay.single.service.core.payment.allocation.convert.AllocationReceiverConvert;
import cn.daxpay.single.service.core.payment.allocation.dao.AllocationGroupReceiverManager;
import cn.daxpay.single.service.core.payment.allocation.dao.AllocationReceiverManager;
@@ -17,9 +23,7 @@ import cn.daxpay.single.service.core.payment.allocation.entity.AllocationReceive
import cn.daxpay.single.service.core.payment.allocation.factory.AllocationReceiverFactory;
import cn.daxpay.single.service.dto.allocation.AllocationReceiverDto;
import cn.daxpay.single.service.func.AbsAllocationReceiverStrategy;
import cn.daxpay.single.service.param.allocation.receiver.AllocationReceiverParam;
import cn.daxpay.single.service.param.allocation.receiver.AllocationReceiverQuery;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor;
@@ -29,6 +33,7 @@ import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
/**
@@ -45,6 +50,8 @@ public class AllocationReceiverService {
private final AllocationGroupReceiverManager groupReceiverManager;
private final AllocationReceiverManager allocationReceiverManager;
private final LockTemplate lockTemplate;
/**
@@ -71,7 +78,6 @@ public class AllocationReceiverService {
);
}
/**
* 根据通道获取分账接收方类型
*/
@@ -90,112 +96,29 @@ public class AllocationReceiverService {
.collect(Collectors.toList());
}
/**
* 添加分账接收方
*/
public void add(AllocationReceiverParam param){
// 首先添加网关的分账接收方
AllocationReceiver receiver = AllocationReceiverConvert.CONVERT.convert(param);
// 获取策略
PayChannelEnum channelEnum = PayChannelEnum.findByCode(param.getChannel());
AbsAllocationReceiverStrategy receiverStrategy = AllocationReceiverFactory.create(channelEnum);
// 校验
receiverStrategy.setAllocationReceiver(receiver);
if (!receiverStrategy.validation()){
throw new BizException("接收方信息校验失败");
}
receiver.setSync(false);
manager.save(receiver);
}
/**
* 修改信息
*/
public void update(AllocationReceiverParam param){
AllocationReceiver receiver = manager.findById(param.getId()).orElseThrow(() -> new PayFailureException("未找到分账接收方"));
if (Objects.equals(receiver.getSync(),true)){
throw new BizException("该接收方已同步到三方支付系统中,无法修改");
}
receiver.setSync(null);
BeanUtil.copyProperties(param,receiver);
manager.updateById(receiver);
}
/**
* 删除分账接收方
*/
public void remove(Long id){
// 未同步可以删除
AllocationReceiver receiver = manager.findById(id).orElseThrow(() -> new PayFailureException("未找到分账接收方"));
if (Objects.equals(receiver.getSync(),true)){
throw new BizException("该接收方已同步到三方支付系统中,无法删除");
}
// 判断是否绑定了分账组
if (groupReceiverManager.isUsed(id)){
throw new PayFailureException("该接收方已被分账组使用,无法删除");
}
manager.deleteById(id);
}
/**
* 同步到三方支付系统中
*/
public void registerByGateway(Long id){
AllocationReceiver receiver = manager.findById(id).orElseThrow(() -> new PayFailureException("未找到分账接收方"));
// 获取策略
PayChannelEnum channelEnum = PayChannelEnum.findByCode(receiver.getChannel());
AbsAllocationReceiverStrategy receiverStrategy = AllocationReceiverFactory.create(channelEnum);
// 校验
receiverStrategy.setAllocationReceiver(receiver);
receiverStrategy.validation();
receiverStrategy.doBeforeHandler();
receiverStrategy.bind();
receiver.setSync(true);
manager.updateById(receiver);
}
/**
* 从三方支付系统中删除
*/
public void removeByGateway(Long id){
if (groupReceiverManager.isUsed(id)){
throw new PayFailureException("该接收方已被使用,无法从第三方支付平台中删除");
}
AllocationReceiver receiver = manager.findById(id).orElseThrow(() -> new PayFailureException("未找到分账接收方"));
// 获取策略
PayChannelEnum channelEnum = PayChannelEnum.findByCode(receiver.getChannel());
AbsAllocationReceiverStrategy receiverStrategy = AllocationReceiverFactory.create(channelEnum);
// 校验
receiverStrategy.setAllocationReceiver(receiver);
receiverStrategy.validation();
receiverStrategy.doBeforeHandler();
receiverStrategy.unbind();
receiver.setSync(false);
manager.updateById(receiver);
}
/**
* 添加分账接收方并同步到三方支付系统中
*/
public void addAndSync(AllocReceiverAddParam param){
public AllocReceiverAddResult addAndSync(AllocReceiverAddParam param){
// 判断是否已经添加
AllocationReceiver receiver = AllocationReceiverConvert.CONVERT.convert(param);
// 获取策略
PayChannelEnum channelEnum = PayChannelEnum.findByCode(param.getChannel());
AbsAllocationReceiverStrategy receiverStrategy = AllocationReceiverFactory.create(channelEnum);
// 校验
receiverStrategy.setAllocationReceiver(receiver);
if (!receiverStrategy.validation()){
throw new PayFailureException("接收方信息校验失败");
}
LockInfo lock = lockTemplate.lock("payment:receiver:" + param.getReceiverNo(),10000,200);
if (Objects.isNull(lock)){
throw new PayFailureException("分账方处理中,请勿重复操作");
}
try {
Optional<AllocationReceiver> receiverOptional = allocationReceiverManager.findByReceiverNo(param.getReceiverNo());
if (receiverOptional.isPresent()){
throw new PayFailureException("该接收方已存在");
}
AllocationReceiver receiver = AllocationReceiverConvert.CONVERT.convert(param);
// 获取策略
PayChannelEnum channelEnum = PayChannelEnum.findByCode(param.getChannel());
AbsAllocationReceiverStrategy receiverStrategy = AllocationReceiverFactory.create(channelEnum);
// 校验
receiverStrategy.setAllocationReceiver(receiver);
if (!receiverStrategy.validation()){
throw new PayFailureException("接收方信息校验失败");
}
// 先添加到三方支付系统中, 然后保存到本地
receiverStrategy.doBeforeHandler();
receiverStrategy.bind();
@@ -203,21 +126,48 @@ public class AllocationReceiverService {
} finally {
lockTemplate.releaseLock(lock);
}
return new AllocReceiverAddResult();
}
/**
* 接口删除
*/
public void remove(){
public AllocReceiverRemoveResult remove(AllocReceiverRemoveParam param){
// 判断是否存在
AllocationReceiver receiver = allocationReceiverManager.findByReceiverNo(param.getReceiverNo())
.orElseThrow(() -> new PayFailureException("该接收方不存在"));
if (groupReceiverManager.isUsed(receiver.getId())){
throw new PayFailureException("该接收方已被使用删除");
}
// 获取策略
PayChannelEnum channelEnum = PayChannelEnum.findByCode(receiver.getChannel());
AbsAllocationReceiverStrategy receiverStrategy = AllocationReceiverFactory.create(channelEnum);
LockInfo lock = lockTemplate.lock("payment:receiver:" + param.getReceiverNo(),10000,200);
if (Objects.isNull(lock)){
throw new PayFailureException("分账方处理中,请勿重复操作");
}
try {
// 校验
receiverStrategy.setAllocationReceiver(receiver);
receiverStrategy.validation();
receiverStrategy.doBeforeHandler();
receiverStrategy.unbind();
manager.deleteById(receiver.getId());
} finally {
lockTemplate.releaseLock(lock);
}
return new AllocReceiverRemoveResult();
}
/**
* 接口查询
*/
public void find(){
public AllocReceiversResult queryAllocReceive(QueryAllocReceiverParam param){
// 查询对应通道分账接收方的信息
List<AllocationReceiver> list = manager.findAllByChannel(param.getChannel());
List<AllocReceiverResult> receivers = list.stream()
.map(AllocationReceiverConvert.CONVERT::toResult)
.collect(Collectors.toList());
return new AllocReceiversResult().setReceivers(receivers);
}
}

View File

@@ -2,6 +2,7 @@ package cn.daxpay.single.service.core.payment.allocation.service;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.daxpay.single.code.AllocDetailResultEnum;
import cn.daxpay.single.code.AllocOrderResultEnum;
import cn.daxpay.single.code.AllocOrderStatusEnum;
@@ -10,9 +11,13 @@ import cn.daxpay.single.exception.pay.PayFailureException;
import cn.daxpay.single.param.payment.allocation.AllocFinishParam;
import cn.daxpay.single.param.payment.allocation.AllocStartParam;
import cn.daxpay.single.param.payment.allocation.AllocSyncParam;
import cn.daxpay.single.param.payment.allocation.QueryAllocOrderParam;
import cn.daxpay.single.result.allocation.AllocOrderDetailResult;
import cn.daxpay.single.result.allocation.AllocOrderResult;
import cn.daxpay.single.result.allocation.AllocationResult;
import cn.daxpay.single.result.allocation.AllocationSyncResult;
import cn.daxpay.single.service.common.local.PaymentContextLocal;
import cn.daxpay.single.service.core.order.allocation.convert.AllocationConvert;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderDetailManager;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderManager;
import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrder;
@@ -37,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 分账服务
@@ -64,7 +70,8 @@ public class AllocationService {
/**
* 开启分账, 使用分账组进行分账
* 开启分账 多次请求只会分账一次
* 优先级 分账接收方列表 > 分账组编号 > 默认分账组
*/
public AllocationResult allocation(AllocStartParam param) {
// 判断是否已经有分账订单
@@ -73,16 +80,15 @@ public class AllocationService {
if (Objects.nonNull(allocationOrder)){
// 重复分账
return this.retryAllocation(allocationOrder);
} else {
// 开启分账
// 首次分账
PayOrder payOrder = this.getAndCheckPayOrder(param);
return this.allocation(param, payOrder);
}
}
/**
* 开启分账, 未传输分账组号, 则使用默认该通道默认分账组
* 开启分账 优先级 分账接收方列表 > 分账组编号 > 默认分账组
*/
public AllocationResult allocation(AllocStartParam param, PayOrder payOrder) {
LockInfo lock = lockTemplate.lock("payment:allocation:" + payOrder.getId(),10000,200);
@@ -90,23 +96,27 @@ public class AllocationService {
throw new RepetitiveOperationException("分账发起处理中,请勿重复操作");
}
try {
// 查询默认分账组
AllocationGroup allocationGroup;
if (Objects.nonNull(param.getAllocationGroupId())) {
allocationGroup = groupManager.findById(param.getAllocationGroupId()).orElseThrow(() -> new DataNotExistException("未查询到分账组"));
} else {
allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel()).orElseThrow(() -> new DataNotExistException("未查询到默认分账组"));
}
List<AllocationGroupReceiverResult> receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId());
// 创建分账单和明细并保存, 同时更新支付订单状态 使用事务
OrderAndDetail orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, payOrder.getAmount(), receiversByGroups);
OrderAndDetail orderAndDetail;
// 判断是否传输了分账接收方列表
if (CollUtil.isNotEmpty(param.getReceivers())) {
orderAndDetail = allocationOrderService.createAndUpdate(param, payOrder);
} else if (Objects.nonNull(param.getGroupNo())){
// 指定分账组
AllocationGroup allocationGroup = groupManager.findByGroupNo(param.getGroupNo()).orElseThrow(() -> new DataNotExistException("未查询到分账组"));
List<AllocationGroupReceiverResult> receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId());
orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, receiversByGroups);
} else {
// 默认分账组
AllocationGroup allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel()).orElseThrow(() -> new PayFailureException("未查询到默认分账组"));
List<AllocationGroupReceiverResult> receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId());
orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, receiversByGroups);
}
// 创建分账策略并初始化
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(payOrder.getChannel());
AllocationOrder order = orderAndDetail.getOrder();
List<AllocationOrderDetail> details = orderAndDetail.getDetails();
allocationStrategy.initParam(order, details);
// 分账预处理
allocationStrategy.doBeforeHandler();
try {
@@ -149,11 +159,9 @@ public class AllocationService {
AllocOrderStatusEnum.ALLOCATION_FAILED.getCode(),
AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode());
if (!list.contains(order.getStatus())){
throw new PayFailureException("分账单状态错误");
throw new PayFailureException("分账单状态错误,无法重试");
}
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(order.getId());
// 创建分账策略并初始化
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(order.getChannel());
allocationStrategy.initParam(order, details);
@@ -204,7 +212,6 @@ public class AllocationService {
if (!AllocOrderStatusEnum.ALLOCATION_END.getCode().equals(allocationOrder.getStatus())){
throw new PayFailureException("分账单状态错误");
}
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
// 创建分账策略并初始化
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
@@ -265,10 +272,9 @@ public class AllocationService {
// 分账完结预处理
allocationStrategy.doBeforeHandler();
allocationStrategy.doSync();
// TODO 保存分账同步记录
// 根据订单明细更新订单的状态和处理结果
this.updateOrderStatus(allocationOrder, detailList);
allocationOrderDetailManager.updateAllById(detailList);
allocationOrderManager.updateById(allocationOrder);
} finally {
@@ -323,7 +329,7 @@ public class AllocationService {
private PayOrder getAndCheckPayOrder(AllocStartParam param) {
// 查询支付单
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getOrderNo(), param.getBizOrderNo())
.orElseThrow(() -> new DataNotExistException("支付单不存在"));
.orElseThrow(() -> new PayFailureException("支付单不存在"));
// 判断订单是否可以分账
if (!payOrder.getAllocation()){
throw new PayFailureException("该订单不允许分账");
@@ -338,9 +344,16 @@ public class AllocationService {
/**
* 查询分账结果
*/
public void query(AllocFinishParam param) {
public AllocOrderResult queryAllocationOrder(QueryAllocOrderParam param) {
// 查询分账单
AllocationOrder allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
.orElseThrow(() -> new PayFailureException("分账单不存在"));
AllocOrderResult result = AllocationConvert.CONVERT.toResult(allocationOrder);
// 查询分账单明细
List<AllocOrderDetailResult> details = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId()).stream()
.map(AllocationConvert.CONVERT::toResult)
.collect(Collectors.toList());
result.setDetails(details);
return result;
}
}

View File

@@ -0,0 +1,20 @@
package cn.daxpay.single.service.core.payment.notice.result;
import cn.daxpay.single.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 分账通知方法
* @author xxm
* @since 2024/5/21
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "分账通知方法")
public class AllocationNoticeResult extends PaymentCommonResult {
}

View File

@@ -74,4 +74,11 @@ public class ClientNoticeAssistService {
.setTradeStatus(order.getStatus());
}
/**
* 构建分账通知
*/
public ClientNoticeTask buildDivideTask(String tradeNo, String tradeStatus){
return null;
}
}

View File

@@ -150,6 +150,14 @@ public class ClientNoticeService {
this.sendData(task, LocalDateTime.now());
}
/**
* 注册分账消息通知任务
*/
@Async("bigExecutor")
public void registerAllocNotice() {
// 创建通知任务并保存
}
/**
* 从redis中执行任务, 通过定时任务触发
*/

View File

@@ -68,8 +68,8 @@ public class ReconcileAssistService {
for (RefundOrder refundOrder : refundOrders) {
generalTradeInfoList.add(new GeneralTradeInfo()
.setTitle(refundOrder.getTitle())
.setTradeNo(refundOrder.getOrderNo())
.setOutTradeNo(refundOrder.getOutOrderNo())
.setTradeNo(refundOrder.getRefundNo())
.setOutTradeNo(refundOrder.getOutRefundNo())
.setFinishTime(refundOrder.getFinishTime())
.setType(PaymentTypeEnum.REFUND.getCode())
.setAmount(refundOrder.getAmount()));
@@ -78,7 +78,7 @@ public class ReconcileAssistService {
}
/**
* 比对生成对账差异单
* 比对生成对账差异单, 通道对账单
* 1. 远程有, 本地无
* 2. 远程无, 本地有
* 3. 远程有, 本地有, 但状态不一致

View File

@@ -23,6 +23,9 @@ public class AllocationGroupReceiverResult {
@Schema(description = "接收方ID")
private Long receiverId;
@Schema(description = "接收方编号")
private String receiverNo;
@Schema(description = "接收方账号别名")
private String name;

View File

@@ -59,10 +59,4 @@ public class AllocationReceiverDto extends BaseDto {
@Schema(description = "关系名称")
private String relationName;
@Schema(description = "是否已经同步到网关")
private Boolean sync;
@Schema(description = "备注")
private String remark;
}

View File

@@ -22,11 +22,14 @@ import java.time.LocalDateTime;
@Schema(title = "分账订单详情")
public class AllocationOrderDetailDto extends BaseDto {
/** 分账订单ID */
@Schema(description = "分账订单ID")
private Long allocationId;
/** 分账接收方编号 */
@Schema(description = "分账接收方编号")
private String receiverNo;
/** 接收者ID */
@Schema(description = "接收者ID")
private Long receiverId;

View File

@@ -13,6 +13,7 @@ import lombok.experimental.Accessors;
* @since 2024/3/28
*/
@Data
@Deprecated
@Accessors(chain = true)
@Schema(title = "分账接收方参数")
public class AllocationReceiverParam {