mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-04 11:37:37 +00:00
ref 分账开发接口开发和结构调整
This commit is contained in:
24
_doc/Task.md
24
_doc/Task.md
@@ -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: 对账完善和系统优化
|
||||
- [ ] 对账提供外部接口调用
|
||||
- [ ] 下载系统账单
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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";
|
||||
|
||||
|
||||
|
||||
|
@@ -35,7 +35,7 @@ public class AllocReceiverAddParam extends PaymentCommonParam {
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 分账接收方类型 个人/商户
|
||||
* 分账接收方类型 根据不同类型的通道进行传输
|
||||
* @see AllocReceiverTypeEnum
|
||||
*/
|
||||
@Schema(description = "分账接收方类型")
|
||||
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
||||
|
@@ -16,4 +16,8 @@ import lombok.experimental.Accessors;
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "查询分账接收者参数")
|
||||
public class QueryAllocReceiverParam extends PaymentCommonParam {
|
||||
|
||||
/** 所属通道 */
|
||||
@Schema(description = "所属通道")
|
||||
private String channel;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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 {
|
||||
}
|
@@ -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 {
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 对账-第三方交易明细, 从三方系统下载的交易记录
|
||||
* 对账-通道交易明细, 从三方系统下载的交易记录
|
||||
* @author xxm
|
||||
* @since 2024/1/18
|
||||
*/
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除默认分账组
|
||||
*/
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
||||
}
|
@@ -74,4 +74,11 @@ public class ClientNoticeAssistService {
|
||||
.setTradeStatus(order.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建分账通知
|
||||
*/
|
||||
public ClientNoticeTask buildDivideTask(String tradeNo, String tradeStatus){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -150,6 +150,14 @@ public class ClientNoticeService {
|
||||
this.sendData(task, LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册分账消息通知任务
|
||||
*/
|
||||
@Async("bigExecutor")
|
||||
public void registerAllocNotice() {
|
||||
// 创建通知任务并保存
|
||||
}
|
||||
|
||||
/**
|
||||
* 从redis中执行任务, 通过定时任务触发
|
||||
*/
|
||||
|
@@ -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. 远程有, 本地有, 但状态不一致
|
||||
|
@@ -23,6 +23,9 @@ public class AllocationGroupReceiverResult {
|
||||
@Schema(description = "接收方ID")
|
||||
private Long receiverId;
|
||||
|
||||
@Schema(description = "接收方编号")
|
||||
private String receiverNo;
|
||||
|
||||
@Schema(description = "接收方账号别名")
|
||||
private String name;
|
||||
|
||||
|
@@ -59,10 +59,4 @@ public class AllocationReceiverDto extends BaseDto {
|
||||
|
||||
@Schema(description = "关系名称")
|
||||
private String relationName;
|
||||
|
||||
@Schema(description = "是否已经同步到网关")
|
||||
private Boolean sync;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -13,6 +13,7 @@ import lombok.experimental.Accessors;
|
||||
* @since 2024/3/28
|
||||
*/
|
||||
@Data
|
||||
@Deprecated
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账接收方参数")
|
||||
public class AllocationReceiverParam {
|
||||
|
Reference in New Issue
Block a user