Commit 631eb1a6edfa36348b57f815a3bc258e09283f37

Authored by huanggang
2 parents 78c0b05e 5259c479

Merge branch 'main' of git3.nong12.com:cashierdesk/dili-cashier

Showing 28 changed files with 554 additions and 162 deletions
cashier-mall/src/main/java/com/diligrp/cashier/mall/api/ManualHandlerApi.java
... ... @@ -3,6 +3,7 @@ package com.diligrp.cashier.mall.api;
3 3 import com.diligrp.cashier.shared.domain.Message;
4 4 import com.diligrp.cashier.shared.spi.IPaymentEventListener;
5 5 import com.diligrp.cashier.shared.spi.domain.PaymentResultBO;
  6 +import com.diligrp.cashier.shared.spi.domain.RefundResultBO;
6 7 import jakarta.annotation.Resource;
7 8 import org.springframework.validation.annotation.Validated;
8 9 import org.springframework.web.bind.annotation.PostMapping;
... ... @@ -15,18 +16,23 @@ import org.springframework.web.bind.annotation.RestController;
15 16 * @author dengwei
16 17 * @version 1.0.0
17 18 * @Description ManualHandlerApi
18   - * @date 2026-01-06 14:00
19 19 */
20 20 @RestController
21 21 @RequestMapping(path = "/mall/manual")
22 22 @Validated
23 23 public class ManualHandlerApi {
24 24 @Resource
25   - private IPaymentEventListener paymentEventListener;
  25 + private IPaymentEventListener payNotifyServiceImpl;
26 26  
27 27 @PostMapping("/payment/event")
28 28 public Message<?> handlePaymentEvent(@RequestBody PaymentResultBO payment) {
29   - paymentEventListener.onEvent(payment);
  29 + payNotifyServiceImpl.onEvent(payment);
  30 + return Message.success();
  31 + }
  32 +
  33 + @PostMapping("/refund/event")
  34 + public Message<?> handlePaymentEvent(@RequestBody RefundResultBO refund) {
  35 + payNotifyServiceImpl.onEvent(refund);
30 36 return Message.success();
31 37 }
32 38  
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/api/RtMallOrderRefundApi.java
... ... @@ -41,7 +41,7 @@ public class RtMallOrderRefundApi {
41 41 @PostMapping("/refund/v1")
42 42 @ParamLogPrint(outPrint = true)
43 43 @Sign(sign = RtMallSign.class)
44   - @RepeatSubmit(prefix = "refund:", value = "#req['order_id']", duplicationSubmit = SpelDuplicationSubmit.class)
  44 + @RepeatSubmit(prefix = "refund:", value = {"#req['order_id']", "#req['trade_id']"}, duplicationSubmit = SpelDuplicationSubmit.class)
45 45 public RtMarkMessage<RefundSuccessVO> refund(@RequestBody Object req) {
46 46 RefundCO refundCo = JsonUtils.convertValue(req, RefundCO.class);
47 47 RtMallValidateUtils.valid(refundCo);
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/api/RtMallOrderPaymentApi.java renamed to cashier-mall/src/main/java/com/diligrp/cashier/mall/api/RtMallScanOrderApi.java
... ... @@ -2,10 +2,15 @@ package com.diligrp.cashier.mall.api;
2 2  
3 3 import com.diligrp.cashier.mall.domain.rtmall.RtMarkMessage;
4 4 import com.diligrp.cashier.mall.domain.rtmall.co.OrderCO;
  5 +import com.diligrp.cashier.mall.domain.rtmall.co.OrderInfoCO;
5 6 import com.diligrp.cashier.mall.domain.rtmall.co.PaymentAllocateCO;
  7 +import com.diligrp.cashier.mall.domain.rtmall.co.RefundCO;
  8 +import com.diligrp.cashier.mall.domain.rtmall.vo.OrderPaymentVO;
6 9 import com.diligrp.cashier.mall.domain.rtmall.vo.OrderSuccessVO;
  10 +import com.diligrp.cashier.mall.domain.rtmall.vo.RefundSuccessVO;
7 11 import com.diligrp.cashier.mall.service.biz.MallBizOrderService;
8 12 import com.diligrp.cashier.mall.service.biz.MallBizPaymentService;
  13 +import com.diligrp.cashier.mall.service.biz.MallBizRefundService;
9 14 import com.diligrp.cashier.mall.sign.RtMallSign;
10 15 import com.diligrp.cashier.mall.type.OrderType;
11 16 import com.diligrp.cashier.mall.util.RtMallValidateUtils;
... ... @@ -31,15 +36,18 @@ import java.util.List;
31 36 @RestController
32 37 @RequestMapping(path = {"/api/rt/mall/scan", "/rt/mall/scan"})
33 38 @Validated
34   -public class RtMallOrderPaymentApi {
  39 +public class RtMallScanOrderApi {
35 40 @Resource
36 41 private MallBizPaymentService mallBizPaymentService;
37 42 @Resource
38 43 private MallBizOrderService mallBizOrderService;
  44 + @Resource
  45 + private MallBizRefundService mallBizRefundService;
39 46  
40 47 /**
41 48 * 扫码下单接口
42 49 * Pos扫支付码后,推送订单信息到商户,商户返回收银台链接
  50 + * https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#oJ2JC
43 51 */
44 52 @PostMapping("/order/v1")
45 53 @ParamLogPrint(outPrint = true)
... ... @@ -55,8 +63,9 @@ public class RtMallOrderPaymentApi {
55 63 /**
56 64 * 支付分摊回调接口
57 65 * POS完成支付分摊后,调用此接口通知商户商品信息已就绪
  66 + * https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#NdciR
58 67 */
59   - @PostMapping("/status/callback")
  68 + @PostMapping("/order/v1/callback")
60 69 @ParamLogPrint(outPrint = true)
61 70 @Sign(sign = RtMallSign.class)
62 71 @RepeatSubmit(prefix = "payment_allocate_callback:", value = {
... ... @@ -67,4 +76,47 @@ public class RtMallOrderPaymentApi {
67 76 mallBizPaymentService.handlePaymentAllocate(allocateCO);
68 77 return RtMarkMessage.success();
69 78 }
  79 +
  80 + /**
  81 + * info
  82 + * @see https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#jRAS2
  83 + * 查询订单详情
  84 + */
  85 + @PostMapping("/order/v1/info")
  86 + @ParamLogPrint(outPrint = true)
  87 + @Sign(sign = RtMallSign.class)
  88 + public RtMarkMessage<OrderPaymentVO> info(@RequestBody Object req) {
  89 + OrderInfoCO orderInfoCo = JsonUtils.convertValue(req, OrderInfoCO.class);
  90 + RtMallValidateUtils.valid(orderInfoCo);
  91 + return RtMarkMessage.success(mallBizOrderService.info(orderInfoCo));
  92 + }
  93 +
  94 + /**
  95 + * status
  96 + * @see https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#iHWnf
  97 + * 查询支付单状态
  98 + */
  99 + @PostMapping("/order/v1/status")
  100 + @ParamLogPrint(outPrint = true)
  101 + @Sign(sign = RtMallSign.class)
  102 + public RtMarkMessage<OrderPaymentVO> status(@RequestBody Object req) {
  103 + OrderInfoCO orderInfoCo = JsonUtils.convertValue(req, OrderInfoCO.class);
  104 + RtMallValidateUtils.valid(orderInfoCo);
  105 + return RtMarkMessage.success(mallBizOrderService.info(orderInfoCo));
  106 + }
  107 +
  108 + /**
  109 + * cancel
  110 + * @see https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#iHWnf
  111 + * 取消支付流水
  112 + */
  113 + @PostMapping("/payment/v1/cancel")
  114 + @ParamLogPrint(outPrint = true)
  115 + @Sign(sign = RtMallSign.class)
  116 + @RepeatSubmit(prefix = "refund:", value = {"#req['order_id']", "#req['trade_id']"}, duplicationSubmit = SpelDuplicationSubmit.class)
  117 + public RtMarkMessage<RefundSuccessVO> cancel(@RequestBody Object req) {
  118 + RefundCO refundCo = JsonUtils.convertValue(req, RefundCO.class);
  119 + RtMallValidateUtils.valid(refundCo);
  120 + return RtMarkMessage.success(mallBizRefundService.refund(refundCo));
  121 + }
70 122 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/api/RtMallScanOrderRefundApi.java 0 → 100644
  1 +package com.diligrp.cashier.mall.api;
  2 +
  3 +import com.diligrp.cashier.mall.domain.rtmall.RtMarkMessage;
  4 +import com.diligrp.cashier.mall.domain.rtmall.co.RefundCO;
  5 +import com.diligrp.cashier.mall.domain.rtmall.co.RefundStatusCO;
  6 +import com.diligrp.cashier.mall.domain.rtmall.vo.RefundSuccessVO;
  7 +import com.diligrp.cashier.mall.domain.rtmall.vo.RefundVO;
  8 +import com.diligrp.cashier.mall.service.biz.MallBizRefundService;
  9 +import com.diligrp.cashier.mall.sign.RtMallSign;
  10 +import com.diligrp.cashier.mall.util.RtMallValidateUtils;
  11 +import com.diligrp.cashier.shared.annotation.ParamLogPrint;
  12 +import com.diligrp.cashier.shared.annotation.RepeatSubmit;
  13 +import com.diligrp.cashier.shared.annotation.Sign;
  14 +import com.diligrp.cashier.shared.handler.duplication.SpelDuplicationSubmit;
  15 +import com.diligrp.cashier.shared.util.JsonUtils;
  16 +import jakarta.annotation.Resource;
  17 +import org.springframework.validation.annotation.Validated;
  18 +import org.springframework.web.bind.annotation.PostMapping;
  19 +import org.springframework.web.bind.annotation.RequestBody;
  20 +import org.springframework.web.bind.annotation.RequestMapping;
  21 +import org.springframework.web.bind.annotation.RestController;
  22 +
  23 +/**
  24 + * @ClassName RtMallOrderRefundApi.java
  25 + * @author dengwei
  26 + * @version 1.0.0
  27 + * @Description RtMallOrderRefundApi
  28 + */
  29 +@RestController
  30 +@RequestMapping(path = {"/api/rt/mall/scan", "/rt/mall/scan"})
  31 +@Validated
  32 +public class RtMallScanOrderRefundApi {
  33 + @Resource
  34 + private MallBizRefundService mallBizRefundService;
  35 +
  36 + /**
  37 + * refund
  38 + * @see https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#jRAS2
  39 + * 申请退款接口
  40 + */
  41 + @PostMapping("/refund/v1")
  42 + @ParamLogPrint(outPrint = true)
  43 + @Sign(sign = RtMallSign.class)
  44 + @RepeatSubmit(prefix = "refund:", value = {"#req['order_id']", "#req['trade_id']"}, duplicationSubmit = SpelDuplicationSubmit.class)
  45 + public RtMarkMessage<RefundSuccessVO> refund(@RequestBody Object req) {
  46 + RefundCO refundCo = JsonUtils.convertValue(req, RefundCO.class);
  47 + RtMallValidateUtils.valid(refundCo);
  48 + return RtMarkMessage.success(mallBizRefundService.refund(refundCo));
  49 + }
  50 +
  51 + /**
  52 + * info
  53 + * @see https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#iYTdn
  54 + * 查询退款状态
  55 + */
  56 + @PostMapping("/refund/v1/status")
  57 + @ParamLogPrint(outPrint = true)
  58 + @Sign(sign = RtMallSign.class)
  59 + public RtMarkMessage<RefundVO> status(@RequestBody Object req) {
  60 + RefundStatusCO refundStatusCo = JsonUtils.convertValue(req, RefundStatusCO.class);
  61 + RtMallValidateUtils.valid(refundStatusCo);
  62 + return RtMarkMessage.success(mallBizRefundService.info(refundStatusCo));
  63 + }
  64 +
  65 + /**
  66 + * info
  67 + * @see https://shopex.yuque.com/hl0rrx/vlp0m4/kmcazgnimg28d8ih?singleDoc#iYTdn
  68 + * 查询退款详情
  69 + */
  70 + @PostMapping("/refund/v1/info")
  71 + @ParamLogPrint(outPrint = true)
  72 + @Sign(sign = RtMallSign.class)
  73 + public RtMarkMessage<RefundVO> info(@RequestBody Object req) {
  74 + RefundStatusCO refundStatusCo = JsonUtils.convertValue(req, RefundStatusCO.class);
  75 + RtMallValidateUtils.valid(refundStatusCo);
  76 + return RtMarkMessage.success(mallBizRefundService.info(refundStatusCo));
  77 + }
  78 +}
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/dao/MallBizPaymentOrderDao.java
... ... @@ -31,4 +31,6 @@ public interface MallBizPaymentOrderDao extends MybatisMapperSupport {
31 31 List<MallBizPaymentOrder> listPaymentOrderByBizPaymentId(@Param("bizPaymentId") Long bizPaymentId);
32 32  
33 33 void updateByPayment(MallBizPayment mallBizPayment);
  34 +
  35 + List<MallBizPaymentOrder> listPaymentOrderByBizOrderId(@Param("bizOrderId") Long bizOrderId);
34 36 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/dao/MallBizRefundDao.java
... ... @@ -3,6 +3,7 @@ package com.diligrp.cashier.mall.dao;
3 3  
4 4 import com.diligrp.cashier.mall.model.MallBizRefund;
5 5 import com.diligrp.cashier.shared.mybatis.MybatisMapperSupport;
  6 +import org.apache.ibatis.annotations.Param;
6 7  
7 8 public interface MallBizRefundDao extends MybatisMapperSupport {
8 9 int deleteByPrimaryKey(Long id);
... ... @@ -18,4 +19,8 @@ public interface MallBizRefundDao extends MybatisMapperSupport {
18 19 int updateByPrimaryKey(MallBizRefund record);
19 20  
20 21 MallBizRefund getMallBizRefund(MallBizRefund refund);
  22 +
  23 + MallBizRefund getByRefundTradeId(@Param("refundTradeId") String refundTradeId);
  24 +
  25 + int countRefund(@Param("bizOrderId") Long bizOrderId);
21 26 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/dto/HourlyRefundCallbackDTO.java
... ... @@ -5,8 +5,8 @@ import com.diligrp.cashier.mall.domain.rtmall.RtMarkBaseCO;
5 5 import com.diligrp.cashier.mall.model.MallBizOrder;
6 6 import com.diligrp.cashier.mall.model.MallBizRefund;
7 7 import com.diligrp.cashier.mall.property.RtMallDynamicProperty;
  8 +import com.diligrp.cashier.pipeline.type.PaymentState;
8 9 import com.diligrp.cashier.shared.jackson.serialization.DateToSecondSerializer;
9   -import com.diligrp.cashier.trade.type.TradeState;
10 10 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
11 11  
12 12 import java.time.LocalDateTime;
... ... @@ -73,12 +73,12 @@ public class HourlyRefundCallbackDTO extends RtMarkBaseCO {
73 73 dto.setRefundBn(mallBizRefund.getRefundBn());
74 74 dto.setRefundId(mallBizRefund.getRefundTradeId());
75 75 dto.setPayFee(mallBizRefund.getRefundFee());
76   - if (Objects.equals(mallBizRefund.getRefundState(), TradeState.SUCCESS.getCode())) {
  76 + if (Objects.equals(mallBizRefund.getRefundState(), PaymentState.SUCCESS.getCode())) {
77 77 dto.setRefundStatus("SUCCESS");
78 78 } else {
79 79 dto.setRefundStatus("ERROR");
  80 + dto.setRefuseReason(mallBizRefund.getRefuseReason());
80 81 }
81   - dto.setRefuseReason(mallBizRefund.getRefuseReason());
82 82 dto.setRefundTime(mallBizRefund.getRefundTime());
83 83 dto.setMethod(MallConstants.HOURLY_REFUND_CALLBACK_METHOD);
84 84 return dto;
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/vo/OrderPaymentVO.java
... ... @@ -22,7 +22,7 @@ public class OrderPaymentVO {
22 22  
23 23 /**
24 24 * 支付状态, 0:待支付,1:支付成功
25   - * @see com.diligrp.cashier.mall.type.PayState
  25 + * @see com.diligrp.cashier.pipeline.type.PaymentState
26 26 */
27 27 private Integer payStatus;
28 28  
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/vo/RefundVO.java
... ... @@ -27,7 +27,7 @@ public class RefundVO {
27 27  
28 28 /**
29 29 * 退款状态
30   - * @see com.diligrp.cashier.trade.type.TradeState
  30 + * @see com.diligrp.cashier.pipeline.type.PaymentState
31 31 */
32 32 private Integer refundStatus;
33 33  
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/model/MallBizPayment.java
... ... @@ -97,7 +97,7 @@ public class MallBizPayment extends BaseDO {
97 97  
98 98 /**
99 99 * 支付状态
100   - * @see com.diligrp.cashier.trade.type.TradeState
  100 + * @see com.diligrp.cashier.pipeline.type.PaymentState
101 101 */
102 102 private Integer payState;
103 103  
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/model/MallBizPaymentOrder.java
... ... @@ -2,8 +2,8 @@ package com.diligrp.cashier.mall.model;
2 2  
3 3 import com.diligrp.cashier.mall.domain.rtmall.vo.OrderPaymentVO;
4 4 import com.diligrp.cashier.mall.type.PayState;
  5 +import com.diligrp.cashier.pipeline.type.PaymentState;
5 6 import com.diligrp.cashier.shared.domain.BaseDO;
6   -import com.diligrp.cashier.trade.type.TradeState;
7 7  
8 8 import java.time.LocalDateTime;
9 9  
... ... @@ -49,7 +49,7 @@ public class MallBizPaymentOrder extends BaseDO {
49 49  
50 50 /**
51 51 * 支付状态
52   - * @see TradeState
  52 + * @see com.diligrp.cashier.pipeline.type.PaymentState
53 53 */
54 54 private Integer payState;
55 55  
... ... @@ -140,7 +140,6 @@ public class MallBizPaymentOrder extends BaseDO {
140 140  
141 141 /**
142 142 * ofOrderPaymentVO
143   - *
144 143 */
145 144 public OrderPaymentVO ofOrderPaymentVO() {
146 145 OrderPaymentVO orderPaymentVO = new OrderPaymentVO();
... ... @@ -151,4 +150,11 @@ public class MallBizPaymentOrder extends BaseDO {
151 150 orderPaymentVO.setTransactionId(payTradeId);
152 151 return orderPaymentVO;
153 152 }
  153 +
  154 + /**
  155 + * cancel
  156 + */
  157 + public void cancel() {
  158 + this.setPayState(PaymentState.FAILED.getCode());
  159 + }
154 160 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/model/MallBizRefund.java
... ... @@ -6,6 +6,7 @@ import com.diligrp.cashier.mall.property.RtMallDynamicProperty;
6 6 import com.diligrp.cashier.mall.type.PayState;
7 7 import com.diligrp.cashier.mall.util.MallSnowflakeKeyManager;
8 8 import com.diligrp.cashier.shared.domain.BaseDO;
  9 +import com.diligrp.cashier.shared.spi.domain.RefundResultBO;
9 10 import com.diligrp.cashier.shared.util.SpringContextUtils;
10 11 import com.diligrp.cashier.trade.type.SnowflakeKey;
11 12 import org.springframework.beans.BeanUtils;
... ... @@ -21,6 +22,16 @@ import java.util.Optional;
21 22 */
22 23 public class MallBizRefund extends BaseDO {
23 24 /**
  25 + * 结算id(mall_biz_payment.id)
  26 + */
  27 + private Long bizPaymentId;
  28 +
  29 + /**
  30 + * 订单id(mall_biz_order.id)
  31 + */
  32 + private Long bizOrderId;
  33 +
  34 + /**
24 35 * 退款单号-系统生成
25 36 */
26 37 private String refundTradeNo;
... ... @@ -103,7 +114,7 @@ public class MallBizRefund extends BaseDO {
103 114  
104 115 /**
105 116 * 退款状态
106   - * @see com.diligrp.cashier.trade.type.TradeState
  117 + * @see com.diligrp.cashier.pipeline.type.PaymentState
107 118 */
108 119 private Integer refundState;
109 120  
... ... @@ -132,6 +143,30 @@ public class MallBizRefund extends BaseDO {
132 143 */
133 144 private List<MallBizRefundItem> refundItemList;
134 145  
  146 + public MallBizRefund() {
  147 + }
  148 +
  149 + public MallBizRefund(String orderId, String tradeId) {
  150 + this.orderId = orderId;
  151 + this.tradeId = tradeId;
  152 + }
  153 +
  154 + public Long getBizPaymentId() {
  155 + return bizPaymentId;
  156 + }
  157 +
  158 + public void setBizPaymentId(Long bizPaymentId) {
  159 + this.bizPaymentId = bizPaymentId;
  160 + }
  161 +
  162 + public Long getBizOrderId() {
  163 + return bizOrderId;
  164 + }
  165 +
  166 + public void setBizOrderId(Long bizOrderId) {
  167 + this.bizOrderId = bizOrderId;
  168 + }
  169 +
135 170 public String getRefundTradeNo() {
136 171 return refundTradeNo;
137 172 }
... ... @@ -324,6 +359,8 @@ public class MallBizRefund extends BaseDO {
324 359 mallBizRefund.setFirmId(mallBizOrder.getFirmId());
325 360 mallBizRefund.setMchId(mallBizOrder.getMchId());
326 361 mallBizRefund.setRefundTradeNo(snowflakeKeyManager.nextId(SnowflakeKey.MALL_BIZ_REFUND_ID).toString());
  362 + mallBizRefund.setBizPaymentId(mallBizPaymentOrder.getBizPaymentId());
  363 + mallBizRefund.setBizOrderId(mallBizPaymentOrder.getBizOrderId());
327 364 mallBizRefund.setTradeId(mallBizPaymentOrder.getTradeId());
328 365 mallBizRefund.setPayTradeNo(mallBizPaymentOrder.getPayTradeNo());
329 366 mallBizRefund.setPayTradeId(mallBizPaymentOrder.getPayTradeId());
... ... @@ -361,4 +398,13 @@ public class MallBizRefund extends BaseDO {
361 398 refundVO.setRefuseReason(this.getRefuseReason());
362 399 return refundVO;
363 400 }
  401 +
  402 + /**
  403 + * payCallBack
  404 + */
  405 + public void payCallBack(RefundResultBO event) {
  406 + this.setRefundState(event.getState());
  407 + this.setRefundTime(event.getWhen());
  408 + this.setRefuseReason(event.getMessage());
  409 + }
364 410 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/MallBizPaymentService.java
... ... @@ -41,4 +41,8 @@ public interface MallBizPaymentService {
41 41 void handlePaymentAllocate(PaymentAllocateCO allocateCO);
42 42  
43 43 void updateByPay(MallBizPayment mallBizPayment);
  44 +
  45 + void cancel(MallBizPaymentOrder mallBizPaymentOrder);
  46 +
  47 + List<MallBizPaymentOrder> listPaymentOrderByBizOrderId(Long bizOrderId);
44 48 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/MallBizRefundService.java
... ... @@ -4,6 +4,7 @@ import com.diligrp.cashier.mall.domain.rtmall.co.RefundCO;
4 4 import com.diligrp.cashier.mall.domain.rtmall.co.RefundStatusCO;
5 5 import com.diligrp.cashier.mall.domain.rtmall.vo.RefundVO;
6 6 import com.diligrp.cashier.mall.domain.rtmall.vo.RefundSuccessVO;
  7 +import com.diligrp.cashier.mall.model.MallBizRefund;
7 8  
8 9 /**
9 10 * @ClassName MallBizRefundService.java
... ... @@ -15,4 +16,10 @@ public interface MallBizRefundService {
15 16 RefundSuccessVO refund(RefundCO refundCo);
16 17  
17 18 RefundVO info(RefundStatusCO refundStatusCo);
  19 +
  20 + MallBizRefund getByRefundTradeId(String refundId);
  21 +
  22 + int countRefund(Long bizOrderId);
  23 +
  24 + void updateByPay(MallBizRefund mallBizRefund);
18 25 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/impl/MallBizOrderItemServiceImpl.java
... ... @@ -14,6 +14,6 @@ import org.springframework.stereotype.Service;
14 14 */
15 15 @Service
16 16 public class MallBizOrderItemServiceImpl implements MallBizOrderItemService {
17   - private static final Logger log = LoggerFactory.getLogger(MallBizOrderItemServiceImpl.class);
  17 + private static final Logger LOG = LoggerFactory.getLogger(MallBizOrderItemServiceImpl.class);
18 18  
19 19 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/impl/MallBizOrderServiceImpl.java
... ... @@ -32,10 +32,8 @@ import org.springframework.stereotype.Service;
32 32 import org.springframework.transaction.annotation.Transactional;
33 33  
34 34 import java.util.List;
35   -import java.util.Map;
36 35 import java.util.Objects;
37 36 import java.util.Optional;
38   -import java.util.stream.Collectors;
39 37  
40 38 /**
41 39 * @ClassName MallBizOrderServiceImpl.java
... ... @@ -46,7 +44,7 @@ import java.util.stream.Collectors;
46 44 */
47 45 @Service
48 46 public class MallBizOrderServiceImpl implements MallBizOrderService {
49   - private static final Logger log = LoggerFactory.getLogger(MallBizOrderServiceImpl.class);
  47 + private static final Logger LOG = LoggerFactory.getLogger(MallBizOrderServiceImpl.class);
50 48  
51 49 @Resource
52 50 private RedisTemplate<String, Object> redisTemplate;
... ... @@ -135,7 +133,7 @@ public class MallBizOrderServiceImpl implements MallBizOrderService {
135 133 throw new RtMartMallException(RtMarkErrorCode.E5001);
136 134 }
137 135 AuthLoginCO authLogin = JsonUtils.fromJsonString(Objects.requireNonNull(cache).toString(), AuthLoginCO.class);
138   - log.info("get auth login info: {}", JsonUtils.toJsonString(authLogin));
  136 + LOG.info("get auth login info: {}", JsonUtils.toJsonString(authLogin));
139 137 return authLogin;
140 138 }
141 139  
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/impl/MallBizPaymentServiceImpl.java
... ... @@ -6,13 +6,10 @@ import com.diligrp.cashier.mall.dao.MallBizOrderDao;
6 6 import com.diligrp.cashier.mall.dao.MallBizOrderItemDao;
7 7 import com.diligrp.cashier.mall.dao.MallBizPaymentDao;
8 8 import com.diligrp.cashier.mall.dao.MallBizPaymentOrderDao;
9   -import com.diligrp.cashier.mall.exception.RtMartMallException;
10 9 import com.diligrp.cashier.mall.domain.rtmall.co.AuthLoginCO;
11   -import com.diligrp.cashier.mall.domain.rtmall.co.OrderInfoCO;
12 10 import com.diligrp.cashier.mall.domain.rtmall.co.OrderPaymentCO;
13 11 import com.diligrp.cashier.mall.domain.rtmall.co.PaymentAllocateCO;
14 12 import com.diligrp.cashier.mall.domain.rtmall.vo.OrderDetailResponseVO;
15   -import com.diligrp.cashier.mall.domain.rtmall.vo.OrderPaymentVO;
16 13 import com.diligrp.cashier.mall.domain.rtmall.vo.OrderSuccessVO;
17 14 import com.diligrp.cashier.mall.exception.RtMartMallException;
18 15 import com.diligrp.cashier.mall.model.MallBizOrder;
... ... @@ -22,7 +19,6 @@ import com.diligrp.cashier.mall.model.MallBizPaymentOrder;
22 19 import com.diligrp.cashier.mall.property.MallDynamicProperty;
23 20 import com.diligrp.cashier.mall.property.RtMallDynamicProperty;
24 21 import com.diligrp.cashier.mall.service.biz.MallBizPaymentService;
25   -import com.diligrp.cashier.mall.type.RtMarkErrorCode;
26 22 import com.diligrp.cashier.mall.type.OrderState;
27 23 import com.diligrp.cashier.mall.type.PayState;
28 24 import com.diligrp.cashier.mall.type.RtMarkErrorCode;
... ... @@ -33,15 +29,11 @@ import com.diligrp.cashier.trade.type.SnowflakeKey;
33 29 import jakarta.annotation.Resource;
34 30 import org.slf4j.Logger;
35 31 import org.slf4j.LoggerFactory;
36   -import org.springframework.beans.BeanUtils;
37 32 import org.springframework.dao.DuplicateKeyException;
38 33 import org.springframework.data.redis.core.RedisTemplate;
39 34 import org.springframework.stereotype.Service;
40 35 import org.springframework.transaction.annotation.Transactional;
41 36  
42   -import java.util.List;
43   -import java.util.Objects;
44   -
45 37 import java.util.ArrayList;
46 38 import java.util.List;
47 39 import java.util.Objects;
... ... @@ -55,7 +47,7 @@ import java.util.Objects;
55 47 */
56 48 @Service
57 49 public class MallBizPaymentServiceImpl implements MallBizPaymentService {
58   - private static final Logger log = LoggerFactory.getLogger(MallBizPaymentServiceImpl.class);
  50 + private static final Logger LOG = LoggerFactory.getLogger(MallBizPaymentServiceImpl.class);
59 51  
60 52 @Resource
61 53 private MallBizPaymentDao mallBizPaymentDao;
... ... @@ -122,7 +114,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
122 114 @Override
123 115 @Transactional(rollbackFor = {Exception.class})
124 116 public OrderSuccessVO createOrderPayment(OrderPaymentCO co) {
125   - log.info("开始处理扫码下单请求, order_id={}, trade_id={}, order_type={}",
  117 + LOG.info("开始处理扫码下单请求, order_id={}, trade_id={}, order_type={}",
126 118 co.getOrderId(), co.getTradeId(), co.getOrderType());
127 119  
128 120 //获取用户信息
... ... @@ -138,16 +130,16 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
138 130 try {
139 131 mallBizOrderDao.insertSelective(order);
140 132 mallBizPaymentDao.insertSelective(payment);
141   - log.info("扫码下单保存成功, order_no={}, out_trade_no={}, trade_id={}",
  133 + LOG.info("扫码下单保存成功, order_no={}, out_trade_no={}, trade_id={}",
142 134 order.getOrderNo(), payment.getPayTradeNo(), co.getTradeId());
143 135 } catch (DuplicateKeyException e) {
144 136 // 如果 order_id+trade_id 已存在,返回错误
145   - log.warn("扫码下单重复请求, trade_id={}", co.getTradeId());
  137 + LOG.warn("扫码下单重复请求, trade_id={}", co.getTradeId());
146 138 throw new RtMartMallException(RtMarkErrorCode.E4003);
147 139 }
148 140  
149 141 //返回结果
150   - log.info("扫码下单处理完成, out_trade_no={}, cashier_url={}", payment.getPayTradeNo(), payment.getCashierUrl());
  142 + LOG.info("扫码下单处理完成, out_trade_no={}, cashier_url={}", payment.getPayTradeNo(), payment.getCashierUrl());
151 143 return new OrderSuccessVO(payment.getPayTradeNo(), payment.getCashierUrl());
152 144 }
153 145  
... ... @@ -160,7 +152,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
160 152 throw new RtMartMallException(RtMarkErrorCode.E5001);
161 153 }
162 154 AuthLoginCO authLogin = JsonUtils.fromJsonString(Objects.requireNonNull(cache).toString(), AuthLoginCO.class);
163   - log.info("获取用户登录信息: userCode={}, username={}", userCode, authLogin.getUsername());
  155 + LOG.info("获取用户登录信息: userCode={}, username={}", userCode, authLogin.getUsername());
164 156 return authLogin;
165 157 }
166 158  
... ... @@ -240,13 +232,13 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
240 232 @Override
241 233 @Transactional(rollbackFor = {Exception.class})
242 234 public void handlePaymentAllocate(PaymentAllocateCO allocateCO) {
243   - log.info("收到支付分摊回调通知, trade_count={}", allocateCO.getTradeList().size());
  235 + LOG.info("收到支付分摊回调通知, trade_count={}", allocateCO.getTradeList().size());
244 236  
245 237 for (PaymentAllocateCO.TradeInfo trade : allocateCO.getTradeList()) {
246 238 handleSingleTradeAllocate(trade);
247 239 }
248 240  
249   - log.info("支付分摊回调处理完成");
  241 + LOG.info("支付分摊回调处理完成");
250 242 }
251 243  
252 244 /**
... ... @@ -254,18 +246,39 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
254 246 */
255 247 @Override
256 248 public void updateByPay(MallBizPayment mallBizPayment) {
257   - mallBizPaymentDao.updateByPrimaryKeySelective(mallBizPayment);
  249 + int num = mallBizPaymentDao.updateByPrimaryKeySelective(mallBizPayment);
  250 + if (num <= 0) {
  251 + LOG.error("更新支付记录失败: mallBizPayment={}", mallBizPayment.getId());
  252 + throw new RtMartMallException(RtMarkErrorCode.E5004);
  253 + }
258 254 mallBizPaymentOrderDao.updateByPayment(mallBizPayment);
259 255 }
260 256  
261 257 /**
  258 + * cancel
  259 + */
  260 + @Override
  261 + public void cancel(MallBizPaymentOrder mallBizPaymentOrder) {
  262 + mallBizPaymentOrder.cancel();
  263 + mallBizPaymentOrderDao.updateByPrimaryKeySelective(mallBizPaymentOrder);
  264 + }
  265 +
  266 + /**
  267 + * return List.of();
  268 + */
  269 + @Override
  270 + public List<MallBizPaymentOrder> listPaymentOrderByBizOrderId(Long bizOrderId) {
  271 + return mallBizPaymentOrderDao.listPaymentOrderByBizOrderId(bizOrderId);
  272 + }
  273 +
  274 + /**
262 275 * 处理单个支付流水的分摊通知
263 276 * 1. 调用大润发订单详情接口获取商品信息
264 277 * 2. 更新订单状态
265 278 * 3. 插入商品明细
266 279 */
267 280 private void handleSingleTradeAllocate(PaymentAllocateCO.TradeInfo trade) {
268   - log.info("处理支付分摊: order_id={}, trade_id={}, user_code={}",
  281 + LOG.info("处理支付分摊: order_id={}, trade_id={}, user_code={}",
269 282 trade.getOrderId(), trade.getTradeId(), trade.getUserCode());
270 283  
271 284 //调用大润发订单详情接口
... ... @@ -277,14 +290,14 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
277 290  
278 291 OrderDetailResponseVO.OrderDetailData orderDetail = detailResponse.getData();
279 292 if (orderDetail == null || orderDetail.getItemList() == null || orderDetail.getItemList().isEmpty()) {
280   - log.warn("订单详情中没有商品信息: order_id={}", trade.getOrderId());
  293 + LOG.warn("订单详情中没有商品信息: order_id={}", trade.getOrderId());
281 294 return;
282 295 }
283 296  
284 297 //查询订单
285 298 MallBizOrder order = mallBizOrderDao.findByOrderIdAndTradeId(trade.getOrderId(), trade.getTradeId());
286 299 if (order == null) {
287   - log.error("找不到订单: order_id={}, trade_id={}", trade.getOrderId(), trade.getTradeId());
  300 + LOG.error("找不到订单: order_id={}, trade_id={}", trade.getOrderId(), trade.getTradeId());
288 301 throw new RtMartMallException(RtMarkErrorCode.E5000);
289 302 }
290 303  
... ... @@ -297,7 +310,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
297 310 //插入商品明细
298 311 insertOrderItems(order, orderDetail.getItemList());
299 312  
300   - log.info("支付分摊处理成功: trade_id={}, item_count={}", trade.getTradeId(), orderDetail.getItemList().size());
  313 + LOG.info("支付分摊处理成功: trade_id={}, item_count={}", trade.getTradeId(), orderDetail.getItemList().size());
301 314 }
302 315  
303 316 /**
... ... @@ -307,7 +320,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
307 320 //查询支付记录
308 321 MallBizPayment payment = mallBizPaymentDao.findByOrderIdAndTradeId(orderId, tradeId);
309 322 if (payment == null) {
310   - log.error("找不到支付记录: order_id={}, trade_id={}", orderId, tradeId);
  323 + LOG.error("找不到支付记录: order_id={}, trade_id={}", orderId, tradeId);
311 324 throw new RtMartMallException(RtMarkErrorCode.E5000);
312 325 }
313 326  
... ... @@ -315,7 +328,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
315 328 if (orderDetail.getTransactionId() != null && !orderDetail.getTransactionId().equals(payment.getPayTradeId())) {
316 329 payment.setPayTradeId(orderDetail.getTransactionId());
317 330 mallBizPaymentDao.updateByPrimaryKeySelective(payment);
318   - log.info("支付记录已更新: trade_id={}, pay_payment_id={}", tradeId, orderDetail.getTransactionId());
  331 + LOG.info("支付记录已更新: trade_id={}, pay_payment_id={}", tradeId, orderDetail.getTransactionId());
319 332 }
320 333 }
321 334  
... ... @@ -327,7 +340,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
327 340 if (newState != null && !newState.equals(order.getState())) {
328 341 order.setState(newState);
329 342 mallBizOrderDao.updateByPrimaryKeySelective(order);
330   - log.info("订单状态已更新: order_id={}, old_state={}, new_state={}",
  343 + LOG.info("订单状态已更新: order_id={}, old_state={}, new_state={}",
331 344 order.getOrderId(), order.getState(), newState);
332 345 }
333 346 }
... ... @@ -394,7 +407,7 @@ public class MallBizPaymentServiceImpl implements MallBizPaymentService {
394 407 // 批量插入商品明细
395 408 if (!orderItems.isEmpty()) {
396 409 mallBizOrderItemDao.batchInsert(orderItems);
397   - log.info("商品明细插入成功: order_id={}, count={}", order.getOrderId(), orderItems.size());
  410 + LOG.info("商品明细插入成功: order_id={}, count={}", order.getOrderId(), orderItems.size());
398 411 }
399 412 }
400 413 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/impl/MallBizRefundServiceImpl.java
1 1 package com.diligrp.cashier.mall.service.biz.impl;
2 2  
3   -import com.diligrp.cashier.mall.context.MallInitializeContext;
4 3 import com.diligrp.cashier.mall.dao.MallBizOrderDao;
5 4 import com.diligrp.cashier.mall.dao.MallBizRefundDao;
  5 +import com.diligrp.cashier.mall.dao.MallBizRefundItemDao;
6 6 import com.diligrp.cashier.mall.domain.rtmall.co.RefundCO;
7 7 import com.diligrp.cashier.mall.domain.rtmall.co.RefundStatusCO;
8 8 import com.diligrp.cashier.mall.domain.rtmall.vo.RefundSuccessVO;
... ... @@ -13,15 +13,25 @@ import com.diligrp.cashier.mall.model.MallBizPaymentOrder;
13 13 import com.diligrp.cashier.mall.model.MallBizRefund;
14 14 import com.diligrp.cashier.mall.service.biz.MallBizPaymentService;
15 15 import com.diligrp.cashier.mall.service.biz.MallBizRefundService;
  16 +import com.diligrp.cashier.mall.type.OrderState;
16 17 import com.diligrp.cashier.mall.type.RtMarkErrorCode;
  18 +import com.diligrp.cashier.pipeline.type.PaymentState;
  19 +import com.diligrp.cashier.shared.spi.ICashierDeskManager;
  20 +import com.diligrp.cashier.shared.spi.IPaymentEventListener;
  21 +import com.diligrp.cashier.shared.spi.domain.CashierRefundBO;
  22 +import com.diligrp.cashier.shared.spi.domain.RefundResultBO;
  23 +import com.diligrp.cashier.shared.util.JsonUtils;
17 24 import jakarta.annotation.Resource;
  25 +import org.apache.commons.lang3.ObjectUtils;
18 26 import org.slf4j.Logger;
19 27 import org.slf4j.LoggerFactory;
20 28 import org.springframework.beans.BeanUtils;
21 29 import org.springframework.stereotype.Service;
22 30 import org.springframework.transaction.annotation.Transactional;
23 31  
  32 +import java.util.List;
24 33 import java.util.Objects;
  34 +import java.util.Optional;
25 35  
26 36 /**
27 37 * @ClassName MallBizRefundServiceImpl.java
... ... @@ -31,7 +41,7 @@ import java.util.Objects;
31 41 */
32 42 @Service
33 43 public class MallBizRefundServiceImpl implements MallBizRefundService {
34   - private static final Logger log = LoggerFactory.getLogger(MallBizRefundServiceImpl.class);
  44 + private static final Logger LOG = LoggerFactory.getLogger(MallBizRefundServiceImpl.class);
35 45  
36 46 @Resource
37 47 private MallBizOrderDao mallBizOrderDao;
... ... @@ -39,6 +49,12 @@ public class MallBizRefundServiceImpl implements MallBizRefundService {
39 49 private MallBizPaymentService mallBizPaymentService;
40 50 @Resource
41 51 private MallBizRefundDao mallBizRefundDao;
  52 + @Resource
  53 + private MallBizRefundItemDao mallBizRefundItemDao;
  54 + @Resource
  55 + protected ICashierDeskManager cashierDeskManager;
  56 + @Resource
  57 + private IPaymentEventListener payNotifyServiceImpl;
42 58  
43 59 /**
44 60 * refund
... ... @@ -47,12 +63,79 @@ public class MallBizRefundServiceImpl implements MallBizRefundService {
47 63 @Override
48 64 @Transactional(rollbackFor = {Exception.class})
49 65 public RefundSuccessVO refund(RefundCO refundCo) {
  66 + MallBizRefund mallBizRefund = mallBizRefundDao.getMallBizRefund(new MallBizRefund(refundCo.getOrderId(), refundCo.getTradeId()));
  67 + if (Objects.nonNull(mallBizRefund)) {
  68 + throw new RtMartMallException(RtMarkErrorCode.E50056);
  69 + }
  70 +
50 71 MallBizOrder mallBizOrder = mallBizOrderDao.getByOrderId(refundCo.getOrderId());
51 72 if (Objects.isNull(mallBizOrder)) {
52 73 throw new RtMartMallException(RtMarkErrorCode.E5004);
53 74 }
54   - MallBizRefund mallBizRefund = MallInitializeContext.getBySource(mallBizOrder.getSource()).refund(refundCo);
55   - return new RefundSuccessVO(mallBizRefund.getPayTradeNo(), mallBizRefund.getRefundTradeNo());
  75 +
  76 + MallBizPaymentOrder mallBizPaymentOrder = getPayment(refundCo);
  77 +
  78 + MallBizRefund refund = MallBizRefund.of(refundCo, mallBizOrder, mallBizPaymentOrder);
  79 + /*
  80 + * 售前-待支付取消 需不需要通知支付进行取消预支付信息
  81 + * 同支付一致:支付状态变更为失败,订单状态改为未支付取消
  82 + */
  83 + if (Objects.equals(mallBizPaymentOrder.getPayState(), PaymentState.PENDING.getCode())) {
  84 + LOG.info("待支付直接取消 mallBizPaymentOrder: {}", JsonUtils.toJsonString(mallBizPaymentOrder));
  85 + mallBizPaymentOrder.setPayState(PaymentState.FAILED.getCode());
  86 + mallBizPaymentService.cancel(mallBizPaymentOrder);
  87 +
  88 + // 更新订单状态
  89 + updateOrderState(mallBizOrder);
  90 + } else {
  91 + // 支付成功才能退款
  92 + if (ObjectUtils.notEqual(mallBizPaymentOrder.getPayState(), PaymentState.SUCCESS.getCode())) {
  93 + throw new RtMartMallException(RtMarkErrorCode.E5005);
  94 + }
  95 +
  96 + // 申请退款
  97 + RefundResultBO refundResultBO = doRefund(refund);
  98 +
  99 + // save refund
  100 + save(refund);
  101 +
  102 + // refund onEvent
  103 + refundManualEvent(refundResultBO);
  104 + }
  105 + return new RefundSuccessVO(refund.getPayTradeNo(), refund.getRefundTradeNo());
  106 + }
  107 +
  108 + /**
  109 + * refundManualEvent
  110 + * 退款成功需要人工处理回调
  111 + */
  112 + private void refundManualEvent(RefundResultBO refundResultBO) {
  113 + if (Objects.nonNull(refundResultBO) && ObjectUtils.notEqual(refundResultBO.getState(), PaymentState.SUCCESS.getCode())) {
  114 + payNotifyServiceImpl.onEvent(refundResultBO);
  115 + }
  116 + }
  117 +
  118 + /**
  119 + * doRefund
  120 + */
  121 + private RefundResultBO doRefund(MallBizRefund refund) {
  122 + CashierRefundBO cashierRefundBO = new CashierRefundBO(refund.getPayTradeId(), refund.getRefundFee(), null, "用户主动取消!");
  123 + RefundResultBO refundResultBO = cashierDeskManager.doRefund(cashierRefundBO);
  124 + refund.setRefundTradeId(refundResultBO.getRefundId());
  125 + return refundResultBO;
  126 + }
  127 +
  128 + /**
  129 + * save
  130 + */
  131 + private void save(MallBizRefund refund) {
  132 + mallBizRefundDao.insertSelective(refund);
  133 + // 退款商品明细
  134 + Optional.ofNullable(refund.getRefundItemList())
  135 + .ifPresent(items -> {
  136 + items.forEach(item -> item.setBizRefundId(refund.getId()));
  137 + mallBizRefundItemDao.batchInsert(items);
  138 + });
56 139 }
57 140  
58 141 /**
... ... @@ -67,10 +150,35 @@ public class MallBizRefundServiceImpl implements MallBizRefundService {
67 150 }
68 151  
69 152 /**
  153 + * getByRefundTradeId
  154 + */
  155 + @Override
  156 + public MallBizRefund getByRefundTradeId(String refundTradeId) {
  157 + MallBizRefund mallBizRefund = mallBizRefundDao.getByRefundTradeId(refundTradeId);
  158 + if (Objects.isNull(mallBizRefund)) {
  159 + throw new RtMartMallException(RtMarkErrorCode.E5004);
  160 + }
  161 + return mallBizRefund;
  162 + }
  163 +
  164 + /**
  165 + * countNoRefund
  166 + */
  167 + @Override
  168 + public int countRefund(Long bizOrderId) {
  169 + return mallBizRefundDao.countRefund(bizOrderId);
  170 + }
  171 +
  172 + @Override
  173 + public void updateByPay(MallBizRefund mallBizRefund) {
  174 + mallBizRefundDao.updateByPrimaryKeySelective(mallBizRefund);
  175 + }
  176 +
  177 + /**
70 178 * getPayment
71 179 */
72 180 private MallBizPaymentOrder getPayment(RefundCO refundCo) {
73   - MallBizPaymentOrder mallBizPaymentOrder = mallBizPaymentService.paymentOrderInfo(new MallBizPaymentOrder(refundCo.getOrderId(), null));
  181 + MallBizPaymentOrder mallBizPaymentOrder = mallBizPaymentService.paymentOrderInfo(new MallBizPaymentOrder(refundCo.getOrderId(), refundCo.getTradeId()));
74 182 if (Objects.isNull(mallBizPaymentOrder)) {
75 183 throw new RtMartMallException(RtMarkErrorCode.E5004);
76 184 }
... ... @@ -87,4 +195,21 @@ public class MallBizRefundServiceImpl implements MallBizRefundService {
87 195 }
88 196 return mallBizRefund;
89 197 }
  198 +
  199 + /**
  200 + * updateOrderState
  201 + * 待定:处理关联结算单状态
  202 + */
  203 + private void updateOrderState(MallBizOrder mallBizOrder) {
  204 + List<MallBizPaymentOrder> paymentOrderList = mallBizPaymentService.listPaymentOrderByBizOrderId(mallBizOrder.getId());
  205 + boolean cancel = paymentOrderList.stream().allMatch(vo -> Objects.equals(vo.getPayState(), PaymentState.FAILED.getCode()));
  206 + if (cancel) {
  207 + mallBizOrder.setState(OrderState.NOT_PAY_CANCEL.getCode());
  208 + int num = mallBizOrderDao.updateByPrimaryKeySelective(mallBizOrder);
  209 + if (num <= 0) {
  210 + LOG.error("更新订单状态失败: mallBizOrder={}", mallBizOrder.getId());
  211 + throw new RtMartMallException(RtMarkErrorCode.E5004);
  212 + }
  213 + }
  214 + }
90 215 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/biz/impl/PayNotifyServiceImpl.java
1 1 package com.diligrp.cashier.mall.service.biz.impl;
2 2  
3 3 import com.diligrp.cashier.mall.context.MallInitializeContext;
  4 +import com.diligrp.cashier.mall.dao.MallBizRefundDao;
4 5 import com.diligrp.cashier.mall.model.MallBizOrder;
5 6 import com.diligrp.cashier.mall.model.MallBizPayment;
  7 +import com.diligrp.cashier.mall.model.MallBizRefund;
6 8 import com.diligrp.cashier.mall.service.biz.MallBizOrderService;
7 9 import com.diligrp.cashier.mall.service.biz.MallBizPaymentService;
8 10 import com.diligrp.cashier.mall.service.biz.PayNotifyService;
  11 +import com.diligrp.cashier.pipeline.type.PaymentState;
9 12 import com.diligrp.cashier.shared.annotation.ParamLogPrint;
10 13 import com.diligrp.cashier.shared.spi.domain.PaymentResultBO;
11 14 import com.diligrp.cashier.shared.spi.domain.RefundResultBO;
12 15 import jakarta.annotation.Resource;
  16 +import org.apache.commons.lang3.ObjectUtils;
13 17 import org.slf4j.Logger;
14 18 import org.slf4j.LoggerFactory;
15 19 import org.springframework.stereotype.Component;
... ... @@ -23,12 +27,14 @@ import org.springframework.stereotype.Component;
23 27 */
24 28 @Component
25 29 public class PayNotifyServiceImpl implements PayNotifyService {
26   - private static final Logger log = LoggerFactory.getLogger(PayNotifyServiceImpl.class);
  30 + private static final Logger LOG = LoggerFactory.getLogger(PayNotifyServiceImpl.class);
27 31  
28 32 @Resource
29 33 private MallBizOrderService mallBizOrderService;
30 34 @Resource
31 35 private MallBizPaymentService mallBizPaymentService;
  36 + @Resource
  37 + private MallBizRefundDao mallBizRefundDao;
32 38  
33 39 /**
34 40 * onEvent
... ... @@ -39,6 +45,10 @@ public class PayNotifyServiceImpl implements PayNotifyService {
39 45 public void onEvent(PaymentResultBO event) {
40 46 String tradeId = event.getTradeId();
41 47 MallBizPayment mallBizPayment = mallBizPaymentService.getByPayTradeId(tradeId);
  48 + if (ObjectUtils.notEqual(mallBizPayment.getPayState(), PaymentState.PENDING.getCode())) {
  49 + LOG.info("paymentOnEvent payState not pending, paymentId: {}", mallBizPayment.getId());
  50 + return;
  51 + }
42 52  
43 53 Long bizOrderId = Long.valueOf(mallBizPayment.getBizOrderId().split(",")[0]);
44 54 MallBizOrder mallBizOrder = mallBizOrderService.getById(bizOrderId);
... ... @@ -53,6 +63,13 @@ public class PayNotifyServiceImpl implements PayNotifyService {
53 63 @Override
54 64 @ParamLogPrint(desc = "RefundResultBO")
55 65 public void onEvent(RefundResultBO event) {
  66 + MallBizRefund mallBizRefund = mallBizRefundDao.getByRefundTradeId(event.getRefundId());
  67 + if (ObjectUtils.notEqual(mallBizRefund.getRefundState(), PaymentState.PENDING.getCode())) {
  68 + LOG.info("refundOnEvent refundState not pending, refundId: {}", mallBizRefund.getId());
  69 + return;
  70 + }
56 71  
  72 + MallBizOrder mallBizOrder = mallBizOrderService.getById(mallBizRefund.getBizOrderId());
  73 + MallInitializeContext.getBySource(mallBizOrder.getSource()).refundOnEvent(event, mallBizRefund);
57 74 }
58 75 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/paychannel/AbstractPayChannel.java
... ... @@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory;
11 11 * 支付渠道抽象层
12 12 */
13 13 public abstract class AbstractPayChannel {
14   - protected final Logger log = LoggerFactory.getLogger(getClass());
  14 + protected final Logger LOG = LoggerFactory.getLogger(getClass());
15 15  
16 16 public abstract Integer getPayChannel();
17 17 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/sourcechannel/AbstractSourceChannel.java
... ... @@ -3,25 +3,21 @@ package com.diligrp.cashier.mall.service.sourcechannel;
3 3 import cn.hutool.core.util.IdUtil;
4 4 import com.diligrp.cashier.mall.MallConstants;
5 5 import com.diligrp.cashier.mall.dao.MallBizOrderDao;
6   -import com.diligrp.cashier.mall.dao.MallBizRefundDao;
7   -import com.diligrp.cashier.mall.dao.MallBizRefundItemDao;
8 6 import com.diligrp.cashier.mall.domain.rtmall.co.AuthLoginCO;
9   -import com.diligrp.cashier.mall.domain.rtmall.co.RefundCO;
10 7 import com.diligrp.cashier.mall.domain.rtmall.vo.UserInfoVO;
11   -import com.diligrp.cashier.mall.exception.RtMartMallException;
12   -import com.diligrp.cashier.mall.model.MallBizOrder;
13 8 import com.diligrp.cashier.mall.model.MallBizPayment;
14 9 import com.diligrp.cashier.mall.model.MallBizPaymentOrder;
15 10 import com.diligrp.cashier.mall.model.MallBizRefund;
16 11 import com.diligrp.cashier.mall.property.RtMallDynamicProperty;
17 12 import com.diligrp.cashier.mall.service.biz.MallBizPaymentService;
18   -import com.diligrp.cashier.mall.type.PayState;
19   -import com.diligrp.cashier.mall.type.RtMarkErrorCode;
  13 +import com.diligrp.cashier.mall.service.biz.MallBizRefundService;
  14 +import com.diligrp.cashier.mall.type.OrderState;
  15 +import com.diligrp.cashier.pipeline.type.PaymentState;
20 16 import com.diligrp.cashier.shared.spi.domain.PaymentResultBO;
  17 +import com.diligrp.cashier.shared.spi.domain.RefundResultBO;
21 18 import com.diligrp.cashier.shared.util.DateUtils;
22 19 import com.diligrp.cashier.shared.util.JsonUtils;
23 20 import jakarta.annotation.Resource;
24   -import org.apache.commons.lang3.ObjectUtils;
25 21 import org.slf4j.Logger;
26 22 import org.slf4j.LoggerFactory;
27 23 import org.springframework.data.redis.core.RedisTemplate;
... ... @@ -30,7 +26,6 @@ import org.springframework.transaction.annotation.Transactional;
30 26 import java.util.Arrays;
31 27 import java.util.List;
32 28 import java.util.Objects;
33   -import java.util.Optional;
34 29 import java.util.concurrent.TimeUnit;
35 30  
36 31 /**
... ... @@ -42,7 +37,7 @@ import java.util.concurrent.TimeUnit;
42 37 * @date 2025-12-25 11:19
43 38 */
44 39 public abstract class AbstractSourceChannel {
45   - private static final Logger log = LoggerFactory.getLogger(AbstractSourceChannel.class);
  40 + private static final Logger LOG = LoggerFactory.getLogger(AbstractSourceChannel.class);
46 41  
47 42 @Resource
48 43 protected RtMallDynamicProperty rtMallDynamicProperty;
... ... @@ -53,9 +48,7 @@ public abstract class AbstractSourceChannel {
53 48 @Resource
54 49 protected MallBizPaymentService mallBizPaymentService;
55 50 @Resource
56   - protected MallBizRefundDao mallBizRefundDao;
57   - @Resource
58   - protected MallBizRefundItemDao mallBizRefundItemDao;
  51 + protected MallBizRefundService mallBizRefundService;
59 52  
60 53 /**
61 54 * authLogin
... ... @@ -78,11 +71,10 @@ public abstract class AbstractSourceChannel {
78 71  
79 72 /**
80 73 * userInfo
81   - *
82 74 */
83 75 public UserInfoVO userInfo(AuthLoginCO authLogin) {
84 76 RtMallDynamicProperty.AppSecretDynamicProperty property = rtMallDynamicProperty.getBySourceAndType(authLogin.getSource(), authLogin.getOrderType());
85   - log.info("authUrl property: {}", JsonUtils.toJsonString(property));
  77 + LOG.info("authUrl property: {}", JsonUtils.toJsonString(property));
86 78  
87 79 UserInfoVO userInfoVO = JsonUtils.convertValue(authLogin, UserInfoVO.class);
88 80 userInfoVO.setUserCode(authLogin.getUserCode() + "_" + authLogin.getChannel());
... ... @@ -93,41 +85,15 @@ public abstract class AbstractSourceChannel {
93 85 }
94 86  
95 87 /**
96   - * refund
97   - */
98   - @Transactional(rollbackFor = {Exception.class})
99   - public MallBizRefund refund(RefundCO refundCo) {
100   - MallBizOrder mallBizOrder = mallBizOrderDao.getByOrderId(refundCo.getOrderId());
101   - MallBizPaymentOrder mallBizPaymentOrder = getPayment(refundCo);
102   -
103   - MallBizRefund refund = MallBizRefund.of(refundCo, mallBizOrder, mallBizPaymentOrder);
104   - // 售前取消 需不需要通知支付进行取消预支付信息
105   - if (ObjectUtils.notEqual(mallBizPaymentOrder.getPayState(), PayState.PENDING.code)) {
106   - refund.setRefundState(PayState.SUCCESS.code);
107   - } else {
108   - // 支付成功才能退款
109   - if (ObjectUtils.notEqual(mallBizPaymentOrder.getPayState(), PayState.SUCCESS.code)) {
110   - throw new RtMartMallException(RtMarkErrorCode.E5005);
111   - }
112   -
113   - // TODO 2025/12/30: 调用支付完善信息
114   - refund.setRefundTradeId("99999999999");
115   - }
116   -
117   - save(refund);
118   - return refund;
119   - }
120   -
121   - /**
122 88 * paymentOnEvent
123 89 * 支付成功回调
124 90 */
125 91 @Transactional(rollbackFor = {Exception.class})
126 92 public void paymentOnEvent(PaymentResultBO event, MallBizPayment mallBizPayment) {
127   - log.info("paymentOnEvent event: {} mallBizPayment: {}", JsonUtils.toJsonString(event), JsonUtils.toJsonString(mallBizPayment));
  93 + LOG.info("paymentOnEvent event: {} mallBizPayment: {}", JsonUtils.toJsonString(event), JsonUtils.toJsonString(mallBizPayment));
128 94 // update mall_biz_order
129 95 List<Long> bizOrderIds = Arrays.stream(mallBizPayment.getBizOrderId().split(",")).map(Long::valueOf).toList();
130   - mallBizOrderDao.updateByIds(bizOrderIds, PayState.SUCCESS.code);
  96 + mallBizOrderDao.updateByIds(bizOrderIds, OrderState.PAYED.code);
131 97  
132 98 // update mall_biz_payment
133 99 mallBizPayment.payCallBack(event);
... ... @@ -138,6 +104,34 @@ public abstract class AbstractSourceChannel {
138 104 }
139 105  
140 106 /**
  107 + * refundOnEvent
  108 + * 退款成功回调
  109 + * 存在一个订单多次支付,需要判断所有退款状态是否都为成功
  110 + */
  111 + @Transactional(rollbackFor = {Exception.class})
  112 + public void refundOnEvent(RefundResultBO event, MallBizRefund mallBizRefund) {
  113 + LOG.info("refundOnEvent event: {} mallBizRefund: {}", JsonUtils.toJsonString(event), JsonUtils.toJsonString(mallBizRefund));
  114 +
  115 + // check all refund state
  116 + List<MallBizPaymentOrder> paymentOrderList = mallBizPaymentService.listPaymentOrderByBizOrderId(mallBizRefund.getBizOrderId());
  117 + boolean success = paymentOrderList.stream().allMatch(vo -> Objects.equals(vo.getPayState(), PaymentState.SUCCESS.getCode()));
  118 + if (success) {
  119 + long count = mallBizRefundService.countRefund(mallBizRefund.getBizOrderId());
  120 + if (paymentOrderList.size() == count) {
  121 + LOG.info("订单全部退款完成,orderId:{}", mallBizRefund.getBizOrderId());
  122 + mallBizOrderDao.updateByIds(List.of(mallBizRefund.getBizOrderId()), OrderState.PAYED_CANCEL.code);
  123 + }
  124 + }
  125 +
  126 + // update mall_biz_refund
  127 + mallBizRefund.payCallBack(event);
  128 + mallBizRefundService.updateByPay(mallBizRefund);
  129 +
  130 + // notify other channel
  131 + refundCallBack(event, mallBizRefund);
  132 + }
  133 +
  134 + /**
141 135 * 渠道
142 136 */
143 137 public abstract Integer source();
... ... @@ -160,29 +154,5 @@ public abstract class AbstractSourceChannel {
160 154 /**
161 155 * refundCallBack
162 156 */
163   - public abstract void refundCallBack(MallBizOrder mallBizOrder, MallBizRefund mallBizRefund);
164   -
165   - /**
166   - * getPayment
167   - */
168   - private MallBizPaymentOrder getPayment(RefundCO refundCo) {
169   - MallBizPaymentOrder mallBizPaymentOrder = mallBizPaymentService.paymentOrderInfo(new MallBizPaymentOrder(refundCo.getOrderId(), null));
170   - if (Objects.isNull(mallBizPaymentOrder)) {
171   - throw new RtMartMallException(RtMarkErrorCode.E5004);
172   - }
173   - return mallBizPaymentOrder;
174   - }
175   -
176   - /**
177   - * save
178   - */
179   - private void save(MallBizRefund refund) {
180   - mallBizRefundDao.insertSelective(refund);
181   - // 退款商品明细
182   - Optional.ofNullable(refund.getRefundItemList())
183   - .ifPresent(items -> {
184   - items.forEach(item -> item.setBizRefundId(refund.getId()));
185   - mallBizRefundItemDao.batchInsert(items);
186   - });
187   - }
  157 + public abstract void refundCallBack(RefundResultBO event, MallBizRefund mallBizRefund);
188 158 }
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/sourcechannel/RtMallChannel.java
... ... @@ -12,9 +12,11 @@ import com.diligrp.cashier.mall.model.MallBizPaymentOrder;
12 12 import com.diligrp.cashier.mall.model.MallBizRefund;
13 13 import com.diligrp.cashier.mall.property.RtMallDynamicProperty;
14 14 import com.diligrp.cashier.mall.type.OrderSource;
  15 +import com.diligrp.cashier.mall.type.OrderType;
15 16 import com.diligrp.cashier.mall.util.HttpClientUtils;
16 17 import com.diligrp.cashier.mall.util.RtMallSignMd5Utils;
17 18 import com.diligrp.cashier.shared.spi.domain.PaymentResultBO;
  19 +import com.diligrp.cashier.shared.spi.domain.RefundResultBO;
18 20 import com.diligrp.cashier.shared.util.DateUtils;
19 21 import com.diligrp.cashier.shared.util.JsonUtils;
20 22 import com.diligrp.cashier.shared.util.UrlParamParserUtils;
... ... @@ -26,6 +28,7 @@ import org.springframework.stereotype.Component;
26 28  
27 29 import java.util.List;
28 30 import java.util.Map;
  31 +import java.util.Objects;
29 32  
30 33 /**
31 34 * @ClassName RtMallChannel.java
... ... @@ -37,26 +40,26 @@ import java.util.Map;
37 40 */
38 41 @Component
39 42 public class RtMallChannel extends AbstractSourceChannel {
40   - private static final Logger log = LoggerFactory.getLogger(RtMallChannel.class);
  43 + private static final Logger LOG = LoggerFactory.getLogger(RtMallChannel.class);
41 44  
42 45 @Override
43 46 public String authUrl(AuthLoginCO authLogin, String token, long timestamp) {
44 47 RtMallDynamicProperty.AppSecretDynamicProperty property = rtMallDynamicProperty.getBySourceAndType(authLogin.getSource(), authLogin.getOrderType());
45   - log.info("authUrl property: {}", JsonUtils.toJsonString(property));
  48 + LOG.info("authUrl property: {}", JsonUtils.toJsonString(property));
46 49 authLogin.setMchId(property.getMchId());
47 50  
48 51 // 替换参数
49 52 String authUrl = property.getAuthUrl();
50 53 authUrl = String.format(authUrl, token, timestamp, authLogin.getLongitude(), authLogin.getLatitude());
51   - log.info("authUrl format1: {}", authUrl);
  54 + LOG.info("authUrl format1: {}", authUrl);
52 55  
53 56 // 获取参数
54 57 Map<String, String> queryParams = UrlParamParserUtils.parseQueryParams(authUrl);
55   - log.info("authUrl queryParams: {}", JsonUtils.toJsonString(queryParams));
  58 + LOG.info("authUrl queryParams: {}", JsonUtils.toJsonString(queryParams));
56 59  
57 60 // 生成签名
58 61 String sign = RtMallSignMd5Utils.generateSign(queryParams, property.getAppSecret());
59   - log.info("authUrl sign: {}", sign);
  62 + LOG.info("authUrl sign: {}", sign);
60 63 authUrl = authUrl.concat("&sign=").concat(sign);
61 64 return authUrl;
62 65 }
... ... @@ -77,10 +80,12 @@ public class RtMallChannel extends AbstractSourceChannel {
77 80 public void payCallBack(PaymentResultBO event, MallBizPayment mallBizPayment) {
78 81 Long bizOrderId = Long.valueOf(mallBizPayment.getBizOrderId().split(",")[0]);
79 82 MallBizOrder mallBizOrder = mallBizOrderDao.selectByPrimaryKey(bizOrderId);
80   -
81   - List<MallBizPaymentOrder> mallBizPaymentOrders = mallBizPaymentService.listPaymentOrderByBizPaymentId(mallBizPayment.getId());
82   - if (CollectionUtils.isNotEmpty(mallBizPaymentOrders)) {
83   - payCallBack(mallBizOrder, mallBizPayment, mallBizPaymentOrders.get(0));
  83 + // 目前大润发只对小程序支付存在回调逻辑
  84 + if (Objects.equals(mallBizOrder.getOrderType(), OrderType.MINI_PROGRAM.code)) {
  85 + List<MallBizPaymentOrder> mallBizPaymentOrders = mallBizPaymentService.listPaymentOrderByBizPaymentId(mallBizPayment.getId());
  86 + if (CollectionUtils.isNotEmpty(mallBizPaymentOrders)) {
  87 + payCallBack(mallBizOrder, mallBizPayment, mallBizPaymentOrders.getFirst());
  88 + }
84 89 }
85 90 }
86 91  
... ... @@ -88,11 +93,11 @@ public class RtMallChannel extends AbstractSourceChannel {
88 93 * payCallBack
89 94 * @see https://shopex.yuque.com/hl0rrx/vlp0m4/nkwt5yrhdfzoy78s?singleDoc#RtKpF
90 95 * 支付回调接口
91   - *
92 96 */
93 97 public void payCallBack(final MallBizOrder mallBizOrder,
94 98 final MallBizPayment mallBizPayment,
95 99 final MallBizPaymentOrder mallBizPaymentOrder) {
  100 + LOG.info("orderType:{} payCallBack orderId: {} tradeId: {}", mallBizOrder.getOrderType(), mallBizPaymentOrder.getOrderId(), mallBizPaymentOrder.getTradeId());
96 101 RtMallDynamicProperty.AppSecretDynamicProperty property = getProperty(mallBizOrder);
97 102 HourlyPaymentCallbackDTO hourlyPaymentCallback = HourlyPaymentCallbackDTO.of(mallBizPaymentOrder, property);
98 103 hourlyPaymentCallback.setSign(sign(hourlyPaymentCallback, property));
... ... @@ -102,9 +107,21 @@ public class RtMallChannel extends AbstractSourceChannel {
102 107 }, "rt-mall");
103 108 } catch (Exception e) {
104 109 // 失败-前期未考虑重试 人工补偿重试!!
105   - log.warn("payCallBack failed: {}", JsonUtils.toJsonString(hourlyPaymentCallback), e);
  110 + LOG.warn("payCallBack failed: {}", JsonUtils.toJsonString(hourlyPaymentCallback), e);
  111 + }
  112 + LOG.info("payCallBack message: {}", JsonUtils.toJsonString(message));
  113 + }
  114 +
  115 + /**
  116 + * refundCallBack
  117 + */
  118 + @Override
  119 + public void refundCallBack(RefundResultBO event, MallBizRefund mallBizRefund) {
  120 + MallBizOrder mallBizOrder = mallBizOrderDao.selectByPrimaryKey(mallBizRefund.getBizOrderId());
  121 + // 目前大润发只对小程序支付存在回调逻辑
  122 + if (Objects.equals(mallBizOrder.getOrderType(), OrderType.MINI_PROGRAM.code)) {
  123 + refundCallBack(mallBizOrder, mallBizRefund);
106 124 }
107   - log.info("payCallBack message: {}", JsonUtils.toJsonString(message));
108 125 }
109 126  
110 127 /**
... ... @@ -112,14 +129,15 @@ public class RtMallChannel extends AbstractSourceChannel {
112 129 * @see https://shopex.yuque.com/hl0rrx/vlp0m4/nkwt5yrhdfzoy78s?singleDoc#RtKpF
113 130 * 退款回调接口
114 131 */
115   - @Override
116   - public void refundCallBack(MallBizOrder mallBizOrder, MallBizRefund mallBizRefund) {
  132 + public void refundCallBack(final MallBizOrder mallBizOrder,
  133 + final MallBizRefund mallBizRefund) {
  134 + LOG.info("orderType:{} refundCallBack orderId: {} tradeId: {}", mallBizOrder.getOrderType(), mallBizRefund.getOrderId(), mallBizRefund.getTradeId());
117 135 RtMallDynamicProperty.AppSecretDynamicProperty property = getProperty(mallBizOrder);
118 136 HourlyRefundCallbackDTO hourlyRefundCallback = HourlyRefundCallbackDTO.of(mallBizOrder, mallBizRefund, property);
119 137 hourlyRefundCallback.setSign(sign(hourlyRefundCallback, property));
120 138 RtMarkMessage<?> message = HttpClientUtils.postJson(mallBizRefund.getRefundCallback(), hourlyRefundCallback, null, new TypeReference<>() {
121 139 }, "rt-mall");
122   - log.info("refundCallBack message: {}", JsonUtils.toJsonString(message));
  140 + LOG.info("refundCallBack message: {}", JsonUtils.toJsonString(message));
123 141 }
124 142  
125 143 /**
... ... @@ -127,7 +145,7 @@ public class RtMallChannel extends AbstractSourceChannel {
127 145 */
128 146 private RtMallDynamicProperty.AppSecretDynamicProperty getProperty(MallBizOrder mallBizOrder) {
129 147 RtMallDynamicProperty.AppSecretDynamicProperty property = rtMallDynamicProperty.getBySourceAndType(mallBizOrder.getSource(), mallBizOrder.getOrderType());
130   - log.info("source {} orderType {} property: {}", mallBizOrder.getSource(), mallBizOrder.getOrderType(), JsonUtils.toJsonString(property));
  148 + LOG.info("source {} orderType {} property: {}", mallBizOrder.getSource(), mallBizOrder.getOrderType(), JsonUtils.toJsonString(property));
131 149 return property;
132 150 }
133 151  
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/type/PayState.java
1 1 package com.diligrp.cashier.mall.type;
2 2  
3 3 import com.diligrp.cashier.mall.exception.RtMartMallException;
4   -import com.diligrp.cashier.trade.type.TradeState;
  4 +import com.diligrp.cashier.pipeline.type.PaymentState;
5 5  
6 6 import java.util.Arrays;
7 7 import java.util.Objects;
... ... @@ -11,22 +11,22 @@ import java.util.Objects;
11 11 * @author dengwei
12 12 * @version 1.0.0
13 13 * @Description PayStatus
14   - * @date 2025-12-26 11:01
15 14 */
16 15 public enum PayState {
17   - PENDING(0, "待支付", TradeState.PENDING),
18   - SUCCESS(1, "成功", TradeState.SUCCESS),
19   - FAILED(2, "失败", TradeState.FAILED),
  16 + PENDING(0, "待支付", PaymentState.PENDING),
  17 + SUCCESS(1, "成功", PaymentState.SUCCESS),
  18 + FAILED(2, "失败", PaymentState.FAILED),
  19 + PROCESSING(3, "支付中", PaymentState.PROCESSING),
20 20 ;
21 21  
22 22 public final int code;
23 23 public final String description;
24   - public final TradeState tradeState;
  24 + public final PaymentState paymentState;
25 25  
26   - PayState(int code, String description, TradeState tradeState) {
  26 + PayState(int code, String description, PaymentState paymentState) {
27 27 this.code = code;
28 28 this.description = description;
29   - this.tradeState = tradeState;
  29 + this.paymentState = paymentState;
30 30 }
31 31  
32 32 public int getCode() {
... ... @@ -37,15 +37,15 @@ public enum PayState {
37 37 return description;
38 38 }
39 39  
40   - public TradeState getTradeState() {
41   - return tradeState;
  40 + public PaymentState getPaymentState() {
  41 + return paymentState;
42 42 }
43 43  
44 44 /**
45 45 * 根据支付返回code转换为三方业务系统code
46 46 */
47 47 public static Integer convertState(Integer tradeState) {
48   - return Arrays.stream(values()).filter(vo -> Objects.equals(tradeState, vo.getTradeState().getCode()))
  48 + return Arrays.stream(values()).filter(vo -> Objects.equals(tradeState, vo.getPaymentState().getCode()))
49 49 .map(PayState::getCode)
50 50 .findFirst()
51 51 .orElseThrow(() -> new RtMartMallException(RtMarkErrorCode.E5003));
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/type/RtMarkErrorCode.java
... ... @@ -20,6 +20,7 @@ public enum RtMarkErrorCode {
20 20 E5003("E5003", "回调状态不匹配"),
21 21 E5004("E5004", "数据异常"),
22 22 E5005("E5005", "支付状态异常"),
  23 + E50056("E5006", "存在相同的申请"),
23 24 ;
24 25  
25 26 public final String code;
... ...
cashier-mall/src/main/java/com/diligrp/cashier/mall/util/RtMallSignMd5Utils.java
... ... @@ -39,7 +39,7 @@ public class RtMallSignMd5Utils {
39 39 }
40 40  
41 41 /**
42   - * 递归规范化并排序,返回拼接字符串(无分隔符)
  42 + * 递归返回拼接字符串
43 43 */
44 44 @SuppressWarnings("unchecked")
45 45 private static String normalizeAndSort(Object obj) {
... ... @@ -60,8 +60,7 @@ public class RtMallSignMd5Utils {
60 60 }
61 61 // 按 key 字典序排序
62 62 List<String> sortedKeys = new ArrayList<>(filtered.keySet());
63   - Collections.sort(sortedKeys); // 字典序
64   -
  63 + Collections.sort(sortedKeys);
65 64  
66 65 StringBuilder sb = new StringBuilder();
67 66 for (String key : sortedKeys) {
... ... @@ -78,7 +77,6 @@ public class RtMallSignMd5Utils {
78 77 }
79 78 // 递归处理(会自动过滤 null、转换 boolean、排序 key)
80 79 return normalizeAndSort(indexMap);
81   - // 递归处理(会自动过滤 null、转换 boolean、排序 key)
82 80 }
83 81 case Object[] array -> {
84 82 // 处理数组类型,转换为 Map 并递归处理
... ... @@ -91,8 +89,6 @@ public class RtMallSignMd5Utils {
91 89 default -> {
92 90 }
93 91 }
94   -
95   - // 基本类型:转字符串
96 92 return obj.toString();
97 93 }
98 94  
... ...
cashier-mall/src/main/resources/com/diligrp/cashier/dao/mapper/MallBizOrderDao.xml
... ... @@ -406,6 +406,12 @@
406 406 when id = #{item.id} then total_amount + #{item.totalAmount}
407 407 </foreach>
408 408 </trim>
  409 +
  410 + <trim prefix="state = case" suffix="end,">
  411 + <foreach collection="list" item="item" index="index">
  412 + when id = #{item.id} then 0
  413 + </foreach>
  414 + </trim>
409 415 </trim>
410 416 <where>
411 417 and id in
... ...
cashier-mall/src/main/resources/com/diligrp/cashier/dao/mapper/MallBizPaymentOrderDao.xml
... ... @@ -174,6 +174,13 @@
174 174 where biz_payment_id = #{bizPaymentId}
175 175 </select>
176 176  
  177 + <select id="listPaymentOrderByBizOrderId" resultType="com.diligrp.cashier.mall.model.MallBizPaymentOrder">
  178 + select
  179 + <include refid="Base_Column_List" />
  180 + from mall_biz_payment_order
  181 + where biz_order_id = #{bizOrderId}
  182 + </select>
  183 +
177 184 <update id="updateByPayment">
178 185 update mall_biz_payment_order
179 186 set
... ...
cashier-mall/src/main/resources/com/diligrp/cashier/dao/mapper/MallBizRefundDao.xml
... ... @@ -3,6 +3,8 @@
3 3 <mapper namespace="com.diligrp.cashier.mall.dao.MallBizRefundDao">
4 4 <resultMap id="BaseResultMap" type="com.diligrp.cashier.mall.model.MallBizRefund">
5 5 <id column="id" jdbcType="BIGINT" property="id" />
  6 + <result column="biz_payment_id" jdbcType="BIGINT" property="bizPaymentId" />
  7 + <result column="biz_order_id" jdbcType="VARCHAR" property="bizOrderId" />
6 8 <result column="refund_trade_no" jdbcType="VARCHAR" property="refundTradeNo" />
7 9 <result column="pay_trade_no" jdbcType="VARCHAR" property="payTradeNo" />
8 10 <result column="refund_bn" jdbcType="VARCHAR" property="refundBn" />
... ... @@ -28,7 +30,8 @@
28 30 <result column="refuse_reason" jdbcType="VARCHAR" property="refuseReason" />
29 31 </resultMap>
30 32 <sql id="Base_Column_List">
31   - id, refund_trade_no, pay_trade_no, refund_bn, order_id, trade_id, refund_trade_id,
  33 + id, biz_payment_id, biz_order_id, refund_trade_no, pay_trade_no, refund_bn, order_id,
  34 + trade_id, refund_trade_id,
32 35 pay_trade_id, refund_card_no, refund_user_id, refund_username, refund_account_id,
33 36 refund_time, refund_fee, freight_fee, refund_state, refund_reason, refund_callback,
34 37 version, creater_name, created_time, refuse_reason
... ... @@ -68,6 +71,12 @@
68 71 <if test="id != null">
69 72 id,
70 73 </if>
  74 + <if test="bizPaymentId != null">
  75 + biz_payment_id,
  76 + </if>
  77 + <if test="bizOrderId != null">
  78 + biz_order_id,
  79 + </if>
71 80 <if test="refundTradeNo != null">
72 81 refund_trade_no,
73 82 </if>
... ... @@ -83,6 +92,12 @@
83 92 <if test="tradeId != null">
84 93 trade_id,
85 94 </if>
  95 + <if test="firmId != null">
  96 + firm_id,
  97 + </if>
  98 + <if test="mchId != null">
  99 + mch_id,
  100 + </if>
86 101 <if test="refundTradeId != null">
87 102 refund_trade_id,
88 103 </if>
... ... @@ -136,6 +151,12 @@
136 151 <if test="id != null">
137 152 #{id,jdbcType=BIGINT},
138 153 </if>
  154 + <if test="bizPaymentId != null">
  155 + #{bizPaymentId,jdbcType=BIGINT},
  156 + </if>
  157 + <if test="bizOrderId != null">
  158 + #{bizOrderId,jdbcType=VARCHAR},
  159 + </if>
139 160 <if test="refundTradeNo != null">
140 161 #{refundTradeNo,jdbcType=VARCHAR},
141 162 </if>
... ... @@ -151,6 +172,12 @@
151 172 <if test="tradeId != null">
152 173 #{tradeId,jdbcType=VARCHAR},
153 174 </if>
  175 + <if test="firmId != null">
  176 + #{firmId,jdbcType=BIGINT},
  177 + </if>
  178 + <if test="mchId != null">
  179 + #{mchId,jdbcType=VARCHAR},
  180 + </if>
154 181 <if test="refundTradeId != null">
155 182 #{refundTradeId,jdbcType=VARCHAR},
156 183 </if>
... ... @@ -255,20 +282,16 @@
255 282 <if test="refundCallback != null">
256 283 refund_callback = #{refundCallback,jdbcType=VARCHAR},
257 284 </if>
258   - <if test="version != null">
259   - version = #{version,jdbcType=INTEGER},
260   - </if>
261 285 <if test="createrName != null">
262 286 creater_name = #{createrName,jdbcType=VARCHAR},
263 287 </if>
264   - <if test="createdTime != null">
265   - created_time = #{createdTime,jdbcType=TIMESTAMP},
266   - </if>
267 288 <if test="refuseReason != null">
268 289 refuse_reason = #{refuseReason,jdbcType=VARCHAR},
269 290 </if>
  291 + version = version + 1,
270 292 </set>
271   - where id = #{id,jdbcType=BIGINT}
  293 + where id = #{id}
  294 + and version = #{version}
272 295 </update>
273 296 <update id="updateByPrimaryKey" parameterType="com.diligrp.cashier.mall.model.MallBizRefund">
274 297 update mall_biz_refund
... ... @@ -310,4 +333,16 @@
310 333 </where>
311 334 </select>
312 335  
  336 + <select id="getByRefundTradeId" resultType="com.diligrp.cashier.mall.model.MallBizRefund">
  337 + select <include refid="Base_Column_List"/>
  338 + from mall_biz_refund
  339 + where refund_trade_id = #{refundTradeId}
  340 + </select>
  341 +
  342 + <select id="countRefund" resultType="java.lang.Integer">
  343 + select count(*)
  344 + from mall_biz_refund
  345 + where biz_order_id = #{bizOrderId}
  346 + and refund_state = 4
  347 + </select>
313 348 </mapper>
... ...