支付回调调整:

原逻辑: 单直接关联payment_id,当一个单发起了多次支付时,会造成混乱.
现更改为: 由支付成功的payment在回调时通过payment_relation表找到对应的单并关联.
1. FinancialMaster: 保存paymentId,更新支付状态;
2. FinancialChange: 保存paymentId,更新支付状态,并把金额加到FinancialDetail与FinancialMaster里;
3. OrderAddSubtract: 保存paymentId,更新支付状态,并把金额加到FinancialDetail与FinancialMaster里;
This commit is contained in:
Hawking 2023-05-31 23:13:21 +08:00
parent 210ade5f47
commit 8df08d1ff1
14 changed files with 226 additions and 74 deletions

View File

@ -7,20 +7,22 @@ import com.ghy.common.adapay.model.Event;
import com.ghy.common.adapay.model.PayCallback; import com.ghy.common.adapay.model.PayCallback;
import com.ghy.common.adapay.model.PaymentDTO; import com.ghy.common.adapay.model.PaymentDTO;
import com.ghy.common.enums.PayStatus; import com.ghy.common.enums.PayStatus;
import com.ghy.order.domain.OrderAddSubtract;
import com.ghy.order.service.IOrderAddSubtractService;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster; import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.PaymentRelation;
import com.ghy.payment.mapper.PaymentRelationMapper;
import com.ghy.payment.service.CallBackService; import com.ghy.payment.service.CallBackService;
import com.ghy.payment.service.FinancialChangeRecordService; import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialDetailService; import com.ghy.payment.service.FinancialDetailService;
import com.ghy.payment.service.FinancialMasterService; import com.ghy.payment.service.FinancialMasterService;
import org.slf4j.Logger; import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -30,106 +32,117 @@ import java.util.concurrent.CompletableFuture;
* *
* @author HH 2022/5/31 * @author HH 2022/5/31
*/ */
@Slf4j
@Service("payCallbackService") @Service("payCallbackService")
public class PayCallbackService implements CallBackService { public class PayCallbackService implements CallBackService {
private static final Logger logger = LoggerFactory.getLogger(PayCallbackService.class);
@Resource @Resource
FinancialMasterService financialMasterService; FinancialMasterService financialMasterService;
@Resource
PaymentRelationMapper paymentRelationMapper;
@Resource @Resource
FinancialDetailService financialDetailService; FinancialDetailService financialDetailService;
@Resource
IOrderAddSubtractService orderAddSubtractService;
@Resource @Resource
FinancialChangeRecordService financialChangeRecordService; FinancialChangeRecordService financialChangeRecordService;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void onCallback(Event event) { public void onCallback(Event event) {
logger.info("支付回调: {}", event); log.info("支付回调: {}", event);
String data = event.getData(); String data = event.getData();
PayCallback payment = JSON.parseObject(data, PayCallback.class); PayCallback payment = JSON.parseObject(data, PayCallback.class);
PaymentDTO dto = financialMasterService.selectPaymentById(payment.getId()); PaymentDTO dto = financialMasterService.selectPaymentById(payment.getId());
// 校验是否是本系统发出去的支付请求 // 支付ID
if (dto != null) { final String paymentId = dto.getId();
CompletableFuture.runAsync(() -> { // 是否支付成功
// 异步更新交易记录 避免被回滚 final boolean succeeded = AdapayStatusEnum.succeeded.code.equals(payment.getStatus());
PaymentDTO param = new PaymentDTO();
param.setId(payment.getId()); // 异步更新交易记录 避免被其它业务异常回滚
CompletableFuture.runAsync(() -> {
PaymentDTO param = new PaymentDTO();
param.setId(payment.getId());
param.setStatus(payment.getStatus());
if (succeeded) {
// 如果支付成功 更新支付渠道支付时间手续费
param.setPayChannel(payment.getPayChannel());
param.setFeeAmt(payment.getFeeAmt()); param.setFeeAmt(payment.getFeeAmt());
param.setStatus(payment.getStatus());
param.setPayTime(LocalDateTime.now()); param.setPayTime(LocalDateTime.now());
financialMasterService.updatePayment(param); if ("delay".equals(dto.getPayMode())) {
}); // 如果支付成功 且是延迟分账模式 更新可用金额=交易金额
if (AdapayStatusEnum.succeeded.code.equals(payment.getStatus())) { param.setAvailableAmt(dto.getPayAmt());
if (payment.getOrderNo().split("_").length > 2) { }
// 支付回调中的加价记录ID }
String fcrIdStr = payment.getOrderNo().split("_")[1]; financialMasterService.updatePayment(param);
String[] fcrIds = fcrIdStr.split(","); });
BigDecimal totalChangeMoney = BigDecimal.ZERO; if (succeeded) {
Long financialMasterId = null; // 支付成功 查询支付关联的订单
for (String fcrId : fcrIds) { List<PaymentRelation> paymentRelations = paymentRelationMapper.selectByPaymentId(paymentId);
FinancialChangeRecord financialChangeRecord = new FinancialChangeRecord(); if (CollectionUtils.isEmpty(paymentRelations)) {
financialChangeRecord.setId(Long.valueOf(fcrId)); log.error("未关联订单的支付回调: {}", data);
financialChangeRecord.setPayStatus(1); return;
// 加价的支付paymentId回填到remark }
financialChangeRecord.setRemark(payment.getId());
financialChangeRecord.setRemark(payment.getId());
financialChangeRecord.setPaymentId(payment.getId());
financialChangeRecordService.update(financialChangeRecord);
// 修改子订单的payMoney for (PaymentRelation relation : paymentRelations) {
FinancialChangeRecord fc = financialChangeRecordService.selectFinancialChangeRecordById(financialChangeRecord.getId()); Long relationId = relation.getRelationId();
FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(fc.getOrderDetailId()); if (PaymentRelation.FINANCIAL_MASTER.equals(relation.getRelationIdType())) {
FinancialDetail financialDetail2Update = new FinancialDetail();
financialDetail2Update.setId(financialDetail.getId()); // 更新主财务单的支付信息
financialDetail2Update.setPayMoney(financialDetail.getPayMoney().add(fc.getChangeMoney())); financialMasterService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
financialDetail2Update.setPayStatus(PayStatus.PAID.getCode()); log.info("主财务单[{}]支付成功", relationId);
financialDetailService.updateFinancialDetail(financialDetail2Update);
totalChangeMoney = totalChangeMoney.add(fc.getChangeMoney()); } else if (PaymentRelation.FINANCIAL_CHANGE.equals(relation.getRelationIdType())) {
if (financialMasterId == null) {
financialMasterId = financialDetail.getFinancialMasterId(); // 更新加价单的支付信息
} financialChangeRecordService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
} FinancialChangeRecord fc = financialChangeRecordService.selectFinancialChangeRecordById(relationId);
// 修改子订单的payMoney
FinancialDetail fd = financialDetailService.selectByOrderDetailId(fc.getOrderDetailId());
FinancialDetail fd2Update = new FinancialDetail();
fd2Update.setId(fd.getId());
fd2Update.setPayMoney(fd.getPayMoney().add(fc.getChangeMoney()));
fd2Update.setPayStatus(PayStatus.PAID.getCode());
financialDetailService.updateFinancialDetail(fd2Update);
// 修改主单的payMoney // 修改主单的payMoney
FinancialMaster financialMaster = financialMasterService.selectById(financialMasterId); FinancialMaster financialMaster = financialMasterService.selectById(fd.getFinancialMasterId());
FinancialMaster financialMaster2Update = new FinancialMaster(); FinancialMaster financialMaster2Update = new FinancialMaster();
financialMaster2Update.setId(financialMaster.getId()); financialMaster2Update.setId(financialMaster.getId());
financialMaster2Update.setPayMoney(financialMaster.getPayMoney().add(totalChangeMoney)); financialMaster2Update.setPayMoney(financialMaster.getPayMoney().add(fc.getChangeMoney()));
financialMaster2Update.setPayStatus(PayStatus.PAID.getCode()); financialMaster2Update.setPayStatus(PayStatus.PAID.getCode());
financialMasterService.updateFinancialMaster(financialMaster2Update); financialMasterService.updateFinancialMaster(financialMaster2Update);
// TODO 拆分对应的分账流水 log.info("FinancialChange[{}]支付成功", relationId);
}else {
// 主单的付款
String masterOrderNo = payment.getOrderNo().split("_")[0];
// 找到主单记录 } else if (PaymentRelation.ORDER_ADD.equals(relation.getRelationIdType())) {
FinancialMaster param = new FinancialMaster(); // 更新订单追加单的支付信息
param.setOrderMasterCode(masterOrderNo); orderAddSubtractService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
List<FinancialMaster> financialMasters = financialMasterService.selectFinancialMasterList(param); OrderAddSubtract orderAdd = orderAddSubtractService.selectById(relationId);
FinancialMaster source = financialMasters.get(0); // 修改子订单的payMoney
// 更新主单paymentId 以及主单状态 FinancialDetail fd = financialDetailService.selectByOrderDetailId(orderAdd.getOrderDetailId());
FinancialDetail fd2Update = new FinancialDetail();
fd2Update.setId(fd.getId());
fd2Update.setPayMoney(fd.getPayMoney().add(orderAdd.getMoney()));
fd2Update.setPayStatus(PayStatus.PAID.getCode());
financialDetailService.updateFinancialDetail(fd2Update);
// 修改主单的payMoney
FinancialMaster financialMaster = financialMasterService.selectById(fd.getFinancialMasterId());
FinancialMaster financialMaster2Update = new FinancialMaster(); FinancialMaster financialMaster2Update = new FinancialMaster();
financialMaster2Update.setId(source.getId()); financialMaster2Update.setId(financialMaster.getId());
financialMaster2Update.setPayMoney(financialMaster.getPayMoney().add(orderAdd.getMoney()));
financialMaster2Update.setPayStatus(PayStatus.PAID.getCode()); financialMaster2Update.setPayStatus(PayStatus.PAID.getCode());
financialMaster2Update.setPaymentId(payment.getId());
financialMasterService.updateFinancialMaster(financialMaster2Update); financialMasterService.updateFinancialMaster(financialMaster2Update);
log.info("订单追加[{}]支付成功", relationId);
} else {
log.error("未知的订单类型: relationIdType={}, relationId={}", relation.getRelationIdType(), relationId);
} }
// 更新主财务单状态
financialMasterService.paySucceeded(payment.getId(), payment.getPayChannel());
} else {
logger.warn("支付失败 : {}", data);
} }
} else {
logger.warn("系统中不存在这条交易记录: {}", event);
} }
} }
@Override @Override
public void onResponse(JSONObject response) { public void onResponse(JSONObject response) {
logger.info("发起支付 Response: {}", response.toJSONString()); log.info("发起支付 Response: {}", response.toJSONString());
// 保存一条支付记录 // 保存一条支付记录
PaymentDTO payment = response.toJavaObject(PaymentDTO.class); PaymentDTO payment = response.toJavaObject(PaymentDTO.class);
String status = payment.getStatus(); String status = payment.getStatus();
@ -137,7 +150,7 @@ public class PayCallbackService implements CallBackService {
financialMasterService.insertPayment(payment); financialMasterService.insertPayment(payment);
if (!AdapayStatusEnum.succeeded.code.equals(status)) { if (!AdapayStatusEnum.succeeded.code.equals(status)) {
logger.warn("发起支付失败 : {}", response.toJSONString()); log.warn("发起支付失败 : {}", response.toJSONString());
} }
} }

View File

@ -1,6 +1,7 @@
package com.ghy.order.mapper; package com.ghy.order.mapper;
import com.ghy.order.domain.OrderAddSubtract; import com.ghy.order.domain.OrderAddSubtract;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -9,13 +10,15 @@ import java.util.List;
*/ */
public interface OrderAddSubtractMapper { public interface OrderAddSubtractMapper {
int insert(OrderAddSubtract insert); int insert(OrderAddSubtract o);
int update(OrderAddSubtract insert); int update(OrderAddSubtract o);
List<OrderAddSubtract> select(OrderAddSubtract insert); List<OrderAddSubtract> select(OrderAddSubtract o);
List<OrderAddSubtract> selectByOrderDetail(Long orderDetailId); List<OrderAddSubtract> selectByOrderDetail(Long orderDetailId);
OrderAddSubtract selectById(Long id); OrderAddSubtract selectById(Long id);
int updatePay(@Param(value = "id") Long id, @Param(value = "paymentId") String paymentId, @Param(value = "payStatus") Integer payStatus);
} }

View File

@ -0,0 +1,28 @@
package com.ghy.order.service;
import com.ghy.order.domain.OrderAddSubtract;
import java.util.List;
public interface IOrderAddSubtractService {
int insert(OrderAddSubtract o);
int update(OrderAddSubtract o);
List<OrderAddSubtract> select(OrderAddSubtract o);
List<OrderAddSubtract> selectByOrderDetail(Long orderDetailId);
OrderAddSubtract selectById(Long id);
/**
* 更新支付信息
*
* @param id OrderAddSubtract ID
* @param paymentId 支付ID
* @param payStatus 支付状态
* @return 1
*/
int updatePay(Long id, String paymentId, Integer payStatus);
}

View File

@ -0,0 +1,46 @@
package com.ghy.order.service.impl;
import com.ghy.order.domain.OrderAddSubtract;
import com.ghy.order.mapper.OrderAddSubtractMapper;
import com.ghy.order.service.IOrderAddSubtractService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class OrderAddSubtractServiceImpl implements IOrderAddSubtractService {
@Resource
private OrderAddSubtractMapper orderAddSubtractMapper;
@Override
public int insert(OrderAddSubtract o) {
return orderAddSubtractMapper.insert(o);
}
@Override
public int update(OrderAddSubtract o) {
return orderAddSubtractMapper.update(o);
}
@Override
public List<OrderAddSubtract> select(OrderAddSubtract o) {
return orderAddSubtractMapper.select(o);
}
@Override
public List<OrderAddSubtract> selectByOrderDetail(Long orderDetailId) {
return orderAddSubtractMapper.selectByOrderDetail(orderDetailId);
}
@Override
public OrderAddSubtract selectById(Long id) {
return orderAddSubtractMapper.selectById(id);
}
@Override
public int updatePay(Long id, String paymentId, Integer payStatus) {
return orderAddSubtractMapper.updatePay(id, paymentId, payStatus);
}
}

View File

@ -44,6 +44,13 @@
WHERE id = #{id} WHERE id = #{id}
</update> </update>
<update id="updatePay">
UPDATE order_add_subtract
SET pay_status = #{payStatus},
payment_id = #{paymentId}
WHERE id = #{id}
</update>
<select id="select" parameterType="com.ghy.order.domain.OrderAddSubtract" resultMap="ColumnMap"> <select id="select" parameterType="com.ghy.order.domain.OrderAddSubtract" resultMap="ColumnMap">
<include refid="selectColumns"/> <include refid="selectColumns"/>
<where> <where>

View File

@ -25,4 +25,9 @@ public class PaymentRelation {
* order_add: 订单追加单 * order_add: 订单追加单
*/ */
private String relationIdType; private String relationIdType;
public static final String FINANCIAL_MASTER = "financial_master";
public static final String FINANCIAL_CHANGE = "financial_change";
public static final String ORDER_ADD = "order_add";
} }

View File

@ -72,4 +72,6 @@ public interface FinancialChangeRecordMapper {
* @param reverseId Adapay撤销支付ID * @param reverseId Adapay撤销支付ID
*/ */
void refundSucceeded(String reverseId); void refundSucceeded(String reverseId);
int updatePay(@Param(value = "id") Long id, @Param(value = "paymentId") String paymentId, @Param(value = "payStatus") Integer payStatus);
} }

View File

@ -86,4 +86,6 @@ public interface FinancialMasterMapper {
void refundSucceeded(@Param("reverseId") String reverseId); void refundSucceeded(@Param("reverseId") String reverseId);
int updatePayStatus(@Param(value = "id") Long id, @Param(value = "payStatus") int payStatus); int updatePayStatus(@Param(value = "id") Long id, @Param(value = "payStatus") int payStatus);
int updatePay(@Param(value = "id") Long id, @Param(value = "paymentId") String paymentId, @Param(value = "payStatus") Integer payStatus);
} }

View File

@ -85,4 +85,14 @@ public interface FinancialChangeRecordService {
* @param reverseId 退款ID * @param reverseId 退款ID
*/ */
void refundSucceeded(String reverseId); void refundSucceeded(String reverseId);
/**
* 更新支付信息
*
* @param id FinancialChange ID
* @param paymentId 支付ID
* @param payStatus 支付状态
* @return 1
*/
int updatePay(Long id, String paymentId, Integer payStatus);
} }

View File

@ -34,7 +34,7 @@ public interface FinancialMasterService {
/** /**
* @param request 主财务单入参 * @param request 主财务单入参
* @return 主财务单集合 * @return 主财务单集合
* */ */
List<FinancialMaster> selectAppList(FinancialMaster request); List<FinancialMaster> selectAppList(FinancialMaster request);
/** /**
@ -102,4 +102,14 @@ public interface FinancialMasterService {
void refundSucceeded(String reverseId); void refundSucceeded(String reverseId);
int updatePayStatus(Long id, int payStatus); int updatePayStatus(Long id, int payStatus);
/**
* 更新支付信息
*
* @param id 主财务单ID
* @param paymentId 支付ID
* @param payStatus 支付状态
* @return 1
*/
int updatePay(Long id, String paymentId, Integer payStatus);
} }

View File

@ -168,4 +168,9 @@ public class FinancialChangeRecordServiceImpl implements FinancialChangeRecordSe
public void refundSucceeded(String reverseId) { public void refundSucceeded(String reverseId) {
financialChangeRecordMapper.refundSucceeded(reverseId); financialChangeRecordMapper.refundSucceeded(reverseId);
} }
@Override
public int updatePay(Long id, String paymentId, Integer payStatus) {
return financialChangeRecordMapper.updatePay(id, paymentId, payStatus);
}
} }

