feat(transaction): 完善分账功能并更新订单状态

- 在订单表中添加分账状态- 新增分账规则校验逻辑
- 更新分账和订单状态处理流程
- 优化分账失败和异常处理
This commit is contained in:
huk 2025-09-04 14:57:31 +08:00
parent 793c34a96a
commit 15690ac810
17 changed files with 209 additions and 85 deletions

View File

@ -76,8 +76,13 @@ public class Order extends BaseAudit {
@Excel(name = "支付方式0->未支付1->支付宝2->微信")
private Integer payType;
@Schema(description = "订单状态0->待支付1->支付中2->已支付3->已关闭4->已退款10->无效订单")
@Excel(name = "订单状态0->待付款1->待发货2->已发货3->已完成4->已关闭5->无效订单")
@Schema(description = "订单状态0->待支付1->支付中2->已支付3->已关闭4->已退款9->已分账10->无效订单")
@Excel(name = "订单状态0->待支付1->支付中2->已支付3->已关闭4->已退款9->已分账10->无效订单")
/**
* 订单状态0->待支付1->支付中2->已支付3->已关闭4->已退款9->已分账10->无效订单
* 枚举类型见{@link com.wzj.soopin.order.emum.OrderStatusEnum}
*/
private Integer status;
@Schema(description = "退款状态枚举值1无售后或售后关闭2售后处理中3退款中4 退款成功")

View File

@ -1,29 +1,24 @@
package com.wzj.soopin.order.emum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 订单状态0->待支付1->支付中2->已支付3->已关闭4->已退款10->无效订单
* 订单状态0->待支付1->支付中2->已支付3->已关闭4->已退款9->已分账10->无效订单
*/
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
UNPAID(0, "待支付"),
PAYMENT(1, "支付中"),
PAID(2, "已支付"),
CLOSED(3, "已关闭"),
REFUNDED(4, "已退款"),
DIVIDED(9, "已分账"),
INVALID(10, "无效订单");
private final Integer value;
private final String info;
OrderStatusEnum(Integer value, String info) {
this.value = value;
this.info = info;
}
public Integer getValue() {
return value;
}
public String getInfo() {
return info;
}
}

View File

@ -11,6 +11,7 @@ import com.wzj.soopin.order.domain.form.ManagerOrderQueryForm;
import com.wzj.soopin.order.domain.vo.*;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
import java.util.Map;
@ -43,4 +44,6 @@ public interface OrderMapper extends BaseMapper<Order> {
Map<String, Object> countOrder();
@Update("update oms_order set status = #{status} where id = #{orderId}")
void updateStatusById(@Param("orderId")Long orderId, @Param("status") Integer status);
}

View File

@ -257,6 +257,10 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
@Override
public void cancel(Long orderId) {
Order order = orderMapper.selectById(orderId);
LoginUser loginUser = LoginHelper.getLoginUser();
Assert.isTrue(Objects.equals(loginUser.getUserId(), order.getMemberId()), () -> new ServiceException("无权限取消非本人订单"));
Assert.isTrue(OrderStatusEnum.UNPAID.getValue().equals(order.getStatus()), () -> new ServiceException("订单已支付,不能取消"));
orderMapper.updateById(Order.builder().id(orderId).status(OrderStatusEnum.CLOSED.getValue()).build());
}

View File

