From 1c930a8b1ab9abdb851a486b2da55bcda34cd082 Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期二, 21 四月 2026 09:20:42 +0800
Subject: [PATCH] Merge branch 'master' of http://139.186.142.91:10010/r/productDev/gtzxinglijicun

---
 server/services/src/main/java/com/doumee/service/business/DriverInfoService.java                |   17 
 server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java                       |    3 
 server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java       |  203 +++++
 server/web/src/main/java/com/doumee/api/web/PaymentCallback.java                                |  169 ++++
 server/services/src/main/java/com/doumee/service/business/NoticeService.java                    |   37 +
 server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java                          |  186 +++++
 server/services/src/main/java/com/doumee/service/business/impl/NoticeServiceImpl.java           |  126 +++
 server/services/src/main/java/com/doumee/dao/dto/DriverPickupDTO.java                           |   28 
 server/services/src/main/java/com/doumee/config/alipay/AlipayProperties.java                    |   41 +
 server/web/src/main/java/com/doumee/api/web/ConfigApi.java                                      |    2 
 server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java                   |   12 
 server/services/src/main/java/com/doumee/dao/dto/AlipayTransferDTO.java                         |   39 +
 server/services/src/main/resources/application-test.yml                                         |    7 
 server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java                         |   16 
 server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java                     |    6 
 server/services/src/main/java/com/doumee/core/constants/Constants.java                          |  168 ++--
 server/services/src/main/java/com/doumee/core/utils/geocode/MapUtil.java                        |  168 ++++
 server/services/src/main/java/com/doumee/service/business/OrdersService.java                    |    4 
 server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java |   94 ++
 server/services/src/main/java/com/doumee/dao/business/NoticeMapper.java                         |   12 
 server/services/src/main/java/com/doumee/core/utils/tencent/MapUtil.java                        |    4 
 server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java                            |   52 +
 server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java         |   15 
 server/services/src/main/resources/application-dev.yml                                          |   13 
 server/services/src/main/java/com/doumee/dao/business/model/OrdersRefund.java                   |    3 
 server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java                                    |    4 
 server/services/src/main/java/com/doumee/dao/business/model/Notice.java                         |   68 +
 server/services/src/main/java/com/doumee/dao/vo/ShopDetailVO.java                               |    9 
 server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java                                  |   26 
 /dev/null                                                                                       |   50 -
 server/services/src/main/java/com/doumee/dao/vo/PlatformAboutVO.java                            |    2 
 server/services/src/main/java/com/doumee/dao/dto/DriverVerifyRequest.java                       |    8 
 server/services/src/main/java/com/doumee/dao/dto/ShopUpdateDTO.java                             |    8 
 server/services/src/main/java/com/doumee/biz/system/impl/AreasBizImpl.java                      |   26 
 server/services/src/main/resources/application-pro.yml                                          |    7 
 server/services/db/db_change.sql                                                                |   14 
 server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java           |   16 
 server/services/src/main/java/com/doumee/dao/dto/ShopApplyDTO.java                              |    4 
 server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java           |  269 ++++++-
 server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java          |  153 ++-
 40 files changed, 1,754 insertions(+), 335 deletions(-)

diff --git a/server/services/db/db_change.sql b/server/services/db/db_change.sql
index 2afd4ab..b240fc2 100644
--- a/server/services/db/db_change.sql
+++ b/server/services/db/db_change.sql
@@ -5,6 +5,20 @@
 
 
 -- ============================================================
+-- 2026/04/20 鍟嗘埛涓庡徃鏈哄鍔犳敮浠樺疂瀹炲悕濮撳悕瀛楁
+-- ============================================================
+ALTER TABLE `shop_info` ADD COLUMN `ALI_NAME` VARCHAR(50) DEFAULT NULL COMMENT '鏀粯瀹濆疄鍚嶅鍚�' AFTER `ALI_ACCOUNT`;
+ALTER TABLE `driver_info` ADD COLUMN `ALI_ACCOUNT` VARCHAR(100) DEFAULT NULL COMMENT '鏀粯瀹濇彁鐜拌处鎴�' AFTER `LATITUDE`;
+ALTER TABLE `driver_info` ADD COLUMN `ALI_NAME` VARCHAR(50) DEFAULT NULL COMMENT '鏀粯瀹濆疄鍚嶅鍚�' AFTER `ALI_ACCOUNT`;
+
+
+-- ============================================================
+-- 2026/04/20 璁㈠崟閫�娆捐褰曡〃澧炲姞閫�娆剧姸鎬佸瓧娈�
+-- ============================================================
+ALTER TABLE `orders_refund` ADD COLUMN `STATUS` INT DEFAULT 0 COMMENT '閫�娆剧姸鎬侊細0=閫�娆句腑锛�1=閫�娆炬垚鍔燂紱2=閫�娆惧け璐�' AFTER `REFUND_REMARK`;
+
+
+-- ============================================================
 -- 2026/04/20 璁㈠崟琛ㄥ鍔犵墿鍝佺骇鍒瓧娈�
 -- ============================================================
 ALTER TABLE `orders` ADD COLUMN `GOOD_LEVEL` INT DEFAULT NULL COMMENT '鐗╁搧绾у埆锛坈ategory涓婚敭锛宼ype=3锛�' AFTER `GOOD_TYPE`;
diff --git a/server/services/src/main/java/com/doumee/biz/system/impl/AreasBizImpl.java b/server/services/src/main/java/com/doumee/biz/system/impl/AreasBizImpl.java
index a26c322..e8769f2 100644
--- a/server/services/src/main/java/com/doumee/biz/system/impl/AreasBizImpl.java
+++ b/server/services/src/main/java/com/doumee/biz/system/impl/AreasBizImpl.java
@@ -1,8 +1,10 @@
 package com.doumee.biz.system.impl;
 
 import com.doumee.biz.system.AreasBiz;
+import com.doumee.dao.business.AreasMapper;
 import com.doumee.dao.business.model.Areas;
 import com.doumee.service.business.AreasService;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -16,15 +18,27 @@
 public class AreasBizImpl implements AreasBiz {
 
     @Autowired
-    private AreasService areasService;
+    private AreasMapper areasMapper;
 
     @Override
     public Areas resolveArea(Integer areaId) {
-        if (areaId == null) {
-            return null;
-        }
-        // cacheData 涓凡涓烘瘡鏉″尯鍘胯褰曞~鍏呬簡 provinceId/provinceName/cityId/cityName
-        return areasService.findById(areaId);
+
+        return areasMapper.selectJoinOne(Areas.class,new MPJLambdaWrapper<Areas>()
+                .selectAll(Areas.class)
+                .select(" a1.id ",Areas::getCityId)
+                .select(" a1.name ",Areas::getCityName)
+                .select(" a2.id ",Areas::getProvinceId)
+                .select(" a2.name ",Areas::getProvinceName)
+                .leftJoin("areas a1 on a1.id = t.PARENT_ID")
+                .leftJoin("areas a2 on a2.id = a1.PARENT_ID")
+                .eq(Areas::getId, areaId)
+        );
+
+//        if (areaId == null) {
+//            return null;
+//        }
+//        // cacheData 涓凡涓烘瘡鏉″尯鍘胯褰曞~鍏呬簡 provinceId/provinceName/cityId/cityName
+//        return areasMapper.selectById(areaId);
     }
 
 }
diff --git a/server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java b/server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java
index e495576..198fb45 100644
--- a/server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java
+++ b/server/services/src/main/java/com/doumee/config/alipay/AlipayFundTransUniTransfer.java
@@ -1,87 +1,108 @@
 package com.doumee.config.alipay;
 
-import com.alipay.v3.ApiException;
 import com.alipay.v3.ApiClient;
-import com.alipay.v3.util.model.AlipayConfig;
+import com.alipay.v3.ApiException;
 import com.alipay.v3.Configuration;
 import com.alipay.v3.api.AlipayFundTransUniApi;
 import com.alipay.v3.model.*;