View File

@ -165,6 +165,11 @@ public class FinancialMasterServiceImpl implements FinancialMasterService {
return financialMasterMapper.updatePayStatus(id, payStatus); return financialMasterMapper.updatePayStatus(id, payStatus);
} }
@Override
public int updatePay(Long id, String paymentId, Integer payStatus) {
return financialMasterMapper.updatePay(id, paymentId, payStatus);
}
@Override @Override
public List<FinancialMaster> selectByOrderMasterIds(Set<Long> orderMasterIds) { public List<FinancialMaster> selectByOrderMasterIds(Set<Long> orderMasterIds) {
if (CollectionUtils.isEmpty(orderMasterIds)) { if (CollectionUtils.isEmpty(orderMasterIds)) {

View File

@ -117,4 +117,12 @@
pay_status = 3 pay_status = 3
WHERE reverse_id = #{reverseId} WHERE reverse_id = #{reverseId}
</update> </update>
<update id="updatePay">
UPDATE financial_change_record
SET pay_status = #{payStatus},
payment_id = #{paymentId},
update_time = NOW()
WHERE id = #{id}
</update>
</mapper> </mapper>

View File

@ -147,6 +147,14 @@
WHERE id = #{id} WHERE id = #{id}
</update> </update>
<update id="updatePay">
UPDATE financial_master SET
payment_id = #{paymentId},
pay_status = #{payStatus},
update_time = NOW()
WHERE id = #{id}
</update>
<insert id="insertFinancialMaster" parameterType="com.ghy.payment.domain.FinancialMaster" useGeneratedKeys="true" keyProperty="id"> <insert id="insertFinancialMaster" parameterType="com.ghy.payment.domain.FinancialMaster" useGeneratedKeys="true" keyProperty="id">
INSERT INTO financial_master( INSERT INTO financial_master(
<if test="deptId != null">dept_id,</if> <if test="deptId != null">dept_id,</if>