mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-28 06:31:32 +00:00
fix 分转元和元转分改为BigDecimal, 防止精度丢失
This commit is contained in:
@@ -18,7 +18,8 @@ public enum PaymentTypeEnum {
|
||||
|
||||
PAY("pay","支付"),
|
||||
REFUND("refund","退款"),
|
||||
TRANSFER("transfer","转账");
|
||||
TRANSFER("transfer","转账"),
|
||||
ALLOCATION("allocation","分账");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
@@ -8,6 +8,7 @@ import cn.daxpay.single.service.code.AliPayCode;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrderDetail;
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alipay.api.AlipayResponse;
|
||||
@@ -55,7 +56,7 @@ public class AliPayAllocationService {
|
||||
List<OpenApiRoyaltyDetailInfoPojo> royaltyParameters = orderDetails.stream()
|
||||
.map(o -> {
|
||||
OpenApiRoyaltyDetailInfoPojo infoPojo = new OpenApiRoyaltyDetailInfoPojo();
|
||||
infoPojo.setAmount(String.valueOf(o.getAmount() / 100.0));
|
||||
infoPojo.setAmount(PayUtil.conversionAmount(o.getAmount()).toString());
|
||||
infoPojo.setTransIn(o.getReceiverAccount());
|
||||
return infoPojo;
|
||||
})
|
||||
@@ -89,7 +90,7 @@ public class AliPayAllocationService {
|
||||
List<OpenApiRoyaltyDetailInfoPojo> royaltyParameters = orderDetails.stream()
|
||||
.map(o -> {
|
||||
OpenApiRoyaltyDetailInfoPojo infoPojo = new OpenApiRoyaltyDetailInfoPojo();
|
||||
infoPojo.setAmount(String.valueOf(o.getAmount() / 100.0));
|
||||
infoPojo.setAmount(PayUtil.conversionAmount(o.getAmount()).toString());
|
||||
infoPojo.setTransIn(o.getReceiverAccount());
|
||||
return infoPojo;
|
||||
})
|
||||
|
@@ -12,9 +12,10 @@ import cn.daxpay.single.service.core.channel.alipay.dao.AliReconcileBillTotalMan
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliReconcileBillDetail;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliReconcileBillTotal;
|
||||
import cn.daxpay.single.service.core.order.reconcile.dao.ReconcileFileManager;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileTradeDetail;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileFile;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileOrder;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileTradeDetail;
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.text.csv.CsvReader;
|
||||
@@ -39,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -174,9 +176,7 @@ public class AliPayReconcileService {
|
||||
*/
|
||||
private ReconcileTradeDetail convert(AliReconcileBillDetail billDetail){
|
||||
// 金额
|
||||
String orderAmount = billDetail.getOrderAmount();
|
||||
double v = Double.parseDouble(orderAmount) * 100;
|
||||
int amount = Math.abs(((int) v));
|
||||
int amount = PayUtil.convertCentAmount(new BigDecimal(billDetail.getOrderAmount()));
|
||||
|
||||
// 默认为支付对账记录
|
||||
ReconcileTradeDetail reconcileTradeDetail = new ReconcileTradeDetail()
|
||||
|
@@ -6,6 +6,7 @@ import cn.daxpay.single.service.code.AliPayCode;
|
||||
import cn.daxpay.single.service.common.context.RefundLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.domain.AlipayTradeRefundModel;
|
||||
import com.alipay.api.response.AlipayTradeRefundResponse;
|
||||
@@ -36,7 +37,7 @@ public class AliPayRefundService {
|
||||
refundModel.setOutTradeNo(refundOrder.getOrderNo());
|
||||
refundModel.setOutRequestNo(refundOrder.getRefundNo());
|
||||
// 金额转换
|
||||
String refundAmount = String.valueOf(refundOrder.getAmount()*0.01);
|
||||
String refundAmount = PayUtil.conversionAmount(refundOrder.getAmount()).toString();
|
||||
refundModel.setRefundAmount(refundAmount);
|
||||
|
||||
// 设置退款信息
|
||||
|
@@ -6,8 +6,8 @@ import cn.daxpay.single.param.channel.AliPayParam;
|
||||
import cn.daxpay.single.param.payment.pay.PayParam;
|
||||
import cn.daxpay.single.service.code.AliPayCode;
|
||||
import cn.daxpay.single.service.code.AliPayWay;
|
||||
import cn.daxpay.single.service.common.context.PayLocal;
|
||||
import cn.daxpay.single.service.common.context.NoticeLocal;
|
||||
import cn.daxpay.single.service.common.context.PayLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
@@ -71,7 +71,7 @@ public class AliPayService {
|
||||
* 调起支付
|
||||
*/
|
||||
public void pay(PayOrder payOrder, AliPayParam aliPayParam, AliPayConfig alipayConfig) {
|
||||
Integer amount = payOrder.getAmount();
|
||||
String amount = PayUtil.conversionAmount(payOrder.getAmount()).toString();
|
||||
String payBody = null;
|
||||
// 异步线程存储
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
|
||||
@@ -102,12 +102,12 @@ public class AliPayService {
|
||||
/**
|
||||
* wap支付
|
||||
*/
|
||||
public String wapPay(int amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
public String wapPay(String amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo();
|
||||
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
|
||||
model.setSubject(payOrder.getTitle());
|
||||
model.setOutTradeNo(payOrder.getOrderNo());
|
||||
model.setTotalAmount(String.valueOf(amount*0.01));
|
||||
model.setTotalAmount(amount);
|
||||
// 过期时间
|
||||
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
|
||||
model.setProductCode(AliPayCode.QUICK_WAP_PAY);
|
||||
@@ -141,7 +141,7 @@ public class AliPayService {
|
||||
/**
|
||||
* app支付
|
||||
*/
|
||||
public String appPay(int amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
public String appPay(String amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
|
||||
|
||||
model.setSubject(payOrder.getTitle());
|
||||
@@ -149,7 +149,7 @@ public class AliPayService {
|
||||
model.setOutTradeNo(payOrder.getOrderNo());
|
||||
// 过期时间
|
||||
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
|
||||
model.setTotalAmount(String.valueOf(amount*0.01));
|
||||
model.setTotalAmount(amount);
|
||||
// 是否分账
|
||||
if (payOrder.getAllocation()){
|
||||
ExtendParams extendParams = new ExtendParams();
|
||||
@@ -171,14 +171,14 @@ public class AliPayService {
|
||||
/**
|
||||
* PC支付
|
||||
*/
|
||||
public String webPay(int amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
public String webPay(String amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
|
||||
|
||||
model.setSubject(payOrder.getTitle());
|
||||
model.setOutTradeNo(payOrder.getOrderNo());
|
||||
// 过期时间
|
||||
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
|
||||
model.setTotalAmount(String.valueOf(amount*0.01));
|
||||
model.setTotalAmount(amount);
|
||||
// 目前仅支持FAST_INSTANT_TRADE_PAY
|
||||
model.setProductCode(AliPayCode.FAST_INSTANT_TRADE_PAY);
|
||||
|
||||
@@ -209,11 +209,11 @@ public class AliPayService {
|
||||
/**
|
||||
* 二维码支付(扫码支付)
|
||||
*/
|
||||
public String qrCodePay(int amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
public String qrCodePay(String amount, PayOrder payOrder, AliPayConfig alipayConfig) {
|
||||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||||
model.setSubject(payOrder.getTitle());
|
||||
model.setOutTradeNo(payOrder.getOrderNo());
|
||||
model.setTotalAmount(String.valueOf(amount*0.01));
|
||||
model.setTotalAmount(amount);
|
||||
// 是否分账
|
||||
if (payOrder.getAllocation()){
|
||||
ExtendParams extendParams = new ExtendParams();
|
||||
@@ -237,7 +237,7 @@ public class AliPayService {
|
||||
/**
|
||||
* 付款码支付
|
||||
*/
|
||||
public void barCode(int amount, PayOrder payOrder, AliPayParam aliPayParam, AliPayConfig alipayConfig) {
|
||||
public void barCode(String amount, PayOrder payOrder, AliPayParam aliPayParam, AliPayConfig alipayConfig) {
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
|
||||
|
||||
AlipayTradePayModel model = new AlipayTradePayModel();
|
||||
@@ -253,7 +253,7 @@ public class AliPayService {
|
||||
}
|
||||
// 过期时间
|
||||
model.setTimeExpire(PayUtil.getAliTimeExpire(payOrder.getExpiredTime()));
|
||||
model.setTotalAmount(String.valueOf(amount*0.01));
|
||||
model.setTotalAmount(amount);
|
||||
try {
|
||||
AlipayTradePayResponse response = AliPayApi.tradePayToResponse(model, alipayConfig.getNotifyUrl());
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.sdk.union.api.UnionPayKit;
|
||||
import cn.daxpay.single.service.sdk.union.bean.UnionRefundOrder;
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import com.egzosn.pay.union.bean.UnionRefundResult;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -31,8 +32,8 @@ public class UnionPayRefundService {
|
||||
public void refund(RefundOrder refundOrder, UnionPayKit unionPayKit) {
|
||||
|
||||
// 金额转换
|
||||
BigDecimal refundAmount = BigDecimal.valueOf(refundOrder.getAmount() * 0.01);
|
||||
BigDecimal orderAmount = BigDecimal.valueOf(refundOrder.getOrderAmount() * 0.01);
|
||||
BigDecimal refundAmount = PayUtil.conversionAmount(refundOrder.getAmount());
|
||||
BigDecimal orderAmount =PayUtil.conversionAmount(refundOrder.getOrderAmount());
|
||||
|
||||
UnionRefundOrder unionRefundOrder = new UnionRefundOrder();
|
||||
unionRefundOrder.setRefundNo(refundOrder.getRefundNo());
|
||||
|
@@ -12,6 +12,7 @@ import cn.daxpay.single.service.core.channel.union.entity.UnionPayConfig;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.sdk.union.api.UnionPayKit;
|
||||
import cn.daxpay.single.service.sdk.union.bean.UnionPayOrder;
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
@@ -66,9 +67,8 @@ public class UnionPayService {
|
||||
* 支付接口
|
||||
*/
|
||||
public void pay(PayOrder payOrder, UnionPayParam unionPayParam, UnionPayKit unionPayKit){
|
||||
Integer amount = payOrder.getAmount();
|
||||
BigDecimal totalFee = BigDecimal.valueOf(amount * 0.01);
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();;
|
||||
BigDecimal totalFee = PayUtil.conversionAmount(payOrder.getAmount());
|
||||
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
|
||||
String payBody = null;
|
||||
PayMethodEnum payMethodEnum = PayMethodEnum.findByCode(payOrder.getMethod());
|
||||
|
||||
@@ -198,6 +198,5 @@ public class UnionPayService {
|
||||
String errMsg = MapUtil.getStr(result, UnionPayCode.RESP_MSG);
|
||||
throw new PayFailureException(errMsg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -14,9 +14,10 @@ import cn.daxpay.single.service.core.channel.wechat.entity.WxReconcileBillDetail
|
||||
import cn.daxpay.single.service.core.channel.wechat.entity.WxReconcileBillTotal;
|
||||
import cn.daxpay.single.service.core.channel.wechat.entity.WxReconcileFundFlowDetail;
|
||||
import cn.daxpay.single.service.core.order.reconcile.dao.ReconcileFileManager;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileTradeDetail;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileFile;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileOrder;
|
||||
import cn.daxpay.single.service.core.order.reconcile.entity.ReconcileTradeDetail;
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
@@ -41,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@@ -195,9 +197,7 @@ public class WechatPayReconcileService{
|
||||
// 支付
|
||||
if (Objects.equals(billDetail.getStatus(), "SUCCESS")){
|
||||
// 金额
|
||||
String orderAmount = billDetail.getOrderAmount();
|
||||
double v = Double.parseDouble(orderAmount) * 100;
|
||||
int amount = Math.abs(((int) v));
|
||||
int amount = PayUtil.convertCentAmount(new BigDecimal( billDetail.getOrderAmount()));
|
||||
reconcileTradeDetail.setType(ReconcileTradeEnum.PAY.getCode())
|
||||
.setAmount(amount);
|
||||
}
|
||||
|
@@ -3,19 +3,15 @@ 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;
|
||||
import cn.daxpay.single.code.PayOrderAllocStatusEnum;
|
||||
import cn.daxpay.single.exception.pay.PayFailureException;
|
||||
import cn.daxpay.single.param.payment.allocation.AllocFinishParam;
|
||||
import cn.daxpay.single.param.payment.allocation.AllocSyncParam;
|
||||
import cn.daxpay.single.param.payment.allocation.AllocationParam;
|
||||
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;
|
||||
@@ -31,7 +27,6 @@ import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.payment.allocation.dao.AllocationGroupManager;
|
||||
import cn.daxpay.single.service.core.payment.allocation.entity.AllocationGroup;
|
||||
import cn.daxpay.single.service.core.payment.allocation.factory.AllocationFactory;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.dto.allocation.AllocationGroupReceiverResult;
|
||||
import cn.daxpay.single.service.func.AbsAllocationStrategy;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
@@ -39,8 +34,6 @@ import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -71,9 +64,9 @@ public class AllocationService {
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final AllocationOrderExtraManager allocationOrderExtraManager;
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
|
||||
/**
|
||||
@@ -249,101 +242,6 @@ public class AllocationService {
|
||||
.setStatus(allocationOrder.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账同步, 开启一个新的事务, 不受外部抛出异常的影响
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public AllocationSyncResult sync(AllocSyncParam param) {
|
||||
// 获取分账订单
|
||||
AllocationOrder allocationOrder = null;
|
||||
if (Objects.nonNull(param.getAllocationNo())){
|
||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
||||
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
||||
}
|
||||
if (Objects.isNull(allocationOrder)){
|
||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getBizAllocationNo())
|
||||
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
||||
}
|
||||
this.sync(allocationOrder);
|
||||
return new AllocationSyncResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账同步
|
||||
*/
|
||||
public void sync(AllocationOrder allocationOrder){
|
||||
LockInfo lock = lockTemplate.lock("payment:allocation:" + allocationOrder.getOrderId(),10000,200);
|
||||
if (Objects.isNull(lock)){
|
||||
throw new RepetitiveOperationException("分账同步中,请勿重复操作");
|
||||
}
|
||||
try {
|
||||
List<AllocationOrderDetail> detailList = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
||||
// 获取分账策略
|
||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
||||
allocationStrategy.initParam(allocationOrder, detailList);
|
||||
// 分账完结预处理
|
||||
allocationStrategy.doBeforeHandler();
|
||||
allocationStrategy.doSync();
|
||||
// TODO 保存分账同步记录
|
||||
|
||||
// 根据订单明细更新订单的状态和处理结果
|
||||
this.updateOrderStatus(allocationOrder, detailList);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单明细更新订单的状态和处理结果, 如果订单是分账结束或失败, 不更新状态
|
||||
* TODO 是否多次同步会产生多次变动, 注意处理多次推送通知的问题, 目前是
|
||||
*/
|
||||
private void updateOrderStatus(AllocationOrder allocationOrder, List<AllocationOrderDetail> details){
|
||||
// 如果是分账结束或失败, 不更新状态
|
||||
String status = allocationOrder.getStatus();
|
||||
|
||||
// 如果是分账结束或失败, 不进行对订单进行处理
|
||||
List<String> list = Arrays.asList(AllocOrderStatusEnum.FINISH.getCode(), AllocOrderStatusEnum.FINISH_FAILED.getCode());
|
||||
if (!list.contains(status)){
|
||||
// 判断明细状态. 获取成功和失败的
|
||||
long successCount = details.stream()
|
||||
.map(AllocationOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.SUCCESS.getCode()::equals)
|
||||
.count();
|
||||
long failCount = details.stream()
|
||||
.map(AllocationOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.FAIL.getCode()::equals)
|
||||
.count();
|
||||
|
||||
// 成功和失败都为0 表示进行中
|
||||
if (successCount == 0 && failCount == 0){
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_PENDING.getCode());
|
||||
} else {
|
||||
if (failCount == details.size()){
|
||||
// 全部失败
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_FAILED.getCode());
|
||||
} else if (successCount == details.size()){
|
||||
// 全部成功
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_SUCCESS.getCode());
|
||||
} else {
|
||||
// 部分成功
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.PART_SUCCESS.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
allocationOrderDetailManager.updateAllById(details);
|
||||
allocationOrderManager.updateById(allocationOrder);
|
||||
|
||||
// 如果状态为完成, 发送通知
|
||||
if (Objects.equals(AllocOrderStatusEnum.ALLOCATION_END.getCode(), allocationOrder.getStatus())){
|
||||
// 发送通知
|
||||
clientNoticeService.registerAllocNotice(allocationOrder, null, details);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取并检查支付订单
|
||||
*/
|
||||
|
@@ -0,0 +1,141 @@
|
||||
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.daxpay.single.code.AllocDetailResultEnum;
|
||||
import cn.daxpay.single.code.AllocOrderResultEnum;
|
||||
import cn.daxpay.single.code.AllocOrderStatusEnum;
|
||||
import cn.daxpay.single.param.payment.allocation.AllocSyncParam;
|
||||
import cn.daxpay.single.result.allocation.AllocationSyncResult;
|
||||
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;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocationOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.allocation.factory.AllocationFactory;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.func.AbsAllocationStrategy;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 对账同步
|
||||
* @author xxm
|
||||
* @since 2024/5/23
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AllocationSyncService {
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
private final AllocationOrderManager allocationOrderManager;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final AllocationOrderDetailManager allocationOrderDetailManager;
|
||||
|
||||
|
||||
/**
|
||||
* 分账同步, 开启一个新的事务, 不受外部抛出异常的影响
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public AllocationSyncResult sync(AllocSyncParam param) {
|
||||
// 获取分账订单
|
||||
AllocationOrder allocationOrder = null;
|
||||
if (Objects.nonNull(param.getAllocationNo())){
|
||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
||||
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
||||
}
|
||||
if (Objects.isNull(allocationOrder)){
|
||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getBizAllocationNo())
|
||||
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
||||
}
|
||||
this.sync(allocationOrder);
|
||||
return new AllocationSyncResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账同步
|
||||
*/
|
||||
public void sync(AllocationOrder allocationOrder){
|
||||
LockInfo lock = lockTemplate.lock("payment:allocation:" + allocationOrder.getOrderId(),10000,200);
|
||||
if (Objects.isNull(lock)){
|
||||
throw new RepetitiveOperationException("分账同步中,请勿重复操作");
|
||||
}
|
||||
try {
|
||||
List<AllocationOrderDetail> detailList = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
||||
// 获取分账策略
|
||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
||||
allocationStrategy.initParam(allocationOrder, detailList);
|
||||
// 分账完结预处理
|
||||
allocationStrategy.doBeforeHandler();
|
||||
allocationStrategy.doSync();
|
||||
// TODO 保存分账同步记录
|
||||
|
||||
// 根据订单明细更新订单的状态和处理结果
|
||||
this.updateOrderStatus(allocationOrder, detailList);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单明细更新订单的状态和处理结果, 如果订单是分账结束或失败, 不更新状态
|
||||
* TODO 是否多次同步会产生多次变动, 注意处理多次推送通知的问题, 目前是
|
||||
*/
|
||||
private void updateOrderStatus(AllocationOrder allocationOrder, List<AllocationOrderDetail> details){
|
||||
// 如果是分账结束或失败, 不更新状态
|
||||
String status = allocationOrder.getStatus();
|
||||
|
||||
// 如果是分账结束或失败, 不进行对订单进行处理
|
||||
List<String> list = Arrays.asList(AllocOrderStatusEnum.FINISH.getCode(), AllocOrderStatusEnum.FINISH_FAILED.getCode());
|
||||
if (!list.contains(status)){
|
||||
// 判断明细状态. 获取成功和失败的
|
||||
long successCount = details.stream()
|
||||
.map(AllocationOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.SUCCESS.getCode()::equals)
|
||||
.count();
|
||||
long failCount = details.stream()
|
||||
.map(AllocationOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.FAIL.getCode()::equals)
|
||||
.count();
|
||||
|
||||
// 成功和失败都为0 表示进行中
|
||||
if (successCount == 0 && failCount == 0){
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_PENDING.getCode());
|
||||
} else {
|
||||
if (failCount == details.size()){
|
||||
// 全部失败
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_FAILED.getCode());
|
||||
} else if (successCount == details.size()){
|
||||
// 全部成功
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_SUCCESS.getCode());
|
||||
} else {
|
||||
// 部分成功
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.PART_SUCCESS.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
allocationOrderDetailManager.updateAllById(details);
|
||||
allocationOrderManager.updateById(allocationOrder);
|
||||
|
||||
// 如果状态为完成, 发送通知
|
||||
if (Objects.equals(AllocOrderStatusEnum.ALLOCATION_END.getCode(), allocationOrder.getStatus())){
|
||||
// 发送通知
|
||||
clientNoticeService.registerAllocNotice(allocationOrder, null, details);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -2,6 +2,7 @@ package cn.daxpay.single.service.core.record.sync.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.daxpay.single.code.AllocOrderStatusEnum;
|
||||
import cn.daxpay.single.code.PayChannelEnum;
|
||||
import cn.daxpay.single.code.RefundSyncStatusEnum;
|
||||
import cn.daxpay.single.code.PaySyncStatusEnum;
|
||||
@@ -46,6 +47,7 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
|
||||
* 三方支付返回状态
|
||||
* @see PaySyncStatusEnum
|
||||
* @see RefundSyncStatusEnum
|
||||
* @see AllocOrderStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "网关返回状态")
|
||||
private String outTradeStatus;
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package cn.daxpay.single.service.handler.excel;
|
||||
|
||||
import cn.daxpay.single.util.PayUtil;
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 金额分转元
|
||||
@@ -23,8 +23,7 @@ public class AmountConverter implements Converter<Integer> {
|
||||
if (value == null){
|
||||
return new WriteCellData<>("");
|
||||
}
|
||||
BigDecimal divide = BigDecimal.valueOf(value)
|
||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
BigDecimal divide = PayUtil.conversionAmount(value);
|
||||
return new WriteCellData<>(divide);
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import cn.daxpay.single.code.AllocOrderStatusEnum;
|
||||
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.payment.allocation.service.AllocationService;
|
||||
import cn.daxpay.single.service.core.payment.allocation.service.AllocationSyncService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.*;
|
||||
@@ -23,6 +24,7 @@ public class AllocationSyncTask implements Job {
|
||||
|
||||
private final AllocationOrderManager allocationOrderManager;
|
||||
|
||||
private final AllocationSyncService allocationSyncService;
|
||||
private final AllocationService allocationService;
|
||||
|
||||
/**
|
||||
@@ -34,7 +36,7 @@ public class AllocationSyncTask implements Job {
|
||||
try {
|
||||
// 分账中走同步逻辑
|
||||
if (allocationOrder.getStatus().equals(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())) {
|
||||
allocationService.sync(allocationOrder);
|
||||
allocationSyncService.sync(allocationOrder);
|
||||
}
|
||||
// 如果分账结束, 调用自动完结逻辑
|
||||
if (allocationOrder.getStatus().equals(AllocOrderStatusEnum.ALLOCATION_END.getCode())) {
|
||||
|
Reference in New Issue
Block a user