+import com.alipay.v3.util.model.AlipayConfig;
+import com.doumee.config.mybatis.SpringUtils;
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.doumee.dao.dto.AlipayTransferDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 
+import javax.annotation.PostConstruct;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * 鏀粯瀹濆崟绗旇浆璐﹀伐鍏风被
+ * @author rk
+ * @date 2026/04/20
+ */
+@Slf4j
+@org.springframework.context.annotation.Configuration
 public class AlipayFundTransUniTransfer {
 
-    public static void main(String[] args) throws ApiException  {
-        // 鍒濆鍖朣DK
-        ApiClient defaultClient = Configuration.getDefaultApiClient();
-        // 鍒濆鍖朼lipay鍙傛暟锛堝叏灞�璁剧疆涓�娆★級
-        defaultClient.setAlipayConfig(getAlipayConfig());
-        // 鏋勯�犺姹傚弬鏁颁互璋冪敤鎺ュ彛
-        AlipayFundTransUniApi api = new AlipayFundTransUniApi();
-        AlipayFundTransUniTransferModel data = new AlipayFundTransUniTransferModel();
-        // 璁剧疆鍟嗗渚у敮涓�璁㈠崟鍙�
-        data.setOutBizNo("202606300001");
-        // 璁剧疆璁㈠崟鎬婚噾棰�
-        data.setTransAmount("1");
-        // 璁剧疆鎻忚堪鐗瑰畾鐨勪笟鍔″満鏅�
-        data.setBizScene("DIRECT_TRANSFER");
-        // 璁剧疆涓氬姟浜у搧鐮�
-        data.setProductCode("TRANS_ACCOUNT_NO_PWD");
-        // 璁剧疆杞处涓氬姟鐨勬爣棰�
-        data.setOrderTitle("201905浠e彂");
-        // 璁剧疆鍘熸敮浠樺疂涓氬姟鍗曞彿
-        data.setOriginalOrderId("20190620110075000006640000063056");
-        // 璁剧疆鏀舵鏂逛俊鎭�
-        Participant payeeInfo = new Participant();
-        payeeInfo.setIdentity("15345690849");
-        payeeInfo.setName("姹熻悕");
-        payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
-        data.setPayeeInfo(payeeInfo);
-        // 璁剧疆涓氬姟澶囨敞
-        data.setRemark("201905浠e彂");
-        // 璁剧疆杞处鍦烘櫙鍚嶇О
-        data.setTransferSceneName("浣i噾鎶ラ叕");
+    private static AlipayConfig alipayConfig;
 
-        // 璁剧疆杞处鍦烘櫙涓婃姤淇℃伅
-        List<TransferSceneReportInfo> transferSceneReportInfos = new ArrayList<TransferSceneReportInfo>();
-        TransferSceneReportInfo transferSceneReportInfos0 = new TransferSceneReportInfo();
-        transferSceneReportInfos0.setInfoType("浣i噾鎶ラ叕璇存槑");
-        transferSceneReportInfos0.setInfoContent("3鏈堝鏀挎湇鍔℃姤閰�");
-        transferSceneReportInfos.add(transferSceneReportInfos0);
-        data.setTransferSceneReportInfos(transferSceneReportInfos);
+    @Autowired
+    private AlipayProperties alipayProperties;
 
-        // 璁剧疆杞处涓氬姟璇锋眰鐨勬墿灞曞弬鏁�
-        data.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");
+    public static AlipayFundTransUniTransfer me() {
+        return SpringUtils.get().getBean(AlipayFundTransUniTransfer.class);
+    }
 
-       /* // 璁剧疆绛惧悕淇℃伅
-        SignData signData = new SignData();
-        signData.setOriSign("EqHFP0z4a9iaQ1ep==");
-        signData.setPartnerId("绛惧悕琚巿鏉冩柟鏀粯瀹濊处鍙稩D");
-        signData.setOriAppId("2021000185629012");
-        signData.setOriOutBizNo("鍟嗘埛璁㈠崟鍙�");
-        signData.setOriSignType("RSA2");
-        signData.setOriCharSet("UTF-8");
-        data.setSignData(signData);
-*/
+    @PostConstruct
+    void init() {
+        this.loadAlipayConfig();
+    }
+
+    public void loadAlipayConfig() {
         try {
-            AlipayFundTransUniTransferResponseModel response = api.transfer(data);
-        } catch (ApiException e) {
-            AlipayFundTransUniTransferDefaultResponse errorObject = (AlipayFundTransUniTransferDefaultResponse) e.getErrorObject();
-            System.out.println("璋冪敤澶辫触:" + errorObject);
+            AlipayConfig config = new AlipayConfig();
+            config.setServerUrl("https://openapi.alipay.com");
+            config.setAppId(StringUtils.trimToNull(alipayProperties.getAppId()));
+            config.setPrivateKey(StringUtils.trimToNull(alipayProperties.getPrivateKey()));
+            config.setAppCertPath(StringUtils.trimToNull(alipayProperties.getAppCertPath()));
+            config.setAlipayPublicCertPath(StringUtils.trimToNull(alipayProperties.getAlipayPublicCertPath()));
+            config.setRootCertPath(StringUtils.trimToNull(alipayProperties.getRootCertPath()));
+            alipayConfig = config;
+            log.info("鏀粯瀹濋厤缃垵濮嬪寲鎴愬姛, appId={}", config.getAppId());
+        } catch (Exception e) {
+            log.error("鏀粯瀹濋厤缃垵濮嬪寲澶辫触: {}", e.getMessage(), e);
         }
     }
 
-    private static AlipayConfig getAlipayConfig() {
-        AlipayConfig alipayConfig = new AlipayConfig();
-        alipayConfig.setServerUrl("https://openapi.alipay.com");
-        alipayConfig.setAppId("2021006147660139");
-        String privateKey  = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEeqqkZztBHfK+vpyBi6ejgDTHZuZ3yiuXds+lRBbMo/g24F5trH+oLHW0gMhSxihFfQBBIpVBXDsPQK4ZkhDWTaOBktnU1UMRoOEiaaZU6EiWy10ePFUmpdXpkCQEp7rc88OwI90p58S3+L+Ckak60WqNwJBdB5YGBaUunryBA78U4zW1KNY7JvoRnZDcFMQiczikwUzhO7EAi0yVrVpsVsc9s87mcS4uOJKx4qb2E83r9RJ1z30db+cIIZRiLP2oNZBLYzgKpOouE+uIgxhQzlh6cOASNZQulXuUjoT/+Y9w4njfl4TmKIXWcJFKIMc6kMiux9tTncpp0TqRwk1tAgMBAAECggEALkSYtJheusnbpRFr95G0i2sggqh3s1PXihZ/dXKgT9Z5GCsj8X3Cng7CNRxykBN73kk+axhCv56Bhej8Vqcv8ddcnqG/TEBgR+Fzws/QTIRau6/uILWic7RvuE2qPbJl7aw1s9/uL/UVPSGFr7CvgltYVUM4e7/Sk1529JCK4XJfoXP5tKJ3OaXssvaFnCKEU8IGQkjRG+lUZJhAHVtClGHtgrhevgRhy2zre5wp2qSa8d/MqrPruSYS02hn9b5Nl6i2PlUS6dGlJ4lrxYTG22ukYYoxAPNPS7gnvmveXonWP7b5tPhKRpZjnoySojz3WECUlhz/v8wM1cDrpq+GQQKBgQDsc7y2rlx4f77a7ORfb5/qWHCOJs1cIzggj0kJ7TgFGe71kbCQ5nywD/Fe5V9OwbW+DCxOME+SrrHeiK4axWiu5si/1JlurJoxNy+4k4ywk3ZA3Nv2aBhlPqfkwDhJ0z7Mgsq2c/YgnVddmSvKZoC39wA77ovks4GDxaBOt8N7PQKBgQDUuPGgzkwcgb60UdaxfMbacrPsW26vDxaE4ceuXo2m8KDiCIqkF2y9r6AdWMTgGGSJwOsk7+FP+21VdRivCg9HcOLWngveUc6xDIuqKHVpemMo3SdCF4Wqf96rRc3VOBr5cfIdWxeorZf5umMyKnIAjAFETOOrK7eLTTmjyLD98QKBgB82S+Plcklpu3zUpnS+nGJn2Du7fYI7F+6cW2zXBn0N5lA+Mgt+kVkAUcFQD9uqkF4M51BO6kIXk10nt6vLAT2NM1S3MKW+XQBAI6l+uKSaYpK/VL3bEdVThwAYK5X7L5/5Z97bwdKeUmkFjhVCoJ0oGrzOiWLgGymUzct2UHSVAoGBAMb+7Cs+Ub0pMrmFBY6r52pbey1Uq0pglvRgMmhQU7sjx50r2GaA81zPer15WVM5/nNPYaoALYqg7jrPe/PjOT/fvpR+7SNg7DZ8QftANfYiY7jKifst/gDt9ePLPS6FedZ4XcJQgOVu34jicAFx64vPbS/zrddm4iEScSVijRBBAoGAXCheERsx8+n16Us/DttXFUa1nc7+D8WR6buM1QMZgQCVF2qp3XtM+FusCKL4+q1+dtag8svLjJFp9QbaAXqX8Zk7rn8wUHbDloPTPy9XWgrPowyL9MPU+e/Rq8Hr6TWPDBd4TU64YzIEfBQYpJXfZbXhVYmK3o7xHXKB1x4vvEM=";
-        alipayConfig.setPrivateKey(privateKey);
-        alipayConfig.setAppCertPath("pay/pro/appCertPublicKey.crt");
-        alipayConfig.setAlipayPublicCertPath("pay/pro/alipayCertPublicKey_RSA2.crt");
-        alipayConfig.setRootCertPath("pay/pro/alipayRootCert.crt");
+    /**
+     * 鍗曠瑪杞处鍒版敮浠樺疂璐︽埛
+     *
+     * @param dto 杞处鍙傛暟
+     * @return 鏀粯瀹濊浆璐﹀崟鍙�
+     */
+    public static String transfer(AlipayTransferDTO dto) throws ApiException {
+        ApiClient defaultClient = Configuration.getDefaultApiClient();
+        defaultClient.setAlipayConfig(alipayConfig);
+        AlipayFundTransUniApi api = new AlipayFundTransUniApi();
+        AlipayFundTransUniTransferModel data = new AlipayFundTransUniTransferModel();
+        data.setOutBizNo(dto.getOutBizNo());
+        data.setTransAmount(dto.getTransAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+        data.setBizScene("DIRECT_TRANSFER");
+        data.setProductCode("TRANS_ACCOUNT_NO_PWD");
+        data.setOrderTitle("浣i噾鎻愮幇");
 
-        return alipayConfig;
+        Participant payeeInfo = new Participant();
+        payeeInfo.setIdentity(dto.getPayeeAccount());
+        payeeInfo.setName(dto.getPayeeName());
+        payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
+        data.setPayeeInfo(payeeInfo);
+
+        data.setRemark(dto.getRemark());
+        data.setTransferSceneName("浣i噾鎶ラ叕");
+
+        List<TransferSceneReportInfo> reportInfos = new ArrayList<>();
+        TransferSceneReportInfo reportInfo = new TransferSceneReportInfo();
+        reportInfo.setInfoType("浣i噾鎶ラ叕璇存槑");
+        reportInfo.setInfoContent("浣i噾鎻愮幇");
+        reportInfos.add(reportInfo);
+        data.setTransferSceneReportInfos(reportInfos);
+
+        data.setBusinessParams("{\"payer_show_name_use_alias\":\"true\"}");
+
+        try {
+            AlipayFundTransUniTransferResponseModel response = api.transfer(data);
+            log.info("鏀粯瀹濊浆璐︽垚鍔�, outBizNo={}, orderId={}", dto.getOutBizNo(), response.getOrderId());
+            return response.getOrderId();
+        } catch (ApiException e) {
+            AlipayFundTransUniTransferDefaultResponse errorObject =
+                    (AlipayFundTransUniTransferDefaultResponse) e.getErrorObject();
+            log.error("鏀粯瀹濊浆璐﹀け璐�, outBizNo={}, error={}", dto.getOutBizNo(), errorObject);
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),
+                    "杞处澶辫触锛�" + (errorObject != null ? errorObject.toString() : e.getMessage()));
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/server/services/src/main/java/com/doumee/config/alipay/AlipayProperties.java b/server/services/src/main/java/com/doumee/config/alipay/AlipayProperties.java
new file mode 100644
index 0000000..6076ebe
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/alipay/AlipayProperties.java
@@ -0,0 +1,41 @@
+package com.doumee.config.alipay;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鏀粯瀹濋厤缃睘鎬�
+ * @author rk
+ * @date 2026/04/20
+ */
+@Component
+@ConfigurationProperties(prefix = "alipay.pay")
+@Data
+public class AlipayProperties {
+
+    /**
+     * 搴旂敤ID
+     */
+    private String appId;
+
+    /**
+     * 搴旂敤绉侀挜
+     */
+    private String privateKey;
+
+    /**
+     * 搴旂敤鍏挜璇佷功璺緞
+     */
+    private String appCertPath;
+
+    /**
+     * 鏀粯瀹濆叕閽ヨ瘉涔﹁矾寰�
+     */
+    private String alipayPublicCertPath;
+
+    /**
+     * 鏀粯瀹濇牴璇佷功璺緞
+     */
+    private String rootCertPath;
+}
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java b/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
index de47dc8..d386941 100644
--- a/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
+++ b/server/services/src/main/java/com/doumee/config/wx/WxMiniConfig.java
@@ -3,9 +3,7 @@
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
 import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
-import com.doumee.biz.system.SystemDictDataBiz;
 import com.doumee.config.mybatis.SpringUtils;
-import com.doumee.core.constants.Constants;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.service.WxPayService;
@@ -13,12 +11,11 @@
 import com.wechat.pay.java.core.Config;
 import com.wechat.pay.java.core.RSAAutoCertificateConfig;
 import com.wechat.pay.java.core.RSAPublicKeyConfig;
-import com.wechat.pay.java.core.http.HostName;
+import com.wechat.pay.java.core.notification.NotificationParser;
 import com.wechat.pay.java.core.notification.RSAPublicKeyNotificationConfig;
-import com.wechat.pay.java.service.billdownload.BillDownloadService;
-import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiService;
-import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiServiceExtension;
+import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
 import com.wechat.pay.java.service.refund.RefundService;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
@@ -28,15 +25,20 @@
 /**
  * 寰俊灏忕▼搴忕粍浠�
  */
+@Slf4j
 @Configuration
 public class WxMiniConfig {
     /********寰俊灏忕▼搴忔湇鍔�**********/
     public static WxMaService wxMaService;
-    /********寰俊灏忕▼搴忔敮浠�**********/
+    /********寰俊灏忕▼搴忔敮浠� V2**********/
     public static WxPayService wxPayService;
     /********寰俊APP鏀粯**********/
     public static WxPayService wxAppPayService;
 
+    /********寰俊鏀粯 V3**********/
+    public static JsapiServiceExtension v3JsapiService;
+    public static RefundService v3RefundService;
+    public static NotificationParser v3NotificationParser;
 
     @Autowired
     private WxPayProperties wxPayProperties;
@@ -49,6 +51,7 @@
     void init() {
         this.load_WxMaService();
         this.load_wxPayService();
+        this.load_wxPayV3Service();
 //        this.load_wxAppPayService();
     }
     /**
@@ -59,15 +62,13 @@
         config.setAppid(StringUtils.trimToNull(wxPayProperties.getAppId()));
         config.setSecret(StringUtils.trimToNull(wxPayProperties.getAppSecret()));
         config.setMsgDataFormat("JSON");
-        //config.setToken("");
-        //config.setAesKey("");
         WxMaService wxMaService = new WxMaServiceImpl();
         wxMaService.setWxMaConfig(config);
         this.wxMaService = wxMaService;
     }
 
     /**
-     * 鍒濆鍖栧井淇″皬绋嬪簭鏀粯
+     * 鍒濆鍖栧井淇″皬绋嬪簭鏀粯 V2
      */
     public void load_wxPayService() {
         WxPayConfig payConfig = new WxPayConfig();
@@ -83,8 +84,39 @@
         this.wxPayService = wxPayService;
     }
 
+    /**
+     * 鍒濆鍖栧井淇℃敮浠� V3锛圝SAPI + 閫�娆� + 鍥炶皟楠岀锛�
+     */
+    public void load_wxPayV3Service() {
+        try {
+            Config config =
+                    new RSAPublicKeyConfig.Builder()
+                            .merchantId(wxPayProperties.getMchId()) //寰俊鏀粯鐨勫晢鎴峰彿
+                            .privateKeyFromPath(wxPayProperties.getPrivateKeyPath()) // 鍟嗘埛API璇佷功绉侀挜鐨勫瓨鏀捐矾寰�
+                            .merchantSerialNumber(wxPayProperties.getSerialNumer()) //鍟嗘埛API璇佷功搴忓垪鍙�
+                            .publicKeyFromPath(wxPayProperties.getPubKeyPath()) //寰俊鏀粯鍏挜鐨勫瓨鏀捐矾寰�
+                            .publicKeyId(wxPayProperties.getPublicKeyId()) //寰俊鏀粯鍏挜ID
+                            .apiV3Key(wxPayProperties.getApiV3Key()) //APIv3瀵嗛挜
+                            .build();
 
 
+            // 鏀粯鍏挜閰嶇疆锛堢敤浜庡洖璋冮獙绛撅級
+            RSAPublicKeyNotificationConfig notifyConfig = new RSAPublicKeyNotificationConfig.Builder()
+                    .publicKeyFromPath(wxPayProperties.getPubKeyPath())
+                    .publicKeyId(wxPayProperties.getPublicKeyId())
+                    .apiV3Key(wxPayProperties.getApiV3Key())
+                    .build();
+
+            v3JsapiService = new JsapiServiceExtension.Builder().config(config).build();
+            v3RefundService = new RefundService.Builder().config(config).build();
+            v3NotificationParser = new NotificationParser(notifyConfig);
+
+            log.info("寰俊鏀粯V3鍒濆鍖栨垚鍔�");
+        } catch (Exception e) {
+            log.error("寰俊鏀粯V3鍒濆鍖栧け璐�: {}", e.getMessage(), e);
+        }
+    }
+
 //    /**
 //     * 鍒濆鍖朅pp鏀粯
 //     */
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxMiniUtilService.java b/server/services/src/main/java/com/doumee/config/wx/WxMiniUtilService.java
deleted file mode 100644
index 1b650b8..0000000
--- a/server/services/src/main/java/com/doumee/config/wx/WxMiniUtilService.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.doumee.config.wx;
-
-import com.doumee.core.constants.ResponseStatus;
-import com.doumee.core.exception.BusinessException;
-import com.doumee.core.utils.ID;
-import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
-import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
-import com.github.binarywang.wxpay.exception.WxPayException;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.math.BigDecimal;
-
-/**
- * 寰俊灏忕▼搴�-鍏叡鏂规硶
- */
-@Service
-@Slf4j
-public class WxMiniUtilService {
-
-
-    /**
-     * 璁㈠崟寰俊閫�娆�
-     * orderNo:鍟嗘埛璁㈠崟鍙�
-     * totalPrice锛氳鍗曟�婚噾棰�
-     * refundPrice锛涢��娆鹃噾棰�
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public String wxRefund(String orderNo, Long totalPrice, Long refundPrice) {
-        try {
-            // 鍙戦�侀��娆捐姹�
-            String refNum = ID.nextGUID();
-            WxPayRefundRequest request = new WxPayRefundRequest();
-            request.setOutTradeNo(orderNo);
-            request.setOutRefundNo(refNum);
-            request.setTotalFee(totalPrice.intValue());
-            request.setRefundFee(refundPrice.intValue());
-            WxPayRefundResult response = WxMiniConfig.wxPayService.refund(request);
-            if ("SUCCESS".equals(response.getReturnCode()) && "SUCCESS".equals(response.getResultCode())) {
-                return refNum;
-            } else {
-                throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),response.getErrCode() + response.getErrCodeDes());
-            }
-        } catch (WxPayException e) {
-            e.printStackTrace();
-        }
-        throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"閫�娆惧彂鐢熷紓甯歌鑱旂郴绠$悊鍛�");
-    }
-}
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java b/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
index e4c45ba..69d36b6 100644
--- a/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
+++ b/server/services/src/main/java/com/doumee/config/wx/WxPayProperties.java
@@ -42,6 +42,16 @@
     private String notifyUrl;
 
     /**
+     * V3鏀粯鍥炶皟鍦板潃
+     */
+    private String v3NotifyUrl;
+
+    /**
+     * V3閫�娆惧洖璋冨湴鍧�
+     */
+    private String v3RefundNotifyUrl;
+
+    /**
      * 鏀粯璇佷功(p12)
      */
     private String keyPath;
@@ -76,13 +86,15 @@
      */
     private String privateCertPath;
 
-
-
     /**
      * 鏀粯key
      */
     private String privateKeyPath;
 
 
+    /**
+     * 寰俊鏀粯鍏挜ID
+     */
+    private String publicKeyId;
 
 }
diff --git a/server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java b/server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java
new file mode 100644
index 0000000..6a5ace2
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/wx/WxPayV3Service.java
@@ -0,0 +1,186 @@
+package com.doumee.config.wx;
+
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.doumee.core.utils.ID;
+import com.wechat.pay.java.core.notification.RequestParam;
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
+import com.wechat.pay.java.service.refund.model.AmountReq;
+import com.wechat.pay.java.service.refund.model.CreateRequest;
+import com.wechat.pay.java.service.refund.model.Refund;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 寰俊鏀粯V3鐗堟湰鏈嶅姟锛圝SAPI涓嬪崟 + 閫�娆� + 鍥炶皟楠岀锛�
+ *
+ * @author rk
+ * @date 2026/04/20
+ */
+@Service
+@Slf4j
+public class WxPayV3Service {
+
+    @Autowired
+    private WxPayProperties wxPayProperties;
+
+    /**
+     * JSAPI涓嬪崟锛岃繑鍥炲墠绔皟璧锋敮浠樻墍闇�鐨勫弬鏁�
+     *
+     * @param outTradeNo  鍟嗘埛璁㈠崟鍙�
+     * @param description 鍟嗗搧鎻忚堪
+     * @param totalCents  閲戦锛堝垎锛�
+     * @param openid      鐢ㄦ埛openid
+     * @param notifyUrl   鏀粯鍥炶皟鍦板潃
+     * @param attach      闄勫姞鏁版嵁锛堝洖璋冩椂鍘熸牱杩斿洖锛岀敤浜庤矾鐢变笉鍚屼笟鍔★級
+     * @return 鍓嶇璋冭捣鏀粯鍙傛暟锛坅ppId, timeStamp, nonceStr, package, signType, paySign锛�
+     */
+    public Map<String, String> createOrder(String outTradeNo, String description,
+                                            Long totalCents, String openid,
+                                            String notifyUrl, String attach) {
+        if (WxMiniConfig.v3JsapiService == null) {
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "寰俊鏀粯V3鏈垵濮嬪寲");
+        }
+        try {
+            PrepayRequest request = new PrepayRequest();
+            request.setAppid(wxPayProperties.getAppId());
+            request.setMchid(wxPayProperties.getMchId());
+            request.setDescription(description);
+            request.setOutTradeNo(outTradeNo);
+            request.setNotifyUrl(notifyUrl);
+            if (attach != null && !attach.isEmpty()) {
+                request.setAttach(attach);
+            }
+
+            com.wechat.pay.java.service.payments.jsapi.model.Amount amount =
+                    new com.wechat.pay.java.service.payments.jsapi.model.Amount();
+            amount.setTotal(1);//totalCents.intValue());
+            amount.setCurrency("CNY");
+            request.setAmount(amount);
+
+            com.wechat.pay.java.service.payments.jsapi.model.Payer payer =
+                    new com.wechat.pay.java.service.payments.jsapi.model.Payer();
+            payer.setOpenid(openid);
+            request.setPayer(payer);
+
+            PrepayWithRequestPaymentResponse response =
+                    WxMiniConfig.v3JsapiService.prepayWithRequestPayment(request);
+
+            Map<String, String> result = new HashMap<>();
+            result.put("appId", response.getAppId());
+            result.put("timeStamp", response.getTimeStamp());
+            result.put("nonceStr", response.getNonceStr());
+            result.put("package", response.getPackageVal());
+            result.put("signType", response.getSignType());
+            result.put("paySign", response.getPaySign());
+            return result;
+        } catch (Exception e) {
+            log.error("寰俊鏀粯V3涓嬪崟澶辫触: {}", e.getMessage(), e);
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鏀粯璋冭捣澶辫触锛�" + e.getMessage());
+        }
+    }
+
+    /**
+     * V3閫�娆�
+     *
+     * @param outTradeNo   鍟嗘埛璁㈠崟鍙�
+     * @param totalCents   鍘熻鍗曢噾棰濓紙鍒嗭級
+     * @param refundCents  閫�娆鹃噾棰濓紙鍒嗭級
+     * @param reason       閫�娆惧師鍥�
+     * @param notifyUrl    閫�娆惧洖璋冨湴鍧�
+     * @return Refund 閫�娆剧粨鏋滐紙鍖呭惈 outRefundNo銆乻tatus 绛夛級
+     */
+    public Refund refund(String outTradeNo, Long totalCents, Long refundCents,
+                         String reason, String notifyUrl) {
+        if (WxMiniConfig.v3RefundService == null) {
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "寰俊鏀粯V3鏈垵濮嬪寲");
+        }
+        try {
+            String outRefundNo = ID.nextGUID();
+
+            CreateRequest request = new CreateRequest();
+            request.setOutTradeNo(outTradeNo);
+            request.setOutRefundNo(outRefundNo);
+            request.setReason(reason);
+            request.setNotifyUrl(notifyUrl);
+
+            AmountReq amount = new AmountReq();
+            amount.setRefund(1L);//refundCents);
+            amount.setTotal(1L);//totalCents);
+            amount.setCurrency("CNY");
+            request.setAmount(amount);
+
+            Refund result = WxMiniConfig.v3RefundService.create(request);
+            log.info("寰俊鏀粯V3閫�娆剧敵璇风粨鏋�, outTradeNo={}, outRefundNo={}, status={}",
+                    outTradeNo, outRefundNo, result.getStatus());
+            return result;
+        } catch (Exception e) {
+            log.error("寰俊鏀粯V3閫�娆惧け璐�: {}", e.getMessage(), e);
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "閫�娆惧け璐ワ細" + e.getMessage());
+        }
+    }
+
+    /**
+     * 瑙f瀽V3鏀粯鍥炶皟閫氱煡
+     *
+     * @param serialNumber  璇佷功搴忓垪鍙凤紙Wechatpay-Serial header锛�
+     * @param timestamp     鏃堕棿鎴筹紙Wechatpay-Timestamp header锛�
+     * @param nonce         闅忔満涓诧紙Wechatpay-Nonce header锛�
+     * @param signature     绛惧悕锛圵echatpay-Signature header锛�
+     * @param body          璇锋眰浣揓SON
+     * @return 瑙f瀽鍚庣殑Transaction瀵硅薄
+     */
+    public com.wechat.pay.java.service.payments.model.Transaction parsePayNotify(
+            String serialNumber, String timestamp, String nonce,
+            String signature, String body) {
+        try {
+            RequestParam requestParam = new RequestParam.Builder()
+                    .serialNumber(serialNumber)
+                    .timestamp(timestamp)
+                    .nonce(nonce)
+                    .signature(signature)
+                    .body(body)
+                    .build();
+
+            return WxMiniConfig.v3NotificationParser.parse(requestParam,
+                    com.wechat.pay.java.service.payments.model.Transaction.class);
+        } catch (Exception e) {
+            log.error("寰俊鏀粯V3鍥炶皟楠岀澶辫触: {}", e.getMessage(), e);
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鍥炶皟楠岀澶辫触");
+        }
+    }
+
+    /**
+     * 瑙f瀽V3閫�娆惧洖璋冮�氱煡
+     *
+     * @param serialNumber  璇佷功搴忓垪鍙�
+     * @param timestamp     鏃堕棿鎴�
+     * @param nonce         闅忔満涓�
+     * @param signature     绛惧悕
+     * @param body          璇锋眰浣揓SON
+     * @return 瑙f瀽鍚庣殑RefundNotification瀵硅薄
+     */
+    public com.wechat.pay.java.service.refund.model.RefundNotification parseRefundNotify(
+            String serialNumber, String timestamp, String nonce,
+            String signature, String body) {
+        try {
+            RequestParam requestParam = new RequestParam.Builder()
+                    .serialNumber(serialNumber)
+                    .timestamp(timestamp)
+                    .nonce(nonce)
+                    .signature(signature)
+                    .body(body)
+                    .build();
+            return WxMiniConfig.v3NotificationParser.parse(requestParam,
+                    com.wechat.pay.java.service.refund.model.RefundNotification.class);
+        } catch (Exception e) {
+            log.error("寰俊鏀粯V3閫�娆惧洖璋冮獙绛惧け璐�: {}", e.getMessage(), e);
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "閫�娆惧洖璋冮獙绛惧け璐�");
+        }
+    }
+}
diff --git a/server/services/src/main/java/com/doumee/core/constants/Constants.java b/server/services/src/main/java/com/doumee/core/constants/Constants.java
index 0409d47..ac995a0 100644
--- a/server/services/src/main/java/com/doumee/core/constants/Constants.java
+++ b/server/services/src/main/java/com/doumee/core/constants/Constants.java
@@ -101,6 +101,7 @@
     public static final int ORDER_LOG_ASSIGN_DRIVER = 3;    // 鎸囨淳鍙告満
     public static final int ORDER_LOG_CANCEL = 4;           // 鍙栨秷璁㈠崟
     public static final int ORDER_LOG_CONFIRM_ARRIVE = 5;   // 纭椤惧鍒板簵
+    public static final int ORDER_LOG_DRIVER_PICKUP = 6;    // 鍙告満瀹屾垚鍙栦欢
 
     public static final String SUCCESS = "SUCCESS";
     public static final String FAIL = "FAIL";
@@ -276,97 +277,6 @@
 
 
 
-    public enum WorkOrderStatus{
-        waitConfirm( 0, "寰呭垎閰峎TS","{title}涓婃姤","","寰呭垎閰峎TS" ),
-        waitAllocation(1, "寰呭垎閰嶄换鍔�","寰呭垎閰嶄换鍔�","","寰呭垎閰嶄换鍔�"),
-        waitDeal(2, "寰呭鐞�","寰呭鐞�","","寰呭伐绋嬪笀澶勭悊"),
-        sheClose(3, "宸茶В鍐�","SHE宸插叧闂�","","SHE宸插叧闂�"),
-        wtsClose(4, "宸茶В鍐�","WTS宸插叧闂�","","WTS宸插叧闂�"),
-        close(5, "宸茶В鍐�","宸茶В鍐�","","宸ョ▼甯堝叧闂�"),
-        urge (6, "鍌績","","","")
-        ;
-
-        private int status;
-        private String statusInfo;
-        private String statusName;
-        private String logTitle;
-        private String noticeContent;
-
-        // 鏋勯�犳柟娉�
-        WorkOrderStatus(int status, String statusInfo,String logTitle,String noticeContent,String statusName ) {
-            this.status = status;
-            this.statusInfo = statusInfo;
-            this.logTitle = logTitle;
-            this.noticeContent = noticeContent;
-            this.statusName = statusName;
-        }
-        public static String getName(int index) {
-            for (WorkOrderStatus c : WorkOrderStatus.values()) {
-                if (c.getKey() == index) {
-                    return c.statusInfo;
-                }
-            }
-            return null;
-        }
-        public static String getStatusName(int index) {
-            for (WorkOrderStatus c : WorkOrderStatus.values()) {
-                if (c.getKey() == index) {
-                    return c.statusName;
-                }
-            }
-            return null;
-        }
-
-        public int getKey() {
-            return status;
-        }
-
-        public void setKey(int key) {
-            this.status = status;
-        }
-
-        public int getStatus() {
-            return status;
-        }
-
-        public void setStatus(int status) {
-            this.status = status;
-        }
-
-        public String getStatusName() {
-            return statusName;
-        }
-
-        public void setStatusName(String statusName) {
-            this.statusName = statusName;
-        }
-
-        public String getStatusInfo() {
-            return statusInfo;
-        }
-
-        public void setStatusInfo(String statusInfo) {
-            this.statusInfo = statusInfo;
-        }
-
-        public String getLogTitle() {
-            return logTitle;
-        }
-
-        public void setLogTitle(String logTitle) {
-            this.logTitle = logTitle;
-        }
-
-        public String getNoticeContent() {
-            return noticeContent;
-        }
-
-        public void setNoticeContent(String noticeContent) {
-            this.noticeContent = noticeContent;
-        }
-    }
-
-
     /**
      * 闄勪欢绫诲瀷锛堝搴� multifile.objType锛�
      */
@@ -497,6 +407,82 @@
     }
 
     /**
+     * 璁㈠崟绔欏唴淇¢�氱煡鏋氫妇
+     * title: 閫氱煡鏍囬
+     * content: 閫氱煡鏂囨妯℃澘锛屽崰浣嶇鐢� {xxx} 琛ㄧず
+     */
+    @Getter
+    @AllArgsConstructor
+    public enum MemberOrderNotify {
+        WAIT_PAY("waitPay", "璁㈠崟寰呮敮浠�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸插垱寤猴紝璇峰湪{timeout}鍒嗛挓鍐呭畬鎴愭敮浠橈紝瓒呮椂灏嗚嚜鍔ㄥ彇娑�"),
+        WAIT_VERIFY("waitVerify", "璁㈠崟寰呮牳楠�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸叉彁浜わ紝绛夊緟闂ㄥ簵鏍搁獙鐗╁搧淇℃伅锛屽瓨浠剁爜{storeCode}"),
+        WAIT_GRAB("waitGrab", "璁㈠崟寰呮姠鍗�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸叉牳楠岋紝姝e湪涓烘偍瀹夋帓鍙栦欢鍙告満"),
+        WAIT_PICKUP_REMIND("waitPickupRemind", "璁㈠崟寰呭彇浠�", "璁㈠崟{orderNo}琛屾潕宸插瘎瀛橈紝璇疯寰楀湪棰勭害鍙栦欢鏃堕棿鍑彇浠剁爜鍓嶅線鎸囧畾闂ㄥ簵鍙栧洖"),
+        WAIT_PICKUP_GRABBED("waitPickupGrabbed", "璁㈠崟宸叉姠鍗�", "鎮ㄧ殑琛屾潕璁㈠崟锛氬凡鏈夊徃鏈簕driverName}鎶㈠崟锛屾鍓嶅線鍙栦欢鍦扮偣"),
+        DELIVERING("delivering", "璁㈠崟閰嶉�佷腑", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸茬敱鍙告満{driverName}鍙栦欢锛屾杩愬線鐩殑鍦�"),
+        ARRIVED_NO_SHOP("arrivedNoShop", "璁㈠崟宸查�佽揪", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸查�佽揪{destination},璇峰強鏃剁‘璁ゆ敹璐�"),
+        ARRIVED_HAS_SHOP("arrivedHasShop", "璁㈠崟宸查�佽揪", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸查�佽揪{destination},璇峰強鏃跺彇浠讹紝鍙栦欢鐮亄pickupCode}"),
+        FINISHED("finished", "璁㈠崟宸插畬鎴�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸插畬鎴愶紝鎰熻阿鎮ㄧ殑鏀寔锛岃瀵规湰娆℃湇鍔″仛鍑鸿瘎浠�"),
+        EVALUATED("evaluated", "璁㈠崟宸茶瘎浠�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}璇勪环宸叉彁浜わ紝鎰熻阿鎮ㄧ殑鐢ㄥ績璇勪环锛岀鎮ㄥ嚭琛岄『鍒╋紝鏃呴�旀剦蹇�!"),
+        CANCELLED("cancelled", "璁㈠崟宸插彇娑�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}宸插彇娑堬紝鎰熻阿鎮ㄧ殑鏀寔锛屾杩庝笅娆″啀浼�!"),
+        DRIVER_CHANGED("driverChanged", "鍙告満鍙樻洿鎻愰啋", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}鍘熷徃鏈哄凡鍙栨秷锛岀郴缁熸鍦ㄤ负鎮ㄥ尮閰嶆柊鍙告満锛岃鐣欐剰閫氱煡銆�"),
+        REFUNDING("refunding", "璁㈠崟閫�娆句腑", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}閫�娆剧敵璇峰凡鎻愪氦锛屽钩鍙颁細灏嗗敖蹇负鎮ㄥ鐞嗛��娆�"),
+        REFUNDED("refunded", "璁㈠崟宸查��娆�", "鎮ㄧ殑琛屾潕璁㈠崟锛歿orderNo}閫�娆惧凡瀹屾垚锛岄噾棰漿amount}鍏冨皢鍘熻矾閫�鍥烇紝璇锋敞鎰忔煡鏀�")
+        ;
+
+        private final String key;
+        private final String title;
+        private final String content;
+
+        /**
+         * 鏍煎紡鍖栭�氱煡鍐呭
+         * @param params 閿�煎锛屽 "orderNo","123" 浜ゆ浛浼犲叆
+         */
+        public String format(String... params) {
+            String result = this.content;
+            for (int i = 0; i < params.length - 1; i += 2) {
+                result = result.replace("{" + params[i] + "}", params[i + 1]);
+            }
+            return result;
+        }
+    }
+
+    /**
+     * 闂ㄥ簵璁㈠崟绔欏唴淇¢�氱煡鏋氫妇
+     * title: 閫氱煡鏍囬
+     * content: 閫氱煡鏂囨妯℃澘锛屽崰浣嶇鐢� {xxx} 琛ㄧず
+     */
+    @Getter
+    @AllArgsConstructor
+    public enum ShopOrderNotify {
+        WAIT_VERIFY("waitVerify", "璁㈠崟寰呮牳楠�", "鏂拌鏉庤鍗曪細{orderNo}宸叉敮浠橈紝璇峰敖蹇牳楠岀敤鎴风墿鍝佷俊鎭�"),
+        WAIT_PICKUP("waitPickup", "璁㈠崟寰呭彇浠�", "琛屾潕璁㈠崟锛歿orderNo}宸叉姠鍗曪紝绛夊緟{name}鍙栦欢"),
+        REFUNDING("refunding", "璁㈠崟閫�娆句腑", "琛屾潕璁㈠崟锛歿orderNo}鐢ㄦ埛鎻愪氦閫�娆剧敵璇凤紝璇风煡鎮�"),
+        DELIVERING("delivering", "璁㈠崟閰嶉�佷腑", "琛屾潕璁㈠崟锛歿orderNo}宸茬敱鍙告満{driverName}鍙栦欢锛屾鍦ㄩ厤閫佷腑"),
+        ARRIVED("arrived", "宸查�佽揪", "琛屾潕璁㈠崟锛歿orderNo}宸查�佽揪{destination},璇疯仈绯荤敤鎴风‘璁ょ鏀�"),
+        FINISHED("finished", "璁㈠崟宸插畬鎴�", "琛屾潕璁㈠崟锛歿orderNo}宸插畬鎴愶紝鐩稿叧璁㈠崟缁撶畻浼氬湪{settleDays}涓伐浣滄棩鍐呭畬鎴�"),
+        EVALUATED("evaluated", "璁㈠崟宸茶瘎浠�", "琛屾潕璁㈠崟锛歿orderNo}鐢ㄦ埛宸插畬鎴愯瘎浠凤紝鍙煡鐪嬭瘎浠峰唴瀹�"),
+        SETTLED("settled", "璁㈠崟缁撶畻", "琛屾潕璁㈠崟锛歿orderNo}骞冲彴宸插畬鎴愮粨绠楋紝閲戦涓簕amount}鍏冿紝璇锋敞鎰忔煡鏀躲��")
+        ;
+
+        private final String key;
+        private final String title;
+        private final String content;
+
+        /**
+         * 鏍煎紡鍖栭�氱煡鍐呭
+         * @param params 閿�煎锛屽 "orderNo","123" 浜ゆ浛浼犲叆
+         */
+        public String format(String... params) {
+            String result = this.content;
+            for (int i = 0; i < params.length - 1; i += 2) {
+                result = result.replace("{" + params[i] + "}", params[i + 1]);
+            }
+            return result;
+        }
+    }
+
+    /**
      * 寰楀埌request瀵硅薄
      *
      * @return
diff --git a/server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java b/server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java
index 66796b6..e18cb9c 100644
--- a/server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java
+++ b/server/services/src/main/java/com/doumee/core/utils/aliyun/AliSmsService.java
@@ -24,17 +24,15 @@
 @Slf4j
 public class AliSmsService {
 
-    private final static String ACCESS_KEY_ID = "LTAI5tMkg7wwV74a8H6Bm3Ej";
-    private final static String ACCESS_KEY_SECRET = "FcHKST36sfwfo706L6bvrweGFIbp3n";
-    private final static String SING_NAME = "姗欐澶╀笅绉戞妧";
+    private final static String ACCESS_KEY_ID = "LTAI5t835zTU4aaYpGHJCccJ";
+    private final static String ACCESS_KEY_SECRET = "98sAF2NchWVuIzu62zcLq0Ns7LIQTp";
+    private final static String SING_NAME = "鍗椾含涓夊彧楣�";
 
 
     public static void main(String[] args) {
         Map<String,Object> tempParam = new java.util.HashMap<>();
-        tempParam.put("order","钁¤悇閲囨憳宸�");
-        tempParam.put("time1","07-23");
-        tempParam.put("time2","07-24");
-        AliSmsService.sendSms("18055151023","SMS_491055243", JSONObject.toJSONString(tempParam));
+        tempParam.put("code","1234");
+        AliSmsService.sendSms("15345690849","SMS_333770877", JSONObject.toJSONString(tempParam));
     }
 
 
diff --git a/server/services/src/main/java/com/doumee/core/utils/geocode/MapUtil.java b/server/services/src/main/java/com/doumee/core/utils/geocode/MapUtil.java
new file mode 100644
index 0000000..f70ae35
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/core/utils/geocode/MapUtil.java
@@ -0,0 +1,168 @@
+package com.doumee.core.utils.geocode;
+
+import com.alibaba.fastjson.JSONObject;
+import com.doumee.core.utils.Http;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+ * 楂樺痉鍦板浘宸ュ叿绫�
+ *
+ * @Author : Rk
+ * @create 2026/4/20
+ */
+@Slf4j
+@Component
+public class MapUtil {
+
+    private static String amapKey;
+
+    /** 閫嗗湴鐞嗚В鏋� */
+    private static final String GEO_URL = "https://restapi.amap.com/v3/geocode/regeo";
+
+    /** 椹捐溅璺緞瑙勫垝 */
+    private static final String DRIVING_URL = "https://restapi.amap.com/v3/direction/driving";
+
+    /** 楠戣璺緞瑙勫垝 */
+    private static final String BICYCLING_URL = "https://restapi.amap.com/v4/direction/bicycling";
+
+    @Value("${geocode_map_key:}")
+    public void setAmapKey(String amapKey) {
+        MapUtil.amapKey = amapKey;
+    }
+
+    /**
+     * 閫嗗湴鐞嗚В鏋� - 鏍规嵁缁忕含搴﹁幏鍙栧湴鍧�淇℃伅
+     * 楂樺痉鍧愭爣绯讳负 lng,lat锛堜笌鑵捐 lat,lng 鐩稿弽锛�
+     *
+     * @param lat 绾害
+     * @param lng 缁忓害
+     * @return 鍖呭惈 ad_info 鍩庡競淇℃伅鐨� JSONObject锛堝吋瀹硅吘璁繑鍥炴牸寮忥級
+     */
+    public static JSONObject reverseGeocode(double lat, double lng) {
+        try {
+            String url = GEO_URL
+                    + "?key=" + amapKey
+                    + "&location=" + lng + "," + lat;
+
+            log.info("楂樺痉鍦板浘閫嗗湴鐞嗚В鏋愯姹�: lat={}, lng={}", lat, lng);
+
+            JSONObject json = new Http().build(url)
+                    .setConnectTimeout(5000)
+                    .setReadTimeout(10000)
+                    .get()
+                    .toJSONObject();
+
+            log.info("楂樺痉鍦板浘閫嗗湴鐞嗚В鏋愬搷搴�: {}", json);
+
+            if (!"1".equals(json.getString("status"))) {
+                throw new RuntimeException("楂樺痉鍦板浘閫嗗湴鐞嗚В鏋愬け璐�: " + json.getString("info"));
+            }
+
+            // 杞崲涓哄吋瀹硅吘璁繑鍥炴牸寮�: result.ad_info.city / adcode / district
+            JSONObject regeocode = json.getJSONObject("regeocode");
+            JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
+
+            JSONObject adInfo = new JSONObject();
+            adInfo.put("adcode", addressComponent.getString("adcode"));
+            adInfo.put("city", addressComponent.getString("city"));
+            adInfo.put("district", addressComponent.getString("district"));
+            adInfo.put("province", addressComponent.getString("province"));
+            adInfo.put("nation", addressComponent.getString("country"));
+
+            JSONObject result = new JSONObject();
+            result.put("ad_info", adInfo);
+            result.put("formatted_addresses", regeocode.getString("formatted_address"));
+            return result;
+        } catch (IOException e) {
+            log.error("楂樺痉鍦板浘閫嗗湴鐞嗚В鏋愬紓甯�", e);
+            throw new RuntimeException("楂樺痉鍦板浘閫嗗湴鐞嗚В鏋愬紓甯�", e);
+        }
+    }
+
+    /**
+     * 鍒ゆ柇涓や釜缁忕含搴︽槸鍚﹀湪鍚屼竴涓煄甯�
+     */
+    public static boolean isSameCity(double lat1, double lng1, double lat2, double lng2) {
+        JSONObject result1 = reverseGeocode(lat1, lng1);
+        JSONObject result2 = reverseGeocode(lat2, lng2);
+
+        String city1 = result1.getJSONObject("ad_info").getString("city");
+        String city2 = result2.getJSONObject("ad_info").getString("city");
+
+        log.info("鍒ゆ柇鍚屽煄: ({},{}) => city={}, ({},{}) => city={}", lat1, lng1, city1, lat2, lng2, city2);
+
+        return city1 != null && city1.equals(city2);
+    }
+
+    /**
+     * 璺緞瑙勫垝锛堢粺涓�鍏ュ彛锛�
+     * 鍐呴儴鏍规嵁 mode 璋冪敤楂樺痉涓嶅悓鐨勮矾寰勮鍒掓帴鍙�
+     *
+     * @param mode 妯″紡锛歞riving(椹捐溅)銆乥icycling(楠戣)
+     * @param from 璧风偣锛屾牸寮忥細lat,lng
+     * @param to   缁堢偣锛屾牸寮忥細lat,lng
+     * @return JSONObject 鍖呭惈 distance(绫�) 鍜� duration(绉�)
+     */
+    public static JSONObject direction(String mode, String from, String to) {
+        // 楂樺痉鍧愭爣绯讳负 lng,lat
+        String[] fromArr = from.split(",");
+        String[] toArr = to.split(",");
+        String origin = fromArr[1] + "," + fromArr[0];   // lng,lat
+        String destination = toArr[1] + "," + toArr[0];  // lng,lat
+
+        try {
+            String url;
+            if ("bicycling".equals(mode)) {
+                url = BICYCLING_URL
+                        + "?key=" + amapKey
+                        + "&origin=" + URLEncoder.encode(origin, "UTF-8")
+                        + "&destination=" + URLEncoder.encode(destination, "UTF-8");
+            } else {
+                // 榛樿椹捐溅
+                url = DRIVING_URL
+                        + "?key=" + amapKey
+                        + "&origin=" + URLEncoder.encode(origin, "UTF-8")
+                        + "&destination=" + URLEncoder.encode(destination, "UTF-8");
+            }
+
+            log.info("楂樺痉鍦板浘璺緞瑙勫垝璇锋眰: mode={}, from={}, to={}", mode, from, to);
+
+            JSONObject json = new Http().build(url)
+                    .setConnectTimeout(5000)
+                    .setReadTimeout(10000)
+                    .get()
+                    .toJSONObject();
+
+            log.info("楂樺痉鍦板浘璺緞瑙勫垝鍝嶅簲: {}", json);
+
+            if (!"1".equals(json.getString("status"))) {
+                throw new RuntimeException("楂樺痉鍦板浘璺緞瑙勫垝澶辫触: " + json.getString("info"));
+            }
+
+            // 鎻愬彇绗竴鏉¤矾寰勭殑 distance 鍜� duration
+            JSONObject routeData;
+            if ("bicycling".equals(mode)) {
+                routeData = json.getJSONObject("data");
+            } else {
+                routeData = json.getJSONObject("route");
+            }
+
+            JSONObject path = routeData.getJSONArray("paths").getJSONObject(0);
+            long distance = path.getLongValue("distance");
+            long duration = path.getLongValue("duration");
+
+            JSONObject result = new JSONObject();
+            result.put("distance", distance);
+            result.put("duration", duration);
+            return result;
+        } catch (IOException e) {
+            log.error("楂樺痉鍦板浘璺緞瑙勫垝寮傚父", e);
+            throw new RuntimeException("楂樺痉鍦板浘璺緞瑙勫垝寮傚父", e);
+        }
+    }
+}
diff --git a/server/services/src/main/java/com/doumee/core/utils/Tencent/MapUtil.java b/server/services/src/main/java/com/doumee/core/utils/tencent/MapUtil.java
similarity index 98%
rename from server/services/src/main/java/com/doumee/core/utils/Tencent/MapUtil.java
rename to server/services/src/main/java/com/doumee/core/utils/tencent/MapUtil.java
index 9604686..db34e51 100644
--- a/server/services/src/main/java/com/doumee/core/utils/Tencent/MapUtil.java
+++ b/server/services/src/main/java/com/doumee/core/utils/tencent/MapUtil.java
@@ -1,4 +1,4 @@
-package com.doumee.core.utils.Tencent;
+package com.doumee.core.utils.tencent;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -20,7 +20,7 @@
  * @create 2026/4/14 15:58
  */
 @Slf4j
-@Component
+//@Component
 public class MapUtil {
 
     private static String tencentKey;
diff --git a/server/services/src/main/java/com/doumee/dao/business/NoticeMapper.java b/server/services/src/main/java/com/doumee/dao/business/NoticeMapper.java
new file mode 100644
index 0000000..36f78f4
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/business/NoticeMapper.java
@@ -0,0 +1,12 @@
+package com.doumee.dao.business;
+
+import com.doumee.dao.business.model.Notice;
+import com.github.yulichang.base.MPJBaseMapper;
+
+/**
+ * 娑堟伅閫氱煡淇℃伅Mapper
+ * @author rk
+ * @date 2026/04/20
+ */
+public interface NoticeMapper extends MPJBaseMapper<Notice> {
+}
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java b/server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java
index 0ccc1e6..606dd65 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/DriverInfo.java
@@ -150,6 +150,12 @@
     @ApiModelProperty(value = "瀹氫綅绾害", example = "39.915")
     private Double latitude;
 
+    @ApiModelProperty(value = "鏀粯瀹濇彁鐜拌处鎴�")
+    private String aliAccount;
+
+    @ApiModelProperty(value = "鏀粯瀹濆疄鍚嶅鍚�")
+    private String aliName;
+
     @ApiModelProperty(value = "杞﹁締鐓х墖鍒楄〃")
     @TableField(exist = false)
     private List<Multifile> carImgList = new ArrayList<>();
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/Notice.java b/server/services/src/main/java/com/doumee/dao/business/model/Notice.java
new file mode 100644
index 0000000..3b1224f
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/business/model/Notice.java
@@ -0,0 +1,68 @@
+package com.doumee.dao.business.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 娑堟伅閫氱煡淇℃伅
+ * @author rk
+ * @date 2026/04/20
+ */
+@Data
+@ApiModel("娑堟伅閫氱煡淇℃伅")
+@TableName("`notice`")
+public class Notice {
+
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "涓婚敭", example = "1")
+    private Integer id;
+
+    @ApiModelProperty(value = "鍒涘缓浜虹紪鐮�", example = "1")
+    private Integer creator;
+
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createDate;
+
+    @ApiModelProperty(value = "鏇存柊浜虹紪鐮�", example = "1")
+    private Integer editor;
+
+    @ApiModelProperty(value = "鏇存柊鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date editDate;
+
+    @ApiModelProperty(value = "鏄惁鍒犻櫎 0鍚� 1鏄�", example = "0")
+    private Integer isdeleted;
+
+    @ApiModelProperty(value = "澶囨敞")
+    private String remark;
+
+    @ApiModelProperty(value = "鐢ㄦ埛绫诲瀷锛�0=浼氬憳鐢ㄦ埛锛�1=鍙告満锛�2=搴楅摵浜哄憳", example = "0")
+    private Integer userType;
+
+    @ApiModelProperty(value = "鐢ㄦ埛涓婚敭锛坢ember/driver_info/shop_info锛�", example = "1")
+    private Integer userId;
+
+    @ApiModelProperty(value = "鏍囬")
+    private String title;
+
+    @ApiModelProperty(value = "鍐呭")
+    private String content;
+
+    @ApiModelProperty(value = "瀵硅薄缂栫爜", example = "1")
+    private Integer objId;
+
+    @ApiModelProperty(value = "瀵硅薄绫诲瀷锛�0=璁㈠崟绫诲瀷锛�99=鍏朵粬绫诲瀷", example = "0")
+    private Integer objType;
+
+    @ApiModelProperty(value = "鐘舵�侊細0=鏈锛�1=宸茶", example = "0")
+    private Integer status;
+
+}
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/OrdersRefund.java b/server/services/src/main/java/com/doumee/dao/business/model/OrdersRefund.java
index 9698da9..bfe5459 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/OrdersRefund.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/OrdersRefund.java
@@ -66,5 +66,8 @@
     @ApiModelProperty(value = "骞冲彴鎿嶄綔浜猴紙type=1浣跨敤锛�", example = "0")
     private Integer userId;
 
+    @ApiModelProperty(value = "閫�娆剧姸鎬侊細0=閫�娆句腑锛�1=閫�娆炬垚鍔燂紱2=閫�娆惧け璐�", example = "0")
+    private Integer status;
+
 
 }
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java b/server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java
index 7b14ba3..aa6ab19 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/ShopInfo.java
@@ -165,6 +165,9 @@
     @ApiModelProperty(value = "鏀粯瀹濇彁鐜拌处鎴�")
     private String aliAccount;
 
+    @ApiModelProperty(value = "鏀粯瀹濆疄鍚嶅鍚�")
+    private String aliName;
+
     @ApiModelProperty(value = "钀ヤ笟鏃堕棿")
     private String shopHours;
 
diff --git a/server/services/src/main/java/com/doumee/dao/dto/AlipayTransferDTO.java b/server/services/src/main/java/com/doumee/dao/dto/AlipayTransferDTO.java
new file mode 100644
index 0000000..5559780
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/dto/AlipayTransferDTO.java
@@ -0,0 +1,39 @@
+package com.doumee.dao.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鏀粯瀹濆崟绗旇浆璐﹁姹傚弬鏁�
+ * @author rk
+ * @date 2026/04/20
+ */
+@Data
+public class AlipayTransferDTO {
+
+    /**
+     * 鍟嗘埛渚у敮涓�璁㈠崟鍙�
+     */
+    private String outBizNo;
+
+    /**
+     * 杞处閲戦锛堝厓锛�
+     */
+    private BigDecimal transAmount;
+
+    /**
+     * 鏀舵鏂规敮浠樺疂璐﹀彿
+     */
+    private String payeeAccount;
+
+    /**
+     * 鏀舵鏂瑰鍚�
+     */
+    private String payeeName;
+
+    /**
+     * 涓氬姟澶囨敞
+     */
+    private String remark;
+}
diff --git a/server/services/src/main/java/com/doumee/dao/dto/DriverPickupDTO.java b/server/services/src/main/java/com/doumee/dao/dto/DriverPickupDTO.java
new file mode 100644
index 0000000..775b3ff
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/dto/DriverPickupDTO.java
@@ -0,0 +1,28 @@
+package com.doumee.dao.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+/**
+ * 鍙告満瀹屾垚鍙栦欢璇锋眰
+ * @author rk
+ * @date 2026/04/20
+ */
+@Data
+@ApiModel("鍙告満瀹屾垚鍙栦欢璇锋眰")
+public class DriverPickupDTO {
+
+    @NotNull(message = "璁㈠崟涓婚敭涓嶈兘涓虹┖")
+    @ApiModelProperty(value = "璁㈠崟涓婚敭", required = true, example = "1")
+    private Integer orderId;
+
+    @NotNull(message = "鍙栦欢鍥剧墖涓嶈兘涓虹┖")
+    @Size(min = 1, max = 3, message = "鍙栦欢鍥剧墖1-3寮�")
+    @ApiModelProperty(value = "鍙栦欢鍥剧墖鍒楄〃锛堟渶澶�3寮狅級", required = true)
+    private List<String> images;
+}
diff --git a/server/services/src/main/java/com/doumee/dao/dto/DriverVerifyRequest.java b/server/services/src/main/java/com/doumee/dao/dto/DriverVerifyRequest.java
index a9fdee4..e414d00 100644
--- a/server/services/src/main/java/com/doumee/dao/dto/DriverVerifyRequest.java
+++ b/server/services/src/main/java/com/doumee/dao/dto/DriverVerifyRequest.java
@@ -72,4 +72,12 @@
     @ApiModelProperty(value = "鍏朵粬璧勬枡鐓х墖锛堟渶澶�3寮狅紝mutifile objType=8锛�")
     private List<String> otherImgUrls;
 
+    @NotEmpty(message = "鏀粯瀹濇彁鐜拌处鎴蜂笉鑳戒负绌�")
+    @ApiModelProperty(value = "鏀粯瀹濇彁鐜拌处鎴�", required = true)
+    private String aliAccount;
+
+    @NotEmpty(message = "鏀粯瀹濆疄鍚嶅鍚嶄笉鑳戒负绌�")
+    @ApiModelProperty(value = "鏀粯瀹濆疄鍚嶅鍚�", required = true)
+    private String aliName;
+
 }
diff --git a/server/services/src/main/java/com/doumee/dao/dto/ShopApplyDTO.java b/server/services/src/main/java/com/doumee/dao/dto/ShopApplyDTO.java
index 9dad07d..a3d8b58 100644
--- a/server/services/src/main/java/com/doumee/dao/dto/ShopApplyDTO.java
+++ b/server/services/src/main/java/com/doumee/dao/dto/ShopApplyDTO.java
@@ -107,4 +107,8 @@
     @ApiModelProperty(value = "鏀粯瀹濇彁鐜拌处鎴�", required = true)
     @NotBlank(message = "鏀粯瀹濇彁鐜拌处鎴蜂笉鑳戒负绌�")
     private String aliAccount;
+
+    @ApiModelProperty(value = "鏀粯瀹濆疄鍚嶅鍚�", required = true)
+    @NotBlank(message = "鏀粯瀹濆疄鍚嶅鍚嶄笉鑳戒负绌�")
+    private String aliName;
 }
diff --git a/server/services/src/main/java/com/doumee/dao/dto/ShopUpdateDTO.java b/server/services/src/main/java/com/doumee/dao/dto/ShopUpdateDTO.java
index f7f252d..079e950 100644
--- a/server/services/src/main/java/com/doumee/dao/dto/ShopUpdateDTO.java
+++ b/server/services/src/main/java/com/doumee/dao/dto/ShopUpdateDTO.java
@@ -110,4 +110,12 @@
     @Size(max = 3, message = "绀句繚缂寸撼璇佹槑鏈�澶�3寮�")
     private List<String> socialSecurityImgs;
 
+    @ApiModelProperty(value = "鏀粯瀹濇彁鐜拌处鎴�", required = true)
+    @NotBlank(message = "鏀粯瀹濇彁鐜拌处鎴蜂笉鑳戒负绌�")
+    private String aliAccount;
+
+    @ApiModelProperty(value = "鏀粯瀹濆疄鍚嶅鍚�", required = true)
+    @NotBlank(message = "鏀粯瀹濆疄鍚嶅鍚嶄笉鑳戒负绌�")
+    private String aliName;
+
 }
diff --git a/server/services/src/main/java/com/doumee/dao/vo/PlatformAboutVO.java b/server/services/src/main/java/com/doumee/dao/vo/PlatformAboutVO.java
index a4dd10c..51bcf87 100644
--- a/server/services/src/main/java/com/doumee/dao/vo/PlatformAboutVO.java
+++ b/server/services/src/main/java/com/doumee/dao/vo/PlatformAboutVO.java
@@ -23,6 +23,6 @@
     @ApiModelProperty(value = "闅愮鍗忚")
     private String privacyAgreement;
 
-    @ApiModelProperty(value = "鏈嶅姟浠嬬粛")
+    @ApiModelProperty(value = "瑙勮寖椤荤煡")
     private String serverIntroduce;
 }
diff --git a/server/services/src/main/java/com/doumee/dao/vo/ShopDetailVO.java b/server/services/src/main/java/com/doumee/dao/vo/ShopDetailVO.java
index c2f9d54..e9288d6 100644
--- a/server/services/src/main/java/com/doumee/dao/vo/ShopDetailVO.java
+++ b/server/services/src/main/java/com/doumee/dao/vo/ShopDetailVO.java
@@ -4,6 +4,7 @@
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import javax.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Date;
@@ -96,6 +97,9 @@
     @ApiModelProperty(value = "瀹℃壒鐘舵�侊細0=寰呭鎵癸紱1=瀹℃壒閫氳繃锛�2=瀹℃壒鏈�氳繃锛�3=宸叉敮浠樻娂閲�")
     private Integer auditStatus;
 
+    @ApiModelProperty(value = "鎶奸噾閲戦")
+    private Long depositAmount;
+
     @ApiModelProperty(value = "鐘舵�侊細0=鍚敤锛�1=绂佺敤")
     private Integer status;
 
@@ -108,6 +112,11 @@
     @ApiModelProperty(value = "瀹℃壒浜哄悕绉�")
     private String auditName;
 
+    @ApiModelProperty(value = "鏀粯瀹濇彁鐜拌处鎴�")
+    private String aliAccount;
+
+    @ApiModelProperty(value = "鏀粯瀹濆疄鍚嶅鍚�")
+    private String aliName;
 
     @ApiModelProperty(value = "OPENID")
     private String openid;
diff --git a/server/services/src/main/java/com/doumee/service/business/DriverInfoService.java b/server/services/src/main/java/com/doumee/service/business/DriverInfoService.java
index 3c7f772..c274cc4 100644
--- a/server/services/src/main/java/com/doumee/service/business/DriverInfoService.java
+++ b/server/services/src/main/java/com/doumee/service/business/DriverInfoService.java
@@ -6,6 +6,7 @@
 import com.doumee.dao.dto.DriverGrabOrderDTO;
 import com.doumee.dao.business.model.DriverInfo;
 import com.doumee.dao.dto.DriverLoginRequest;
+import com.doumee.dao.dto.DriverPickupDTO;
 import com.doumee.dao.dto.DriverRegisterRequest;
 import com.doumee.dao.dto.DriverVerifyRequest;
 import com.doumee.dao.vo.AccountResponse;
@@ -224,4 +225,20 @@
      */
     void cancelOrder(Integer driverId, Integer orderId, String reason);
 
+    /**
+     * 鍙告満鎶㈠崟锛岃鍗曠姸鎬佷粠宸插瘎瀛�(2)鍙樹负宸叉帴鍗�(3)
+     *
+     * @param driverId 鍙告満涓婚敭
+     * @param orderId  璁㈠崟涓婚敭
+     */
+    void grabOrder(Integer driverId, Integer orderId);
+
+    /**
+     * 鍙告満瀹屾垚鍙栦欢锛岃鍗曠姸鎬佷粠宸叉帴鍗�(3)鍙樹负娲鹃�佷腑(4)
+     *
+     * @param driverId 鍙告満涓婚敭
+     * @param dto      鍙栦欢璇锋眰鍙傛暟
+     */
+    void confirmPickup(Integer driverId, DriverPickupDTO dto);
+
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/NoticeService.java b/server/services/src/main/java/com/doumee/service/business/NoticeService.java
new file mode 100644
index 0000000..d89d0a8
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/service/business/NoticeService.java
@@ -0,0 +1,37 @@
+package com.doumee.service.business;
+
+import com.doumee.core.model.PageData;
+import com.doumee.core.model.PageWrap;
+import com.doumee.dao.business.model.Notice;
+
+import java.util.List;
+
+/**
+ * 娑堟伅閫氱煡淇℃伅Service瀹氫箟
+ * @author rk
+ * @date 2026/04/20
+ */
+public interface NoticeService {
+
+    Integer create(Notice notice);
+
+    void deleteById(Integer id);
+
+    void delete(Notice notice);
+
+    void deleteByIdInBatch(List<Integer> ids);
+
+    void updateById(Notice notice);
+
+    void updateByIdInBatch(List<Notice> notices);
+
+    Notice findById(Integer id);
+
+    Notice findOne(Notice notice);
+
+    List<Notice> findList(Notice notice);
+
+    PageData<Notice> findPage(PageWrap<Notice> pageWrap);
+
+    long count(Notice notice);
+}
diff --git a/server/services/src/main/java/com/doumee/service/business/OrdersService.java b/server/services/src/main/java/com/doumee/service/business/OrdersService.java
index 91ecdf9..48daf2e 100644
--- a/server/services/src/main/java/com/doumee/service/business/OrdersService.java
+++ b/server/services/src/main/java/com/doumee/service/business/OrdersService.java
@@ -327,10 +327,10 @@
     /**
      * 闂ㄥ簵鏀粯鎶奸噾锛堝敜璧峰井淇℃敮浠橈級
      *
-     * @param shopId 闂ㄥ簵涓婚敭
+     * @param memberId 鐢ㄦ埛涓婚敭
      * @return 鏀粯鍝嶅簲
      */
