记得上下班打卡 | git大法好,push需谨慎

Commit 0d43204a authored by wangyifan's avatar wangyifan

修复收钱吧订单下单、退款bug;优化逻辑

parent 0b919365
...@@ -8,6 +8,8 @@ import com.liquidnet.commons.lang.util.IDGenerator; ...@@ -8,6 +8,8 @@ import com.liquidnet.commons.lang.util.IDGenerator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.liquidnet.commons.lang.util.JsonUtils; import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst; import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.*; import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinSqbOrder; import com.liquidnet.service.goblin.entity.GoblinSqbOrder;
...@@ -23,10 +25,12 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -23,10 +25,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList;
import java.util.List; import java.util.List;
/** /**
...@@ -115,6 +119,11 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService { ...@@ -115,6 +119,11 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
// ================================ 申请退款 ================================ // ================================ 申请退款 ================================
/**
* 申请退款。
* 流程:校验订单状态 → 主单锁定为退款中(61) → 调收钱吧退款API → 成功后子单(61) + 扩展单落库。
* 退款最终完成以收钱吧回调 targetState=20 为准,本方法不主动扣/还库存。
*/
@Override @Override
public ResponseDto<Boolean> refund(String userId, String orderId, String reason) { public ResponseDto<Boolean> refund(String userId, String orderId, String reason) {
log.info("[收钱吧-退款] 开始 userId={}, orderId={}", userId, orderId); log.info("[收钱吧-退款] 开始 userId={}, orderId={}", userId, orderId);
...@@ -175,11 +184,18 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService { ...@@ -175,11 +184,18 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
} }
try { try {
List<CouponRefundRequest.RefundItem> refundItems = buildRefundItem(orderSkuVos);
if (CollectionUtils.isEmpty(refundItems)) {
log.error("[收钱吧-退款] 退款商品明细为空, orderId={}", orderId);
syncOrderStatus(orderId, 1);
return ResponseDto.failure("退款商品数据异常");
}
CouponRefundData refundData = sqbBiz.refundCoupon(orderVo.getSqbOrderSn(), CouponRefundData refundData = sqbBiz.refundCoupon(orderVo.getSqbOrderSn(),
orderVo.getSqbOrderSignature(), orderVo.getSqbOrderSignature(),
orderVo.getAmount(), orderVo.getAmount(),
(byte) 2, // 2-按金额退款 (byte) 2, // 2-按金额退款
buildRefundItem(orderSkuVos), // 需要构建退款商品 refundItems,
reason, reason,
buildRequestId(IDGenerator.nextSnowId()) buildRequestId(IDGenerator.nextSnowId())
); );
...@@ -192,15 +208,14 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService { ...@@ -192,15 +208,14 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
return ResponseDto.failure("退款失败,请稍后重试"); return ResponseDto.failure("退款失败,请稍后重试");
} }
// 退款成功 // 退款申请成功(最终完成以回调为准)
orderVo.setRefundSn(refundData.getTicketsSn()); orderVo.setRefundSn(refundData.getTicketsSn());
orderVo.setRefundSignature(refundData.getTicketSignature()); orderVo.setRefundSignature(refundData.getTicketSignature());
orderVo.setRefundReason(reason); orderVo.setRefundReason(reason);
orderVo.setUpdatedAt(LocalDateTime.now().format(DTF)); orderVo.setUpdatedAt(LocalDateTime.now().format(DTF));
goblinSqbRedisUtils.setSqbOrder(orderId, orderVo); goblinSqbRedisUtils.setSqbOrder(orderId, orderVo);
goblinRedisUtils.incrSkuStock(null, orderVo.getSkuId(), orderVo.getQuantity()); persistRefundSuccess(orderId, orderVo, orderSkuVos, now);
// syncOrderStatus(orderId, 3);
log.info("[收钱吧-退款] 调用收钱吧退款成功,orderId={}", orderId); log.info("[收钱吧-退款] 调用收钱吧退款成功,orderId={}", orderId);
return ResponseDto.success(Boolean.TRUE); return ResponseDto.success(Boolean.TRUE);
...@@ -213,6 +228,39 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService { ...@@ -213,6 +228,39 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
} }
} }
/**
* 退款申请成功后,批量持久化子单状态(Redis/Mongo) + 扩展单退款字段 + 子单 status (MySQL)。
* 合并为一次 MQ 消息发送,避免多消息顺序不一致。
*/
private void persistRefundSuccess(String orderId, GoblinSqbOrderVo orderVo, List<GoblinOrderSkuVo> orderSkuVos, String nowStr) {
LocalDateTime nowLdt = LocalDateTime.now();
LinkedList<String> sqls = new LinkedList<>();
sqls.add(SqlMapping.get("goblin_sqb_order.update_refund"));
sqls.add(SqlMapping.get("goblin_order.store.refundSkuPrice"));
LinkedList<Object[]> sqbArgs = new LinkedList<>();
sqbArgs.add(new Object[]{
orderVo.getRefundSn(), orderVo.getRefundSignature(), orderVo.getRefundReason(),
orderVo.getUpdatedAt(), orderId, orderVo.getUpdatedAt(), orderVo.getUpdatedAt()
});
LinkedList<Object[]> skuArgs = new LinkedList<>();
if (!CollectionUtils.isEmpty(orderSkuVos)) {
for (GoblinOrderSkuVo skuVo : orderSkuVos) {
skuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_61.getValue());
skuVo.setPriceRefund(BigDecimal.ZERO);
goblinRedisUtils.setGoblinOrderSku(skuVo.getOrderSkuId(), skuVo);
goblinMongoUtils.updateGoblinOrderSkuVo(skuVo.getOrderSkuId(), skuVo);
skuArgs.add(new Object[]{BigDecimal.ZERO, GoblinStatusConst.Status.ORDER_STATUS_61.getValue(), nowLdt, skuVo.getOrderSkuId(), nowLdt, nowLdt});
}
}
if (queueUtils != null) {
queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
SqlMapping.gets(sqls, sqbArgs, skuArgs));
}
}
private List<CouponRefundRequest.RefundItem> buildRefundItem(List<GoblinOrderSkuVo> orderSkuVos) { private List<CouponRefundRequest.RefundItem> buildRefundItem(List<GoblinOrderSkuVo> orderSkuVos) {
List<CouponRefundRequest.RefundItem> refundItems = new ArrayList<>(); List<CouponRefundRequest.RefundItem> refundItems = new ArrayList<>();
for (GoblinOrderSkuVo orderSkuVo : orderSkuVos) { for (GoblinOrderSkuVo orderSkuVo : orderSkuVos) {
...@@ -504,6 +552,10 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService { ...@@ -504,6 +552,10 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
* @param orderId * @param orderId
* @param status * @param status
*/ */
/**
* 将收钱吧内部状态码(0待支付/1已支付/2已核销/3已退款/4退款中)映射为商城主单 status,
* 并同步更新 Redis / MongoDB / MySQL。
*/
private void syncOrderStatus(String orderId, int status) { private void syncOrderStatus(String orderId, int status) {
final int zhengzaiStatus = sqbOrderStatusConvert(status); final int zhengzaiStatus = sqbOrderStatusConvert(status);
...@@ -526,22 +578,23 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService { ...@@ -526,22 +578,23 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
// 3. 同步 MySQL (复用下单 MQ 发送 Update 语句) // 3. 同步 MySQL (复用下单 MQ 发送 Update 语句)
String sql; String sql;
Object[] data; Object[] data;
LocalDateTime nowLdt = LocalDateTime.now();
if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) { if (zhengzaiStatus == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
sql = "UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ?"; sql = SqlMapping.get("goblin_sqb.syncStatusPay");
data = new Object[]{zhengzaiStatus, storeOrderVo.getPayTime(), now, orderId}; data = new Object[]{zhengzaiStatus, storeOrderVo.getPayTime(), now, orderId, nowLdt, nowLdt};
} else { } else {
sql = "UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ?"; sql = SqlMapping.get("goblin_sqb.syncStatus");
data = new Object[]{zhengzaiStatus, now, orderId}; data = new Object[]{zhengzaiStatus, now, orderId, nowLdt, nowLdt};
} }
java.util.LinkedList<String> sqls = new java.util.LinkedList<>(); LinkedList<String> sqls = new LinkedList<>();
sqls.add(sql); sqls.add(sql);
java.util.LinkedList<Object[]> sqlData = new java.util.LinkedList<>(); LinkedList<Object[]> sqlData = new LinkedList<>();
sqlData.add(data); sqlData.add(data);
if (queueUtils != null) { if (queueUtils != null) {
queueUtils.sendMsgByRedis(com.liquidnet.service.base.constant.MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(), queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
com.liquidnet.service.base.SqlMapping.gets(sqls, sqlData)); SqlMapping.gets(sqls, sqlData));
} }
} }
......
...@@ -206,3 +206,8 @@ gpblin_bracelet_order_update= update goblin_bracelet_order set out_trans_id=?, e ...@@ -206,3 +206,8 @@ gpblin_bracelet_order_update= update goblin_bracelet_order set out_trans_id=?, e
goblin_bracelet_order_update_cardno=UPDATE goblin_bracelet_order SET cardno=?,updated_at=? WHERE order_id=? goblin_bracelet_order_update_cardno=UPDATE goblin_bracelet_order SET cardno=?,updated_at=? WHERE order_id=?
goblin_bracelet_order_update_fout_trade_no=UPDATE goblin_bracelet_order SET fout_trade_no=?,updated_at=? WHERE order_id=? goblin_bracelet_order_update_fout_trade_no=UPDATE goblin_bracelet_order SET fout_trade_no=?,updated_at=? WHERE order_id=?
goblin_bracelet_order_update_refund=UPDATE goblin_bracelet_order SET status=?,refund_status=?,refund_status_note=?,updated_at=? WHERE order_id=? goblin_bracelet_order_update_refund=UPDATE goblin_bracelet_order SET status=?,refund_status=?,refund_status_note=?,updated_at=? WHERE order_id=?
# ---- 收钱吧退款 ----
goblin_order.store.refundSkuPrice=UPDATE goblin_order_sku SET price_refund = ? ,status = ? , updated_at = ? WHERE order_sku_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_sqb_order.update_refund=UPDATE goblin_sqb_order SET sqb_refund_sn = ?, sqb_refund_signature = ?, refund_reason = ?, updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_sqb.syncStatus=UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_sqb.syncStatusPay=UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
\ No newline at end of file
...@@ -78,4 +78,8 @@ dragon_orders.updateOrderStatus=update dragon_orders t set t.status = ? ,t.paym ...@@ -78,4 +78,8 @@ dragon_orders.updateOrderStatus=update dragon_orders t set t.status = ? ,t.paym
dragon_orders.updateNotifyStatus=update dragon_orders t set t.notify_status = ? ,t.updated_at =? where t.code = ? dragon_orders.updateNotifyStatus=update dragon_orders t set t.notify_status = ? ,t.updated_at =? where t.code = ?
#---- \u85CF\u54C1\u8BA2\u5355\u5173\u8054\u85CF\u54C1ID #---- \u85CF\u54C1\u8BA2\u5355\u5173\u8054\u85CF\u54C1ID
goblin_nft_order.update_artwork=UPDATE goblin_nft_order SET artwork_id=? WHERE order_id=? goblin_nft_order.update_artwork=UPDATE goblin_nft_order SET artwork_id=? WHERE order_id=?
# ---- 收钱吧退款回调 ----
goblin_sqb_order.update_refund=UPDATE goblin_sqb_order SET sqb_refund_sn = ?, sqb_refund_signature = ?, refund_reason = ?, updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_sqb.syncStatus=UPDATE goblin_store_order SET status = ?, updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_sqb.syncStatusPay=UPDATE goblin_store_order SET status = ?, pay_time = ?, updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
#---- #----
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment