From 967700806dbe285876ad2879e878af84320bb09b Mon Sep 17 00:00:00 2001
From: rk <94314517@qq.com>
Date: 星期一, 20 四月 2026 20:25:15 +0800
Subject: [PATCH] 代码生成

---
 server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java |  405 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 347 insertions(+), 58 deletions(-)

diff --git a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
index 5224b0f..5098a38 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -8,14 +8,16 @@
 import com.doumee.biz.system.OperationConfigBiz;
 import com.doumee.biz.system.SystemDictDataBiz;
 import com.doumee.config.wx.WxMiniConfig;
-import com.doumee.config.wx.WxMiniUtilService;
+import com.doumee.config.wx.WxPayProperties;
+import com.doumee.config.wx.WxPayV3Service;
+import com.wechat.pay.java.service.refund.model.Refund;
 import com.doumee.core.constants.Constants;
 import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.exception.BusinessException;
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
 import com.doumee.core.utils.DateUtil;
-import com.doumee.core.utils.Tencent.MapUtil;
+import com.doumee.core.utils.geocode.MapUtil;
 import com.doumee.core.utils.Utils;
 import com.doumee.dao.business.*;
 import com.doumee.dao.business.model.*;
@@ -30,10 +32,12 @@
 import com.doumee.dao.dto.MyOrderDTO;
 import com.doumee.dao.dto.OrderItemDTO;
 import com.doumee.dao.vo.*;
+import com.doumee.service.business.NoticeService;
 import com.doumee.service.business.OrderLogService;
 import com.doumee.service.business.OrdersService;
+import com.doumee.dao.business.model.Notice;
 import com.doumee.service.business.AreasService;
-import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
+import com.doumee.service.business.PricingRuleService;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
@@ -44,17 +48,11 @@
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
 
-import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
 
 /**
  * 瀵勫瓨璁㈠崟淇℃伅Service瀹炵幇
@@ -103,14 +101,17 @@
     @Autowired
     private RevenueMapper revenueMapper;
 
-    @Autowired
-    private WxMiniUtilService wxMiniUtilService;
+
 
     @Autowired
     private SystemUserMapper systemUserMapper;
 
     @Autowired
     private PricingRuleMapper pricingRuleMapper;
+
+    @Autowired
+    private PricingRuleService pricingRuleService;
+
     @Autowired
     private RedisTemplate<String, Object> redisTemplate;
 
@@ -122,6 +123,15 @@
 
     @Autowired
     private AreasService areasService;
+
+    @Autowired
+    private NoticeService noticeService;
+
+    @Autowired
+    private WxPayV3Service wxPayV3Service;
+
+    @Autowired
+    private WxPayProperties wxPayProperties;
 
     @Override
     public Integer create(Orders orders) {
@@ -303,9 +313,9 @@
      */
     @Override
     public PriceCalculateVO calculateLocalPrice(CalculateLocalPriceDTO dto) {
-        // 澶╂暟鏍¢獙锛屾渶灏�1澶�
-        int days = dto.getEstimatedDepositDays() != null && dto.getEstimatedDepositDays() > 0
-                ? dto.getEstimatedDepositDays() : 1;
+        // 鏍规嵁寮�濮嬪拰缁撴潫鏃堕棿璁$畻澶╂暟锛屾渶灏�1澶�
+        long diffMs = dto.getDepositEndTime().getTime() - dto.getDepositStartTime().getTime();
+        int days = (int) Math.max(1, (diffMs / (1000 * 60 * 60 * 24)) + 1);
 
         // 鏀堕泦鎵�鏈夌墿鍝佺被鍨婭D
         List<Integer> categoryIds = new ArrayList<>();
@@ -364,9 +374,9 @@
             itemPriceTotal += subtotal;
         }
 
-        // 淇濅环璐圭敤锛氭姤浠烽噾棰� 脳 淇濅环璐圭巼(瀛楀吀 INSURANCE_RATE)锛屽厓鈫掑垎
+        // 淇濅环璐圭敤锛氭姤浠烽噾棰� 脳 淇濅环璐圭巼(瀛楀吀 INSURANCE_RATE)锛屽厓鈫掑垎锛堜繚浠烽噾棰�>0鏃惰璐癸級
         long insuranceFeeFen = 0L;