-    PayResponse payShopDeposit(Integer shopId);
+    PayResponse payShopDeposit(Integer memberId);
 
     /**
      * 闂ㄥ簵鎶奸噾鏀粯鍥炶皟澶勭悊
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java
index 8110145..920b9e6 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/DriverInfoServiceImpl.java
@@ -32,19 +32,15 @@
 import com.doumee.dao.business.model.Orders;
 import com.doumee.dao.business.model.OrdersDetail;
 import com.doumee.dao.business.model.Revenue;
+import com.doumee.dao.dto.*;
 import com.doumee.dao.vo.AccountResponse;
 import com.doumee.dao.vo.DriverCenterVO;
 import com.doumee.dao.vo.DriverGrabOrderVO;
 import com.doumee.dao.vo.DriverOrderDetailVO;
-import com.doumee.dao.dto.AuditDTO;
-import com.doumee.dao.dto.ChangeStatusDTO;
-import com.doumee.dao.dto.DriverLoginRequest;
-import com.doumee.dao.dto.DriverRegisterRequest;
-import com.doumee.dao.dto.DriverVerifyRequest;
-import com.doumee.dao.dto.DriverActiveOrderDTO;
-import com.doumee.dao.dto.DriverGrabOrderDTO;
 import com.doumee.core.utils.aliyun.AliSmsService;
+import com.doumee.dao.business.model.Notice;
 import com.doumee.service.business.DriverInfoService;
+import com.doumee.service.business.NoticeService;
 import com.alibaba.fastjson.JSONObject;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.apache.commons.lang3.RandomStringUtils;
@@ -107,6 +103,43 @@
 
     @Autowired
     private OperationConfigBiz operationConfigBiz;
+
+    @Autowired
+    private NoticeService noticeService;
+
+    /**
+     * 鍙戦�佽鍗曠珯鍐呬俊閫氱煡
+     */
+    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);
+    }
 
     @Override
     public Integer create(DriverInfo driverInfo) {
@@ -462,7 +495,8 @@
                 .set(DriverInfo::getCardEndDate, request.getCardEndDate())
                 .set(DriverInfo::getIdcardImg, request.getIdcardImg())
                 .set(DriverInfo::getIdcardImgBack, request.getIdcardImgBack())
-                .set(DriverInfo::getAuditStatus, Constants.ZERO)
+                .set(DriverInfo::getAliAccount, request.getAliAccount())
+                .set(DriverInfo::getAliName, request.getAliName())
                 .set(DriverInfo::getUpdateTime, now)
                 .set(DriverInfo::getAuditRemark, null)
                 .set(DriverInfo::getAuditTime, null)
@@ -1131,6 +1165,159 @@
         log.setCreateTime(new Date());
         log.setDeleted(Constants.ZERO);
         orderLogMapper.insert(log);
+
+        // 閫氱煡浼氬憳锛氬徃鏈哄彉鏇�
+        sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.DRIVER_CHANGED, orderId,
+                "orderNo", order.getCode());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void grabOrder(Integer driverId, Integer orderId) {
+        // 1. 鏍¢獙鍙告満
+        DriverInfo driver = driverInfoMapper.selectById(driverId);
+        if (driver == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "鍙告満淇℃伅涓嶅瓨鍦�");
+        }
+        // 2. 鏍¢獙鍙告満鎺ュ崟鐘舵��
+        if (!Constants.ONE.equals(driver.getAcceptingStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇峰厛寮�鍚帴鍗曠姸鎬�");
+        }
+        if (!Integer.valueOf(3).equals(driver.getAuditStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鍙告満瀹℃牳鏈�氳繃鎴栨湭缂寸撼鎶奸噾");
+        }
+        if (driver.getDriverLevel() == null) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鍙告満绛夌骇鏈缃�");
+        }
+
+        // 3. 鏍¢獙璁㈠崟
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null || Constants.ONE.equals(order.getDeleted())) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+        if (!Constants.ONE.equals(order.getType())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "浠呭紓鍦板瘎瀛樿鍗曞彲鎶㈠崟");
+        }
+        if (!Constants.TWO.equals(order.getStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽鎶㈠崟");
+        }
+
+        // 4. 鏍¢獙鍙告満绛夌骇 鈮� 璁㈠崟绛夌骇
+        if (order.getGoodLevel() != null && driver.getDriverLevel() < order.getGoodLevel()) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鍙告満绛夌骇涓嶈冻锛屾棤娉曟姠璇ヨ鍗�");
+        }
+
+        // 5. 鍘熷瓙鏇存柊锛氬甫 status=2 鏉′欢闃叉骞跺彂閲嶅鎶㈠崟
+        Date now = new Date();
+        int rows = ordersMapper.update(new UpdateWrapper<Orders>().lambda()
+                .set(Orders::getAcceptDriver, driverId)
+                .set(Orders::getAcceptTime, now)
+                .set(Orders::getAcceptType, 0) // 0=鎵嬪姩鎶㈠崟
+                .set(Orders::getStatus, Constants.OrderStatus.accepted.getStatus())
+                .set(Orders::getUpdateTime, now)
+                .eq(Orders::getId, orderId)
+                .eq(Orders::getStatus, Constants.TWO));
+        if (rows == 0) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鎶㈠崟澶辫触锛岃鍗曞凡琚姠鎴栫姸鎬佸凡鍙樻洿");
+        }
+
+        // 6. 鍐欏叆鎿嶄綔鏃ュ織
+        OrderLog log = new OrderLog();
+        log.setOrderId(orderId);
+        log.setTitle("鍙告満鎶㈠崟");
+        log.setLogInfo("鍙告満銆�" + driver.getName() + "銆戞姠鍗曟垚鍔�");
+        log.setObjType(Constants.ORDER_LOG_DRIVER_PICKUP);
+        log.setOptUserId(driver.getMemberId());
+        log.setOptUserType(Constants.ONE);
+        log.setOrderStatus(Constants.OrderStatus.accepted.getStatus());
+        log.setCreateTime(now);
+        log.setDeleted(Constants.ZERO);
+        orderLogMapper.insert(log);
+
+        // 7. 閫氱煡浼氬憳锛氬徃鏈哄凡鎶㈠崟
+        sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_GRABBED, orderId,
+                "driverName", driver.getName());
+
+        // 閫氱煡瀛樹欢闂ㄥ簵锛氳鍗曞凡鎶㈠崟寰呭彇浠�
+        if (order.getDepositShopId() != null) {
+            sendShopNotice(order.getDepositShopId(), Constants.ShopOrderNotify.WAIT_PICKUP, orderId,
+                    "orderNo", order.getCode());
+        }
+    }
+
+    @Override
+    @Transactional
+    public void confirmPickup(Integer driverId, DriverPickupDTO dto) {
+        Integer orderId = dto.getOrderId();
+
+        // 1. 鏍¢獙鍙告満
+        DriverInfo driver = driverInfoMapper.selectById(driverId);
+        if (driver == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "鍙告満淇℃伅涓嶅瓨鍦�");
+        }
+
+        // 2. 鏍¢獙璁㈠崟
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null || Constants.ONE.equals(order.getDeleted())) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+        if (!Constants.ONE.equals(order.getType())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "浠呭紓鍦板瘎瀛樿鍗曟敮鎸佹鎿嶄綔");
+        }
+        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.accepted.getStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽鍙栦欢纭");
+        }
+        if (!driverId.equals(order.getAcceptDriver())) {
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鏃犳潈鎿嶄綔璇ヨ鍗�");
+        }
+
+        // 3. 淇濆瓨鍙栦欢鍥剧墖
+        Date now = new Date();
+        if (dto.getImages() != null && !dto.getImages().isEmpty()) {
+            int sortNum = 0;
+            for (String url : dto.getImages()) {
+                Multifile multifile = new Multifile();
+                multifile.setObjId(orderId);
+                multifile.setObjType(Constants.FileType.DRIVER_TAKE.getKey());
+                multifile.setType(Constants.ZERO);
+                multifile.setFileurl(url);
+                multifile.setIsdeleted(Constants.ZERO);
+                multifile.setCreateDate(now);
+                multifile.setSortnum(sortNum++);
+                multifileMapper.insert(multifile);
+            }
+        }
+
+        // 4. 鏇存柊璁㈠崟鐘舵�佷负娲鹃�佷腑(4)
+        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
+                .set(Orders::getStatus, Constants.OrderStatus.delivering.getStatus())
+                .set(Orders::getUpdateTime, now)
+                .eq(Orders::getId, orderId));
+
+        // 5. 鍐欏叆鎿嶄綔鏃ュ織
+        OrderLog log = new OrderLog();
+        log.setOrderId(orderId);
+        log.setTitle("鍙告満瀹屾垚鍙栦欢");
+        log.setLogInfo("鍙告満銆�" + driver.getName() + "銆戝畬鎴愬彇浠讹紝寮�濮嬫淳閫�");
+        log.setObjType(Constants.ORDER_LOG_DRIVER_PICKUP);
+        log.setOptUserId(driver.getMemberId());
+        log.setOptUserType(Constants.ONE);
+        log.setOrderStatus(Constants.OrderStatus.delivering.getStatus());
+        log.setCreateTime(now);
+        log.setDeleted(Constants.ZERO);
+        orderLogMapper.insert(log);
+
+        // 閫氱煡浼氬憳锛氳鍗曢厤閫佷腑
+        sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.DELIVERING, orderId,
+                "orderNo", order.getCode(),
+                "driverName", driver.getName());
+
+        // 閫氱煡鍙栦欢闂ㄥ簵锛氳鍗曢厤閫佷腑
+        if (order.getTakeShopId() != null) {
+            sendShopNotice(order.getTakeShopId(), Constants.ShopOrderNotify.DELIVERING, orderId,
+                    "orderNo", order.getCode(),
+                    "driverName", driver.getName());
+        }
     }
 
     private List<String> getFileUrls(Integer orderId, int objType, String prefix) {
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
index a4554eb..b73f56c 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -350,15 +350,13 @@
      * 闂ㄥ簵鐢ㄦ埛韬唤鏃讹紝濉厖闂ㄥ簵瀹℃牳鐘舵��
      */
     private void fillShopInfo(UserCenterVO userCenterVO, Member member) {
-        if (Constants.TWO.equals(member.getUserType())) {
-            ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
-                    .eq(ShopInfo::getRegionMemberId, member.getId())
-                    .eq(ShopInfo::getDeleted, Constants.ZERO)
-                    .last("limit 1"));
-            if (shopInfo != null) {
-                userCenterVO.setShopId(shopInfo.getId());
-                userCenterVO.setShopAuditStatus(shopInfo.getAuditStatus());
-            }
+        ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
+                .eq(ShopInfo::getRegionMemberId, member.getId())
+                .eq(ShopInfo::getDeleted, Constants.ZERO)
+                .last("limit 1"));
+        if (shopInfo != null) {
+            userCenterVO.setShopId(shopInfo.getId());
+            userCenterVO.setShopAuditStatus(shopInfo.getAuditStatus());
         }
         // 鏍规嵁openid鏌ヨ褰撳墠缁戝畾鐨勯棬搴�
         if (StringUtils.isNotBlank(member.getOpenid())) {
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/NoticeServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/NoticeServiceImpl.java
new file mode 100644
index 0000000..b5a458a
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/service/business/impl/NoticeServiceImpl.java
@@ -0,0 +1,126 @@
+package com.doumee.service.business.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.doumee.core.model.PageData;
+import com.doumee.core.model.PageWrap;
+import com.doumee.dao.business.NoticeMapper;
+import com.doumee.dao.business.model.Notice;
+import com.doumee.service.business.NoticeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 娑堟伅閫氱煡淇℃伅Service瀹炵幇
+ * @author rk
+ * @date 2026/04/20
+ */
+@Service
+public class NoticeServiceImpl implements NoticeService {
+
+    @Autowired
+    private NoticeMapper noticeMapper;
+
+    @Override
+    public Integer create(Notice notice) {
+        noticeMapper.insert(notice);
+        return notice.getId();
+    }
+
+    @Override
+    public void deleteById(Integer id) {
+        noticeMapper.deleteById(id);
+    }
+
+    @Override
+    public void delete(Notice notice) {
+        QueryWrapper<Notice> deleteWrapper = new QueryWrapper<>(notice);
+        noticeMapper.delete(deleteWrapper);
+    }
+
+    @Override
+    public void deleteByIdInBatch(List<Integer> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return;
+        }
+        noticeMapper.deleteBatchIds(ids);
+    }
+
+    @Override
+    public void updateById(Notice notice) {
+        noticeMapper.updateById(notice);
+    }
+
+    @Override
+    public void updateByIdInBatch(List<Notice> notices) {
+        if (notices == null || notices.isEmpty()) {
+            return;
+        }
+        for (Notice notice : notices) {
+            this.updateById(notice);
+        }
+    }
+
+    @Override
+    public Notice findById(Integer id) {
+        return noticeMapper.selectById(id);
+    }
+
+    @Override
+    public Notice findOne(Notice notice) {
+        QueryWrapper<Notice> wrapper = new QueryWrapper<>(notice);
+        return noticeMapper.selectOne(wrapper);
+    }
+
+    @Override
+    public List<Notice> findList(Notice notice) {
+        QueryWrapper<Notice> wrapper = new QueryWrapper<>(notice);
+        return noticeMapper.selectList(wrapper);
+    }
+
+    @Override
+    public PageData<Notice> findPage(PageWrap<Notice> pageWrap) {
+        IPage<Notice> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
+        QueryWrapper<Notice> queryWrapper = new QueryWrapper<>();
+        if (pageWrap.getModel() != null) {
+            if (pageWrap.getModel().getIsdeleted() != null) {
+                queryWrapper.lambda().eq(Notice::getIsdeleted, pageWrap.getModel().getIsdeleted());
+            }
+            if (pageWrap.getModel().getUserType() != null) {
+                queryWrapper.lambda().eq(Notice::getUserType, pageWrap.getModel().getUserType());
+            }
+            if (pageWrap.getModel().getUserId() != null) {
+                queryWrapper.lambda().eq(Notice::getUserId, pageWrap.getModel().getUserId());
+            }
+            if (pageWrap.getModel().getObjType() != null) {
+                queryWrapper.lambda().eq(Notice::getObjType, pageWrap.getModel().getObjType());
+            }
+            if (pageWrap.getModel().getStatus() != null) {
+                queryWrapper.lambda().eq(Notice::getStatus, pageWrap.getModel().getStatus());
+            }
+            if (pageWrap.getModel().getTitle() != null) {
+                queryWrapper.lambda().like(Notice::getTitle, pageWrap.getModel().getTitle());
+            }
+            if (pageWrap.getModel().getCreateDate() != null) {
+                queryWrapper.lambda().ge(Notice::getCreateDate, pageWrap.getModel().getCreateDate());
+            }
+        }
+        for (PageWrap.SortData sortData : pageWrap.getSorts()) {
+            if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
+                queryWrapper.orderByDesc(sortData.getProperty());
+            } else {
+                queryWrapper.orderByAsc(sortData.getProperty());
+            }
+        }
+        return PageData.from(noticeMapper.selectPage(page, queryWrapper));
+    }
+
+    @Override
+    public long count(Notice notice) {
+        QueryWrapper<Notice> wrapper = new QueryWrapper<>(notice);
+        return noticeMapper.selectCount(wrapper);
+    }
+}
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 8fa0b27..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,11 +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.doumee.service.business.PricingRuleService;
-import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
@@ -45,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瀹炵幇
@@ -104,8 +101,7 @@
     @Autowired
     private RevenueMapper revenueMapper;
 
-    @Autowired
-    private WxMiniUtilService wxMiniUtilService;
+
 
     @Autowired
     private SystemUserMapper systemUserMapper;
@@ -127,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) {
@@ -413,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);
@@ -518,16 +523,17 @@
 
         // 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);
@@ -666,9 +672,9 @@
                 takeLocationValue = takeShop.getAddress();
             } else if (dto.getTakeLat() != null && dto.getTakeLgt() != null && StringUtils.isNotBlank(dto.getTakeLocation())) {
                 // 鏃犲彇浠堕棬搴楋紝鏍¢獙瀛樹欢鐐逛笌鑷�夊彇浠剁偣鏄惁鍦ㄥ悓涓�鍩庡競
-                if (MapUtil.isSameCity(depositShop.getLatitude(), depositShop.getLongitude(),
+                if (!MapUtil.isSameCity(depositShop.getLatitude(), depositShop.getLongitude(),
                         dto.getTakeLat().doubleValue(), dto.getTakeLgt().doubleValue())) {
-                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "寮傚湴瀵勫瓨璁㈠崟瀛樺彇鐐逛笉鑳藉湪鍚屼竴鍩庡競锛屽闇�鍚屽煄瀵勫瓨璇烽�夋嫨灏辫繎闂ㄥ簵");
+                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "寮傚湴瀵勫瓨璁㈠崟瀛樺彇鐐逛笉鍦ㄥ悓涓�鍩庡競锛屽闇�璇烽�夋嫨鍚屽煄闂ㄥ簵");
                 }
                 takeLat = dto.getTakeLat();
                 takeLgt = dto.getTakeLgt();
@@ -836,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;
     }
