feat 修复回调消息签名不一致问题, SDK支持分账操作, 调整前端查询接口

This commit is contained in:
DaxPay
2024-05-30 20:59:27 +08:00
parent 1b3277533a
commit fa54a853a5
37 changed files with 684 additions and 192 deletions

View File

@@ -13,7 +13,7 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface PlatformInitContext {
public @interface InitPaymentContext {
/**
* 接口标识

View File

@@ -12,7 +12,9 @@ import lombok.Getter;
@AllArgsConstructor
public enum ClientNoticeTypeEnum {
PAY("pay", "支付通知"),
REFUND("refund", "退款通知");
REFUND("refund", "退款通知"),
ALLOCATION("Allocation", "分账通知"),
;
private final String type;
private final String name;

View File

@@ -5,6 +5,8 @@ import cn.daxpay.single.result.order.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.core.order.allocation.entity.AllocationOrderExtra;
import cn.daxpay.single.service.core.payment.notice.result.AllocDetailNoticeResult;
import cn.daxpay.single.service.core.payment.notice.result.AllocNoticeResult;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDetailDto;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDto;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderExtraDto;
@@ -20,7 +22,6 @@ import org.mapstruct.factory.Mappers;
public interface AllocationConvert {
AllocationConvert CONVERT = Mappers.getMapper(AllocationConvert.class);
AllocationOrderDto convert(AllocationOrder in);
AllocationOrderExtraDto convert(AllocationOrderExtra in);
@@ -31,4 +32,8 @@ public interface AllocationConvert {
AllocationOrderDetailDto convert(AllocationOrderDetail in);
AllocNoticeResult toNotice(AllocationOrder in);
AllocDetailNoticeResult toNotice(AllocationOrderDetail in);
}

View File

@@ -0,0 +1,93 @@
package cn.daxpay.single.service.core.order.allocation.service;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.dto.LabelValue;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.ResultConvertUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
import cn.daxpay.single.code.PayChannelEnum;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderDetailManager;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderExtraManager;
import cn.daxpay.single.service.core.order.allocation.dao.AllocationOrderManager;
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.core.order.allocation.entity.AllocationOrderExtra;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDetailDto;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderDto;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderExtraDto;
import cn.daxpay.single.service.param.order.AllocationOrderQuery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
/**
* 分账订单查询服务类
* @author xxm
* @since 2024/5/30
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class AllocationOrderQueryService {
private final AllocationOrderDetailManager allocationOrderDetailManager;
private final AllocationOrderManager allocationOrderManager;
private final AllocationOrderExtraManager allocationOrderExtraManager;
/**
* 获取可以分账的通道
*/
public List<LabelValue> findChannels(){
return Arrays.asList(
new LabelValue(PayChannelEnum.ALI.getName(),PayChannelEnum.ALI.getCode()),
new LabelValue(PayChannelEnum.WECHAT.getName(),PayChannelEnum.WECHAT.getCode())
);
}
/**
* 分页查询
*/
public PageResult<AllocationOrderDto> page(PageParam pageParam, AllocationOrderQuery param){
return MpUtil.convert2DtoPageResult(allocationOrderManager.page(pageParam, param));
}
/**
* 查询详情
*/
public AllocationOrderDto findById(Long id) {
return allocationOrderManager.findById(id).map(AllocationOrder::toDto).orElseThrow(() -> new DataNotExistException("分账订单不存在"));
}
/**
* 查询详情
*/
public AllocationOrderDto findByAllocNo(String allocNo) {
return allocationOrderManager.findByAllocationNo(allocNo).map(AllocationOrder::toDto).orElseThrow(() -> new DataNotExistException("分账订单不存在"));
}
/**
* 查询订单明细列表
*/
public List<AllocationOrderDetailDto> findDetailsByOrderId(Long orderId){
return ResultConvertUtil.dtoListConvert(allocationOrderDetailManager.findAllByOrderId(orderId));
}
/**
* 查询订单明细详情
*/
public AllocationOrderDetailDto findDetailById(Long id){
return allocationOrderDetailManager.findById(id).map(AllocationOrderDetail::toDto).orElseThrow(() -> new DataNotExistException("分账订单明细不存在"));
}
/**
* 查询扩展订单信息
*/
public AllocationOrderExtraDto findExtraById(Long id) {
return allocationOrderExtraManager.findById(id).map(AllocationOrderExtra::toDto)
.orElseThrow(() -> new DataNotExistException("未找到"));
}
}

View File

@@ -1,14 +1,7 @@
package cn.daxpay.single.service.core.order.allocation.service;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.dto.LabelValue;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.common.core.util.ResultConvertUtil;
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
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;
@@ -27,10 +20,6 @@ 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;
import cn.daxpay.single.service.dto.order.allocation.AllocationOrderExtraDto;
import cn.daxpay.single.service.param.order.AllocationOrderQuery;
import cn.daxpay.single.util.OrderNoGenerateUtil;
import cn.hutool.core.util.IdUtil;
import lombok.RequiredArgsConstructor;
@@ -41,7 +30,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -66,54 +54,6 @@ public class AllocationOrderService {
private final AllocationOrderExtraManager allocationOrderExtraManager;
/**
* 获取可以分账的通道
*/
public List<LabelValue> findChannels(){
return Arrays.asList(
new LabelValue(PayChannelEnum.ALI.getName(),PayChannelEnum.ALI.getCode()),
new LabelValue(PayChannelEnum.WECHAT.getName(),PayChannelEnum.WECHAT.getCode())
);
}
/**
* 分页查询
*/
public PageResult<AllocationOrderDto> page(PageParam pageParam, AllocationOrderQuery param){
return MpUtil.convert2DtoPageResult(allocationOrderManager.page(pageParam, param));
}
/**
* 查询详情
*/
public AllocationOrderDto findById(Long id) {
return allocationOrderManager.findById(id).map(AllocationOrder::toDto).orElseThrow(() -> new DataNotExistException("分账订单不存在"));
}
/**
* 查询订单明细列表
*/
public List<AllocationOrderDetailDto> findDetailsByOrderId(Long orderId){
return ResultConvertUtil.dtoListConvert(allocationOrderDetailManager.findAllByOrderId(orderId));
}
/**
* 查询订单明细详情
*/
public AllocationOrderDetailDto findDetailById(Long id){
return allocationOrderDetailManager.findById(id).map(AllocationOrderDetail::toDto).orElseThrow(() -> new DataNotExistException("分账订单明细不存在"));
}
/**
* 查询扩展订单信息
*/
public AllocationOrderExtraDto findExtraById(Long id) {
return allocationOrderExtraManager.findById(id).map(AllocationOrderExtra::toDto)
.orElseThrow(() -> new DataNotExistException("未找到"));
}
/**
* 生成分账订单, 根据分账组创建
*/

View File

@@ -2,7 +2,7 @@ package cn.daxpay.single.service.core.payment.common.aop;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.daxpay.single.exception.pay.PayFailureException;
import cn.daxpay.single.service.annotation.PlatformInitContext;
import cn.daxpay.single.service.annotation.InitPaymentContext;
import cn.daxpay.single.service.core.system.config.dao.PayApiConfigManager;
import cn.daxpay.single.service.core.system.config.entity.PayApiConfig;
import cn.daxpay.single.service.core.system.config.service.PayApiConfigService;
@@ -36,7 +36,7 @@ public class InitPlatformInfoAop {
* 拦截注解
*/
@Around("@annotation(platformContext)")
public Object beforeMethod(ProceedingJoinPoint pjp, PlatformInitContext platformContext) throws Throwable {
public Object beforeMethod(ProceedingJoinPoint pjp, InitPaymentContext platformContext) throws Throwable {
String code = platformContext.value();
// 接口信息
PayApiConfig api = payApiConfigManager.findByCode(code)

View File

@@ -0,0 +1,64 @@
package cn.daxpay.single.service.core.payment.notice.result;
import cn.daxpay.single.code.AllocDetailResultEnum;
import cn.daxpay.single.code.AllocReceiverTypeEnum;
import cn.daxpay.single.serializer.LocalDateTimeToTimestampSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 分账响应结果
* @author xxm
* @since 2024/5/30
*/
@Data
@Accessors(chain = true)
@Schema(title = "分账响应结果")
public class AllocDetailNoticeResult {
@Schema(description = "分账接收方编号")
private String receiverNo;
/** 分账金额 */
@Schema(description = "分账金额")
private Integer amount;
/**
* 分账接收方类型
* @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 = "分账完成时间")
@JsonSerialize(using = LocalDateTimeToTimestampSerializer.class)
private LocalDateTime finishTime;
}

View File

@@ -0,0 +1,121 @@
package cn.daxpay.single.service.core.payment.notice.result;
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 cn.daxpay.single.serializer.LocalDateTimeToTimestampSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
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 AllocNoticeResult 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 = "分账订单完成时间")
@JsonSerialize(using = LocalDateTimeToTimestampSerializer.class)
private LocalDateTime finishTime;
/** 商户扩展参数,回调时会原样返回 */
@Schema(description = "商户扩展参数,回调时会原样返回")
private String attach;
/** 分账明细 */
@Schema(description = "分账明细")
private List<AllocDetailNoticeResult> details;
/**
* 错误码
*/
@Schema(description = "错误码")
private String errorCode;
/**
* 错误信息
*/
@Schema(description = "错误原因")
private String errorMsg;
}

View File

@@ -1,20 +0,0 @@
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

@@ -24,13 +24,13 @@ import java.time.LocalDateTime;
@Schema(title = "支付异步通知类")
public class PayNoticeResult extends PaymentCommonResult {
@Schema(description = "支付订单号")
private String orderNo;
/** 商户订单号 */
@Schema(description = "商户订单号")
private String bizOrderNo;
@Schema(description = "支付订单号")
private String orderNo;
/** 通道系统交易号 */
@Schema(description = "通道支付订单号")
private String outOrderNo;
@@ -47,7 +47,7 @@ public class PayNoticeResult extends PaymentCommonResult {
@Schema(description = "是否需要分账")
private Boolean allocation;
/** 是否开启自动分账, 不传输为不开启 */
/** 是否开启自动分账 */
@Schema(description = "是否开启自动分账")
private Boolean autoAllocation;
@@ -68,10 +68,6 @@ public class PayNoticeResult extends PaymentCommonResult {
@Schema(description = "金额")
private Integer amount;
/** 可退款余额 */
@Schema(description = "可退款余额")
private Integer refundableBalance;
/**
* 支付状态
* @see PayStatusEnum

View File

@@ -1,8 +1,6 @@
package cn.daxpay.single.service.core.payment.notice.service;
import cn.bootx.platform.common.jackson.util.JacksonUtil;
import cn.daxpay.single.result.order.AllocOrderDetailResult;
import cn.daxpay.single.result.order.AllocOrderResult;
import cn.daxpay.single.service.code.ClientNoticeTypeEnum;
import cn.daxpay.single.service.core.notice.entity.ClientNoticeTask;
import cn.daxpay.single.service.core.order.allocation.convert.AllocationConvert;
@@ -16,6 +14,8 @@ import cn.daxpay.single.service.core.order.refund.convert.RefundOrderConvert;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
import cn.daxpay.single.service.core.order.refund.entity.RefundOrderExtra;
import cn.daxpay.single.service.core.payment.common.service.PaymentSignService;
import cn.daxpay.single.service.core.payment.notice.result.AllocDetailNoticeResult;
import cn.daxpay.single.service.core.payment.notice.result.AllocNoticeResult;
import cn.daxpay.single.service.core.payment.notice.result.PayNoticeResult;
import cn.daxpay.single.service.core.payment.notice.result.RefundNoticeResult;
import lombok.RequiredArgsConstructor;
@@ -80,20 +80,21 @@ public class ClientNoticeAssistService {
*/
public ClientNoticeTask buildAllocTask(AllocationOrder order, AllocationOrderExtra orderExtra, List<AllocationOrderDetail> list){
// 分账
AllocOrderResult allocOrderResult = AllocationConvert.CONVERT.toResult(order);
AllocNoticeResult allocOrderResult = AllocationConvert.CONVERT.toNotice(order);
// 分账详情
List<AllocOrderDetailResult> details = list.stream()
.map(AllocationConvert.CONVERT::toResult)
List<AllocDetailNoticeResult> details = list.stream()
.map(AllocationConvert.CONVERT::toNotice)
.collect(Collectors.toList());
// 分账扩展
allocOrderResult.setAttach(orderExtra.getAttach());
// 分账扩展和明细
allocOrderResult.setAttach(orderExtra.getAttach())
.setDetails(details);
// 签名
paymentSignService.sign(allocOrderResult);
return new ClientNoticeTask()
.setUrl(orderExtra.getNotifyUrl())
// 时间序列化进行了重写
.setContent(JacksonUtil.toJson(allocOrderResult))
.setNoticeType(ClientNoticeTypeEnum.REFUND.getType())
.setNoticeType(ClientNoticeTypeEnum.ALLOCATION.getType())
.setSendCount(0)
.setTradeId(order.getId())
.setTradeNo(order.getAllocationNo())

View File

@@ -0,0 +1,20 @@
package cn.daxpay.single.service.dto.order.allocation;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 分账订单和扩展信息
* @author xxm
* @since 2024/5/29
*/
@Data
@Accessors(chain = true)
@Schema(title = "分账订单和扩展信息")
public class AllocationOrderAndExtraDto {
@Schema(description = "分账订单")
private AllocationOrderDto order;
@Schema(description = "分账订单扩展信息")
private AllocationOrderExtraDto extra;
}

View File

@@ -25,6 +25,17 @@ public class AllocationOrderDto extends BaseDto {
@Schema(description = "分账订单号")
private String allocationNo;
/**
* 商户分账单号
*/
@Schema(description = "商户分账单号")
private String bizAllocationNo;
/**
* 通道分账单号
*/
@Schema(description = "通道分账单号")
private String outAllocationNo;
/**
* 支付订单ID
*/
@@ -55,12 +66,6 @@ public class AllocationOrderDto extends BaseDto {
@Schema(description = "支付订单标题")
private String title;
/**
* 通道分账单号
*/
@Schema(description = "通道分账单号")
private String outAllocationNo;
/**
* 所属通道
*/

View File

@@ -1,16 +0,0 @@
package cn.daxpay.single.service.dto.order.allocation;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
*
* @author xxm
* @since 2024/5/29
*/
@Data
@Accessors(chain = true)
@Schema(title = "")
public class AllocationOrderInfoDto {
}

View File

@@ -10,7 +10,7 @@ import lombok.Data;
*/
@Data
@Schema(title = "支付订单和扩展信息")
public class PayOrderInfoDto {
public class PayOrderAndExtraDto {
@Schema(description = "支付订单")
private PayOrderDto payOrder;
@Schema(description = "支付订单扩展信息")

View File

@@ -12,7 +12,7 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(title = "退款订单信息")
public class RefundOrderDetailDto {
public class RefundOrderAndExtraDto {
@Schema(description = "退款订单")
RefundOrderDto refundOrder;
@Schema(description = "退款订单扩展信息")