add
yj
2024-12-05 b9900893177c78fc559223521fe839aa21000017
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
package com.iotechn.unimall.biz.pay;
 
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dobbinsoft.fw.core.exception.AppServiceException;
import com.dobbinsoft.fw.core.exception.ServiceException;
import com.dobbinsoft.fw.pay.enums.PayChannelType;
import com.dobbinsoft.fw.pay.exception.PayServiceException;
import com.dobbinsoft.fw.pay.handler.MatrixPayCallbackHandler;
import com.dobbinsoft.fw.pay.model.notify.MatrixPayNotifyResponse;
import com.dobbinsoft.fw.pay.model.notify.MatrixPayOrderNotifyResult;
import com.dobbinsoft.fw.support.mq.DelayedMessageQueue;
import com.iotechn.unimall.biz.client.erp.ErpClient;
import com.iotechn.unimall.biz.executor.GlobalExecutor;
import com.iotechn.unimall.biz.service.groupshop.GroupShopBizService;
import com.iotechn.unimall.biz.service.notify.AdminNotifyBizService;
import com.iotechn.unimall.biz.service.order.OrderBizService;
import com.iotechn.unimall.biz.service.product.ProductBizService;
import com.iotechn.unimall.data.domain.OrderDO;
import com.iotechn.unimall.data.domain.OrderSkuDO;
import com.iotechn.unimall.data.dto.order.OrderDTO;
import com.iotechn.unimall.data.enums.DMQHandlerType;
import com.iotechn.unimall.data.enums.OrderStatusType;
import com.iotechn.unimall.data.enums.SpuActivityType;
import com.iotechn.unimall.data.exception.ExceptionDefinition;
import com.iotechn.unimall.data.mapper.OrderMapper;
import com.iotechn.unimall.data.mapper.OrderSkuMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
 
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
 
public class OrderPayCallbackHandler implements MatrixPayCallbackHandler {
 
    private static final Logger logger = LoggerFactory.getLogger(OrderPayCallbackHandler.class);
 
    @Autowired
    private OrderBizService orderBizService;
 
    @Autowired
    private OrderSkuMapper orderSkuMapper;
 
    @Autowired
    private OrderMapper orderMapper;
 
    @Autowired
    private ErpClient erpClient;
 
    @Autowired
    private ProductBizService productBizService;
 
    @Autowired
    private GroupShopBizService groupShopBizService;
 
    @Autowired
    private DelayedMessageQueue delayedMessageQueue;
 
    @Autowired
    private AdminNotifyBizService adminNotifyBizService;
 