@@ -871,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);
     }
 
     /**
@@ -906,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;
+    }
 
 
 
@@ -1240,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);
@@ -1664,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());
@@ -1676,6 +1713,9 @@
             ordersMapper.updateById(order);
 
             saveCancelLog(order, "浼氬憳鍙栨秷璁㈠崟锛堝緟瀵勫瓨锛屽叏棰濋��娆撅級", reason, memberId);
+            // 閫氱煡浼氬憳锛氶��娆句腑
+            sendOrderNotice(memberId, Constants.MemberOrderNotify.REFUNDING, orderId,
+                    "orderNo", order.getCode());
             return;
         }
 
@@ -1686,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;
         }
 
@@ -1724,6 +1769,52 @@
         log.setCreateTime(new Date());
         log.setDeleted(Constants.ZERO);
         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
@@ -1767,6 +1858,17 @@
             }
         }
         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
@@ -1810,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
@@ -1878,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(), "闂ㄥ簵涓嶅瓨鍦�");
         }
@@ -1904,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
@@ -2048,6 +2153,12 @@
                     }
                 }
             }
+
+            // 閫氱煡鐩稿叧闂ㄥ簵锛氳鍗曞凡缁撶畻
+            notifyBothShops(order, Constants.ShopOrderNotify.SETTLED,
+                    "orderNo", order.getCode(),
+                    "amount", String.valueOf(Constants.getFormatMoney(
+                            order.getTotalAmount() != null ? order.getTotalAmount() : 0L)));
         }
     }
 
@@ -2144,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());
     }
 
     /**
@@ -2246,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) {
@@ -2268,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(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽鏍搁攢");
         }
@@ -2344,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);
         }
 
@@ -2364,6 +2502,14 @@
             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
@@ -2401,6 +2547,15 @@
         // 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
@@ -2552,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);
+        }
     }
 
     /**
@@ -2953,7 +3128,7 @@
         // 鑵捐鍦板浘璺濈鐭╅樀API璁$畻瀹為檯璺濈
         String from = fromLat + "," + fromLng;
         String to = toLat + "," + toLng;
-        JSONObject distanceResult = MapUtil.distanceSingle("driving", from, to);
+        JSONObject distanceResult = MapUtil.direction("driving", from, to);
 
         // 鑾峰彇璺濈锛堢背锛夛紝杞叕閲�
         int distanceMeters = distanceResult.getIntValue("distance");
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java
index f08ea2e..cd636c8 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/ShopInfoServiceImpl.java
@@ -239,8 +239,6 @@
     public void applyShop(ShopApplyDTO request) {
         Member member = memberMapper.selectById(request.getMemberId());
 
-        // 1. 鏍¢獙闂ㄥ簵鎵嬫満鍙峰敮涓�鎬э紙shop_info.telephone锛�
-        checkTelephoneUnique(request.getTelephone(), null);
 
         // 2. 鏍规嵁绫诲瀷鏍¢獙闄勪欢
         if (Constants.equalsInteger(request.getCompanyType(), Constants.ZERO)) {
@@ -315,14 +313,17 @@
             existing.setPassword(encryptedPassword);
             existing.setSalt(salt);
             existing.setAliAccount(request.getAliAccount());
-            existing.setAuditStatus(Constants.ZERO);
+            existing.setAliName(request.getAliName());
             existing.setUpdateTime(now);
             existing.setAuditRemark(null);
             existing.setAuditTime(null);
             existing.setAuditUserId(null);
+            existing.setAuditStatus(Constants.ZERO);
             shopInfoMapper.updateById(existing);
             shopId = existing.getId();
         } else {
+            // 1. 鏍¢獙闂ㄥ簵鎵嬫満鍙峰敮涓�鎬э紙shop_info.telephone锛�
+            checkTelephoneUnique(request.getTelephone(), null);
             // 鏂板缓
             ShopInfo shopInfo = new ShopInfo();
             shopInfo.setCompanyType(request.getCompanyType());
@@ -344,8 +345,7 @@
             shopInfo.setPassword(encryptedPassword);
             shopInfo.setSalt(salt);
             shopInfo.setAliAccount(request.getAliAccount());
-            shopInfo.setOpenid(member.getOpenid());
-            shopInfo.setAuditStatus(Constants.ZERO);
+            shopInfo.setAliName(request.getAliName());
             shopInfo.setStatus(Constants.ZERO);
             shopInfo.setDeleted(Constants.ZERO);
             shopInfo.setCreateTime(now);
@@ -552,6 +552,8 @@
         shopInfo.setLegalPersonName(request.getLegalPersonName());
         shopInfo.setLegalPersonPhone(request.getLegalPersonPhone());
         shopInfo.setLegalPersonCard(request.getLegalPersonCard());
+        shopInfo.setAliAccount(request.getAliAccount());
+        shopInfo.setAliName(request.getAliName());
         shopInfo.setUpdateTime(now);
         shopInfoMapper.updateById(shopInfo);
 
@@ -655,6 +657,9 @@
         vo.setPayStatus(shopInfo.getPayStatus());
         vo.setScore(shopInfo.getScore());
         vo.setCreateTime(shopInfo.getCreateTime());
+        vo.setAliAccount(shopInfo.getAliAccount());
+        vo.setAliName(shopInfo.getAliName());
+        vo.setDepositAmount(shopInfo.getDepositAmount());
 
         // 鎷兼帴鍥剧墖鍓嶇紑
         String imgPrefix = "";
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
index 3484958..0d0b4c4 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/WithdrawalOrdersServiceImpl.java
@@ -19,6 +19,8 @@
 import com.doumee.dao.business.model.ShopInfo;
 import com.doumee.dao.business.model.WithdrawalOrders;
 import com.doumee.dao.dto.WithdrawalApproveDTO;
+import com.doumee.config.alipay.AlipayFundTransUniTransfer;
+import com.doumee.dao.dto.AlipayTransferDTO;
 import com.doumee.dao.dto.WithdrawalDTO;
 import com.doumee.dao.system.SystemUserMapper;
 import com.doumee.dao.system.model.SystemUser;
@@ -27,6 +29,7 @@
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
@@ -229,6 +232,7 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void approve(WithdrawalApproveDTO dto) {
         if (dto == null || dto.getId() == null || dto.getStatus() == null) {
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "瀹℃壒鍙傛暟涓嶅畬鏁�");
@@ -249,13 +253,95 @@
         Integer currentUserId = getCurrentUserId();
         Date now = new Date();
 
+        // 瀹℃壒閫氳繃鏃讹紝璋冪敤鏀粯瀹濇墦娆�
+        Integer finalStatus = dto.getStatus();
+        String doneInfo = null;
+        if (Constants.ONE.equals(dto.getStatus())) {
+            String aliAccount = order.getAliAccount();
+            String aliName = null;
+
+            // 浠庡徃鏈烘垨闂ㄥ簵鑾峰彇鏀粯瀹濊处鎴峰拰瀹炲悕濮撳悕
+            if (StringUtils.isBlank(aliAccount)) {
+                if (Constants.equalsInteger(order.getMemberType(), Constants.ONE)) {
+                    DriverInfo driver = driverInfoMapper.selectOne(new QueryWrapper<DriverInfo>().lambda()
+                            .eq(DriverInfo::getMemberId, order.getMemberId())
+                            .eq(DriverInfo::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+                    if (driver != null) {
+                        aliAccount = driver.getAliAccount();
+                        aliName = driver.getAliName();
+                    }
+                } else if (Constants.equalsInteger(order.getMemberType(), Constants.TWO)) {
+                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
+                            .eq(ShopInfo::getRegionMemberId, order.getMemberId())
+                            .eq(ShopInfo::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+                    if (shop != null) {
+                        aliAccount = shop.getAliAccount();
+                        aliName = shop.getAliName();
+                    }
+                }
+            } else {
+                // 浠� WithdrawalOrders 鐨� aliAccount 鏌ュ搴斿鍚�
+                if (Constants.equalsInteger(order.getMemberType(), Constants.ONE)) {
+                    DriverInfo driver = driverInfoMapper.selectOne(new QueryWrapper<DriverInfo>().lambda()
+                            .eq(DriverInfo::getMemberId, order.getMemberId())
+                            .eq(DriverInfo::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+                    if (driver != null) {
+                        aliName = driver.getAliName();
+                    }
+                } else if (Constants.equalsInteger(order.getMemberType(), Constants.TWO)) {
+                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
+                            .eq(ShopInfo::getRegionMemberId, order.getMemberId())
+                            .eq(ShopInfo::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+                    if (shop != null) {
+                        aliName = shop.getAliName();
+                    }
+                }
+            }
+
+            if (StringUtils.isBlank(aliAccount)) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鏀粯瀹濇彁鐜拌处鎴锋湭閰嶇疆锛屾棤娉曟墦娆�");
+            }
+
+            // 閲戦杞崲锛氬垎 鈫� 鍏�
+            Long amountFen = order.getAmount() != null ? order.getAmount() : 0L;
+            BigDecimal transAmount = new BigDecimal(amountFen).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
+
+            AlipayTransferDTO transferDTO = new AlipayTransferDTO();
+            transferDTO.setOutBizNo(order.getOutBillNo());
+            transferDTO.setTransAmount(transAmount);
+            transferDTO.setPayeeAccount(aliAccount);
+            transferDTO.setPayeeName(aliName);
+            transferDTO.setRemark("鎻愮幇鎵撴");
+
+            String alipayOrderId;
+            try {
+                alipayOrderId = AlipayFundTransUniTransfer.transfer(transferDTO);
+            } catch (BusinessException e) {
+                throw e;
+            } catch (Exception e) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鏀粯瀹濇墦娆惧け璐ワ細" + e.getMessage());
+            }
+            doneInfo = "鏀粯瀹濊浆璐﹀崟鍙凤細" + alipayOrderId;
+        }
+
         WithdrawalOrders update = new WithdrawalOrders();
         update.setId(dto.getId());
-        update.setStatus(dto.getStatus());
+        update.setStatus(finalStatus);
         update.setUserId(currentUserId);
         update.setApproveTime(now);
         update.setApproveRemark(dto.getApproveRemark());
         update.setUpdateTime(now);
+        if (Constants.ONE.equals(finalStatus)) {
+            update.setDoneTime(now);
+            update.setDoneInfo(doneInfo);
+        } else if (doneInfo != null) {
+            update.setDoneTime(now);
+            update.setDoneInfo(doneInfo);
+        }
         withdrawalOrdersMapper.updateById(update);
 
         // 鏇存柊鍏宠仈鐨勬彁鐜� Revenue 璁板綍鐘舵��
@@ -267,15 +353,15 @@
                 .eq(Revenue::getDeleted, Constants.ZERO)
                 .last("limit 1"));
         if (withdrawalRevenue != null) {
-            Integer revenueStatus = Constants.ONE.equals(dto.getStatus()) ? Constants.ZERO : Constants.ONE; // 閫氳繃=0鎴愬姛, 椹冲洖=1澶辫触
+            Integer revenueStatus = Constants.ONE.equals(finalStatus) ? Constants.ZERO : Constants.ONE; // 閫氳繃=0鎴愬姛, 椹冲洖=1澶辫触
             revenueMapper.update(new UpdateWrapper<Revenue>().lambda()
                     .set(Revenue::getStatus, revenueStatus)
                     .set(Revenue::getUpdateTime, now)
                     .eq(Revenue::getId, withdrawalRevenue.getId()));
         }
 
-        // 椹冲洖鏃堕��鍥炰綑棰�
-        if (Constants.TWO.equals(dto.getStatus())) {
+        // 椹冲洖鎴栨墦娆惧け璐ユ椂閫�鍥炰綑棰�
+        if (Constants.TWO.equals(finalStatus)) {
             Long amountFen = order.getAmount() != null ? order.getAmount() : 0L;
             if (amountFen > 0 && order.getMemberId() != null) {
                 if (Constants.equalsInteger(order.getMemberType(), Constants.ONE)) {
diff --git a/server/services/src/main/resources/application-dev.yml b/server/services/src/main/resources/application-dev.yml
index fa3d1ce..368cafd 100644
--- a/server/services/src/main/resources/application-dev.yml
+++ b/server/services/src/main/resources/application-dev.yml
@@ -95,12 +95,15 @@
     mchKey: u4TSNtv0wFP7WRfnxBgijYOtRhS9FvlM #鍟嗘埛绉橀挜
     apiV3Key: 7tG4Vk9Zp2L8dXw5Jq0N3hR6yE1sF3cB #apiV3Key
     serialNumer: 3FE90C2F3D40A56E1C51926F31B8A8D22426CCE0 #鍟嗘埛璇佷功搴忓垪鍙�
-    notifyUrl: http://xiaopiqiu2.natapp1.cc/web/wxPayNotify
-    refundNotifyUrl: http://xiaopiqiu2.natapp1.cc/web/wxRefundNotify
+    publicKeyId: PUB_KEY_ID_0112298170022025071700291836000600
+    pubKeyPath: D:\DouMee\1229817002_20220310_cert\pub_key.pem #鍟嗘埛鏀粯鍏挜
     keyPath: D:\DouMee\1229817002_20220310_cert\apiclient_cert.p12
     privateCertPath: D:\DouMee\1229817002_20220310_cert\apiclient_cert.pem
     privateKeyPath: D:\DouMee\1229817002_20220310_cert\apiclient_key.pem
-    pubKeyPath: D:\DouMee\1229817002_20220310_cert\pub_key.pem #鍟嗘埛鏀粯鍏挜
+    notifyUrl: http://xiaopiqiu2.natapp1.cc/web/wxPayNotify
+    refundNotifyUrl: http://xiaopiqiu2.natapp1.cc/web/wxRefundNotify
+    v3NotifyUrl: http://xiaopiqiu2.natapp1.cc/web/api/wxPayV3Notify
+    v3RefundNotifyUrl: http://xiaopiqiu2.natapp1.cc/web/api/wxRefundV3Notify
 
 #    appId: wx6264b4f3a697cbe8
 #    appSecret: 23734577e8978138c946b727f0394027
@@ -123,5 +126,9 @@
 # 鑵捐鍦板浘apikey
 tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE
 
+# 楂樺痉鍦板浘apikey
+geocode_map_key: 9a62636d82d6c7c2372e57d80f99287c
+
+
 
 
diff --git a/server/services/src/main/resources/application-pro.yml b/server/services/src/main/resources/application-pro.yml
index d47e4ed..ba0b29d 100644
--- a/server/services/src/main/resources/application-pro.yml
+++ b/server/services/src/main/resources/application-pro.yml
@@ -60,6 +60,8 @@
     serialNumer: 3FE90C2F3D40A56E1C51926F31B8A8D22426CCE0 #鍟嗘埛璇佷功搴忓垪鍙�
     notifyUrl: http://xiaopiqiu2.natapp1.cc/web/wxPayNotify
     refundNotifyUrl: http://xiaopiqiu2.natapp1.cc/web/wxRefundNotify
+    v3NotifyUrl: http://xiaopiqiu2.natapp1.cc/web/api/wxPayV3Notify
+    v3RefundNotifyUrl: http://xiaopiqiu2.natapp1.cc/web/api/wxRefundV3Notify
     keyPath: D:\DouMee\1229817002_20220310_cert\apiclient_cert.p12
     privateCertPath: D:\DouMee\1229817002_20220310_cert\apiclient_cert.pem
     privateKeyPath: D:\DouMee\1229817002_20220310_cert\apiclient_key.pem
@@ -84,4 +86,7 @@
 
 
 # 鑵捐鍦板浘apikey
-tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE
\ No newline at end of file
+tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE
+
+# 楂樺痉鍦板浘apikey
+geocode_map_key:
\ No newline at end of file
diff --git a/server/services/src/main/resources/application-test.yml b/server/services/src/main/resources/application-test.yml
index 27f42d6..96c3955 100644
--- a/server/services/src/main/resources/application-test.yml
+++ b/server/services/src/main/resources/application-test.yml
@@ -83,6 +83,8 @@
     #mchKey: W97N53Q71326D6JZ2E9HY5M4VT4BAC8S
     notifyUrl: https://test.doumee.cn/jinkuai_admin/web/wxPayNotify
     refundNotifyUrl: https://test.doumee.cn/jinkuai_admin/web/wxRefundNotify
+    v3NotifyUrl: https://test.doumee.cn/jinkuai_admin/web/api/wxPayV3Notify
+    v3RefundNotifyUrl: https://test.doumee.cn/jinkuai_admin/web/api/wxRefundV3Notify
     keyPath: /usr/local/jars/payFile/apiclient_cert.p12
     privateCertPath: /usr/local/jars/payFile/apiclient_cert.pem
     privateKeyPath: /usr/local/jars/payFile/apiclient_key.pem
@@ -117,4 +119,7 @@
 
 
 # 鑵捐鍦板浘apikey
-tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE
\ No newline at end of file
+tencent_key: WE3BZ-HN6WS-ONDOH-62QCV-MNL6F-5NFNE
+
+# 楂樺痉鍦板浘apikey
+geocode_map_key:
\ No newline at end of file
diff --git a/server/web/src/main/java/com/doumee/api/web/ConfigApi.java b/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
index bc17bac..deb2560 100644
--- a/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/ConfigApi.java
@@ -3,7 +3,7 @@
 import com.doumee.core.annotation.LoginRequired;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
-import com.doumee.core.utils.Tencent.MapUtil;
+import com.doumee.core.utils.geocode.MapUtil;
 import com.doumee.dao.business.model.Areas;
 import com.doumee.dao.business.model.Banner;
 import com.doumee.dao.business.model.Category;
diff --git a/server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java b/server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java
index 2dc0bc4..45b6b08 100644
--- a/server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/DriverInfoApi.java
@@ -10,6 +10,7 @@
 import com.doumee.dao.dto.DriverActiveOrderDTO;
 import com.doumee.dao.dto.DriverGrabOrderDTO;
 import com.doumee.dao.dto.DriverLoginRequest;
+import com.doumee.dao.dto.DriverPickupDTO;
 import com.doumee.dao.dto.DriverRegisterRequest;
 import com.doumee.dao.dto.DriverVerifyRequest;
 import com.doumee.dao.vo.AccountResponse;
@@ -142,6 +143,19 @@
 
     @LoginDriverRequired
     @Trace
+    @ApiOperation(value = "鍙告満鎶㈠崟", notes = "瀵瑰凡瀵勫瓨(status=2)鐨勫紓鍦板瘎瀛樿鍗曞彂璧锋姠鍗�")
+    @PostMapping("/grabOrder")
+    @ApiImplicitParams({
+            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
+            @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "orderId", value = "璁㈠崟涓婚敭", required = true)
+    })
+    public ApiResponse grabOrder(@RequestParam Integer orderId) {
+        driverInfoService.grabOrder(this.getDriverId(), orderId);
+        return ApiResponse.success("鎶㈠崟鎴愬姛");
+    }
+
+    @LoginDriverRequired
+    @Trace
     @ApiOperation(value = "鍙告満杩涜涓鍗�", notes = "鏌ヨ宸叉姠鍗�(status=3)鎴栨淳閫佷腑(status=4)鐨勮鍗曞垪琛�")
     @PostMapping("/activeOrders")
     @ApiImplicitParams({
@@ -176,4 +190,16 @@
         return ApiResponse.success("鍙栨秷鎴愬姛");
     }
 
+    @LoginDriverRequired
+    @Trace
+    @ApiOperation(value = "鍙告満瀹屾垚鍙栦欢", notes = "宸叉帴鍗�(status=3)鏃剁‘璁ゅ彇浠讹紝璁㈠崟杩涘叆娲鹃�佷腑(status=4)")
+    @PostMapping("/confirmPickup")
+    @ApiImplicitParams({
+            @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true)
+    })
+    public ApiResponse confirmPickup(@RequestBody @Valid DriverPickupDTO dto) {
+        driverInfoService.confirmPickup(this.getDriverId(), dto);
+        return ApiResponse.success("鎿嶄綔鎴愬姛");
+    }
+
 }
diff --git a/server/web/src/main/java/com/doumee/api/web/PaymentCallback.java b/server/web/src/main/java/com/doumee/api/web/PaymentCallback.java
index 328d3fa..40e530d 100644
--- a/server/web/src/main/java/com/doumee/api/web/PaymentCallback.java
+++ b/server/web/src/main/java/com/doumee/api/web/PaymentCallback.java
@@ -1,21 +1,28 @@
 package com.doumee.api.web;
 
 import com.doumee.config.wx.WxMiniConfig;
+import com.doumee.config.wx.WxPayV3Service;
 import com.doumee.core.constants.Constants;
 import com.doumee.core.utils.ID;
+import com.doumee.dao.business.OrdersRefundMapper;
+import com.doumee.dao.business.OrdersMapper;
+import com.doumee.dao.business.model.Notice;
+import com.doumee.dao.business.model.Orders;
+import com.doumee.dao.business.model.OrdersRefund;
+import com.doumee.service.business.NoticeService;
 import com.doumee.service.business.OrdersService;
 import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import com.wechat.pay.java.service.refund.model.RefundNotification;
+import com.wechat.pay.java.service.refund.model.Status;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
-import java.util.Date;
-import java.util.Objects;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * 鏀粯鍥炶皟
@@ -31,37 +38,43 @@
     @Autowired
     private OrdersService ordersService;
 
+    @Autowired
+    private WxPayV3Service wxPayV3Service;
+
+    @Autowired
+    private OrdersRefundMapper ordersRefundMapper;
+
+    @Autowired
+    private OrdersMapper ordersMapper;
+
+    @Autowired
+    private NoticeService noticeService;
+
+
+    // ==================== V2 鍥炶皟 ====================
 
     @PostMapping("/web/api/wxPayNotify")
     public String wxPay_notify(@RequestBody String xmlResult) {
         String wxId = ID.nextGUID();
-        log.info("鏀粯鍥炶皟淇℃伅("+wxId+") = > "  + xmlResult);
-        if (StringUtils.isEmpty(xmlResult)){
+        log.info("V2鏀粯鍥炶皟淇℃伅(" + wxId + ") => " + xmlResult);
+        if (StringUtils.isEmpty(xmlResult)) {
             return null;
         }
         try {
             WxPayOrderNotifyResult result = WxMiniConfig.wxPayService.parseOrderNotifyResult(xmlResult);
-            //鑷畾涔夎鍗曞彿
             String outTradeNo = result.getOutTradeNo();
-            //寰俊璁㈠崟鍙�
             String paymentNo = result.getTransactionId();
 
-
-
             if (Constants.SUCCESS.equals(result.getReturnCode())) {
-                // 鏀粯鎴愬姛
                 switch (result.getAttach()) {
-                    //瀵勫瓨璁㈠崟
                     case "storageOrder": {
                         ordersService.handleStorageOrderPayNotify(outTradeNo, paymentNo);
                         break;
                     }
-                    //搴楅摵鎶奸噾璁㈠崟
                     case "shopDeposit": {
                         ordersService.handleShopDepositPayNotify(outTradeNo, paymentNo);
                         break;
                     }
-                    //閫炬湡璐圭敤璁㈠崟
                     case "overdueFee": {
                         ordersService.handleOverdueFeePayNotify(outTradeNo, paymentNo);
                         break;
@@ -72,11 +85,133 @@
             return WxPayNotifyResponse.fail(result.getReturnMsg());
         } catch (Exception e) {
             e.printStackTrace();
-            log.error("寰俊鍥炶皟缁撴灉寮傚父,寮傚父鍘熷洜{}", e.getLocalizedMessage());
+            log.error("V2寰俊鍥炶皟缁撴灉寮傚父,寮傚父鍘熷洜{}", e.getLocalizedMessage());
             return WxPayNotifyResponse.fail(e.getMessage());
         }
     }
 
+    // ==================== V3 鍥炶皟 ====================
 
+    /**
+     * V3鏀粯鍥炶皟
+     */
+    @PostMapping("/web/api/wxPayV3Notify")
+    public Map<String, String> wxPayV3Notify(
+            @RequestHeader("Wechatpay-Serial") String serialNumber,
+            @RequestHeader("Wechatpay-Timestamp") String timestamp,
+            @RequestHeader("Wechatpay-Nonce") String nonce,
+            @RequestHeader("Wechatpay-Signature") String signature,
+            @RequestBody String body) {
+        String wxId = ID.nextGUID();
+        log.info("V3鏀粯鍥炶皟淇℃伅({}) => {}", wxId, body);
+        try {
+            Transaction transaction = wxPayV3Service.parsePayNotify(
+                    serialNumber, timestamp, nonce, signature, body);
+
+            String outTradeNo = transaction.getOutTradeNo();
+            String paymentNo = transaction.getTransactionId();
+
+            if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
+                String attach = transaction.getAttach();
+                if (StringUtils.isNotBlank(attach)) {
+                    switch (attach) {
+                        case "storageOrder":
+                            ordersService.handleStorageOrderPayNotify(outTradeNo, paymentNo);
+                            break;
+                        case "shopDeposit":
+                            ordersService.handleShopDepositPayNotify(outTradeNo, paymentNo);
+                            break;
+                        case "overdueFee":
+                            ordersService.handleOverdueFeePayNotify(outTradeNo, paymentNo);
+                            break;
+                    }
+                }
+            }
+
+            Map<String, String> response = new HashMap<>();
+            response.put("code", "SUCCESS");
+            response.put("message", "澶勭悊鎴愬姛");
+            return response;
+        } catch (Exception e) {
+            log.error("V3鏀粯鍥炶皟寮傚父,寮傚父鍘熷洜{}", e.getLocalizedMessage());
+            Map<String, String> response = new HashMap<>();
+            response.put("code", "FAIL");
+            response.put("message", e.getMessage());
+            return response;
+        }
+    }
+
+    /**
+     * V3閫�娆惧洖璋�
+     */
+    @PostMapping("/web/api/wxRefundV3Notify")
+    public Map<String, String> wxRefundV3Notify(
+            @RequestHeader("Wechatpay-Serial") String serialNumber,
+            @RequestHeader("Wechatpay-Timestamp") String timestamp,
+            @RequestHeader("Wechatpay-Nonce") String nonce,
+            @RequestHeader("Wechatpay-Signature") String signature,
+            @RequestBody String body) {
+        String wxId = ID.nextGUID();
+        log.info("V3閫�娆惧洖璋冧俊鎭�({}) => {}", wxId, body);
+        try {
+            RefundNotification refundNotification = wxPayV3Service.parseRefundNotify(
+                    serialNumber, timestamp, nonce, signature, body);
+
+            log.info("V3閫�娆惧洖璋冪粨鏋�, outTradeNo={}, outRefundNo={}, refundStatus={}",
+                    refundNotification.getOutTradeNo(),
+                    refundNotification.getOutRefundNo(),
+                    refundNotification.getRefundStatus());
+
+            // 鏍规嵁閫�娆惧崟鍙锋洿鏂伴��娆捐褰曠姸鎬�
+            String outRefundNo = refundNotification.getOutRefundNo();
+            OrdersRefund refundRecord = ordersRefundMapper.selectOne(
+                    new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<OrdersRefund>().lambda()
+                            .eq(OrdersRefund::getRefundCode, outRefundNo)
+                            .eq(OrdersRefund::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+            if (refundRecord != null) {
+                Status refundStatus = refundNotification.getRefundStatus();
+                if (Status.SUCCESS.equals(refundStatus)) {
+                    refundRecord.setStatus(Constants.ONE); // 閫�娆炬垚鍔�
+                    refundRecord.setRefundTime(new java.util.Date());
+                } else if (Status.CLOSED.equals(refundStatus) || Status.ABNORMAL.equals(refundStatus)) {
+                    refundRecord.setStatus(Constants.TWO); // 閫�娆惧け璐�
+                }
+                ordersRefundMapper.updateById(refundRecord);
+                log.info("閫�娆捐褰曠姸鎬佸凡鏇存柊, refundRecordId={}, status={}", refundRecord.getId(), refundRecord.getStatus());
+
+                // 閫�娆炬垚鍔� 鈫� 閫氱煡浼氬憳
+                if (Status.SUCCESS.equals(refundStatus) && refundRecord.getOrderId() != null) {
+                    Orders refundOrder = ordersMapper.selectById(refundRecord.getOrderId());
+                    if (refundOrder != null) {
+                        Notice notice = new Notice();
+                        notice.setUserType(0);
+                        notice.setUserId(refundOrder.getMemberId());
+                        notice.setTitle(Constants.MemberOrderNotify.REFUNDED.getTitle());
+                        notice.setContent(Constants.MemberOrderNotify.REFUNDED.format(
+                                "orderNo", refundOrder.getCode(),
+                                "amount", String.valueOf(Constants.getFormatMoney(refundOrder.getRefundAmount() != null ? refundOrder.getRefundAmount() : 0L))));
+                        notice.setObjId(refundOrder.getId());
+                        notice.setObjType(0);
+                        notice.setStatus(0);
+                        notice.setIsdeleted(Constants.ZERO);
+                        notice.setCreateDate(new java.util.Date());
+                        noticeService.create(notice);
+                    }
+                }
+            }
+
+            Map<String, String> response = new HashMap<>();
+            response.put("code", "SUCCESS");
+            response.put("message", "澶勭悊鎴愬姛");
+            return response;
+        } catch (Exception e) {
+            log.error("V3閫�娆惧洖璋冨紓甯�,寮傚父鍘熷洜{}", e.getLocalizedMessage());
+            Map<String, String> response = new HashMap<>();
+            response.put("code", "FAIL");
+            response.put("message", e.getMessage());
+            return response;
+        }
+    }
 
 }
diff --git a/server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java b/server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java
index d16ee9f..6595950 100644
--- a/server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java
+++ b/server/web/src/main/java/com/doumee/api/web/ShopInfoApi.java
@@ -94,14 +94,14 @@
         return ApiResponse.success(shopInfoService.getShopMaintainInfo(this.getMemberId()));
     }
 
-    @LoginShopRequired
+    @LoginRequired
     @ApiOperation("闂ㄥ簵鏀粯鎶奸噾")
     @PostMapping("/payDeposit")
     @ApiImplicitParams({
             @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "闂ㄥ簵token鍊�", required = true)
     })
     public ApiResponse<PayResponse> payDeposit() {
-        return ApiResponse.success("鎿嶄綔鎴愬姛", ordersService.payShopDeposit(getShopId()));
+        return ApiResponse.success("鎿嶄綔鎴愬姛", ordersService.payShopDeposit(getMemberId()));
     }
 
 }

--
Gitblit v1.9.3