-        if (Boolean.TRUE.equals(dto.getInsured()) && dto.getDeclaredAmount() != null) {
+        if (dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0) {
             BigDecimal insuranceFeeYuan = calculateInsuranceFee(dto.getDeclaredAmount());
             insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue();
         }
@@ -408,7 +418,7 @@
         // 1. 璋冪敤鑵捐鍦板浘璺濈鐭╅樀API璁$畻椹捐溅璺濈
         String from = dto.getFromLat() + "," + dto.getFromLgt();
         String to = dto.getToLat() + "," + dto.getToLgt();
-        JSONObject distanceResult = MapUtil.distanceSingle("driving", from, to);
+        JSONObject distanceResult = MapUtil.direction("driving", from, to);
         BigDecimal distance = distanceResult.getBigDecimal("distance");
         // distance 鍗曚綅涓虹背锛岃浆涓哄叕閲�
         BigDecimal distanceKm = distance.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
@@ -504,25 +514,26 @@
             itemPriceTotal += subtotal;
         }
 
-        // 4. 淇濅环璐圭敤锛氭姤浠烽噾棰� 脳 淇濅环璐圭巼(瀛楀吀 INSURANCE_RATE)锛屽厓鈫掑垎
+        // 4. 淇濅环璐圭敤锛氭姤浠烽噾棰� 脳 淇濅环璐圭巼(瀛楀吀 INSURANCE_RATE)锛屽厓鈫掑垎锛堜繚浠烽噾棰�>0鏃惰璐癸級
         long insuranceFeeFen = 0L;
-        if (Boolean.TRUE.equals(dto.getInsured()) && dto.getDeclaredAmount() != null) {
+        if (dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0) {
             BigDecimal insuranceFeeYuan = calculateInsuranceFee(dto.getDeclaredAmount());
             insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue();
         }
 
         // 5. 鍔犳�ヨ垂鐢細鐗╁搧浠锋牸 脳 鍔犳�ョ郴鏁�(瀛楀吀 URGENT_COEFFICIENT)
         long urgentFeeFen = 0L;
-        if (Boolean.TRUE.equals(dto.getUrgent())) {
-            String urgentRateStr = systemDictDataBiz.queryByCode(
-                    Constants.OPERATION_CONFIG, Constants.OP_URGENT_COEFFICIENT).getCode();
-            BigDecimal urgentRate = new BigDecimal(urgentRateStr);
-            urgentFeeFen = new BigDecimal(itemPriceTotal).multiply(urgentRate)
-                    .setScale(0, RoundingMode.HALF_UP).longValue();
-        }
+        String urgentRateStr = systemDictDataBiz.queryByCode(
+                Constants.OPERATION_CONFIG, Constants.OP_URGENT_COEFFICIENT).getCode();
+        BigDecimal urgentRate = new BigDecimal(urgentRateStr);
+        urgentFeeFen = new BigDecimal(itemPriceTotal).multiply(urgentRate)
+                .setScale(0, RoundingMode.HALF_UP).longValue();
 
-        // 6. 鎬讳环鏍� = 鐗╁搧浠锋牸 + 淇濅环璐圭敤 + 鍔犳�ヨ垂鐢�
-        long totalPrice = itemPriceTotal + insuranceFeeFen + urgentFeeFen;
+        // 6. 鎬讳环鏍� = 鐗╁搧浠锋牸 + 淇濅环璐圭敤 + 鍔犳�ヨ垂鐢紙鍔犳�ユ椂鎵嶅寘鍚姞鎬ヨ垂锛�
+        long totalPrice = itemPriceTotal + insuranceFeeFen;
+        if (Boolean.TRUE.equals(dto.getUrgent())) {
+            totalPrice += urgentFeeFen;
+        }
 
         PriceCalculateVO result = new PriceCalculateVO();
         result.setItemList(itemList);
@@ -531,6 +542,33 @@
         result.setUrgentFee(urgentFeeFen);
         result.setTotalPrice(totalPrice);
         result.setDistance(distanceKm);
+
+        // 7. 棰勮閫佽揪鏃堕暱锛歱ricing_rule type=2锛坒ieldA=1鏍囬�熻揪锛宖ieldA=2鏋侀�熻揪锛�
+        List<PricingRule> timeRules = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda()
+                .eq(PricingRule::getDeleted, Constants.ZERO)
+                .eq(PricingRule::getType, Constants.TWO)
+                .eq(PricingRule::getCityId, dto.getCityId())
+                .in(PricingRule::getFieldA, Arrays.asList("1", "2")));
+        for (PricingRule tr : timeRules) {
+            BigDecimal baseKm = new BigDecimal(tr.getFieldB());
+            int baseHours = Integer.parseInt(tr.getFieldC());
+            BigDecimal extraKm = new BigDecimal(tr.getFieldD());
+            int extraHours = Integer.parseInt(tr.getFieldE());
+            int hours;
+            if (distanceKm.compareTo(baseKm) <= 0) {
+                hours = baseHours;
+            } else {
+                BigDecimal overDistance = distanceKm.subtract(baseKm);
+                int extraCount = overDistance.divide(extraKm, 0, RoundingMode.CEILING).intValue();
+                hours = baseHours + extraCount * extraHours;
+            }
+            if ("1".equals(tr.getFieldA())) {
+                result.setStandardHours(hours);
+            } else if ("2".equals(tr.getFieldA())) {
+                result.setUrgentHours(hours);
+            }
+        }
+
         return result;
     }
 
@@ -633,6 +671,11 @@
                 takeLgt = BigDecimal.valueOf(takeShop.getLongitude());
                 takeLocationValue = takeShop.getAddress();
             } else if (dto.getTakeLat() != null && dto.getTakeLgt() != null && StringUtils.isNotBlank(dto.getTakeLocation())) {
+                // 鏃犲彇浠堕棬搴楋紝鏍¢獙瀛樹欢鐐逛笌鑷�夊彇浠剁偣鏄惁鍦ㄥ悓涓�鍩庡競
+                if (!MapUtil.isSameCity(depositShop.getLatitude(), depositShop.getLongitude(),
+                        dto.getTakeLat().doubleValue(), dto.getTakeLgt().doubleValue())) {
+                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "寮傚湴瀵勫瓨璁㈠崟瀛樺彇鐐逛笉鍦ㄥ悓涓�鍩庡競锛屽闇�璇烽�夋嫨鍚屽煄闂ㄥ簵");
+                }
                 takeLat = dto.getTakeLat();
                 takeLgt = dto.getTakeLgt();
                 takeLocationValue = dto.getTakeLocation();
@@ -647,15 +690,12 @@
         // ========== 3. 璁$畻璐圭敤 ==========
         PriceCalculateVO priceResult;
         if (Constants.ZERO.equals(dto.getType())) {
-            // 灏卞湴瀵勫瓨锛氳绠楀ぉ鏁�
-            long diffMs = takeTime.getTime() - depositTime.getTime();
-            int days = (int) Math.max(1, (diffMs / (1000 * 60 * 60 * 24)) + 1);
-
+            // 灏卞湴瀵勫瓨
             CalculateLocalPriceDTO priceDTO = new CalculateLocalPriceDTO();
             priceDTO.setCityId(dto.getCityId());
-            priceDTO.setEstimatedDepositDays(days);
+            priceDTO.setDepositStartTime(depositTime);
+            priceDTO.setDepositEndTime(takeTime);
             priceDTO.setItems(dto.getItems());
-            priceDTO.setInsured(dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0);
             priceDTO.setDeclaredAmount(dto.getDeclaredAmount());
             priceResult = calculateLocalPrice(priceDTO);
         } else {
@@ -667,7 +707,6 @@
             priceDTO.setToLat(takeLat);
             priceDTO.setToLgt(takeLgt);
             priceDTO.setItems(dto.getItems());
-            priceDTO.setInsured(dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0);
             priceDTO.setDeclaredAmount(dto.getDeclaredAmount());
             priceDTO.setUrgent(Constants.ONE.equals(dto.getIsUrgent()));
             priceResult = calculateRemotePrice(priceDTO);
@@ -736,6 +775,7 @@
 
         // 鐗╁搧淇℃伅
         orders.setGoodType(dto.getGoodType());
+        orders.setGoodLevel(goodTypeCategory.getRelationId());
         // 鎷兼帴鐗╁搧淇℃伅锛氱墿鍝佺被鍨嬪悕绉般�佸昂瀵稿悕绉�*鏁伴噺锛堟暟缁勫瓧绗︿覆锛�
         List<String> goodsParts = new ArrayList<>();
         for (ItemPriceVO itemVO : priceResult.getItemList()) {
@@ -802,7 +842,8 @@
         if (member == null || StringUtils.isBlank(member.getOpenid())) {
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鐢ㄦ埛淇℃伅寮傚父锛屾棤娉曞彂璧锋敮浠�");
         }
-        PayResponse payResponse = wxPay(orders, member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER);
+        PayResponse payResponse = wxPayV3(orders.getOutTradeNo(), orders.getTotalAmount(), orders.getId(),
+                member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER);
         payResponse.setLockKey(lockKey);
         return payResponse;
     }
@@ -837,7 +878,8 @@
         if (member == null || StringUtils.isBlank(member.getOpenid())) {
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鐢ㄦ埛淇℃伅寮傚父锛屾棤娉曞彂璧锋敮浠�");
         }
-        return wxPay(orders, member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER);
+        return wxPayV3(orders.getOutTradeNo(), orders.getTotalAmount(), orders.getId(),
+                member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER);
     }
 
     /**
@@ -872,7 +914,32 @@
         }
     }
 
+    /**
+     * 鍞よ捣寰俊鏀粯V3
+     *
+     * @param outTradeNo   鍟嗘埛璁㈠崟鍙�
+     * @param totalCents   鏀粯閲戦锛堝垎锛�
+     * @param orderId      璁㈠崟涓婚敭
+     * @param openid       鐢ㄦ埛寰俊openid
+     * @param ordersAttach 璁㈠崟鏀粯绫诲瀷
+     * @return PayResponse 鍖呭惈寰俊璋冭捣鍙傛暟鍜岃鍗曚富閿�
+     */
+    private PayResponse wxPayV3(String outTradeNo, Long totalCents, Integer orderId,
+                                String openid, Constants.OrdersAttach ordersAttach) {
+        Map<String, String> payParams = wxPayV3Service.createOrder(
+                outTradeNo,
+                ordersAttach.getName(),
+                totalCents != null ? totalCents : 0L,
+                openid,
+                wxPayProperties.getV3NotifyUrl(),
+                ordersAttach.getKey()
+        );
 
+        PayResponse payResponse = new PayResponse();
+        payResponse.setResponse(payParams);
+        payResponse.setOrderId(orderId);
+        return payResponse;
+    }
 
 
 