    @Override
    public void beforeCheckSign(HttpServletRequest httpServletRequest) {
 
    }
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object handle(MatrixPayOrderNotifyResult result, HttpServletRequest request) {
        try {
            logger.info("处理{}支付平台的订单支付", result.getPayChannel().getMsg());
            logger.info(JSONObject.toJSONString(result));
            /* 之前传过去的我们系统的订单ID */
            // 现在是不知道是父订单还是普通订单
            String orderAbstractNo = result.getOutTradeNo();
            boolean isParent = !orderAbstractNo.contains("S");
            String payId = result.getTransactionId();
 
            List<OrderDO> orderDOList;
            if (isParent) {
                orderDOList = orderMapper.selectList(
                        new QueryWrapper<OrderDO>()
                                .eq("parent_order_no", orderAbstractNo));
            } else {
                orderDOList = orderMapper.selectList(
                        new QueryWrapper<OrderDO>()
                                .eq("order_no", orderAbstractNo));
            }
 
            if (CollectionUtils.isEmpty(orderDOList)) {
                return MatrixPayNotifyResponse.fail("订单不存在 orderNo=" + orderAbstractNo);
            }
 
            int status = orderDOList.get(0).getStatus().intValue();
            int actualPrice = 0;
 
            for (OrderDO orderDO : orderDOList) {
                actualPrice += orderDO.getActualPrice();
                if (orderDO.getStatus().intValue() != status) {
                    return MatrixPayNotifyResponse.fail("订单子单状态不一致");
                }
            }
 
            if (status != OrderStatusType.UNPAY.getCode()) {
                return MatrixPayNotifyResponse.success("订单已经处理过了");
            }
 
            Integer totalFee = result.getTotalFee();
 
            // 检查支付订单金额
            if (!totalFee.equals(actualPrice)) {
                return MatrixPayNotifyResponse.fail(orderAbstractNo + " : 支付金额不符合 totalFee=" + totalFee);
            }
 
            /**************** 在此之前都没有 数据库修改 操作 所以前面是直接返回错误的 **********************/
 
            //1. 更新订单状态
            Date now = new Date();
            OrderDO updateOrderDO = new OrderDO();
            updateOrderDO.setPayId(payId);
            updateOrderDO.setPayChannel(result.getPayChannel().getCode());
            updateOrderDO.setPayPrice(result.getTotalFee());
            updateOrderDO.setGmtPay(now);
            updateOrderDO.setGmtUpdate(now);
            updateOrderDO.setStatus(OrderStatusType.WAIT_STOCK.getCode());
            updateOrderDO.setAppId(result.getAppid());
            List<OrderSkuDO> orderSkuDOList;
 
            if (isParent) {
                // 父单支付
                updateOrderDO.setSubPay(0);
                List<String> orderNos = orderDOList.stream().map(item -> item.getOrderNo()).collect(Collectors.toList());
                orderSkuDOList = orderSkuMapper.selectList(
                        new QueryWrapper<OrderSkuDO>()
                                .in("order_no", orderNos));
                if (orderSkuDOList.stream().filter(item -> (item.getActivityType() != null && item.getActivityType() == SpuActivityType.GROUP_SHOP.getCode())).count() > 0) {
                    // 走团购商品逻辑 更新状态只能按单独子单更新
                    List<OrderDO> subOrderList = orderBizService.checkOrderExistByParentNo(orderAbstractNo, null);
                    // 将orderSkuList转换为以子单为Key的Map
                    Map<String, List<OrderSkuDO>> orderSkuMap = orderSkuDOList.stream().collect(Collectors.groupingBy(OrderSkuDO::getOrderNo));
                    // 各个认领自己的skuList
                    for (OrderDO subOrder : subOrderList) {
                        List<OrderSkuDO> subOrderSkuList = orderSkuMap.get(subOrder.getOrderNo());
                        List<OrderSkuDO> groupShopSkuList = subOrderSkuList.stream().filter(item -> (item.getActivityType() != null && item.getActivityType() == SpuActivityType.GROUP_SHOP.getCode())).collect(Collectors.toList());
                        if (groupShopSkuList.size() > 0) {
                            // 若存在团购商品
                            OrderDO groupShopUpdateDO = new OrderDO();
                            groupShopUpdateDO.setPayId(payId);
                            groupShopUpdateDO.setPayChannel(PayChannelType.WX.getCode());
                            groupShopUpdateDO.setPayPrice(result.getTotalFee());
                            groupShopUpdateDO.setGmtPay(now);
                            groupShopUpdateDO.setGmtUpdate(now);
                            groupShopUpdateDO.setStatus(OrderStatusType.GROUP_SHOP_WAIT.getCode());
                            groupShopUpdateDO.setSubPay(1);
                            // 增加buyer count
                            for (OrderSkuDO orderSkuDO : groupShopSkuList) {
                                groupShopBizService.incGroupShopNum(orderSkuDO.getActivityId(), orderSkuDO.getNum());
                            }
                            orderBizService.changeOrderSubStatus(subOrder.getOrderNo(), OrderStatusType.UNPAY.getCode(), groupShopUpdateDO);
                        } else {
                            erpClient.takeSalesHeader(subOrder.getOrderNo());
                            orderBizService.changeOrderSubStatus(subOrder.getOrderNo(), OrderStatusType.UNPAY.getCode(), updateOrderDO);
                        }
                    }
                } else {
                    // 因为现在只有团购需要分单,所以这种情况并不会发生
                    // 走普通商品 并且更新状态 可以打包更新
                    orderBizService.changeOrderParentStatus(orderAbstractNo, OrderStatusType.UNPAY.getCode(), updateOrderDO, orderDOList.size());
                }
            } else {
                // 子单支付
                updateOrderDO.setSubPay(1);
                orderSkuDOList = orderSkuMapper.selectList(
                        new QueryWrapper<OrderSkuDO>()
                                .eq("order_no", orderAbstractNo));
                List<OrderSkuDO> groupShopSkuList = orderSkuDOList.stream().filter(item -> (item.getActivityType() != null && item.getActivityType() == SpuActivityType.GROUP_SHOP.getCode())).collect(Collectors.toList());
                if (groupShopSkuList.size() > 0) {
                    // 若存在团购商品
                    OrderDO groupShopUpdateDO = new OrderDO();
                    groupShopUpdateDO.setPayId(payId);
                    groupShopUpdateDO.setPayChannel(PayChannelType.WX.getCode());
                    groupShopUpdateDO.setPayPrice(result.getTotalFee());
                    groupShopUpdateDO.setGmtPay(now);
                    groupShopUpdateDO.setGmtUpdate(now);
                    groupShopUpdateDO.setStatus(OrderStatusType.GROUP_SHOP_WAIT.getCode());
                    groupShopUpdateDO.setSubPay(1);
                    // 增加buyer count
                    for (OrderSkuDO orderSkuDO : groupShopSkuList) {
                        groupShopBizService.incGroupShopNum(orderSkuDO.getActivityId(), orderSkuDO.getNum());
                    }
                    orderBizService.changeOrderSubStatus(orderAbstractNo, OrderStatusType.UNPAY.getCode(), groupShopUpdateDO);
                } else {
                    erpClient.takeSalesHeader(orderDOList.get(0).getOrderNo());
                    orderBizService.changeOrderSubStatus(orderAbstractNo, OrderStatusType.UNPAY.getCode(), updateOrderDO);
                }
            }
 
            //2. 增加商品销量
            // 可能存在两个相同的Spu,不同的Sku的情况
            Map<Long, Integer> salesMap = orderSkuDOList.stream().collect(Collectors.toMap(OrderSkuDO::getSpuId, OrderSkuDO::getNum, (k1, k2) -> k1.intValue() + k2.intValue()));
            productBizService.incSpuSales(salesMap);
 
 
            //3. 通知管理员发货 & 删除延迟消息队列取消订单消息
            Map<String, List<OrderSkuDO>> orderSkuMap = orderSkuDOList.stream().collect(Collectors.groupingBy(OrderSkuDO::getOrderNo));
            Map<String, List<OrderDO>> orderMap = orderDOList.stream().collect(Collectors.groupingBy(OrderDO::getOrderNo));
            for (String subOrderNo : orderSkuMap.keySet()) {
                OrderDTO finalOrderDTO = new OrderDTO();
                OrderDO orderDO = orderMap.get(subOrderNo).get(0);
                BeanUtils.copyProperties(orderDO, finalOrderDTO);
                finalOrderDTO.setPayChannel(PayChannelType.WX.getCode());
                finalOrderDTO.setSkuList(orderSkuMap.get(subOrderNo));
                GlobalExecutor.execute(() -> {
                    adminNotifyBizService.newOrder(finalOrderDTO);
                });
                delayedMessageQueue.deleteTask(DMQHandlerType.ORDER_AUTO_CANCEL.getCode(), subOrderNo);
                logger.info("[订单微信支付成功] orderNo:" + subOrderNo);
            }
            return MatrixPayNotifyResponse.success("支付成功");
        } catch (ServiceException e) {
            throw new PayServiceException(e.getMessage());
        }
    }
}