@ -1,5 +1,7 @@
package com.wzj.soopin.transaction.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -27,6 +29,12 @@ public class SeparateApplyBO {
*/
private Long payId;
/**
* 分账id
*/
private Long divideId;
/**
* 支付完成时间
*/

View File

@ -49,6 +49,9 @@ public class SeparateRespInfoList {
private Long sepaRatio;
/**
* 分账单状态处理中成功失败已退款
* REFUNDED 分账已回退
* SUCCESS 分账成功
* PENDING 待处理
*/
private String sepaStatus;
/**

View File

@ -61,6 +61,7 @@ public class Divide extends BaseEntity {
/**
* 状态
* 枚举类型见 {@link com.wzj.soopin.transaction.enums.DivideStatus}
*/
@Schema(description = "状态")
@ExcelProperty(value = "状态", order = 5)
@ -89,5 +90,7 @@ public class Divide extends BaseEntity {
@ExcelProperty(value = "订单编号", order = 9)
private String orderSn;
private String delFlag;
}

View File

@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.math.BigDecimal;
@ -17,6 +18,7 @@ import java.math.BigDecimal;
* @author wzj
* @date 2023-03-07
*/
@EqualsAndHashCode(callSuper = true)
@Schema(description = "订单分账明细")
@Data
@TableName("trans_divide_detail")
@ -78,10 +80,11 @@ public class DivideDetail extends BaseEntity {
* */
private Integer type;
/**
* 状态
* 枚举类型见 {@link com.wzj.soopin.transaction.enums.DivideStatus}
*/
@Schema(description = "状态 0 未分账 1 分账成功 2 分账失败")
@ExcelProperty(value = "状态", order = 5)
private Integer status;

View File

@ -67,5 +67,7 @@ public class DivideRule extends BaseEntity {
@ExcelProperty(value ="类型", order = 8)
private Integer type;
private String delFlag;
}

View File

@ -6,10 +6,14 @@ import lombok.Getter;
public enum DivideStatus {
PENDING(0, "待分账"),
SUCCESS(1, "分账成功"),
FAIL(2, "分账失败");
private int code;
private String desc;
PROCESSING(1, "分账中"),
SUCCESS(2, "分账成功"),
FAIL(3, "分账失败"),
REFUNDED(4, "已退款");
private final int code;
private final String desc;
DivideStatus(int code, String desc) {
this.code = code;

View File

@ -3,8 +3,12 @@ package com.wzj.soopin.transaction.mapper;
import com.wzj.soopin.transaction.domain.po.DivideDetail;
import com.wzj.soopin.transaction.domain.vo.DivideDetailVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* 意见反馈Mapper接口
*
@ -13,4 +17,6 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@Mapper
public interface DivideDetailMapper extends BaseMapperPlus<DivideDetail, DivideDetailVO> {
@Select("select * from trans_divide_detail where divide_id = #{divideId} and del_flag = '0' ")
List<DivideDetail> selectByDivideId(@Param("divideId") Long divideId);
}

View File

@ -6,6 +6,7 @@ import com.wzj.soopin.transaction.domain.vo.DivideVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* 意见反馈Mapper接口
@ -17,6 +18,9 @@ public interface DivideMapper extends BaseMapper<Divide> {
DivideVO getVOById(Long divideId);
@Select("select * from trans_divide where order_id = #{orderId}")
@Select("select * from trans_divide where order_id = #{orderId} and del_flag = '0'")
Divide selectByOrderId(@Param("orderId") Long orderId);
@Update("update trans_divide set status = #{divideStatus} where id = #{divideId}")
void updateStatus(@Param("divideId") Long divideId, @Param("divideStatus") int divideStatus);
}

View File

@ -2,12 +2,18 @@ package com.wzj.soopin.transaction.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wzj.soopin.transaction.domain.po.DivideRule;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* 意见反馈Mapper接口
*
* @author zcc
*/
@Mapper
public interface DivideRuleMapper extends BaseMapper<DivideRule> {
@Select("select * from trans_divide_rule where type = #{type} and status = #{status} and del_flag = '0'")
DivideRule getByTypeAndStatus(@Param("type") Integer type, @Param("status") int status);
}

View File

@ -3,7 +3,11 @@ package com.wzj.soopin.transaction.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.wzj.soopin.transaction.domain.bo.DivideRuleBO;
import com.wzj.soopin.transaction.domain.po.DivideRule;
import com.wzj.soopin.transaction.domain.vo.DivideRuleDetailVO;
import com.wzj.soopin.transaction.domain.vo.DivideRuleVO;
import com.wzj.soopin.transaction.enums.DivideRuleFeeType;
import java.util.List;
public interface IDivideRuleService extends IService<DivideRule> {
@ -12,4 +16,6 @@ public interface IDivideRuleService extends IService<DivideRule> {
DivideRuleVO getVOById(Long divideId);
DivideRuleVO getVOByOrderType(Integer orderType);
void checkRule(List<DivideRuleDetailVO> details, DivideRuleFeeType divideRuleFeeType);
}

View File

@ -1,6 +1,7 @@
package com.wzj.soopin.transaction.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.StrBuilder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.transaction.convert.DivideRuleConvert;
@ -8,18 +9,19 @@ import com.wzj.soopin.transaction.convert.DivideRuleDetailConvert;
import com.wzj.soopin.transaction.domain.bo.DivideRuleBO;
import com.wzj.soopin.transaction.domain.po.DivideRule;
import com.wzj.soopin.transaction.domain.po.DivideRuleDetail;
import com.wzj.soopin.transaction.domain.vo.DivideRuleDetailVO;
import com.wzj.soopin.transaction.domain.vo.DivideRuleVO;
import com.wzj.soopin.transaction.enums.DivideRuleDetailType;
import com.wzj.soopin.transaction.enums.DivideRuleFeeType;
import com.wzj.soopin.transaction.enums.DivideRuleStatus;
import com.wzj.soopin.transaction.mapper.DivideRuleDetailMapper;
import com.wzj.soopin.transaction.mapper.DivideRuleMapper;
import com.wzj.soopin.transaction.service.IDivideRuleService;
import jodd.util.CollectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.io.Serializable;
import java.util.List;
@ -103,8 +105,8 @@ public class DivideRuleServiceImpl extends ServiceImpl<DivideRuleMapper, DivideR
@Override
public DivideRuleVO getVOByOrderType(Integer orderType) {
List<DivideRule> divideRuleList = baseMapper.selectList(new QueryWrapper<DivideRule>().lambda()
.eq(DivideRule::getType,orderType)
.eq(DivideRule::getStatus,DivideRuleStatus.ON.getCode()));
.eq(DivideRule::getType, orderType)
.eq(DivideRule::getStatus, DivideRuleStatus.ON.getCode()));
Assert.notEmpty(divideRuleList, () -> new ServiceException("未找到品类的分账规则"));
Assert.isTrue(divideRuleList.size() == 1, () -> new ServiceException("品类分账规则不唯一"));
DivideRule divideRule = divideRuleList.get(0);
@ -114,4 +116,37 @@ public class DivideRuleServiceImpl extends ServiceImpl<DivideRuleMapper, DivideR
vo.setDetails(detailConvert.toVO(detailList));
return vo;
}
/**
* 校验分账规则详情和规则中的手续费承担类型是否一致
*
* @param details
* @param divideRuleFeeType
*/
@Override
public void checkRule(List<DivideRuleDetailVO> details, DivideRuleFeeType divideRuleFeeType) {
String type = null;
if (DivideRuleFeeType.SELLER == divideRuleFeeType) {
if (details.stream().filter(item -> item.getType() == DivideRuleDetailType.SELLER.getValue()).count() != 1) {
type = DivideRuleDetailType.SELLER.getDesc();
}
}
if (DivideRuleFeeType.PLATFORM == divideRuleFeeType) {
if (details.stream().filter(item -> item.getType() == DivideRuleDetailType.PLATFORM.getValue()).count() != 1) {
type = DivideRuleDetailType.PLATFORM.getDesc();
}
}
if (DivideRuleFeeType.PROXY == divideRuleFeeType) {
if (details.stream().filter(item -> item.getType() == DivideRuleDetailType.PROXY.getValue()).count() != 1) {
type = DivideRuleDetailType.PROXY.getDesc();
}
}
if (DivideRuleFeeType.REFERENCE == divideRuleFeeType) {
if (details.stream().filter(item -> item.getType() == DivideRuleDetailType.REFERENCE.getValue()).count() != 1) {
type = DivideRuleDetailType.REFERENCE.getDesc();
}
}
String finalType = type;
Assert.isTrue(type == null, () -> new ServiceException("分账规则中的手续费承担者[" + finalType + "]未配置相应的分账规则详情"));
}
}

View File

@ -3,6 +3,7 @@ package com.wzj.soopin.transaction.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -73,7 +74,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
private final IEasypayService easypayService;
private final ISysTenantService sysTenantService;
private final DivideMapper divideMapper;
@Override
@ -130,7 +131,8 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
if (divide == null) {
return null;
}
List<DivideDetail> detailList = detailMapper.selectList(new QueryWrapper<DivideDetail>().lambda().eq(DivideDetail::getDivideId, divideId));
detailMapper.selectByDivideId(divideId);
List<DivideDetail> detailList = detailMapper.selectByDivideId(divideId);
divide.setDetails(detailConvert.toVO(detailList));
return divide;
}
@ -163,23 +165,23 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
Integer feeType = rule.getFeeType();
DivideRuleFeeType divideRuleFeeType = DivideRuleFeeType.getByValue(feeType);
List<DivideRuleDetailVO> details = rule.getDetails();
checkRule(details, divideRuleFeeType);
ruleService.checkRule(details, divideRuleFeeType);
//根据易生支付的合同查看手续费金额
BigDecimal totalAmount = order.getTotalAmount();
//计算订单可分配金额,订单只考虑整单退不考虑单独退所以直接计算订单金额
//先生成主表信息
Divide divide = Divide.builder()
Divide divide = divideMapper.selectByOrderId(orderId);
if (divide == null) {
divide = Divide.builder()
.ruleId(rule.getId())
.orderMoney(totalAmount)
.separateBatchTrace(StrBuilder.create(TRACE_PREFIX).append(System.currentTimeMillis()).append(RandomUtil.randomString(4)).toString())
// .fee(totalFee)
// .actualMoney(actualMoney)
.orderSn(order.getOrderSn())
.status(DivideStatus.PENDING.getCode())
.build();
super.save(divide);
}
Long divideId = divide.getId();
List<DivideDetail> detailList = new ArrayList<>();
List<SeparateItemBO> separateItemBOList = new ArrayList<>();
// 从租户信息得到商户的分账比例,先分给商户
@ -191,13 +193,13 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
.filter(item -> item.getType() == DivideRuleDetailType.PROXY.getValue())
.findFirst()
.ifPresent(ruleDetailVO -> {
DivideDetail proxyDivideDetail = divideProxy(totalAmount, ruleDetailVO, divide.getId(), order.getTenantId(),divideRuleFeeType, detailList, separateItemBOList);
DivideDetail proxyDivideDetail = divideProxy(totalAmount, ruleDetailVO, divideId, order.getTenantId(), divideRuleFeeType, detailList, separateItemBOList);
});
rule.getDetails().stream()
.filter(item -> item.getType() == DivideRuleDetailType.REFERENCE.getValue())
.findFirst()
.ifPresent(ruleDetailVO -> {
DivideDetail divideReference = divideReference(totalAmount, ruleDetailVO, divide.getId(), order.getMemberId(),divideRuleFeeType, detailList, separateItemBOList);
DivideDetail divideReference = divideReference(totalAmount, ruleDetailVO, divideId, order.getMemberId(), divideRuleFeeType, detailList, separateItemBOList);
detailList.add(divideReference);
});
@ -205,7 +207,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
.filter(item -> item.getType() == DivideRuleDetailType.PLATFORM.getValue())
.findFirst()
.ifPresent(ruleDetailVO -> {
DivideDetail dividePlatform = dividePlatform(totalAmount, ruleDetailVO, divide.getId(),divideRuleFeeType, detailList, separateItemBOList);
DivideDetail dividePlatform = dividePlatform(totalAmount, ruleDetailVO, divideId, divideRuleFeeType, detailList, separateItemBOList);
detailList.add(dividePlatform);
});
@ -216,6 +218,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
SeparateApplyBO separateApplyBO = SeparateApplyBO.builder()
.orderId(order.getId())
.payId(order.getPayId())
.divideId(divide.getId())
.transDate(payOrder.getEndTransDate())
.transSumAmt(payOrder.getTransAmount())
.transSumCount((long) separateItemBOList.size())
@ -226,32 +229,6 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
return true;
}
/**
* 校验分账规则详情和规则中的手续费承担类型是否一致
*
* @param details
* @param divideRuleFeeType
*/
private void checkRule(List<DivideRuleDetailVO> details, DivideRuleFeeType divideRuleFeeType) {
if (DivideRuleFeeType.SELLER == divideRuleFeeType) {
long count = details.stream().filter(item -> item.getType() == DivideRuleDetailType.SELLER.getValue()).count();
Assert.isTrue(count == 1, () -> new ServiceException("分账总规则中已配置商户承担手续费,但未配置商户分账规则详情"));
}
if (DivideRuleFeeType.PLATFORM == divideRuleFeeType) {
long count = details.stream().filter(item -> item.getType() == DivideRuleDetailType.PLATFORM.getValue()).count();
Assert.isTrue(count == 1, () -> new ServiceException("分账总规则中已配置平台承担手续费,但未配置平台分账规则详情"));
}
if (DivideRuleFeeType.PROXY == divideRuleFeeType) {
long count = details.stream().filter(item -> item.getType() == DivideRuleDetailType.PROXY.getValue()).count();
Assert.isTrue(count == 1, () -> new ServiceException("分账总规则中已配置代理承担手续费,但未配置代理分账规则详情"));
}
if (DivideRuleFeeType.REFERENCE == divideRuleFeeType) {
long count = details.stream().filter(item -> item.getType() == DivideRuleDetailType.REFERENCE.getValue()).count();
Assert.isTrue(count == 1, () -> new ServiceException("分账总规则中已配置达人承担手续费,但未配置达人分账规则详情"));
}
}
/**
* 商户分账
*
@ -278,7 +255,9 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
.accountCode(mchtCode)
.money(sellerAmount)
.moneyPercent(divideRate)
.type(DivideRuleDetailType.SELLER.getValue()).build();
.type(DivideRuleDetailType.SELLER.getValue())
.status(DivideStatus.PENDING.getCode())
.build();
detailMapper.insert(sellerDetail);
detailList.add(sellerDetail);
Integer sepaFeeAmount = 0;
@ -319,6 +298,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
.money(proxyAmount)
.moneyPercent(rule.getMoneyPercent())
.type(DivideRuleDetailType.PROXY.getValue())
.status(DivideStatus.PENDING.getCode())
.build();
detailMapper.insert(proxyDetail);
detailList.add(proxyDetail);
@ -360,6 +340,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
.money(proxyAmount)
.moneyPercent(rule.getMoneyPercent())
.type(DivideRuleDetailType.REFERENCE.getValue())
.status(DivideStatus.PENDING.getCode())
.build();
detailMapper.insert(referenceDetail);
detailList.add(referenceDetail);
@ -389,6 +370,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
.money(platformAmount)
.moneyPercent(rule.getMoneyPercent())
.type(DivideRuleDetailType.PLATFORM.getValue())
.status(DivideStatus.PENDING.getCode())
.build();
detailMapper.insert(platformDetail);
detailList.add(platformDetail);

View File

@ -24,6 +24,7 @@ import com.wzj.soopin.transaction.config.EasypayConfig;
import com.wzj.soopin.transaction.config.WechatMiniProgramConfig;
import com.wzj.soopin.transaction.domain.bo.PaymentBO;
import com.wzj.soopin.transaction.domain.bo.SeparateApplyBO;
import com.wzj.soopin.transaction.domain.bo.SeparateItemBO;
import com.wzj.soopin.transaction.domain.bo.easypay.*;
import com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.req.RefundApplyReqBody;
import com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.req.RefundReqOrderInfo;
@ -31,6 +32,7 @@ import com.wzj.soopin.transaction.domain.bo.easypay.refund.apply.resp.RefundAppl
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.req.SeparateApplyReqBody;
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.req.SeparateReqOrderInfo;
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp.SeparateApplyRespBody;
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp.SeparateRespInfoList;
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp.SeparateRespOrderInfo;
import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.req.*;
import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.resp.JsApiRespBody;
@ -41,18 +43,20 @@ import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.TradeQueryR
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.TradeQueryRespOrderInfo;
import com.wzj.soopin.transaction.domain.entity.WxAuthResponse;
import com.wzj.soopin.transaction.domain.po.Divide;
import com.wzj.soopin.transaction.domain.po.DivideDetail;
import com.wzj.soopin.transaction.domain.po.DivideRule;
import com.wzj.soopin.transaction.domain.po.PayOrder;
import com.wzj.soopin.transaction.domain.vo.EasypayAccountVO;
import com.wzj.soopin.transaction.domain.vo.EasypayTransResultVO;
import com.wzj.soopin.transaction.domain.vo.EasypayPrePayVO;
import com.wzj.soopin.transaction.domain.vo.*;
import com.wzj.soopin.transaction.enums.DivideRuleFeeType;
import com.wzj.soopin.transaction.enums.DivideRuleStatus;
import com.wzj.soopin.transaction.enums.DivideStatus;
import com.wzj.soopin.transaction.enums.TransState;
import com.wzj.soopin.transaction.enums.easypay.DelaySettleFlag;
import com.wzj.soopin.transaction.enums.easypay.PatnerSettleFlag;
import com.wzj.soopin.transaction.enums.easypay.PayType;
import com.wzj.soopin.transaction.enums.easypay.SplitSettleFlag;
import com.wzj.soopin.transaction.enums.easypay.*;
import com.wzj.soopin.transaction.mapper.DivideDetailMapper;
import com.wzj.soopin.transaction.mapper.DivideMapper;
import com.wzj.soopin.transaction.mapper.DivideRuleMapper;
import com.wzj.soopin.transaction.mapper.PayOrderMapper;
import com.wzj.soopin.transaction.service.IDivideRuleService;
import com.wzj.soopin.transaction.service.IEasypayService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -64,8 +68,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.rmi.ServerException;
import java.util.*;
import java.util.stream.Collectors;
import static com.wzj.soopin.transaction.constans.EasypayConstants.*;
@ -91,7 +97,7 @@ public class EasypayServiceImpl implements IEasypayService {
private final DivideMapper divideMapper;
private final DivideDetailMapper divideDetailMapper;
private final DivideRuleMapper divideRuleMapper;
/**
@ -490,7 +496,20 @@ public class EasypayServiceImpl implements IEasypayService {
.paymentTime(LocalDateTimeUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString(), "yyyyMMddHHmmss"))
.payType(PayType.getByValue(payOrder.getPayType()).getChannel())
.build());
}else{
// 生产待分账信息
DivideRule divideRule = divideRuleMapper.getByTypeAndStatus(order.getType(), DivideRuleStatus.ON.getCode());
if (divideRule == null) {
log.warn("订单类型的分账规则不存在,暂不生成待分账记录");
} else {
divideMapper.insert(Divide.builder()
.ruleId(divideRule.getId())
.orderMoney(order.getTotalAmount())
.separateBatchTrace(StrBuilder.create(TRACE_PREFIX).append(System.currentTimeMillis()).append(RandomUtil.randomString(4)).toString())
.orderSn(order.getOrderSn())
.status(DivideStatus.PENDING.getCode())
.build());
}
} else {
// 支付失败支付状态重置为待支付
payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.PENDING.getCode()).build());
}
@ -553,7 +572,7 @@ public class EasypayServiceImpl implements IEasypayService {
if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK)) {
// 更新支付单退款状态
payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.REFUNDED.getCode()).refundDate(new Date()).build());
orderMapper.updateById(Order.builder().id(order.getId()).status(OrderStatusEnum.REFUNDED.getValue()).build());
orderMapper.updateStatusById(order.getId(), OrderStatusEnum.REFUNDED.getValue());
}
} else {
log.error("易生退款失败:{}", respStateInfo.getRespDesc());
@ -653,6 +672,7 @@ public class EasypayServiceImpl implements IEasypayService {
.reqSign(reqSign)
.build();
log.debug("调用易生请求分账接口请求:{}", JSONObject.toJSONString(easyRequest));
divideMapper.updateStatus(separateApplyBO.getDivideId(), DivideStatus.PENDING.getCode());
String url = StrBuilder.create(easypayConfig.getApiPathPrefix()).append("/trade/separate/orderApply").toString();
String body = HttpRequest.post(url)
.timeout(3000)
@ -688,13 +708,48 @@ public class EasypayServiceImpl implements IEasypayService {
*
* @param respOrderInfo
*/
private SeparateApplyBO handleSeparateInfo(SeparateApplyBO separateApplyBO, SeparateRespOrderInfo respOrderInfo) {
private void handleSeparateInfo(SeparateApplyBO separateApplyBO, SeparateRespOrderInfo respOrderInfo) {
Long orderId = separateApplyBO.getOrderId();
Divide divide = divideMapper.selectByOrderId(orderId);
return separateApplyBO;
Map<String, SeparateItemBO> separateItemBOMap = separateApplyBO.getSeparateItemBOList().stream().collect(Collectors.toMap(SeparateItemBO::getSeparateTrade, o -> o));
List<DivideDetail> updateDetailList = new ArrayList<>();
List<SeparateRespInfoList> separateRespInfoList = respOrderInfo.getSeparateRespInfoList();
separateRespInfoList.forEach(separateRespInfo -> {
String separateTrade = separateRespInfo.getSeparateTrade();
SeparateItemBO separateItemBO = separateItemBOMap.get(separateTrade);
DivideDetail divideDetail = DivideDetail.builder()
.id(Long.valueOf(separateItemBO.getSeparateTrade()))
.separateTrade(separateRespInfo.getSeparateTrade())
.build();
if (separateRespInfo.getSepaFeeAmount() != null) {
divideDetail.setMoney(BigDecimal.valueOf(separateRespInfo.getSepaFeeAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
}
if (separateRespInfo.getSepaFeeAmount() != null) {
divideDetail.setFee(BigDecimal.valueOf(separateRespInfo.getSepaFeeAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
}
SepaStatus sepaStatus = SepaStatus.getByValue(separateRespInfo.getSepaStatus());
switch (sepaStatus) {
case SUCCESS -> divideDetail.setStatus(DivideStatus.SUCCESS.getCode());
case FAIL -> divideDetail.setStatus(DivideStatus.FAIL.getCode());
case PENDING -> divideDetail.setStatus(DivideStatus.PENDING.getCode());
case REFUNDED -> divideDetail.setStatus(DivideStatus.REFUNDED.getCode());
case PROCESSING -> divideDetail.setStatus(DivideStatus.PROCESSING.getCode());
default -> divideDetail.setStatus(DivideStatus.PROCESSING.getCode());
}
updateDetailList.add(divideDetail);
});
long itemOkCount = updateDetailList.stream().filter(item -> item.getStatus() == DivideStatus.SUCCESS.getCode())
.count();
int actualSeparate = separateItemBOMap.values().stream().mapToInt(SeparateItemBO::getSepaTransAmount).sum();
Divide divideUpdate = Divide.builder()
.id(separateApplyBO.getDivideId())
.actualMoney(BigDecimal.valueOf(actualSeparate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))
.status(DivideStatus.PROCESSING.getCode()).build();
if (itemOkCount == separateItemBOMap.size()) {
divideUpdate.setStatus(DivideStatus.SUCCESS.getCode());
orderMapper.updateStatusById(orderId, OrderStatusEnum.DIVIDED.getValue());
}
divideMapper.updateById(divideUpdate);
}
@Override
public EasypayAccountVO getEasypayAccount(Long memberId) {