@@ -1206,14 +1273,17 @@
         // 瀵勪欢闂ㄥ簵鍗犳瘮锛歠ieldA=0(浼佷笟瀵�)/1(涓汉瀵�)
         int depositFieldA = Constants.equalsInteger(depositShop.getCompanyType(), Constants.ONE) ? Constants.ZERO : Constants.ONE;
         BigDecimal depositShopRata = getRevenueShareRata(cityId, depositFieldA);
-        // 鍙栦欢闂ㄥ簵鍗犳瘮锛歠ieldA=2(浼佷笟鍙�)/3(涓汉鍙�)
-        int takeFieldA = Constants.equalsInteger(takeShop.getCompanyType(), Constants.ONE) ? Constants.TWO : Constants.THREE;
-        BigDecimal takeShopRata = getRevenueShareRata(cityId, takeFieldA);
+        // 鍙栦欢闂ㄥ簵鍗犳瘮锛氭棤鍙栦欢闂ㄥ簵鏃舵瘮渚嬩负0
+        BigDecimal takeShopRata = BigDecimal.ZERO;
+        if (takeShop != null) {
+            int takeFieldA = Constants.equalsInteger(takeShop.getCompanyType(), Constants.ONE) ? Constants.TWO : Constants.THREE;
+            takeShopRata = getRevenueShareRata(cityId, takeFieldA);
+        }
 
         // 璁$畻钖叕锛堝垎锛夛細totalAmount 涓哄垎锛宺ata 涓烘瘮渚嬪�硷紙濡� 0.15 琛ㄧず 15%锛�
         long driverFee = new BigDecimal(totalAmount).multiply(driverRata).longValue();
         long depositShopFee = new BigDecimal(totalAmount).multiply(depositShopRata).longValue();
-        long takeShopFee = totalAmount - driverFee - depositShopFee;
+        long takeShopFee = new BigDecimal(totalAmount).multiply(takeShopRata).longValue();
 
         orders.setDriverFee(driverFee);
         orders.setDepositShopFee(depositShopFee);
@@ -1630,10 +1700,11 @@
             refund.setCreateTime(now);
             refund.setDeleted(Constants.ZERO);
 
-            // 璋冪敤寰俊閫�娆撅紝鍏ㄩ閫�娆�
-            String refundCode = wxMiniUtilService.wxRefund(order.getOutTradeNo(), order.getPayAmount(), order.getPayAmount());
-            refund.setRefundCode(refundCode);
-            refund.setRefundTime(new Date());
+            // 璋冪敤寰俊閫�娆綱3锛屽叏棰濋��娆�
+            Refund refundResult = wxPayV3Service.refund(order.getOutTradeNo(), order.getPayAmount(), order.getPayAmount(),
+                    "璁㈠崟閫�娆�", wxPayProperties.getV3RefundNotifyUrl());
+            refund.setRefundCode(refundResult.getOutRefundNo());
+            refund.setStatus(Constants.ZERO); // 閫�娆句腑
             ordersRefundMapper.insert(refund);
 
             order.setStatus(Constants.OrderStatus.cancelled.getStatus());
@@ -1642,6 +1713,9 @@
             ordersMapper.updateById(order);
 
             saveCancelLog(order, "浼氬憳鍙栨秷璁㈠崟锛堝緟瀵勫瓨锛屽叏棰濋��娆撅級", reason, memberId);
+            // 閫氱煡浼氬憳锛氶��娆句腑
+            sendOrderNotice(memberId, Constants.MemberOrderNotify.REFUNDING, orderId,
+                    "orderNo", order.getCode());
             return;
         }
 
@@ -1652,6 +1726,11 @@
             order.setCancelTime(now);
             ordersMapper.updateById(order);
             saveCancelLog(order, "浼氬憳鐢宠鍙栨秷璁㈠崟锛堝凡瀵勫瓨/宸叉帴鍗曪級", reason, memberId);
+            // 閫氱煡瀛樹欢闂ㄥ簵锛氶��娆剧敵璇�
+            if (order.getDepositShopId() != null) {
+                sendShopNotice(order.getDepositShopId(), Constants.ShopOrderNotify.REFUNDING, orderId,
+                        "orderNo", order.getCode());
+            }
             return;
         }
 
@@ -1692,6 +1771,52 @@
         orderLogService.create(log);
     }
 
+    /**
+     * 鍙戦�佽鍗曠珯鍐呬俊閫氱煡
+     */
+    private void sendOrderNotice(Integer memberId, Constants.MemberOrderNotify notify, Integer orderId, String... params) {
+        Notice notice = new Notice();
+        notice.setUserType(0); // 0=浼氬憳
+        notice.setUserId(memberId);
+        notice.setTitle(notify.getTitle());
+        notice.setContent(notify.format(params));
+        notice.setObjId(orderId);
+        notice.setObjType(0); // 0=璁㈠崟
+        notice.setStatus(0);  // 0=鏈
+        notice.setIsdeleted(Constants.ZERO);
+        notice.setCreateDate(new Date());
+        noticeService.create(notice);
+    }
+
+    /**
+     * 鍙戦�侀棬搴楃珯鍐呬俊閫氱煡
+     */
+    private void sendShopNotice(Integer shopId, Constants.ShopOrderNotify notify, Integer orderId, String... params) {
+        Notice notice = new Notice();
+        notice.setUserType(2); // 2=闂ㄥ簵
+        notice.setUserId(shopId);
+        notice.setTitle(notify.getTitle());
+        notice.setContent(notify.format(params));
+        notice.setObjId(orderId);
+        notice.setObjType(0); // 0=璁㈠崟
+        notice.setStatus(0);  // 0=鏈
+        notice.setIsdeleted(Constants.ZERO);
+        notice.setCreateDate(new Date());
+        noticeService.create(notice);
+    }
+
+    /**
+     * 閫氱煡瀛樹欢闂ㄥ簵鍜屽彇浠堕棬搴楋紙璁㈠崟瀹屾垚/璇勪环绛夛級
+     */
+    private void notifyBothShops(Orders order, Constants.ShopOrderNotify notify, String... params) {
+        if (order.getDepositShopId() != null) {
+            sendShopNotice(order.getDepositShopId(), notify, order.getId(), params);
+        }
+        if (order.getTakeShopId() != null) {
+            sendShopNotice(order.getTakeShopId(), notify, order.getId(), params);
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = {Exception.class, BusinessException.class})
     public void handleStorageOrderPayNotify(String outTradeNo, String wxTradeNo) {
@@ -1714,7 +1839,36 @@
         order.setUpdateTime(now);
         // 鐢熸垚浼氬憳鏍搁攢鐮�
         order.setMemberVerifyCode(generateVerifyCode());
+        // 寮傚湴瀵勫瓨锛氳绠楅璁¢�佽揪鏃堕棿
+        if (Constants.ONE.equals(order.getType())
+                && order.getDepositLat() != null && order.getDepositLgt() != null
+                && order.getTakeLat() != null && order.getTakeLgt() != null) {
+            EstimatedDeliveryResultVO deliveryResult = calculateEstimatedDelivery(
+                    Integer.valueOf(order.getCityId()),
+                    order.getDepositLat().doubleValue(), order.getDepositLgt().doubleValue(),
+                    order.getTakeLat().doubleValue(), order.getTakeLgt().doubleValue());
+            // isUrgent: 0=鏍囬�熻揪; 1=鏋侀�熻揪
+            BigDecimal hours = Constants.ONE.equals(order.getIsUrgent())
+                    ? deliveryResult.getExpressHours()
+                    : deliveryResult.getStandardHours();
+            if (hours != null) {
+                long millis = hours.multiply(new BigDecimal("3600000"))
+                        .setScale(0, RoundingMode.HALF_UP).longValue();
+                order.setEstimatedDeliveryTime(new Date(now.getTime() + millis));
+            }
+        }
         ordersMapper.updateById(order);
+
+        // 閫氱煡浼氬憳锛氳鍗曞緟鏍搁獙
+        sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_VERIFY, order.getId(),
+                "orderNo", order.getCode(),
+                "storeCode", order.getMemberVerifyCode());
+
+        // 灏卞湴瀵勫瓨璁㈠崟锛氶�氱煡瀛樹欢闂ㄥ簵寰呮牳楠�
+        if (Constants.ZERO.equals(order.getType()) && order.getDepositShopId() != null) {
+            sendShopNotice(order.getDepositShopId(), Constants.ShopOrderNotify.WAIT_VERIFY, order.getId(),
+                    "orderNo", order.getCode());
+        }
     }
 
     @Override
@@ -1758,8 +1912,9 @@
         otherOrders.setCreateTime(now);
         otherOrdersMapper.insert(otherOrders);
 
-        // 5. 鍞よ捣寰俊鏀粯
-        return wxPayForOtherOrder(otherOrders, member.getOpenid(), Constants.OrdersAttach.OVERDUE_FEE);
+        // 5. 鍞よ捣寰俊鏀粯V3
+        return wxPayV3(otherOrders.getOutTradeNo(), otherOrders.getPayAccount(), otherOrders.getId(),
+                member.getOpenid(), Constants.OrdersAttach.OVERDUE_FEE);
     }
 
     @Override
@@ -1826,9 +1981,10 @@
 
     @Override
     @Transactional(rollbackFor = {Exception.class, BusinessException.class})
-    public PayResponse payShopDeposit(Integer shopId) {
+    public PayResponse payShopDeposit(Integer memberId) {
         // 1. 鏌ヨ闂ㄥ簵淇℃伅
-        ShopInfo shopInfo = shopInfoMapper.selectById(shopId);
+        ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
+                .eq(ShopInfo::getRegionMemberId,memberId));
         if (shopInfo == null) {
             throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "闂ㄥ簵涓嶅瓨鍦�");
         }
@@ -1852,14 +2008,15 @@
         otherOrders.setMemberId(shopInfo.getRegionMemberId());
         otherOrders.setPayAccount(shopInfo.getDepositAmount());
         otherOrders.setPayStatus(Constants.ZERO);
-        otherOrders.setCode("SD" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now) + shopId);
+        otherOrders.setCode("SD" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now) + shopInfo.getId());
         otherOrders.setOutTradeNo(outTradeNo);
         otherOrders.setDeleted(Constants.ZERO);
         otherOrders.setCreateTime(now);
         otherOrdersMapper.insert(otherOrders);
 
-        // 5. 鍞よ捣寰俊鏀粯
-        return wxPayForOtherOrder(otherOrders, member.getOpenid(), Constants.OrdersAttach.SHOP_DEPOSIT);
+        // 5. 鍞よ捣寰俊鏀粯V3
+        return wxPayV3(otherOrders.getOutTradeNo(), otherOrders.getPayAccount(), otherOrders.getId(),
+                member.getOpenid(), Constants.OrdersAttach.SHOP_DEPOSIT);
     }
 
     @Override
@@ -1996,6 +2153,12 @@
                     }
                 }
             }
+
+            // 閫氱煡鐩稿叧闂ㄥ簵锛氳鍗曞凡缁撶畻
+            notifyBothShops(order, Constants.ShopOrderNotify.SETTLED,
+                    "orderNo", order.getCode(),
+                    "amount", String.valueOf(Constants.getFormatMoney(
+                            order.getTotalAmount() != null ? order.getTotalAmount() : 0L)));
         }
     }
 
@@ -2092,6 +2255,14 @@
         if (isRemote && order.getAcceptDriver() != null) {
             updateTargetScore(Constants.THREE, order.getAcceptDriver());
         }
+
+        // 閫氱煡浼氬憳锛氳鍗曞凡璇勪环
+        sendOrderNotice(memberId, Constants.MemberOrderNotify.EVALUATED, order.getId(),
+                "orderNo", order.getCode());
+
+        // 閫氱煡瀛樹欢闂ㄥ簵鍜屽彇浠堕棬搴楋細璁㈠崟宸茶瘎浠�
+        notifyBothShops(order, Constants.ShopOrderNotify.EVALUATED,
+                "orderNo", order.getCode());
     }
 
     /**
@@ -2194,6 +2365,16 @@
             saveVerifyImages(order.getId(), images, Constants.FileType.ORDER_DEPOSIT.getKey(), shopId);
             // 璁板綍璁㈠崟鏃ュ織
             saveShopVerifyLog(order, "闂ㄥ簵纭瀵勫瓨", "闂ㄥ簵銆�" + shopName + "銆戠‘璁ゅ瘎瀛�", remark, shopId);
+            // 閫氱煡浼氬憳锛氶棬搴楁牳閿�鎴愬姛
+            if (Constants.equalsInteger(order.getType(), Constants.ONE)) {
+                // 寮傚湴瀵勫瓨 鈫� 寰呮姠鍗�
+                sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_GRAB, order.getId(),
+                        "orderNo", order.getCode());
+            } else {
+                // 灏卞湴瀵勫瓨 鈫� 寰呭彇浠舵彁閱�
+                sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_REMIND, order.getId(),
+                        "orderNo", order.getCode());
+            }
         } else if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) {
             // 寮傚湴瀵勫瓨 + 鏃犲彇浠堕棬搴� 鈫� 鏃犳硶鏍搁攢锛堝鎴疯嚜鍙栵紝鏃犻棬搴楁搷浣滐級
             if (Constants.equalsInteger(order.getType(), Constants.ONE) && order.getTakeShopId() == null) {
@@ -2216,6 +2397,14 @@
             generateRevenueRecords(order.getId());
             // 璁板綍璁㈠崟鏃ュ織
             saveShopVerifyLog(order, "闂ㄥ簵纭鍙栦欢", "闂ㄥ簵銆�" + shopName + "銆戠‘璁ゅ彇浠讹紝璁㈠崟瀹屾垚", remark, shopId);
+            // 閫氱煡浼氬憳锛氳鍗曞凡瀹屾垚
+            sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.FINISHED, order.getId(),
+                    "orderNo", order.getCode());
+            // 閫氱煡瀛樹欢闂ㄥ簵鍜屽彇浠堕棬搴楋細璁㈠崟宸插畬鎴�
+            String settleDays = operationConfigBiz.getConfig().getSettlementDate();
+            notifyBothShops(order, Constants.ShopOrderNotify.FINISHED,
+                    "orderNo", order.getCode(),
+                    "settleDays", settleDays != null ? settleDays : "7");
         } else {
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽鏍搁攢");
         }
@@ -2292,13 +2481,14 @@
             refundRecord.setDeleted(Constants.ZERO);
             ordersRefundMapper.insert(refundRecord);
 
-            // 璋冪敤寰俊閫�娆撅紙鏀惧湪鏈�鍚庯紝纭繚鍓嶇疆鎿嶄綔鍏ㄩ儴鎴愬姛锛�
-            String refundCode = wxMiniUtilService.wxRefund(
-                    order.getOutTradeNo(), order.getPayAmount(), order.getRefundAmount());
+            // 璋冪敤寰俊閫�娆綱3锛堟斁鍦ㄦ渶鍚庯紝纭繚鍓嶇疆鎿嶄綔鍏ㄩ儴鎴愬姛锛�
+            Refund refundResult = wxPayV3Service.refund(
+                    order.getOutTradeNo(), order.getPayAmount(), order.getRefundAmount(),
+                    "璁㈠崟閫�娆�", wxPayProperties.getV3RefundNotifyUrl());
 
-            // 閫�娆炬垚鍔熷悗鍥炲~閫�娆惧崟鍙峰拰鏃堕棿
-            refundRecord.setRefundCode(refundCode);
-            refundRecord.setRefundTime(new Date());
+            // 閫�娆炬垚鍔熷悗鍥炲~閫�娆惧崟鍙凤紝鏍囪閫�娆句腑
+            refundRecord.setRefundCode(refundResult.getOutRefundNo());
+            refundRecord.setStatus(Constants.ZERO); // 閫�娆句腑
             ordersRefundMapper.updateById(refundRecord);
         }
 
@@ -2312,6 +2502,60 @@
             logInfo += "锛岄��娆�" + Constants.getFormatMoney(order.getRefundAmount()) + "鍏�";
         }
         saveShopVerifyLog(order, "闂ㄥ簵纭鍑哄簱", logInfo, remark, shopId);
+        // 閫氱煡浼氬憳锛氳鍗曞凡瀹屾垚
+        sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.FINISHED, order.getId(),
+                "orderNo", order.getCode());
+        // 閫氱煡瀛樹欢闂ㄥ簵鍜屽彇浠堕棬搴楋細璁㈠崟宸插畬鎴�
+        String settleDays = operationConfigBiz.getConfig().getSettlementDate();
+        notifyBothShops(order, Constants.ShopOrderNotify.FINISHED,
+                "orderNo", order.getCode(),
+                "settleDays", settleDays != null ? settleDays : "7");
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void memberConfirmReceipt(Integer orderId, Integer memberId) {
+        // 1. 鏌ヨ璁㈠崟
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+        // 2. 鏍¢獙褰掑睘
+        if (!memberId.equals(order.getMemberId())) {
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鏃犳潈鎿嶄綔璇ヨ鍗�");
+        }
+        // 3. 鏍¢獙璁㈠崟绫诲瀷锛氬紓鍦板瘎瀛�
+        if (!Constants.ONE.equals(order.getType())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "浠呭紓鍦板瘎瀛樿鍗曞彲鎿嶄綔");
+        }
+        // 4. 鏍¢獙鏃犲彇浠堕棬搴�
+        if (order.getTakeShopId() != null) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇ヨ鍗曟湁鍙栦欢闂ㄥ簵锛岄渶闂ㄥ簵纭鍑哄簱");
+        }
+        // 5. 鏍¢獙鐘舵�侊細宸查�佽揪(5)
+        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽纭鏀惰揣");
+        }
+
+        // 6. 鏇存柊璁㈠崟鐘舵�佷负宸插畬鎴�
+        Date now = new Date();
+        order.setStatus(Constants.OrderStatus.finished.getStatus());
+        order.setFinishTime(now);
+        order.setUpdateTime(now);
+        ordersMapper.updateById(order);
+
+        // 7. 鐢熸垚鏀剁泭璁板綍
+        calculateAndSaveOrderFees(orderId);
+        generateRevenueRecords(orderId);
+
+        // 閫氱煡浼氬憳锛氳鍗曞凡瀹屾垚
+        sendOrderNotice(memberId, Constants.MemberOrderNotify.FINISHED, orderId,
+                "orderNo", order.getCode());
+        // 閫氱煡瀛樹欢闂ㄥ簵鍜屽彇浠堕棬搴楋細璁㈠崟宸插畬鎴�
+        String settleDays = operationConfigBiz.getConfig().getSettlementDate();
+        notifyBothShops(order, Constants.ShopOrderNotify.FINISHED,
+                "orderNo", order.getCode(),
+                "settleDays", settleDays != null ? settleDays : "7");
     }
 
     @Override
@@ -2463,6 +2707,26 @@
 
         // 淇濆瓨闄勪欢锛坥bj_type=3 闂ㄥ簵鍏ュ簱鍥剧墖锛屾渶澶�3寮狅級
         saveVerifyImages(order.getId(), images, Constants.FileType.ORDER_TAKE.getKey(), driverId);
+
+        // 閫氱煡浼氬憳锛氳鍗曞凡閫佽揪
+        String destination = order.getTakeShopAddress() != null ? order.getTakeShopAddress() : "";
+        if (order.getMemberVerifyCode() != null) {
+            sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.ARRIVED_HAS_SHOP, order.getId(),
+                    "orderNo", order.getCode(),
+                    "destination", destination,
+                    "pickupCode", order.getMemberVerifyCode());
+        } else {
+            sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.ARRIVED_NO_SHOP, order.getId(),
+                    "orderNo", order.getCode(),
+                    "destination", destination);
+        }
+
+        // 閫氱煡鍙栦欢闂ㄥ簵锛氳鍗曞凡閫佽揪
+        if (order.getTakeShopId() != null) {
+            sendShopNotice(order.getTakeShopId(), Constants.ShopOrderNotify.ARRIVED, order.getId(),
+                    "orderNo", order.getCode(),
+                    "destination", destination);
+        }
     }
 
     /**
@@ -2857,4 +3121,29 @@
         return Math.max(days, 0);
     }
 
+    @Override
+    public EstimatedDeliveryResultVO calculateEstimatedDelivery(Integer cityId,
+                                                                Double fromLat, Double fromLng,
+                                                                Double toLat, Double toLng) {
+        // 鑵捐鍦板浘璺濈鐭╅樀API璁$畻瀹為檯璺濈
+        String from = fromLat + "," + fromLng;
+        String to = toLat + "," + toLng;
+        JSONObject distanceResult = MapUtil.direction("driving", from, to);
+
+        // 鑾峰彇璺濈锛堢背锛夛紝杞叕閲�
+        int distanceMeters = distanceResult.getIntValue("distance");
+        BigDecimal distanceKm = new BigDecimal(distanceMeters)
+                .divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
+
+        // 鏍规嵁pricing_rule type=2 璁$畻 鏍囬�熻揪(1) 鍜� 鏋侀�熻揪(2) 鏃舵晥
+        BigDecimal standardTime = pricingRuleService.calculateEstimatedTime(cityId, 1, distanceKm);
+        BigDecimal expressTime = pricingRuleService.calculateEstimatedTime(cityId, 2, distanceKm);
+
+        EstimatedDeliveryResultVO vo = new EstimatedDeliveryResultVO();
+        vo.setDistanceKm(distanceKm);
+        vo.setStandardHours(standardTime);
+        vo.setExpressHours(expressTime);
+        return vo;
+    }
+
 }

--
Gitblit v1.9.3