From 668e570bd1db6bd00e4293b6977e6d3d051053ce Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期四, 27 十一月 2025 00:07:46 +0800
Subject: [PATCH] feat: 修改app录入界面及车辆用户同步

---
 dryad-payment/src/main/resources/mapper/NotifyLogMapper.xml                                                   |   55 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java                               |    9 
 sql/dryad_payment_tables.sql                                                                                  |  126 
 dryad-payment/src/main/resources/META-INF/spring.factories                                                    |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskPayment.java                                        |  267 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/DepartmentSyncTask.java                                      |   24 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java                                         |    1 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/AlipayConfig.java                         |   55 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/QrCodeUtil.java                             |   61 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java                          |   94 
 sql/add_emergency_resync_flag.sql                                                                             |    9 
 dryad-payment/src/main/java/com/ruoyi/payment/common/AjaxResult.java                                          |   87 
 dryad-payment/src/main/resources/mapper/PaymentOrderMapper.xml                                                |   77 
 ruoyi-ui/src/views/task/detail/index.vue                                                                      |  104 
 app/pages/task/create-emergency.vue                                                                           |  176 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/DepartmentSyncDTO.java                                     |    2 
 sql/additional_fee_sync_update.sql                                                                            |   34 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/PayChannel.java                                    |   40 
 prd/分公司默认出发地配置功能说明.md                                                                                         |  189 
 dryad-payment/doc/代码生成总结.md                                                                                   |  268 
 dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentService.java                         |  338 +
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java                                   |   39 
 app/plugins/index.js                                                                                          |    3 
 dryad-payment/README.md                                                                                       |  254 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/event/PaymentSuccessEvent.java                           |   50 
 app/pages/task/detail.vue                                                                                     |  218 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java                                               |   11 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentOrderMapper.java       |   40 
 app/pages/task/edit-emergency.vue                                                                             |  554 +
 app/components/OrganizationSelector.vue                                                                       |    6 
 dryad-payment/.gitignore                                                                                      |   35 
 ruoyi-admin/src/main/resources/application.yml                                                                |   55 
 dryad-payment/src/main/resources/mapper/PaymentTransactionMapper.xml                                          |   74 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskEmergencyMapper.java                                |   10 
 ruoyi-system/src/main/java/com/ruoyi/system/event/PaymentSuccessEventListener.java                            |   52 
 dryad-payment/src/main/resources/application.yml                                                              |   98 
 dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentNotifyController.java              |  128 
 sql/task_payment_method_dict.sql                                                                              |   15 
 dryad-payment/pom.xml                                                                                         |  199 
 ruoyi-admin/src/main/resources/application-dev.yml                                                            |    2 
 dryad-payment/src/main/java/com/ruoyi/payment/config/PaymentAutoConfiguration.java                            |   48 
 dryad-payment/doc/支付宝第三方接口测试文档.md                                                                             |  320 +
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/BizCallbackLogMapper.java     |   29 
 ruoyi-system/src/main/resources/mapper/system/PaidMoneyAddMapper.xml                                          |   82 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/model/BizCallbackLog.java                                |   49 
 dryad-payment/src/main/resources/mapper/BizCallbackLogMapper.xml                                              |   50 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java                                          |   21 
 ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java                               |   54 
 pom.xml                                                                                                       |    1 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java                                              |    9 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentResultVO.java                                |   81 
 ruoyi-ui/src/api/task.js                                                                                      |   31 
 dryad-payment/API接口文档.md                                                                                      |  470 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskEmergencyService.java                             |    9 
 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java                                    |  111 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayUtil.java                   |   43 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java                                      |   11 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyMapper.java                                       |   67 
 app/api/map.js                                                                                                |    3 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/PaymentCallbackController.java                      |   75 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAdditionalFeeMapper.java                            |   75 
 doc/转运任务支付功能设计方案.md                                                                                           |  172 
 ruoyi-system/pom.xml                                                                                          |    5 
 dryad-payment/src/main/java/com/ruoyi/payment/example/PaymentIntegrationExample.java                          |  140 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskPaymentService.java                               |   92 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java                     |  202 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentModuleServiceImpl.java                        |  118 
 sql/PaidMoney.sql                                                                                             |   16 
 sql/resync_vehicle_personnel_job.sql                                                                          |   96 
 dryad-payment/src/main/resources/sql/schema.sql                                                               |  134 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentTransaction.java                            |   66 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskPaymentMapper.java                                  |  108 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ILegacySystemSyncService.java                             |   17 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentSyncService.java                                  |   44 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskEmergencyServiceImpl.java                     |   26 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SignUtil.java                               |   63 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java                       |   70 
 ruoyi-system/src/main/resources/mapper/system/PaidMoneyMapper.xml                                             |  109 
 app/components/DepartureSelector.vue                                                                          |  419 +
 dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/ClientType.java                                    |   40 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayV2Client.java                |  179 
 dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentResponse.java                             |   33 
 sql/update_task_payment_20250123.sql                                                                          |    8 
 ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java                                    |   18 
 ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml                                      |   30 
 dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentRequest.java                              |   38 
 dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/HealthController.java                     |   38 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java                               |    0 
 sql/sys_dept_add_departure_fields.sql                                                                         |   14 
 app/components/HospitalSelector.vue                                                                           |    6 
 ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java                                                     |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java                                      |   28 
 sql/task_payment_tables.sql                                                                                   |   53 
 app/pages/task/settlement.vue                                                                                 |  832 ++
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayUtil.java                    |  129 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/model/NotifyLog.java                                     |   46 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/model/OperationAudit.java                                |   40 
 dryad-payment/src/main/java/com/ruoyi/payment/interfaces/callback/PaymentCallback.java                        |   32 
 prd/支付信息双向同步功能说明.md                                                                                           |  276 +
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentInfoVO.java                                  |  158 
 ruoyi-system/src/main/resources/mapper/system/SysTaskPaymentMapper.xml                                        |  156 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/TransactionStatus.java                             |   46 
 dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentNotifyService.java                   |  218 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentTransactionMapper.java |   44 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SnowflakeIdGenerator.java                   |   96 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/OperationAuditMapper.java     |   24 
 ruoyi-system/src/main/resources/mapper/system/DepartmentSyncMapper.xml                                        |   18 
 sql/update_additional_fee_type_dict.sql                                                                       |   10 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoneyAdd.java                                          |  118 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayThirdPartyClient.java       |  196 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IAdditionalFeeSyncService.java                            |   42 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java                       |  415 +
 app/plugins/dict.js                                                                                           |    7 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/model/GoodsDetail.java                                   |   51 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java                   |    6 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/OrderStatus.java                                   |   52 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyAddMapper.java                                    |   68 
 dryad-payment/src/main/java/com/ruoyi/payment/application/service/BizCallbackService.java                     |  247 
 sql/PaidMoney_Add.sql                                                                                         |   12 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/BusinessCallbackConfig.java               |   37 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java                    |  315 +
 doc/支付功能实现进度.md                                                                                               |  137 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java                           |    2 
 sql/payment_sync_job.sql                                                                                      |  113 
 dryad-payment/src/main/java/com/ruoyi/payment/PaymentApplication.java                                         |   29 
 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml                                               |   24 
 dryad-payment/doc/支付宝第三方接口开发总结.md                                                                             |  248 
 doc/支付宝支付方式配置说明.md                                                                                            |   85 
 dryad-payment/src/main/resources/mapper/OperationAuditMapper.xml                                              |   31 
 dryad-payment/doc/支付宝第三方接口-快速开始.md                                                                            |  171 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/WechatPayConfig.java                      |   36 
 dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentOrder.java                                  |   88 
 ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentModuleService.java                                |   36 
 dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentController.java                    |  122 
 ruoyi-admin/pom.xml                                                                                           |    8 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/QrCodeConfig.java                         |   22 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java                             |   85 
 prd/附加费用双向同步功能说明.md                                                                                           |  285 +
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskPaymentController.java                         |  107 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/NotifyLogMapper.java          |   35 
 dryad-payment/集成使用指南.md                                                                                       |  317 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java                          |  298 +
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAdditionalFee.java                                  |  168 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java                              |  327 +
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/DepartmentSyncMapper.java                                  |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoney.java                                             |  191 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentCreateVO.java                                |   56 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java                                       |   49 
 sql/payment_sync_update.sql                                                                                   |   34 
 dryad-payment/doc/支付宝第三方接口使用说明.md                                                                             |  199 
 dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayF2FClient.java              |  173 
 dryad-payment/doc/设计方案.md                                                                                     | 1067 +++
 app/api/payment.js                                                                                            |   56 
 ruoyi-system/src/main/resources/mapper/system/SysTaskAdditionalFeeMapper.xml                                  |   86 
 154 files changed, 15,992 insertions(+), 276 deletions(-)

diff --git a/app/api/map.js b/app/api/map.js
index 163ff1d..03b2060 100644
--- a/app/api/map.js
+++ b/app/api/map.js
@@ -85,6 +85,9 @@
   })
 }
 
+// 鍒悕锛屼笌baiduGeocoding鍔熻兘鐩稿悓
+export const baiduGeocode = baiduGeocoding
+
 // 鐧惧害鍦板浘璺嚎瑙勫垝API锛堣绠椾袱涓潗鏍囦箣闂寸殑椹捐溅璺濈锛�
 export function baiduRouteDriving(origin, destination) {
   // 鍙傛暟楠岃瘉
diff --git a/app/api/payment.js b/app/api/payment.js
new file mode 100644
index 0000000..782398b
--- /dev/null
+++ b/app/api/payment.js
@@ -0,0 +1,56 @@
+import request from '@/utils/request'
+
+/**
+ * 鑾峰彇浠诲姟鏀粯淇℃伅
+ */
+export function getPaymentInfo(taskId) {
+  return request({
+    url: '/task/payment/info',
+    method: 'get',
+    params: { taskId }
+  })
+}
+
+/**
+ * 鏂板闄勫姞璐圭敤
+ */
+export function addAdditionalFee(data) {
+  return request({
+    url: '/task/payment/additional-fee/add',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 鍒犻櫎闄勫姞璐圭敤
+ */
+export function removeAdditionalFee(data) {
+  return request({
+    url: '/task/payment/additional-fee/remove',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 鍒涘缓鏀粯
+ */
+export function createPayment(data) {
+  return request({
+    url: '/task/payment/create',
+    method: 'post',
+    data
+  })
+}
+
+/**
+ * 鏌ヨ鏀粯鐘舵��
+ */
+export function getPaymentStatus(taskId, paymentId) {
+  return request({
+    url: '/task/payment/status',
+    method: 'get',
+    params: { taskId, paymentId }
+  })
+}
diff --git a/app/components/DepartureSelector.vue b/app/components/DepartureSelector.vue
new file mode 100644
index 0000000..b863f91
--- /dev/null
+++ b/app/components/DepartureSelector.vue
@@ -0,0 +1,419 @@
+<template>
+  <view class="departure-selector">
+    <view class="form-item">
+      <view class="form-label" :class="{ required: required }" v-if="showLabel">{{ label }}</view>
+      <view class="departure-input-container">
+        <view class="address-input-wrapper">
+          <input 
+            class="form-input departure-input" 
+            :placeholder="placeholder" 
+            :value="addressValue"
+            @input="onAddressInput"
+            @focus="onAddressFocus"
+          />
+          <view class="address-suggestions" v-if="showAddressSuggestions && addressSuggestions.length > 0">
+            <view 
+              class="address-suggestion-item" 
+              v-for="(item, index) in addressSuggestions" 
+              :key="index"
+              @click="selectAddressSuggestion(item)"
+            >
+              <view class="suggestion-name">{{ item.name }}</view>
+              <view class="suggestion-address">{{ item.district }}{{ item.address }}</view>
+            </view>
+          </view>
+        </view>
+        
+        <view class="current-location-btn" @click="getCurrentLocation">
+          <uni-icons type="location" size="20" color="#007AFF"></uni-icons>
+          <text>褰撳墠浣嶇疆</text>
+        </view>
+      </view>
+      
+      <view class="form-tip" v-if="showTip && addressValue">
+        <text>{{ tipText }}</text>
+      </view>
+      
+      <view class="coordinate-info" v-if="showCoordinates && hasCoordinates">
+        <text class="coordinate-label">GPS鍧愭爣锛�</text>
+        <text class="coordinate-value">{{ longitudeValue }}, {{ latitudeValue }}</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import { baiduPlaceSuggestion, reverseGeocoder } from "@/api/map"
+
+export default {
+  name: 'DepartureSelector',
+  props: {
+    // 鏍囩鏂囨湰
+    label: {
+      type: String,
+      default: '鍑哄彂鍦�'
+    },
+    // 鏄惁鏄剧ず鏍囩
+    showLabel: {
+      type: Boolean,
+      default: true
+    },
+    // 鏄惁蹇呭~
+    required: {
+      type: Boolean,
+      default: false
+    },
+    // 鍗犱綅绗�
+    placeholder: {
+      type: String,
+      default: '璇疯緭鍏ュ嚭鍙戝湴鍦板潃'
+    },
+    // 褰撳墠鍦板潃
+    address: {
+      type: String,
+      default: ''
+    },
+    // 缁忓害
+    longitude: {
+      type: [Number, String],
+      default: null
+    },
+    // 绾害
+    latitude: {
+      type: [Number, String],
+      default: null
+    },
+    // 褰撳墠鍖哄煙锛堢敤浜庡湴鍧�鎼滅储锛�
+    region: {
+      type: String,
+      default: '骞垮窞'
+    },
+    // 鏄惁鏄剧ず鎻愮ず淇℃伅
+    showTip: {
+      type: Boolean,
+      default: true
+    },
+    // 鎻愮ず鏂囨湰
+    tipText: {
+      type: String,
+      default: '鎻愮ず锛氬彲淇敼榛樿鍑哄彂鍦板湴鍧�'
+    },
+    // 鏄惁鏄剧ず鍧愭爣淇℃伅
+    showCoordinates: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      // 鍦板潃寤鸿鐩稿叧
+      addressSuggestions: [],
+      showAddressSuggestions: false,
+      addressSearchTimer: null
+    }
+  },
+  computed: {
+    addressValue() {
+      return this.address || ''
+    },
+    longitudeValue() {
+      return this.longitude || null
+    },
+    latitudeValue() {
+      return this.latitude || null
+    },
+    hasCoordinates() {
+      return this.longitudeValue !== null && this.latitudeValue !== null
+    }
+  },
+  methods: {
+    // 鍦板潃杈撳叆
+    onAddressInput(e) {
+      const address = e.detail.value
+      
+      // 瑙﹀彂鍦板潃鏇存柊浜嬩欢
+      this.$emit('update:address', address)
+      this.$emit('address-change', address)
+      
+      // 闃叉姈澶勭悊鍦板潃鎼滅储
+      if (this.addressSearchTimer) {
+        clearTimeout(this.addressSearchTimer)
+      }
+      
+      if (!address || address.trim() === '') {
+        this.addressSuggestions = []
+        this.showAddressSuggestions = false
+        return
+      }
+      
+      this.addressSearchTimer = setTimeout(() => {
+        this.searchAddress(address)
+      }, 300)
+    },
+    
+    // 鎼滅储鍦板潃寤鸿
+    searchAddress(query) {
+      baiduPlaceSuggestion(query, this.region).then(response => {
+        if (response.code === 200 && response.data) {
+          this.addressSuggestions = response.data
+          this.showAddressSuggestions = true
+        } else {
+          this.addressSuggestions = []
+          this.showAddressSuggestions = false
+        }
+      }).catch(error => {
+        console.error('鎼滅储鍦板潃澶辫触:', error)
+        this.addressSuggestions = []
+        this.showAddressSuggestions = false
+      })
+    },
+    
+    // 鍦板潃杈撳叆妗嗚幏寰楃劍鐐�
+    onAddressFocus() {
+      if (this.addressValue && this.addressSuggestions.length > 0) {
+        this.showAddressSuggestions = true
+      }
+    },
+    
+    // 閫夋嫨鍦板潃寤鸿
+    selectAddressSuggestion(item) {
+      const fullAddress = item.district + item.address
+      
+      // 鏇存柊鍦板潃
+      this.$emit('update:address', fullAddress)
+      
+      // 鏇存柊鍧愭爣
+      if (item.location) {
+        this.$emit('update:longitude', item.location.lng)
+        this.$emit('update:latitude', item.location.lat)
+      }
+      
+      // 瑙﹀彂閫夋嫨浜嬩欢
+      this.$emit('address-selected', {
+        address: fullAddress,
+        longitude: item.location ? item.location.lng : null,
+        latitude: item.location ? item.location.lat : null,
+        location: item.location
+      })
+      
+      this.showAddressSuggestions = false
+      this.addressSuggestions = []
+    },
+    
+    // 鑾峰彇褰撳墠浣嶇疆
+    getCurrentLocation() {
+      uni.showLoading({
+        title: '鑾峰彇浣嶇疆涓�...'
+      })
+      
+      // 浣跨敤uni-app鐨凣PS瀹氫綅鍔熻兘
+      uni.getLocation({
+        type: 'gcj02', // 杩斿洖鍥芥祴灞�鍧愭爣锛岄�傜敤浜庡浗鍐呭湴鍥�
+        success: (res) => {
+          console.log('鑾峰彇鍒癎PS鍧愭爣:', res)
+          const latitude = res.latitude
+          const longitude = res.longitude
+          
+          // 鏇存柊GPS鍧愭爣
+          this.$emit('update:longitude', longitude)
+          this.$emit('update:latitude', latitude)
+          
+          // 璋冪敤閫嗗湴鐞嗙紪鐮佹帴鍙o紝灏嗗潗鏍囪浆鎹负鍦板潃
+          reverseGeocoder(latitude, longitude)
+            .then(response => {
+              uni.hideLoading()
+              
+              if (response.code === 200 && response.data) {
+                // 鑾峰彇璇︾粏鍦板潃
+                const address = response.data.address || response.data.formattedAddress || ''
+                
+                // 鏇存柊鍦板潃
+                this.$emit('update:address', address)
+                
+                // 瑙﹀彂浣嶇疆鑾峰彇鎴愬姛浜嬩欢
+                this.$emit('location-success', {
+                  address: address,
+                  longitude: longitude,
+                  latitude: latitude
+                })
+                
+                console.log('閫嗗湴鐞嗙紪鐮佹垚鍔�:', address)
+                this.$modal.showToast('宸茶幏鍙栧綋鍓嶄綅缃�')
+              } else {
+                console.error('閫嗗湴鐞嗙紪鐮佸け璐�:', response.msg)
+                
+                // 鍗充娇鍦板潃瑙f瀽澶辫触锛屽潗鏍囧凡淇濆瓨锛岃Е鍙戜簨浠�
+                this.$emit('location-success', {
+                  address: '',
+                  longitude: longitude,
+                  latitude: latitude
+                })
+                
+                this.$modal.showToast('浣嶇疆瑙f瀽澶辫触锛岃鎵嬪姩杈撳叆鍦板潃')
+              }
+            })
+            .catch(error => {
+              uni.hideLoading()
+              console.error('閫嗗湴鐞嗙紪鐮佸け璐�:', error)
+              
+              // 鍗充娇鍦板潃瑙f瀽澶辫触锛屽潗鏍囧凡淇濆瓨锛岃Е鍙戜簨浠�
+              this.$emit('location-success', {
+                address: '',
+                longitude: longitude,
+                latitude: latitude
+              })
+              
+              this.$modal.showToast('浣嶇疆瑙f瀽澶辫触锛屼絾GPS鍧愭爣宸蹭繚瀛�')
+            })
+        },
+        fail: (err) => {
+          uni.hideLoading()
+          console.error('鑾峰彇浣嶇疆澶辫触:', err)
+          
+          // 鎻愮ず鐢ㄦ埛鍙兘鐨勫師鍥�
+          let errorMsg = '鑾峰彇浣嶇疆澶辫触'
+          if (err.errMsg && err.errMsg.includes('auth deny')) {
+            errorMsg = '璇峰湪璁剧疆涓紑鍚綅缃潈闄�'
+          } else if (err.errMsg && err.errMsg.includes('timeout')) {
+            errorMsg = '瀹氫綅瓒呮椂锛岃绋嶅悗閲嶈瘯'
+          }
+          
+          // 瑙﹀彂澶辫触浜嬩欢
+          this.$emit('location-error', err)
+          
+          this.$modal.showToast(errorMsg)
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.departure-selector {
+  .form-item {
+    margin-bottom: 40rpx;
+    
+    .form-label {
+      font-size: 28rpx;
+      margin-bottom: 15rpx;
+      color: #333;
+      
+      &.required::before {
+        content: '*';
+        color: #ff0000;
+        margin-right: 5rpx;
+      }
+    }
+    
+    .departure-input-container {
+      display: flex;
+      align-items: flex-start;
+      gap: 15rpx;
+      
+      .address-input-wrapper {
+        flex: 1;
+        position: relative;
+        
+        .departure-input {
+          width: 100%;
+          height: 70rpx;
+          padding: 0 20rpx;
+          border: 1rpx solid #eee;
+          border-radius: 10rpx;
+          font-size: 28rpx;
+          box-sizing: border-box;
+        }
+        
+        .address-suggestions {
+          position: absolute;
+          top: 75rpx;
+          left: 0;
+          right: 0;
+          max-height: 400rpx;
+          overflow-y: auto;
+          background-color: white;
+          border: 1rpx solid #eee;
+          border-radius: 10rpx;
+          box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+          z-index: 100;
+          
+          .address-suggestion-item {
+            padding: 20rpx;
+            border-bottom: 1rpx solid #f0f0f0;
+            
+            &:last-child {
+              border-bottom: none;
+            }
+            
+            &:active {
+              background-color: #f5f5f5;
+            }
+            
+            .suggestion-name {
+              font-size: 28rpx;
+              color: #333;
+              margin-bottom: 8rpx;
+            }
+            
+            .suggestion-address {
+              font-size: 24rpx;
+              color: #999;
+            }
+          }
+        }
+      }
+      
+      .current-location-btn {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        padding: 10rpx 20rpx;
+        background-color: #f0f7ff;
+        border-radius: 10rpx;
+        white-space: nowrap;
+        min-height: 70rpx;
+        
+        &:active {
+          background-color: #e0f0ff;
+        }
+        
+        text {
+          font-size: 22rpx;
+          color: #007AFF;
+          margin-top: 4rpx;
+        }
+      }
+    }
+    
+    .form-tip {
+      margin-top: 10rpx;
+      font-size: 24rpx;
+      color: #999;
+      line-height: 1.5;
+    }
+    
+    .coordinate-info {
+      margin-top: 10rpx;
+      padding: 10rpx 15rpx;
+      background-color: #f0f7ff;
+      border-radius: 8rpx;
+      display: flex;
+      align-items: center;
+      
+      .coordinate-label {
+        font-size: 24rpx;
+        color: #666;
+        margin-right: 10rpx;
+      }
+      
+      .coordinate-value {
+        font-size: 24rpx;
+        color: #007AFF;
+        font-family: monospace;
+      }
+    }
+  }
+}
+</style>
diff --git a/app/components/HospitalSelector.vue b/app/components/HospitalSelector.vue
index 77ff0f3..5f3c420 100644
--- a/app/components/HospitalSelector.vue
+++ b/app/components/HospitalSelector.vue
@@ -312,6 +312,8 @@
       this.$emit('change', hospitalData)
     },
     
+
+    
     // 鍚堝苟鍖婚櫌鍦板潃锛堢渷 + 甯� + 鍖� + 璇︾粏鍦板潃锛�
     buildFullAddress(hospital) {
       const parts = []
@@ -385,10 +387,6 @@
       this.$emit('input', {
         ...this.value,
         address: fullAddress
-      })
-      this.$emit('address-selected', {
-        address: fullAddress,
-        location: item.location
       })
           
       this.showAddressSuggestions = false
diff --git a/app/components/OrganizationSelector.vue b/app/components/OrganizationSelector.vue
index 9371f8f..531aaf9 100644
--- a/app/components/OrganizationSelector.vue
+++ b/app/components/OrganizationSelector.vue
@@ -158,7 +158,11 @@
           deptId: organization.deptId,
           deptName: organization.deptName,
           serviceOrderClass: organization.serviceOrderClass || '',
-          region: region
+          region: region,
+          // 鍑哄彂鍦颁俊鎭�
+          departureAddress: organization.departureAddress || '',
+          departureLongitude: organization.departureLongitude || null,
+          departureLatitude: organization.departureLatitude || null
         })
       }
     },
diff --git a/app/pages/task/create-emergency.vue b/app/pages/task/create-emergency.vue
index ef16aec..2a6c730 100644
--- a/app/pages/task/create-emergency.vue
+++ b/app/pages/task/create-emergency.vue
@@ -30,6 +30,16 @@
         />
       </view>
       
+      <DepartureSelector
+        :address.sync="departureAddress"
+        :longitude.sync="departureLongitude"
+        :latitude.sync="departureLatitude"
+        :region="selectedRegion"
+        :required="false"
+        @address-selected="onDepartureAddressSelected"
+        @location-success="onDepartureLocationSuccess"
+      />
+      
       <view class="form-item">
         <view class="form-label required">浠诲姟绫诲瀷</view>
         <picker mode="selector" :range="emergencyTaskTypeOptions" range-key="text" @change="onEmergencyTaskTypeChange">
@@ -321,8 +331,9 @@
 import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
 import { addTask } from "@/api/task"
 import { listAvailableVehicles, getUserBoundVehicle } from "@/api/vehicle"
+import { searchHospitals, searchHospitalsByDeptRegion } from "@/api/hospital"
+import DepartureSelector from '@/components/DepartureSelector.vue'
 import { calculateDistance, baiduDistanceByAddress, baiduPlaceSuggestion } from "@/api/map"
-import { searchHospitals, getFrequentOutHospitals, getFrequentInHospitals, searchHospitalsByDeptRegion } from "@/api/hospital"
 import { listBranchUsers } from "@/api/system/user"
 import { searchIcd10 } from "@/api/icd10"
 import { calculateTransferPrice } from "@/api/price"
@@ -343,7 +354,8 @@
     MapSelector,
     OrganizationSelector,
     HospitalSelector,
-    DiseaseSelector
+    DiseaseSelector,
+    DepartureSelector
   },
   data() {
     return {
@@ -352,6 +364,9 @@
       selectedOrganizationId: null, // 褰掑睘鏈烘瀯ID锛堥儴闂↖D锛�
       selectedOrganizationServiceOrderClass: '', // 褰掑睘鏈烘瀯鐨勬湇鍔″崟缂栫爜
       selectedRegion: '', // 浠庡綊灞炴満鏋勪腑鎻愬彇鐨勫湴鍩熶俊鎭紙濡傦細骞垮窞銆佹繁鍦崇瓑锛�
+      departureAddress: '', // 鍑哄彂鍦板湴鍧�
+      departureLongitude: null, // 鍑哄彂鍦扮粡搴�
+      departureLatitude: null, // 鍑哄彂鍦扮含搴�
       selectedEmergencyTaskType: '', // 閫変腑鐨勪换鍔$被鍨嬫枃鏈�
       selectedEmergencyTaskTypeId: null, // 閫変腑鐨勪换鍔$被鍨婭D
       selectedDocumentType: '', // 閫変腑鐨勫崟鎹被鍨嬫枃鏈�
@@ -403,10 +418,6 @@
       documentTypeOptions: [], // 鍗曟嵁绫诲瀷閫夐」锛堢敤浜巔icker鏄剧ず锛�
       departmentOptions: [], // 绉戝瀛楀吀鏁版嵁
       loading: false,
-      addressCoordinates: {
-        hospitalOutAddress: null,
-        hospitalInAddress: null
-      },
       // 鏅鸿兘璇嗗埆鐩稿叧
       rawText: '',
       parseLoading: false
@@ -517,10 +528,18 @@
     },
     
     onOrganizationChange(orgData) {
-      // orgData 鍖呭惈锛歞eptId, deptName, serviceOrderClass, region
+      // orgData 鍖呭惈锛歞eptId, deptName, serviceOrderClass, region, departureAddress, departureLongitude, departureLatitude
       this.selectedOrganizationId = orgData.deptId
       this.selectedOrganizationServiceOrderClass = orgData.serviceOrderClass
       this.selectedRegion = orgData.region
+      
+      // 鑷姩濉厖鍑哄彂鍦颁俊鎭紙鏈烘瀯鐨勫湴鍧�鍜屽潗鏍囷級
+      if (orgData.departureAddress) {
+        this.departureAddress = orgData.departureAddress
+        this.departureLongitude = orgData.departureLongitude || null
+        this.departureLatitude = orgData.departureLatitude || null
+        console.log('鑷姩濉厖鏈烘瀯鍑哄彂鍦�:', this.departureAddress, '鍧愭爣:', this.departureLongitude, this.departureLatitude)
+      }
       
       console.log('閫変腑褰掑睘鏈烘瀯:', orgData.deptName, '閮ㄩ棬ID:', orgData.deptId, '鏈嶅姟鍗曠紪鐮�:', orgData.serviceOrderClass, '鍦板煙:', orgData.region)
     },
@@ -635,16 +654,10 @@
       }
     },
     
-    // 杞嚭鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+    // 杞嚭鍖婚櫌鍦板潃閫夋嫨浜嬩欢锛堢畝鍖栵紝绉婚櫎GPS澶勭悊锛�
     onHospitalOutAddressSelected(data) {
-      // data 鍖呭惈锛歛ddress, location
-      if (data.location) {
-        this.addressCoordinates.hospitalOutAddress = data.location
-        
-        // 濡傛灉杞叆鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
-        if (this.taskForm.hospitalIn.address) {
-          this.calculateDistanceByManualAddress()
-        }
+      if (this.taskForm.hospitalIn.address) {
+        this.calculateDistanceByManualAddress()
       }
     },
     
@@ -665,16 +678,10 @@
       }
     },
     
-    // 杞叆鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+    // 杞叆鍖婚櫌鍦板潃閫夋嫨浜嬩欢锛堢畝鍖栵紝绉婚櫎GPS澶勭悊锛�  
     onHospitalInAddressSelected(data) {
-      // data 鍖呭惈锛歛ddress, location
-      if (data.location) {
-        this.addressCoordinates.hospitalInAddress = data.location
-        
-        // 濡傛灉杞嚭鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
-        if (this.taskForm.hospitalOut.address) {
-          this.calculateDistanceByManualAddress()
-        }
+      if (this.taskForm.hospitalOut.address) {
+        this.calculateDistanceByManualAddress()
       }
     },
     
@@ -1072,7 +1079,7 @@
         // 鐥呮儏ID鍒楄〃锛堢敤浜庡悓姝ヨ皟搴﹀崟鐨凮rdICD_ID鍙傛暟锛�
         diseaseIds: this.selectedDiseases.filter(d => d.id !== null).map(d => d.id),
         // 灏嗚浆鍑哄尰闄㈠湴鍧�浣滀负鍑哄彂鍦帮紝杞叆鍖婚櫌鍦板潃浣滀负鐩殑鍦�
-        departureAddress: this.taskForm.hospitalOut.address || '',
+        departureAddress: this.departureAddress || this.taskForm.hospitalOut.address || '',
         destinationAddress: this.taskForm.hospitalIn.address || '',
         patient: {
           ...this.taskForm.patient,
@@ -1085,34 +1092,27 @@
               icdName: d.icdName
             }))
         },
-        // 鍖婚櫌淇℃伅锛堝寘鍚尰闄D銆佺瀹ゅ悕绉般�佺瀹D绛夊畬鏁翠俊鎭級
-        hospitalOut: this.taskForm.hospitalOut,  // 鍖呭惈: id, name, department, departmentId, bedNumber, address
-        hospitalIn: this.taskForm.hospitalIn,    // 鍖呭惈: id, name, department, departmentId, bedNumber, address
+        // 鍖婚櫌淇℃伅锛堝寘鍚尰闄D銆佺瀹ゅ悕绉般�佺瀹D銆丟PS鍧愭爣绛夊畬鏁翠俊鎭級
+        hospitalOut: {
+          ...this.taskForm.hospitalOut
+          // GPS鍧愭爣鐢卞悗绔嚜鍔ㄨ幏鍙�
+        },
+        hospitalIn: {
+          ...this.taskForm.hospitalIn
+          // GPS鍧愭爣鐢卞悗绔嚜鍔ㄨ幏鍙�
+        },
+        
         transferDistance: this.taskForm.transferDistance ? parseFloat(this.taskForm.transferDistance) : null,
         price: this.taskForm.price ? parseFloat(this.taskForm.price) : null
       }
       
-      if (this.addressCoordinates.hospitalOutAddress) {
-        // 杞嚭鍖婚櫌GPS鍧愭爣鍐欏叆鎵╁睍琛�
-        if (!submitData.hospitalOut) submitData.hospitalOut = {}
-        submitData.hospitalOut.longitude = this.addressCoordinates.hospitalOutAddress.lng
-        submitData.hospitalOut.latitude = this.addressCoordinates.hospitalOutAddress.lat
-        
-        // 鍚屾椂鍐欏叆涓讳换鍔¤〃鐨勫嚭鍙戝湴缁忕含搴�
-        submitData.departureLongitude = this.addressCoordinates.hospitalOutAddress.lng
-        submitData.departureLatitude = this.addressCoordinates.hospitalOutAddress.lat
+      // 鍑哄彂鍦癎PS鍧愭爣锛堜紭鍏堜娇鐢ㄨ嚜瀹氫箟鐨勫嚭鍙戝湴鍧愭爣锛�
+      if (this.departureLongitude && this.departureLatitude) {
+        submitData.departureLongitude = this.departureLongitude
+        submitData.departureLatitude = this.departureLatitude
       }
       
-      if (this.addressCoordinates.hospitalInAddress) {
-        // 杞叆鍖婚櫌GPS鍧愭爣鍐欏叆鎵╁睍琛�
-        if (!submitData.hospitalIn) submitData.hospitalIn = {}
-        submitData.hospitalIn.longitude = this.addressCoordinates.hospitalInAddress.lng
-        submitData.hospitalIn.latitude = this.addressCoordinates.hospitalInAddress.lat
-        
-        // 鍚屾椂鍐欏叆涓讳换鍔¤〃鐨勭洰鐨勫湴缁忕含搴�
-        submitData.destinationLongitude = this.addressCoordinates.hospitalInAddress.lng
-        submitData.destinationLatitude = this.addressCoordinates.hospitalInAddress.lat
-      }
+      // 鐩爣鍦癎PS鍧愭爣鐢卞悗绔牴鎹浆鍏ュ尰闄㈠湴鍧�鑷姩鑾峰彇
       
       return submitData
     },
@@ -1151,6 +1151,79 @@
     
    goBack() {
       uni.navigateBack()
+    },
+    
+    // 鑾峰彇褰撳墠浣嶇疆
+    getCurrentLocation() {
+      uni.showLoading({
+        title: '鑾峰彇浣嶇疆涓�...'
+      })
+      
+      // 浣跨敤uni-app鐨凣PS瀹氫綅鍔熻兘
+      uni.getLocation({
+        type: 'gcj02', // 杩斿洖鍥芥祴灞�鍧愭爣锛岄�傜敤浜庡浗鍐呭湴鍥�
+        success: (res) => {
+          console.log('鑾峰彇鍒癎PS鍧愭爣:', res)
+          const latitude = res.latitude
+          const longitude = res.longitude
+          
+          // 淇濆瓨GPS鍧愭爣
+          this.departureLatitude = latitude
+          this.departureLongitude = longitude
+          
+          // 璋冪敤閫嗗湴鐞嗙紪鐮佹帴鍙o紝灏嗗潗鏍囪浆鎹负鍦板潃
+          reverseGeocoder(latitude, longitude)
+            .then(response => {
+              uni.hideLoading()
+              
+              if (response.code === 200 && response.data) {
+                // 鑾峰彇璇︾粏鍦板潃
+                const address = response.data.address || response.data.formattedAddress || ''
+                this.departureAddress = address
+                
+                console.log('閫嗗湴鐞嗙紪鐮佹垚鍔�:', address)
+                this.$modal.showToast('宸茶幏鍙栧綋鍓嶄綅缃�')
+              } else {
+                console.error('閫嗗湴鐞嗙紪鐮佸け璐�:', response.msg)
+                this.$modal.showToast('浣嶇疆瑙f瀽澶辫触锛岃鎵嬪姩杈撳叆鍦板潃')
+              }
+            })
+            .catch(error => {
+              uni.hideLoading()
+              console.error('閫嗗湴鐞嗙紪鐮佸け璐�:', error)
+              // 鍗充娇鍦板潃瑙f瀽澶辫触锛屼篃淇濈暀GPS鍧愭爣
+              this.$modal.showToast('浣嶇疆瑙f瀽澶辫触锛屼絾GPS鍧愭爣宸蹭繚瀛�')
+            })
+        },
+        fail: (err) => {
+          uni.hideLoading()
+          console.error('鑾峰彇浣嶇疆澶辫触:', err)
+          
+          // 鎻愮ず鐢ㄦ埛鍙兘鐨勫師鍥�
+          let errorMsg = '鑾峰彇浣嶇疆澶辫触'
+          if (err.errMsg && err.errMsg.includes('auth deny')) {
+            errorMsg = '璇峰湪璁剧疆涓紑鍚綅缃潈闄�'
+          } else if (err.errMsg && err.errMsg.includes('timeout')) {
+            errorMsg = '瀹氫綅瓒呮椂锛岃绋嶅悗閲嶈瘯'
+          }
+          
+          this.$modal.showToast(errorMsg)
+        }
+      })
+    },
+    
+    // 鍑哄彂鍦板湴鍧�閫夋嫨锛堜粠鍦板浘寤鸿涓�夋嫨锛�
+    onDepartureAddressSelected(data) {
+      // data 鍖呭惈: address, longitude, latitude, location
+      console.log('鍑哄彂鍦板湴鍧�閫夋嫨:', data)
+      // 缁勪欢宸茬粡閫氳繃 .sync 鏇存柊浜� departureAddress, departureLongitude, departureLatitude
+    },
+    
+    // 鍑哄彂鍦癎PS瀹氫綅鎴愬姛
+    onDepartureLocationSuccess(data) {
+      // data 鍖呭惈: address, longitude, latitude
+      console.log('鍑哄彂鍦癎PS瀹氫綅鎴愬姛:', data)
+      // 缁勪欢宸茬粡閫氳繃 .sync 鏇存柊浜� departureAddress, departureLongitude, departureLatitude
     },
     
     // ==================== 鏅鸿兘璇嗗埆鐩稿叧鏂规硶 ====================
@@ -1781,6 +1854,13 @@
         font-size: 28rpx;
       }
       
+      .form-tip {
+        margin-top: 10rpx;
+        font-size: 24rpx;
+        color: #999;
+        line-height: 1.5;
+      }
+      
       .disease-container {
         .disease-tags {
           display: flex;
diff --git a/app/pages/task/detail.vue b/app/pages/task/detail.vue
index ffd445d..fcbd8d7 100644
--- a/app/pages/task/detail.vue
+++ b/app/pages/task/detail.vue
@@ -189,8 +189,58 @@
           <view class="value">{{ taskDetail.emergencyInfo.transferDistance }}鍏噷</view>
         </view>
         <view class="info-item" v-if="taskDetail.emergencyInfo.transferPrice">
-          <view class="label">杞繍璐圭敤</view>
+          <view class="label">鍩虹璐圭敤</view>
           <view class="value">锟{ taskDetail.emergencyInfo.transferPrice }}</view>
+        </view>
+        <view class="info-item" v-if="paymentInfo">
+          <view class="label">闄勫姞璐圭敤</view>
+          <view class="value">锟{ paymentInfo.additionalAmount || 0 }}</view>
+        </view>
+        <view class="info-item" v-if="paymentInfo">
+          <view class="label">鎬昏垂鐢�</view>
+          <view class="value" style="color: #e54d42; font-weight: bold;">锟{ paymentInfo.totalAmount || 0 }}</view>
+        </view>
+        <view class="info-item" v-if="paymentInfo && paymentInfo.paidAmount > 0">
+          <view class="label">宸叉敮浠�</view>
+          <view class="value" style="color: #34C759;">锟{ paymentInfo.paidAmount }}</view>
+        </view>
+        <view class="info-item" v-if="paymentInfo && paymentInfo.paidAmount > 0">
+          <view class="label">鍓╀綑鏈粯</view>
+          <view class="value" style="color: #ff9900; font-weight: bold;">锟{ getRemainingAmount() }}</view>
+        </view>
+      </view>
+      
+      <!-- 鏀粯璁板綍鏄庣粏 -->
+      <view class="detail-section" v-if="paymentInfo && paymentInfo.paidPayments && paymentInfo.paidPayments.length > 0">
+        <view class="section-title">鏀粯璁板綍</view>
+        <view 
+          class="payment-record-item" 
+          v-for="payment in paymentInfo.paidPayments" 
+          :key="payment.id"
+        >
+          <view class="payment-header">
+            <view 
+              class="payment-method-tag" 
+              :class="[
+                payment.paymentMethod === '1' ? 'method-cash' : '',
+                payment.paymentMethod === '2' ? 'method-bank' : '',
+                payment.paymentMethod === '3' ? 'method-wechat' : '',
+                payment.paymentMethod === '4' ? 'method-alipay' : '',
+                payment.paymentMethod === '5' ? 'method-pos' : '',
+                payment.paymentMethod === '6' ? 'method-account' : '',
+                payment.paymentMethod === '7' ? 'method-yyt' : ''
+              ]"
+            >
+              {{ getPaymentMethodLabel(payment.paymentMethod) }}
+            </view>
+            <view class="payment-amount">锟{ payment.settlementAmount }}</view>
+          </view>
+          <view class="payment-time" v-if="payment.payTime">
+            {{ formatPaymentTime(payment.payTime) }}
+          </view>
+          <view class="payment-remark" v-if="payment.remark">
+            澶囨敞锛歿{ payment.remark }}
+          </view>
         </view>
       </view>
       
@@ -345,7 +395,16 @@
         </button>
       </template>
       
-      <!-- 宸插畬鎴�/宸插彇娑�: 涓嶆樉绀烘寜閽� -->
+      <!-- 宸插畬鎴�/宸插彇娑�: 涓嶆樉绀烘寜閽紝浣嗗鏋滄槸杞繍浠诲姟鍒欐樉绀虹粨绠楁寜閽� -->
+      
+      <!-- 杞繍浠诲姟鐨勭粨绠楁寜閽細浠呭畬鎴�/鍙栨秷鐘舵�佷笉鏄剧ず -->
+      <button 
+        v-if="taskDetail.taskType === 'EMERGENCY_TRANSFER' && !isTaskFinished"
+        class="action-btn settlement" 
+        @click="handleSettlement"
+      >
+        缁撶畻
+      </button>
     </view>
   </view>
 </template>
@@ -353,6 +412,7 @@
 <script>
   import { getTask, changeTaskStatus } from '@/api/task'
   import { checkVehicleActiveTasks } from '@/api/task'
+  import { getPaymentInfo } from '@/api/payment'
   import { formatDateTime } from '@/utils/common'
   import AttachmentUpload from '@/components/AttachmentUpload.vue'
   
@@ -363,7 +423,8 @@
     data() {
       return {
         taskDetail: null,
-        taskId: null
+        taskId: null,
+        paymentInfo: null // 鏀粯淇℃伅
       }
     },
     computed: {
@@ -456,10 +517,67 @@
           console.log('鍑哄彂鍦板潃:', this.taskDetail.departureAddress)
           console.log('鐩殑鍦板潃:', this.taskDetail.destinationAddress)
           console.log('杞繍浠诲姟淇℃伅 (emergencyInfo):', this.taskDetail.emergencyInfo)
+          
+          // 濡傛灉鏄浆杩愪换鍔★紝鍔犺浇鏀粯淇℃伅
+          if (this.taskDetail.taskType === 'EMERGENCY_TRANSFER') {
+            this.loadPaymentInfo()
+          }
         }).catch(error => {
           console.error('鍔犺浇浠诲姟璇︽儏澶辫触:', error)
           this.$modal.showToast('鍔犺浇浠诲姟璇︽儏澶辫触')
         })
+      },
+      
+      // 鍔犺浇鏀粯淇℃伅
+      loadPaymentInfo() {
+        getPaymentInfo(this.taskId).then(res => {
+          this.paymentInfo = res.data
+          console.log('鏀粯淇℃伅:', this.paymentInfo)
+        }).catch(err => {
+          console.error('鍔犺浇鏀粯淇℃伅澶辫触', err)
+        })
+      },
+      
+      // 鏍规嵁鏀粯鏂瑰紡瀛楀吀鍊艰幏鍙栨樉绀烘爣绛�
+      getPaymentMethodLabel(dictValue) {
+        const methodMap = {
+          '1': '鐜伴噾',
+          '2': '閾惰杞处',
+          '3': '寰俊鏀粯',
+          '4': '鏀粯瀹�',
+          '5': 'POS鏀舵',
+          '6': '鎸傝处',
+          '7': '鏄撳尰閫氭寕璐�',
+          '8': '閫�娆�',
+          '9': '绉垎'
+        }
+        return methodMap[dictValue] || dictValue
+      },
+      
+      // 鏍煎紡鍖栨敮浠樻椂闂�
+      formatPaymentTime(time) {
+        if (!time) return '鏈煡'
+        const date = new Date(time)
+        const year = date.getFullYear()
+        const month = String(date.getMonth() + 1).padStart(2, '0')
+        const day = String(date.getDate()).padStart(2, '0')
+        const hour = String(date.getHours()).padStart(2, '0')
+        const minute = String(date.getMinutes()).padStart(2, '0')
+        return `${year}-${month}-${day} ${hour}:${minute}`
+      },
+      
+      // 璁$畻鍓╀綑鏈粯閲戦
+      getRemainingAmount() {
+        if (!this.paymentInfo) {
+          return '0.00'
+        }
+        const total = parseFloat(this.paymentInfo.totalAmount || 0)
+        const paid = parseFloat(this.paymentInfo.paidAmount || 0)
+        const remaining = total - paid
+        console.log('鎬婚噾棰�:', total.toFixed(2))
+        console.log('宸蹭粯閲戦:', paid.toFixed(2))
+        console.log('鍓╀綑鏈粯閲戦:', remaining.toFixed(2))
+        return remaining > 0 ? remaining.toFixed(2) : '0.00'
       },
       
       // 鑾峰彇杞﹁締淇℃伅
@@ -565,6 +683,13 @@
           'WELFARE': '绂忕杞�'
         }
         return typeMap[type] || '鏈煡绫诲瀷'
+      },
+      
+      // 澶勭悊缁撶畻
+      handleSettlement() {
+        uni.navigateTo({
+          url: '/pages/task/settlement?taskId=' + this.taskId
+        })
       },
       
       // 澶勭悊浠诲姟鎿嶄綔
@@ -674,10 +799,10 @@
         if (!this.taskDetail) {
           return null;
         }
-        
-        // 浠庤溅杈嗗垪琛ㄤ腑鑾峰彇绗竴涓溅杈嗙殑ID
-        if (this.taskDetail.vehicleList && this.taskDetail.vehicleList.length > 0) {
-          return this.taskDetail.vehicleList[0].vehicleId;
+        console.log("taskDetail assignedVehicles",this.taskDetail.assignedVehicles); 
+        // 浠庤溅杈嗗垪琛ㄤ腑鑾峰彇绗竴涓溅杈嗙殑ID锛堝悗绔繑鍥炵殑瀛楁鍚嶆槸assignedVehicles锛�
+        if (this.taskDetail.assignedVehicles && this.taskDetail.assignedVehicles.length > 0) {
+          return this.taskDetail.assignedVehicles[0].vehicleId;
         }
         
         // 鎴栬�呬粠鍗曚釜杞﹁締瀵硅薄鑾峰彇
@@ -1128,6 +1253,80 @@
       }
     }
     
+    // 鏀粯璁板綍鏍峰紡
+    .payment-record-item {
+      background-color: #f9f9f9;
+      border-radius: 10rpx;
+      padding: 20rpx;
+      margin-bottom: 20rpx;
+      
+      &:last-child {
+        margin-bottom: 0;
+      }
+      
+      .payment-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 15rpx;
+        
+        .payment-method-tag {
+          display: inline-block;
+          padding: 6rpx 16rpx;
+          border-radius: 6rpx;
+          font-size: 24rpx;
+          color: white;
+          font-weight: 500;
+          
+          &.method-cash {
+            background-color: #34C759;
+          }
+          
+          &.method-bank {
+            background-color: #5AC8FA;
+          }
+          
+          &.method-wechat {
+            background-color: #09BB07;
+          }
+          
+          &.method-alipay {
+            background-color: #1677FF;
+          }
+          
+          &.method-pos {
+            background-color: #FF9500;
+          }
+          
+          &.method-account {
+            background-color: #FF9500;
+          }
+          
+          &.method-yyt {
+            background-color: #AF52DE;
+          }
+        }
+        
+        .payment-amount {
+          font-size: 32rpx;
+          font-weight: bold;
+          color: #34C759;
+        }
+      }
+      
+      .payment-time {
+        font-size: 24rpx;
+        color: #999;
+        margin-bottom: 10rpx;
+      }
+      
+      .payment-remark {
+        font-size: 24rpx;
+        color: #666;
+        line-height: 1.5;
+      }
+    }
+    
     .loading {
       display: flex;
       flex-direction: column;
@@ -1176,6 +1375,11 @@
           color: white;
         }
         
+        &.settlement {
+          background-color: #34C759;
+          color: white;
+        }
+        
         &:first-child {
           margin-left: 0;
         }
diff --git a/app/pages/task/edit-emergency.vue b/app/pages/task/edit-emergency.vue
index 2dd9009..3aafe37 100644
--- a/app/pages/task/edit-emergency.vue
+++ b/app/pages/task/edit-emergency.vue
@@ -37,6 +37,28 @@
         />
       </view>
       
+      <view class="form-item">
+        <view class="form-label">鎵ц浠诲姟浜哄憳</view>
+        <view class="staff-list">
+          <view class="staff-item" v-for="(staff, index) in selectedStaff" :key="staff.userId">
+            <view class="staff-info">
+              <text class="staff-name">{{ staff.nickName }}</text>
+              <text class="staff-role">({{ getUserTypeName(staff.type) || '鏈煡鑱屼綅' }})</text>
+            </view>
+            <uni-icons 
+              type="closeempty" 
+              size="20" 
+              color="#ff4d4f"
+              @click="removeStaff(index)"
+            ></uni-icons>
+          </view>
+          <view class="add-staff" @click="showStaffSelector">
+            <uni-icons type="plusempty" size="20" color="#007AFF"></uni-icons>
+            <text>娣诲姞浜哄憳</text>
+          </view>
+        </view>
+      </view>
+      
       <view class="form-section-title">鎮h�呬俊鎭�</view>
       <view class="form-item">
         <view class="form-label required">鑱旂郴浜�</view>
@@ -166,6 +188,80 @@
         ></map-selector>
       </view>
     </uni-popup>
+    
+    <!-- 浜哄憳閫夋嫨鍣ㄥ脊绐� -->
+    <uni-popup ref="staffPopup" type="bottom" :mask-click="false">
+      <view class="staff-popup-container">
+        <view class="popup-header">
+          <view class="popup-title">閫夋嫨鎵ц浜哄憳</view>
+          <view class="close-btn" @click="closeStaffSelector">
+            <uni-icons type="closeempty" size="20" color="#999"></uni-icons>
+          </view>
+        </view>
+        
+        <view class="search-bar">
+          <input 
+            class="search-input" 
+            placeholder="鎼滅储濮撳悕鎴栫數璇�" 
+            v-model="staffSearchKeyword"
+            @input="onStaffSearch"
+          />
+        </view>
+        
+        <view class="filter-tabs">
+          <view 
+            class="filter-tab" 
+            :class="{ active: staffFilterType === 'driver' }"
+            @click="filterStaff('driver')"
+          >
+            鍙告満
+          </view>
+          <view 
+            class="filter-tab" 
+            :class="{ active: staffFilterType === 'doctor' }"
+            @click="filterStaff('doctor')"
+          >
+            鍖荤敓
+          </view>
+          <view 
+            class="filter-tab" 
+            :class="{ active: staffFilterType === 'nurse' }"
+            @click="filterStaff('nurse')"
+          >
+            鎶ゅ+
+          </view>
+        </view>
+        
+        <scroll-view class="staff-list-scroll" scroll-y="true">
+          <view 
+            class="staff-list-item" 
+            v-for="staff in filteredStaffList" 
+            :key="staff.userId"
+            @click="toggleStaffSelection(staff)"
+          >
+            <view class="staff-item-info">
+              <text class="staff-item-name">{{ staff.nickName }}</text>
+              <text class="staff-item-dept">{{ staff.deptName }}</text>
+            </view>
+            <view class="staff-item-check">
+              <uni-icons 
+                v-if="isStaffSelected(staff.userId)" 
+                type="checkmarkempty" 
+                size="24" 
+                color="#007AFF"
+              ></uni-icons>
+            </view>
+          </view>
+          <view v-if="filteredStaffList.length === 0" class="empty-tip">
+            鏆傛棤浜哄憳鏁版嵁
+          </view>
+        </scroll-view>
+        
+        <view class="popup-footer">
+          <button class="confirm-btn" @click="confirmStaffSelection">纭畾(宸查�墈{ selectedStaff.length }})</button>
+        </view>
+      </view>
+    </uni-popup>
   </scroll-view>
 </template>
 
@@ -174,6 +270,7 @@
 import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue'
 import uniPopup from '@/uni_modules/uni-popup/components/uni-popup/uni-popup.vue'
 import { getTask, updateTask } from "@/api/task"
+import { listBranchUsers } from "@/api/system/user"
 import { baiduDistanceByAddress } from "@/api/map"
 import { calculateTransferPrice } from "@/api/price"
 import MapSelector from '@/components/map-selector.vue'
@@ -196,18 +293,23 @@
   mixins: [distanceCalculator],
   data() {
     return {
+      loading: false,
       taskId: null,
       taskDetail: null,
       selectedVehicleId: null,
       selectedOrganizationId: null,
       selectedRegion: '',
       mapSelectorType: '',
-      // 鍦板潃鍧愭爣锛堢敤浜庢墜鍔ㄨ緭鍏ュ湴鍧�鏃惰绠楄窛绂伙級
-      addressCoordinates: {
-        hospitalOutAddress: null,
-        hospitalInAddress: null
-      },
+      // 鍑哄彂鍦颁俊鎭�
+      departureAddress: '',
+      departureLongitude: null,
+      departureLatitude: null,
       selectedDiseases: [], // 宸查�夋嫨鐨勭梾鎯呭垪琛�
+      selectedStaff: [], // 宸查�夋嫨鐨勪汉鍛樺垪琛�
+      allStaffList: [], // 鎵�鏈変汉鍛樺垪琛�
+      filteredStaffList: [], // 杩囨护鍚庣殑浜哄憳鍒楄〃
+      staffSearchKeyword: '', // 浜哄憳鎼滅储鍏抽敭璇�
+      staffFilterType: 'driver', // 浜哄憳绛涢�夌被鍨�
       taskForm: {
         transferTime: '',
         patient: {
@@ -237,8 +339,7 @@
         },
         transferDistance: '',
         price: ''
-      },
-      loading: false
+      }
     }
   },
   computed: {
@@ -255,6 +356,7 @@
     if (options.id) {
       this.taskId = options.id
       this.loadTaskDetail()
+      this.loadDeptStaff() // 鍔犺浇浜哄憳鍒楄〃
     } else {
       this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
       setTimeout(() => {
@@ -311,12 +413,30 @@
           this.taskForm.hospitalOut.bedNumber = info.hospitalOutBedNumber || ''
           this.taskForm.hospitalOut.address = info.hospitalOutAddress || ''
           
+          // 鍔犺浇杞嚭鍖婚櫌GPS鍧愭爣锛堜笉鏄剧ず锛屼絾淇濆瓨鍦ㄦ暟鎹腑锛�
+          if (info.hospitalOutLongitude && info.hospitalOutLatitude) {
+            this.addressCoordinates.hospitalOutAddress = {
+              lng: info.hospitalOutLongitude,
+              lat: info.hospitalOutLatitude
+            }
+            console.log('鍔犺浇杞嚭鍖婚櫌GPS鍧愭爣:', info.hospitalOutLongitude, info.hospitalOutLatitude)
+          }
+          
           // 杞叆鍖婚櫌淇℃伅
           this.taskForm.hospitalIn.id = info.hospitalInId || null
           this.taskForm.hospitalIn.name = info.hospitalInName || ''
           this.taskForm.hospitalIn.department = info.hospitalInDepartment || ''
           this.taskForm.hospitalIn.bedNumber = info.hospitalInBedNumber || ''
           this.taskForm.hospitalIn.address = info.hospitalInAddress || ''
+          
+          // 鍔犺浇杞叆鍖婚櫌GPS鍧愭爣锛堜笉鏄剧ず锛屼絾淇濆瓨鍦ㄦ暟鎹腑锛�
+          if (info.hospitalInLongitude && info.hospitalInLatitude) {
+            this.addressCoordinates.hospitalInAddress = {
+              lng: info.hospitalInLongitude,
+              lat: info.hospitalInLatitude
+            }
+            console.log('鍔犺浇杞叆鍖婚櫌GPS鍧愭爣:', info.hospitalInLongitude, info.hospitalInLatitude)
+          }
           
           // 杞繍璺濈鍜屼环鏍�
           this.taskForm.transferDistance = info.transferDistance ? String(info.transferDistance) : ''
@@ -346,20 +466,43 @@
           console.warn('鏈壘鍒板綊灞炴満鏋勪俊鎭�')
         }
         
-        // 璁剧疆鍦板潃鍧愭爣锛堜娇鐢╩ixin涓殑鏂规硶锛�
+        // 璁剧疆鍑哄彂鍦颁俊鎭紙鍦板潃鍜屽潗鏍囷級
+        if (this.taskDetail.departureAddress) {
+          this.departureAddress = this.taskDetail.departureAddress
+        }
         if (this.taskDetail.departureLongitude && this.taskDetail.departureLatitude) {
-          this.setStartLocation({
-            lng: this.taskDetail.departureLongitude,
-            lat: this.taskDetail.departureLatitude
-          })
-          console.log('璁剧疆鍑哄彂鍦板潗鏍�')
+          this.departureLongitude = this.taskDetail.departureLongitude
+          this.departureLatitude = this.taskDetail.departureLatitude
+          console.log('璁剧疆鍑哄彂鍦板潗鏍�:', this.departureLongitude, this.departureLatitude)
+        }
+        
+        // 璁剧疆鐩爣鍦颁俊鎭紙杞叆鍖婚櫌鐨勫湴鍧�鍜屽潗鏍囷級
+        if (this.taskDetail.destinationAddress) {
+          // 鐩爣鍦板湴鍧�宸茬粡鍦� taskForm.hospitalIn.address 涓缃�
+          console.log('鐩爣鍦板湴鍧�:', this.taskDetail.destinationAddress)
         }
         if (this.taskDetail.destinationLongitude && this.taskDetail.destinationLatitude) {
-          this.setEndLocation({
+          this.addressCoordinates.hospitalInAddress = {
             lng: this.taskDetail.destinationLongitude,
             lat: this.taskDetail.destinationLatitude
-          })
-          console.log('璁剧疆鐩殑鍦板潗鏍�')
+          }
+          console.log('璁剧疆鐩爣鍦板潗鏍�:', this.taskDetail.destinationLongitude, this.taskDetail.destinationLatitude)
+        }
+        
+        // 璁剧疆鎵ц浜哄憳
+        if (this.taskDetail.assignees && this.taskDetail.assignees.length > 0) {
+          console.log('鍘熷鎵ц浜哄憳鏁版嵁:', this.taskDetail.assignees)
+          this.selectedStaff = this.taskDetail.assignees.map(assignee => ({
+            userId: assignee.userId,
+            nickName: assignee.userName,
+            type: assignee.userType || 'driver',
+            phonenumber: '',
+            deptName: ''
+          }))
+          console.log('澶勭悊鍚庣殑鎵ц浜哄憳鍒楄〃:', this.selectedStaff)
+        } else {
+          console.warn('浠诲姟娌℃湁鍒嗛厤鎵ц浜哄憳鎴朼ssignees涓虹┖')
+          console.log('taskDetail.assignees:', this.taskDetail.assignees)
         }
         
         console.log('琛ㄥ崟鏁版嵁濉厖瀹屾垚:', this.taskForm)
@@ -402,16 +545,10 @@
       }
     },
     
-    // 杞嚭鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+    // 杞嚭鍖婚櫌鍦板潃閫夋嫨浜嬩欢锛堢畝鍖栵級
     onHospitalOutAddressSelected(data) {
-      // data 鍖呭惈锛歛ddress, location
-      if (data.location) {
-        this.addressCoordinates.hospitalOutAddress = data.location
-        
-        // 濡傛灉杞叆鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
-        if (this.taskForm.hospitalIn.address) {
-          this.calculateDistanceByManualAddress()
-        }
+      if (this.taskForm.hospitalIn.address) {
+        this.calculateDistanceByManualAddress()
       }
     },
     
@@ -432,16 +569,10 @@
       }
     },
     
-    // 杞叆鍖婚櫌鍦板潃閫夋嫨锛堝綋閫夋嫨"瀹朵腑"鏃朵娇鐢ㄧ櫨搴﹀湴鍥惧湴鍧�寤鸿锛�
+    // 杞叆鍖婚櫌鍦板潃閫夋嫨浜嬩欢锛堢畝鍖栵級
     onHospitalInAddressSelected(data) {
-      // data 鍖呭惈锛歛ddress, location
-      if (data.location) {
-        this.addressCoordinates.hospitalInAddress = data.location
-        
-        // 濡傛灉杞嚭鍦板潃涔熷凡濉啓,鑷姩璁$畻璺濈
-        if (this.taskForm.hospitalOut.address) {
-          this.calculateDistanceByManualAddress()
-        }
+      if (this.taskForm.hospitalOut.address) {
+        this.calculateDistanceByManualAddress()
       }
     },
     
@@ -449,6 +580,156 @@
     onDiseaseChange(diseases) {
       console.log('鐥呮儏鍙樺寲:', diseases)
       // 缁勪欢宸茬粡閫氳繃 v-model 鏇存柊浜� selectedDiseases
+    },
+    
+    // 鍔犺浇褰撳墠鐢ㄦ埛鎵�鍦ㄥ垎鍏徃鐨勬墍鏈変汉鍛�
+    loadDeptStaff() {
+      console.log('寮�濮嬪姞杞戒汉鍛樺垪琛�')
+      
+      listBranchUsers().then(response => {
+        console.log('浜哄憳鍒楄〃API鍝嶅簲:', response)
+        const userList = response.data || []
+        console.log('瑙f瀽鍑虹殑鐢ㄦ埛鍒楄〃:', userList, '鏁伴噺:', userList.length)
+        
+        this.allStaffList = userList.map(user => ({
+          userId: user.userId,
+          nickName: user.nickName,
+          phonenumber: user.phonenumber,
+          deptName: user.dept?.deptName || '',
+          postName: user.posts && user.posts.length > 0 ? user.posts[0].postName : '',
+          roleName: user.roles && user.roles.length > 0 ? user.roles[0].roleName : '',
+          type: this.getUserType(user)
+        }))
+        
+        console.log('澶勭悊鍚庣殑浜哄憳鍒楄〃:', this.allStaffList, '鏁伴噺:', this.allStaffList.length)
+        
+        this.filterStaffList()
+      }).catch(error => {
+        console.error('鍔犺浇浜哄憳鍒楄〃澶辫触:', error)
+        this.$modal.showToast('鍔犺浇浜哄憳鍒楄〃澶辫触')
+      })
+    },
+    
+    // 鏍规嵁鐢ㄦ埛鐨勫矖浣嶆垨瑙掕壊鍒ゆ柇绫诲瀷
+    getUserType(user) {
+      const postName = user.posts && user.posts.length > 0 ? user.posts[0].postName : ''
+      const roleName = user.roles && user.roles.length > 0 ? user.roles[0].roleName : ''
+      const deptName = user.dept?.deptName || ''
+      
+      if (postName.includes('鍙告満') || roleName.includes('鍙告満') || deptName.includes('杞﹂槦') || deptName.includes('鍙告満')) {
+        return 'driver'
+      }
+      if (postName.includes('鎶ゅ+') || roleName.includes('鎶ゅ+') || deptName.includes('鎶ゅ+')) {
+        return 'nurse'
+      }
+      if (postName.includes('鍖荤敓') || roleName.includes('鍖荤敓') || deptName.includes('鍖荤敓')) {
+        return 'doctor'
+      }
+      if (deptName.includes('鍖绘姢')) {
+        return 'doctor'
+      }
+      
+      return 'driver'
+    },
+    
+    getUserTypeName(staffType) {
+      switch(staffType) {
+        case 'nurse':
+          return '鎶ゅ+'
+        case 'doctor':
+          return '鍖荤敓'
+        case 'driver':
+          return '鍙告満'
+        default:
+          return '鍙告満'
+      }
+    },
+    
+    // 鏄剧ず浜哄憳閫夋嫨寮圭獥
+    showStaffSelector() {
+      this.$refs.staffPopup.open()
+      this.filterStaffList()
+    },
+    
+    // 鍏抽棴浜哄憳閫夋嫨寮圭獥
+    closeStaffSelector() {
+      this.$refs.staffPopup.close()
+      this.staffSearchKeyword = ''
+      this.staffFilterType = 'driver'
+    },
+    
+    // 浜哄憳鎼滅储
+    onStaffSearch(e) {
+      this.staffSearchKeyword = e.detail.value
+      this.filterStaffList()
+    },
+    
+    // 绛涢�変汉鍛樼被鍨�
+    filterStaff(type) {
+      this.staffFilterType = type
+      this.filterStaffList()
+    },
+    
+    // 杩囨护浜哄憳鍒楄〃
+    filterStaffList() {
+      console.log('寮�濮嬭繃婊や汉鍛樺垪琛紝鍘熷鏁伴噺:', this.allStaffList.length)
+      let list = [...this.allStaffList]
+      
+      // 鎸夌被鍨嬭繃婊�
+      if (this.staffFilterType === 'driver') {
+        list = list.filter(staff => staff.type === 'driver')
+      } else if (this.staffFilterType === 'doctor') {
+        list = list.filter(staff => staff.type === 'doctor')
+      } else if (this.staffFilterType === 'nurse') {
+        list = list.filter(staff => staff.type === 'nurse')
+      }
+      
+      console.log('鎸夌被鍨嬭繃婊ゅ悗:', this.staffFilterType, '鏁伴噺:', list.length)
+      
+      // 鎸夊叧閿瘝鎼滅储
+      if (this.staffSearchKeyword && this.staffSearchKeyword.trim() !== '') {
+        const keyword = this.staffSearchKeyword.trim().toLowerCase()
+        list = list.filter(staff => {
+          return staff.nickName.toLowerCase().includes(keyword) || 
+                 (staff.phonenumber && staff.phonenumber.includes(keyword))
+        })
+      }
+      
+      console.log('鎸夊叧閿瘝杩囨护鍚庯紝鏁伴噺:', list.length)
+      
+      this.filteredStaffList = list
+    },
+    
+    // 鍒囨崲浜哄憳閫変腑鐘舵��
+    toggleStaffSelection(staff) {
+      const index = this.selectedStaff.findIndex(s => s.userId === staff.userId)
+      
+      if (index > -1) {
+        // 宸查�変腑锛岀Щ闄�
+        this.selectedStaff.splice(index, 1)
+      } else {
+        // 鏈�変腑锛屾坊鍔�
+        this.selectedStaff.push(staff)
+      }
+    },
+    
+    // 鍒ゆ柇浜哄憳鏄惁宸查�変腑
+    isStaffSelected(userId) {
+      return this.selectedStaff.some(staff => staff.userId === userId)
+    },
+    
+    // 纭浜哄憳閫夋嫨
+    confirmStaffSelection() {
+      if (this.selectedStaff.length === 0) {
+        this.$modal.showToast('璇疯嚦灏戦�夋嫨涓�鍚嶄汉鍛�')
+        return
+      }
+      this.closeStaffSelector()
+    },
+    
+    // 绉婚櫎浜哄憳
+    removeStaff(index) {
+      this.selectedStaff.splice(index, 1)
     },
     
     // 瑙f瀽鐥呮儏淇℃伅锛堜粠瀛楃涓茶В鏋愬嚭ICD-10鐤剧梾鍒楄〃锛�
@@ -634,10 +915,18 @@
         deptId: this.selectedOrganizationId,
         vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [],
         plannedStartTime: this.taskForm.transferTime,
-        departureAddress: this.taskForm.hospitalOut.address,
+        // 鍑哄彂鍦颁娇鐢� departureAddress锛堝鏋滄湁锛夛紝鍚﹀垯浣跨敤杞嚭鍖婚櫌鍦板潃
+        departureAddress: this.departureAddress || this.taskForm.hospitalOut.address,
+        // 鐩爣鍦颁娇鐢ㄨ浆鍏ュ尰闄㈠湴鍧�
         destinationAddress: this.taskForm.hospitalIn.address,
         // 鐥呮儏ID鍒楄〃锛堢敤浜庡悓姝ヨ皟搴﹀崟鐨凮rdICD_ID鍙傛暟锛�
         diseaseIds: this.selectedDiseases.map(d => d.id).filter(id => id !== null),
+        // 鎵ц浜哄憳鍒楄〃
+        assignees: this.selectedStaff.map(staff => ({
+          userId: staff.userId,
+          userName: staff.nickName,
+          userType: staff.type
+        })),
         emergencyInfo: {
           patientContact: this.taskForm.patient.contact,
           patientPhone: this.taskForm.patient.phone,
@@ -649,10 +938,16 @@
           hospitalOutDepartment: this.taskForm.hospitalOut.department,
           hospitalOutBedNumber: this.taskForm.hospitalOut.bedNumber,
           hospitalOutAddress: this.taskForm.hospitalOut.address,
+          // 杞嚭鍖婚櫌GPS鍧愭爣锛堜繚瀛樺埌鎵╁睍琛級
+          hospitalOutLongitude: this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lng : null,
+          hospitalOutLatitude: this.addressCoordinates.hospitalOutAddress ? this.addressCoordinates.hospitalOutAddress.lat : null,
           hospitalInName: this.taskForm.hospitalIn.name,
           hospitalInDepartment: this.taskForm.hospitalIn.department,
           hospitalInBedNumber: this.taskForm.hospitalIn.bedNumber,
           hospitalInAddress: this.taskForm.hospitalIn.address,
+          // 杞叆鍖婚櫌GPS鍧愭爣锛堜繚瀛樺埌鎵╁睍琛級
+          hospitalInLongitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lng : null,
+          hospitalInLatitude: this.addressCoordinates.hospitalInAddress ? this.addressCoordinates.hospitalInAddress.lat : null,
           transferDistance: this.taskForm.transferDistance ? parseFloat(this.taskForm.transferDistance) : null,
           transferPrice: this.taskForm.price ? parseFloat(this.taskForm.price) : null,
           // 鐥呮儏璇︾粏淇℃伅锛堣繃婊ゆ帀绌虹殑鐥呮儏鍚嶇О锛�
@@ -666,16 +961,13 @@
         }
       }
       
-      // 娣诲姞GPS鍧愭爣
-      if (this.addressCoordinates.start) {
-        submitData.departureLongitude = this.addressCoordinates.start.lng
-        submitData.departureLatitude = this.addressCoordinates.start.lat
+      // 鍑哄彂鍦癎PS鍧愭爣
+      if (this.departureLongitude && this.departureLatitude) {
+        submitData.departureLongitude = this.departureLongitude
+        submitData.departureLatitude = this.departureLatitude
       }
       
-      if (this.addressCoordinates.end) {
-        submitData.destinationLongitude = this.addressCoordinates.end.lng
-        submitData.destinationLatitude = this.addressCoordinates.end.lat
-      }
+      // 鐩爣鍦癎PS鍧愭爣鐢卞悗绔嚜鍔ㄨ幏鍙�
       
       return submitData
     },
@@ -688,8 +980,6 @@
       this.$modal.confirm('纭畾瑕佷繚瀛樹慨鏀瑰悧锛�').then(() => {
         this.loading = true
         const submitData = this.buildSubmitData()
-        
-        console.log('鎻愪氦鏁版嵁:', JSON.stringify(submitData, null, 2))
         
         updateTask(submitData).then(response => {
           this.loading = false
@@ -946,6 +1236,51 @@
           color: #333;
         }
       }
+      
+      .staff-list {
+        .staff-item {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          padding: 20rpx;
+          margin-bottom: 15rpx;
+          background-color: #f8f8f8;
+          border-radius: 10rpx;
+          
+          .staff-info {
+            display: flex;
+            align-items: center;
+            gap: 10rpx;
+            
+            .staff-name {
+              font-size: 28rpx;
+              color: #333;
+            }
+            
+            .staff-role {
+              font-size: 24rpx;
+              color: #999;
+            }
+          }
+        }
+        
+        .add-staff {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          gap: 10rpx;
+          padding: 20rpx;
+          border: 2rpx dashed #007AFF;
+          border-radius: 10rpx;
+          color: #007AFF;
+          font-size: 28rpx;
+          cursor: pointer;
+          
+          &:active {
+            background-color: #f0f8ff;
+          }
+        }
+      }
     }
     
     .form-actions {
@@ -1011,5 +1346,132 @@
       }
     }
   }
+  
+  .staff-popup-container {
+    height: 80vh;
+    background-color: white;
+    border-top-left-radius: 20rpx;
+    border-top-right-radius: 20rpx;
+    display: flex;
+    flex-direction: column;
+    
+    .popup-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 20rpx 30rpx;
+      border-bottom: 1rpx solid #f0f0f0;
+      
+      .popup-title {
+        font-size: 32rpx;
+        font-weight: bold;
+        color: #333;
+      }
+      
+      .close-btn {
+        width: 50rpx;
+        height: 50rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+    
+    .search-bar {
+      padding: 20rpx 30rpx;
+      border-bottom: 1rpx solid #f0f0f0;
+      
+      .search-input {
+        height: 70rpx;
+        padding: 0 20rpx;
+        background-color: #f5f5f5;
+        border-radius: 10rpx;
+        font-size: 28rpx;
+      }
+    }
+    
+    .filter-tabs {
+      display: flex;
+      padding: 20rpx 30rpx;
+      gap: 20rpx;
+      border-bottom: 1rpx solid #f0f0f0;
+      
+      .filter-tab {
+        flex: 1;
+        height: 60rpx;
+        line-height: 60rpx;
+        text-align: center;
+        background-color: #f5f5f5;
+        border-radius: 10rpx;
+        font-size: 28rpx;
+        color: #666;
+        
+        &.active {
+          background-color: #007AFF;
+          color: white;
+        }
+      }
+    }
+    
+    .staff-list-scroll {
+      flex: 1;
+      padding: 20rpx 30rpx;
+      
+      .staff-list-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 20rpx;
+        margin-bottom: 15rpx;
+        background-color: #f8f8f8;
+        border-radius: 10rpx;
+        
+        .staff-item-info {
+          flex: 1;
+          
+          .staff-item-name {
+            display: block;
+            font-size: 30rpx;
+            color: #333;
+            margin-bottom: 8rpx;
+          }
+          
+          .staff-item-dept {
+            display: block;
+            font-size: 24rpx;
+            color: #999;
+          }
+        }
+        
+        .staff-item-check {
+          width: 50rpx;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+        }
+      }
+      
+      .empty-tip {
+        text-align: center;
+        padding: 100rpx 0;
+        color: #999;
+        font-size: 28rpx;
+      }
+    }
+    
+    .popup-footer {
+      padding: 20rpx 30rpx;
+      border-top: 1rpx solid #f0f0f0;
+      
+      .confirm-btn {
+        width: 100%;
+        height: 80rpx;
+        background-color: #007AFF;
+        color: white;
+        border-radius: 10rpx;
+        font-size: 32rpx;
+      }
+    }
+  }
 }
-</style>
+</style>
\ No newline at end of file
diff --git a/app/pages/task/settlement.vue b/app/pages/task/settlement.vue
index 9cdffdc..920ef2f 100644
--- a/app/pages/task/settlement.vue
+++ b/app/pages/task/settlement.vue
@@ -13,7 +13,7 @@
         
         <view class="info-item">
           <view class="label">浠诲姟绫诲瀷:</view>
-          <view class="value">{{ getTaskTypeText(task.type) }}</view>
+          <view class="value">{{ taskTypeText }}</view>
         </view>
         
         <view class="info-item">
@@ -51,6 +51,40 @@
           <view class="label">鎬昏垂鐢�:</view>
           <view class="value total">楼{{ totalAmount }}</view>
         </view>
+        
+        <view class="amount-item paid-amount" v-if="paidAmount > 0">
+          <view class="label">宸叉敮浠�:</view>
+          <view class="value" style="color: #34C759;">楼{{ paidAmount }}</view>
+        </view>
+        
+        <view class="amount-item remaining-amount" v-if="paidAmount > 0">
+          <view class="label">鍓╀綑鏈粯:</view>
+          <view class="value" style="color: #ff9900; font-weight: bold;">楼{{ remainingAmount }}</view>
+        </view>
+      </view>
+      
+      <!-- 宸叉敮浠樿褰曞垪琛� -->
+      <view class="payment-history-section" v-if="paidPaymentList.length > 0">
+        <view class="section-title">鏀粯璁板綍</view>
+        <view 
+          class="payment-item" 
+          v-for="payment in paidPaymentList" 
+          :key="payment.id"
+        >
+          <view class="payment-info">
+            <view class="payment-method">
+              <text class="method-tag" :class="['method-' + payment.paymentMethod.toLowerCase()]">
+                {{ getPaymentMethodText(payment.paymentMethod) }}
+              </text>
+            </view>
+            <view class="payment-time">
+              {{ formatPaymentTime(payment.payTime) }}
+            </view>
+          </view>
+          <view class="payment-amount">
+            楼{{ payment.settlementAmount }}
+          </view>
+        </view>
       </view>
       
       <view class="settlement-form">
@@ -80,25 +114,11 @@
             class="form-textarea" 
             placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" 
             v-model="remark"
-          />
+          ></textarea>
         </view>
       </view>
       
-      <!-- 鏀粯浜岀淮鐮佸尯鍩� -->
-      <view v-if="showQRCode" class="qr-code-section">
-        <view class="section-title">璇锋壂鐮佹敮浠�</view>
-        <view class="qr-code-container">
-          <image class="qr-code" :src="qrCodeImage" mode="widthFix"></image>
-          <view class="qr-tip">璇蜂娇鐢▄{ selectedPaymentMethod }}鎵爜鏀粯</view>
-        </view>
-        <view class="payment-status">
-          <view v-if="paymentStatus === 'pending'" class="status-pending">绛夊緟鏀粯...</view>
-          <view v-if="paymentStatus === 'success'" class="status-success">
-            <uni-icons type="checkmarkempty" size="24" color="#4cd964"></uni-icons>
-            鏀粯鎴愬姛
-          </view>
-        </view>
-      </view>
+
     </scroll-view>
     
     <view class="action-section">
@@ -111,6 +131,57 @@
         淇濆瓨缁撶畻
       </button>
     </view>
+    
+    <!-- 鏀粯浜岀淮鐮佸脊绐� -->
+    <uni-popup ref="qrCodePopup" type="center" :mask-click="false">
+      <view class="qr-popup-content">
+        <view class="qr-popup-header">
+          <text class="qr-popup-title">{{ selectedPaymentMethod }}鏀粯</text>
+        </view>
+        
+        <view class="qr-popup-body">
+          <view class="qr-code-box" v-if="qrCodeImage">
+            <image class="qr-image" :src="qrCodeImage" mode="widthFix"></image>
+          </view>
+          
+          <view class="qr-loading" v-else>
+            <uni-icons type="spinner-cycle" size="40" color="#007AFF"></uni-icons>
+            <text class="loading-text">姝e湪鐢熸垚浜岀淮鐮�...</text>
+          </view>
+          
+          <view class="qr-tip-text">璇蜂娇鐢▄{ selectedPaymentMethod }}鎵爜鏀粯</view>
+          <view class="qr-amount">楼{{ settlementAmount }}</view>
+          
+          <view class="payment-status-box">
+            <view v-if="paymentStatus === 'pending'" class="status-waiting">
+              <uni-icons type="spinner-cycle" size="20" color="#ff9900"></uni-icons>
+              <text>绛夊緟鏀粯涓�...</text>
+            </view>
+            <view v-if="paymentStatus === 'success'" class="status-paid">
+              <uni-icons type="checkmarkempty" size="24" color="#4cd964"></uni-icons>
+              <text>鏀粯鎴愬姛</text>
+            </view>
+          </view>
+        </view>
+        
+        <view class="qr-popup-footer">
+          <button 
+            class="cancel-pay-btn" 
+            @click="cancelPayment"
+            v-if="paymentStatus !== 'success'"
+          >
+            鍙栨秷鏀粯
+          </button>
+          <button 
+            class="confirm-pay-btn" 
+            @click="confirmPaymentSuccess"
+            v-if="paymentStatus === 'success'"
+          >
+            纭畾
+          </button>
+        </view>
+      </view>
+    </uni-popup>
     
     <!-- 闄勫姞璐圭敤寮圭獥 -->
     <uni-popup ref="additionalFeesPopup" type="bottom">
@@ -150,18 +221,23 @@
         </view>
         
         <!-- 宸叉坊鍔犵殑璐圭敤鍒楄〃 -->
-        <view class="added-fees-list" v-if="selectedAdditionalFees.length > 0">
+        <view class="added-fees-list" v-if="additionalFeeList.length > 0">
           <view class="section-title">宸叉坊鍔犺垂鐢�</view>
           <view 
             class="fee-item" 
-            v-for="(fee, index) in selectedAdditionalFees" 
-            :key="index"
+            v-for="fee in additionalFeeList" 
+            :key="fee.id"
           >
             <view class="fee-info">
-              <view class="fee-name">{{ fee.name }}</view>
-              <view class="fee-price">楼{{ fee.price }} 脳 {{ fee.quantity }}</view>
+              <view class="fee-name">{{ fee.feeName }}</view>
+              <view class="fee-price">楼{{ fee.unitAmount }} 脳 {{ fee.quantity }}</view>
             </view>
-            <view class="fee-total">楼{{ (fee.price * fee.quantity).toFixed(2) }}</view>
+            <view class="fee-actions">
+              <view class="fee-total">楼{{ fee.totalAmount }}</view>
+              <view class="delete-btn" @click="removeFee(fee.id)" v-if="!paySuccess">
+                <uni-icons type="trash" size="20" color="#e54d42"></uni-icons>
+              </view>
+            </view>
           </view>
         </view>
         
@@ -174,103 +250,321 @@
 </template>
 
 <script>
+import { getPaymentInfo, addAdditionalFee, removeAdditionalFee, createPayment, getPaymentStatus } from '@/api/payment'
+import { getTask } from '@/api/task'
+
   export default {
     data() {
       return {
-        task: {
-          id: 1,
-          taskNo: 'RW20230515001',
-          type: 'emergency',
-          vehicle: '绮12345',
-          startLocation: '骞垮窞甯傚ぉ娌冲尯XX璺�123鍙�',
-          endLocation: '骞垮窞甯傜櫧浜戝尯YY璺�456鍙�'
-        },
-        baseAmount: 1000, // 鍩虹璐圭敤
-        additionalAmount: 0, // 闄勫姞璐圭敤
+        taskId: null,
+        task: {},
+        baseAmount: 0, // 鍩虹璐圭敤(鎴愪氦浠�)
+        additionalAmount: 0, // 闄勫姞璐圭敤姹囨��
         settlementAmount: '', // 缁撶畻閲戦
         remark: '', // 澶囨敞
-        paymentMethods: ['鐜伴噾', '鏀粯瀹�', '寰俊', '鎸傚笎'],
+        paymentMethods: [], // 浠庡瓧鍏稿姞杞芥敮浠樻柟寮�
+        paymentMethodDict: [], // 瀛楀吀鍘熷鏁版嵁
         selectedPaymentMethod: '',
         showQRCode: false,
         paymentStatus: 'pending', // pending, success
-        qrCodeImage: '/static/images/qrcode.png', // 浜岀淮鐮佸浘鐗囪矾寰�
-        additionalFeeTypes: [
-          { name: '鎷呮灦璐�', price: 200 },
-          { name: '绛夊緟璐�', price: 100 },
-          { name: '鍠勫悗璐�', price: 150 },
-          { name: '澶滈棿鏈嶅姟璐�', price: 300 },
-          { name: '闀块�旇垂', price: 500 }
-        ],
-        selectedAdditionalFees: [], // 宸查�夋嫨鐨勯檮鍔犺垂鐢�
+        qrCodeImage: '', // 浜岀淮鐮佸浘鐗囪矾寰�
+        paymentId: null,
+        pollTimer: null, // 杞瀹氭椂鍣�
+        additionalFeeTypes: [], // 浠庡瓧鍏稿姞杞�
+        additionalFeeList: [], // 宸叉坊鍔犵殑闄勫姞璐圭敤鍒楄〃
         selectedFeeTypeName: '', // 閫変腑鐨勮垂鐢ㄧ被鍨嬪悕绉�
-        newFeePrice: '' // 鏂板璐圭敤浠锋牸
+        selectedFeeTypeValue: '', // 閫変腑鐨勮垂鐢ㄧ被鍨嬪��
+        newFeePrice: '', // 鏂板璐圭敤浠锋牸
+        loading: false,
+        paySuccess: false, // 鏀粯鎴愬姛鏍囪
+        paidAmount: 0, // 宸叉敮浠橀噾棰�
+        paidPaymentList: [] // 宸叉敮浠樿褰曞垪琛�
       }
     },
     computed: {
       totalAmount() {
         return this.baseAmount + this.additionalAmount;
       },
+      // 鍓╀綑鏈敮浠橀噾棰�
+      remainingAmount() {
+        return this.totalAmount - this.paidAmount;
+      },
+      // 浠诲姟绫诲瀷鏄剧ず
+      taskTypeText() {
+        const typeMap = {
+          'EMERGENCY_TRANSFER': '鎬ユ晳杞繍',
+          'SCHEDULED_TRANSFER': '璁″垝杞繍',
+          'EMERGENCY_RESCUE': '鎬ユ晳鎶㈡晳',
+          'ORDINARY_TASK': '鏅�氫换鍔�'
+        }
+        return typeMap[this.task.type] || this.task.type
+      },
       canSave() {
-        // 鐜伴噾鍜屾寕甯愬彲浠ョ洿鎺ヤ繚瀛橈紝鍏朵粬鏀粯鏂瑰紡闇�瑕佹敮浠樻垚鍔熷悗鎵嶈兘淇濆瓨
+        // 宸插叏棰濇敮浠樺悗涓嶈兘鍐嶆淇濆瓨
+        if (this.remainingAmount <= 0) {
+          return false
+        }
+        
         if (!this.settlementAmount || !this.selectedPaymentMethod) {
-          return false;
+          return false
         }
         
-        if (this.selectedPaymentMethod === '鐜伴噾' || this.selectedPaymentMethod === '鎸傚笎') {
-          return true;
+        const amount = parseFloat(this.settlementAmount)
+        
+        // 鏍¢獙缁撶畻閲戦蹇呴』澶т簬0涓斾笉瓒呰繃鍓╀綑閲戦
+        if (amount <= 0 || amount > this.remainingAmount) {
+          return false
         }
         
-        // 鏀粯瀹濄�佸井淇$瓑闇�瑕佹敮浠樻垚鍔�
-        return this.paymentStatus === 'success';
+        const dictValue = this.getPaymentMethodValue(this.selectedPaymentMethod)
+        
+        // 1-鐜伴噾, 6-鎸傝处, 7-鏄撳尰閫氭寕璐� 鍙互鐩存帴淇濆瓨
+        if (dictValue === '1' || dictValue === '6' || dictValue === '7') {
+          return true
+        }
+        
+        // 3-寰俊鏀粯, 4-鏀粯瀹� 闇�瑕佹敮浠樻垚鍔熷悗鎵嶈兘淇濆瓨
+        if (dictValue === '3' || dictValue === '4') {
+          return this.paymentStatus === 'success'
+        }
+        
+        // 2-閾惰杞处, 5-POS鏀舵 鐩存帴淇濆瓨
+        return true
       },
       // 鑾峰彇璐圭敤绫诲瀷鍚嶇О鏁扮粍
       additionalFeeTypeNames() {
-        return this.additionalFeeTypes.map(fee => fee.name);
+        return this.additionalFeeTypes.map(fee => fee.dictLabel);
       }
     },
     onLoad(options) {
-      // 瀹為檯椤圭洰涓繖閲屼細閫氳繃API鑾峰彇浠诲姟璇︽儏
-      // const taskId = options.id;
-      // this.getTaskDetail(taskId);
+      if (options.taskId) {
+        this.taskId = options.taskId
+        this.loadPaymentMethods() // 鍔犺浇鏀粯鏂瑰紡瀛楀吀
+        this.loadPaymentInfo()
+        this.loadFeeTypes()
+      } else {
+        this.$modal.showToast('浠诲姟ID涓嶈兘涓虹┖')
+        setTimeout(() => {
+          uni.navigateBack()
+        }, 1500)
+      }
+    },
+    onUnload() {
+      // 娓呴櫎杞瀹氭椂鍣�
+      if (this.pollTimer) {
+        clearInterval(this.pollTimer)
+      }
     },
     methods: {
-      getTaskTypeText(type) {
-        const typeMap = {
-          'maintenance': '缁翠慨淇濆吇',
-          'refuel': '鍔犳补',
-          'inspection': '宸℃',
-          'emergency': '杞繍浠诲姟',
-          'welfare': '绂忕杞�'
-        }
-        return typeMap[type] || '鏈煡绫诲瀷'
+      // 鍔犺浇鏀粯鏂瑰紡瀛楀吀
+      loadPaymentMethods() {
+        this.$dict.getDicts('task_payment_method').then(res => {
+          // 杩囨护鎺夐��娆�(8)鍜岀Н鍒�(9)锛屽彧鏄剧ず1-7
+          this.paymentMethodDict = (res.data || []).filter(item => {
+            const value = parseInt(item.dictValue)
+            return value >= 1 && value <= 7
+          })
+          // 鎻愬彇鏄剧ず鍚嶇О鏁扮粍鐢ㄤ簬picker
+          this.paymentMethods = this.paymentMethodDict.map(item => item.dictLabel)
+        }).catch(err => {
+          console.error('鍔犺浇鏀粯鏂瑰紡瀛楀吀澶辫触', err)
+          this.$modal.showToast('鍔犺浇鏀粯鏂瑰紡澶辫触')
+        })
+      },
+      
+      // 鏍规嵁閫変腑鐨勫悕绉拌幏鍙栧瓧鍏稿��
+      getPaymentMethodValue(label) {
+        const method = this.paymentMethodDict.find(item => item.dictLabel === label)
+        return method ? method.dictValue : ''
+      },
+      
+      // 鍔犺浇鏀粯淇℃伅
+      loadPaymentInfo() {
+        this.loading = true
+        getPaymentInfo(this.taskId).then(res => {
+          const data = res.data
+          
+          // 浠诲姟鍩烘湰淇℃伅
+          this.task = {
+            taskNo: data.taskCode || '',
+            type: data.taskType || '',
+            vehicle: data.vehicleInfo || '鏈垎閰�',
+            startLocation: data.departureAddress || '鏈缃�',
+            endLocation: data.destinationAddress || '鏈缃�'
+          }
+          
+          // 璐圭敤淇℃伅
+          this.baseAmount = data.transferPrice || 0
+          this.additionalAmount = data.additionalAmount || 0
+          this.additionalFeeList = data.additionalFees || []
+          this.paidAmount = data.paidAmount || 0
+          this.paidPaymentList = data.paidPayments || [] // 鍔犺浇宸叉敮浠樿褰曞垪琛�
+          
+          // 榛樿缁撶畻閲戦涓哄墿浣欐湭鏀粯閲戦
+          const remaining = (data.totalAmount || 0) - this.paidAmount
+          this.settlementAmount = remaining > 0 ? remaining.toString() : ''
+          
+          // 濡傛灉宸插叏棰濇敮浠橈紝鎻愮ず宸茬粨绠�
+          if (remaining <= 0) {
+            this.paySuccess = true
+            this.$modal.showToast('璇ヤ换鍔″凡缁撶畻')
+          }
+          
+          this.loading = false
+        }).catch(err => {
+          console.error('鍔犺浇鏀粯淇℃伅澶辫触', err)
+          this.loading = false
+          this.$modal.showToast('鍔犺浇鏀粯淇℃伅澶辫触')
+        })
+      },
+      
+      // 鍔犺浇璐圭敤绫诲瀷瀛楀吀
+      loadFeeTypes() {
+        this.$dict.getDicts('task_additional_fee_type').then(res => {
+          this.additionalFeeTypes = res.data || []
+        })
       },
       
       onPaymentMethodChange(e) {
-        this.selectedPaymentMethod = this.paymentMethods[e.detail.value];
+        this.selectedPaymentMethod = this.paymentMethods[e.detail.value]
+        const dictValue = this.getPaymentMethodValue(this.selectedPaymentMethod)
         
-        // 濡傛灉閫夋嫨鏀粯瀹濇垨寰俊锛屾樉绀轰簩缁寸爜
-        if (this.selectedPaymentMethod === '鏀粯瀹�' || this.selectedPaymentMethod === '寰俊') {
-          this.showQRCode = true;
-          this.paymentStatus = 'pending';
-          // 妯℃嫙鏀粯鐘舵�佹鏌�
-          this.checkPaymentStatus();
+        // 3-寰俊鏀粯, 4-鏀粯瀹�
+        if (dictValue === '3' || dictValue === '4') {
+          this.openQRCodePopup(dictValue)
         } else {
-          this.showQRCode = false;
-          this.paymentStatus = 'pending';
+          // 鍏朵粬鏀粯鏂瑰紡涓嶆樉绀轰簩缁寸爜
+          this.showQRCode = false
+          this.paymentStatus = 'pending'
         }
+      },
+      
+      // 鎵撳紑鏀粯浜岀淮鐮佸脊绐�
+      openQRCodePopup(dictValue) {
+        // 閲嶇疆鐘舵��
+        this.qrCodeImage = ''
+        this.paymentStatus = 'pending'
+        this.showQRCode = true
+        
+        // 鎵撳紑寮圭獥
+        this.$refs.qrCodePopup.open()
+        
+        // 鐢熸垚浜岀淮鐮�
+        this.generateQRCode(dictValue)
+      },
+      
+      // 鍙栨秷鏀粯
+      cancelPayment() {
+        // 娓呴櫎杞
+        if (this.pollTimer) {
+          clearInterval(this.pollTimer);
+          this.pollTimer = null;
+        }
+        
+        // 鍏抽棴寮圭獥
+        this.$refs.qrCodePopup.close();
+        
+        // 閲嶇疆鐘舵��
+        this.selectedPaymentMethod = '';
+        this.showQRCode = false;
+        this.qrCodeImage = '';
+        this.paymentStatus = 'pending';
+      },
+      
+      // 纭鏀粯鎴愬姛
+      confirmPaymentSuccess() {
+        // 鍏抽棴寮圭獥
+        this.$refs.qrCodePopup.close();
+        
+        // 閲嶆柊鍔犺浇鏀粯淇℃伅锛屽埛鏂版樉绀�
+        this.loadPaymentInfo();
+        
+        // 閲嶇疆鐘舵�侊紝鍑嗗涓嬩竴绗旀敮浠�
+        this.selectedPaymentMethod = '';
+        this.showQRCode = false;
+        this.qrCodeImage = '';
+        this.paymentStatus = 'pending';
+        this.remark = '';
+        // settlementAmount 浼氬湪 loadPaymentInfo 涓嚜鍔ㄨ缃负鍓╀綑閲戦
+      },
+      
+      // 鐢熸垚鏀粯浜岀淮鐮�
+      generateQRCode(paymentMethod) {
+        // 鏍¢獙缁撶畻閲戦
+        if (!this.settlementAmount) {
+          this.$modal.showToast('璇峰厛杈撳叆缁撶畻閲戦');
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+          return;
+        }
+        
+        const amount = parseFloat(this.settlementAmount);
+        if (amount <= 0) {
+          this.$modal.showToast('缁撶畻閲戦蹇呴』澶т簬0');
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+          return;
+        }
+        
+        if (amount > this.remainingAmount) {
+          this.$modal.showToast(`缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑閲戦楼${this.remainingAmount}`);
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+          return;
+        }
+        
+        const data = {
+          taskId: this.taskId,
+          paymentMethod: paymentMethod,
+          settlementAmount: amount,
+          remark: this.remark
+        };
+        
+        createPayment(data).then(res => {
+          const result = res.data;
+          this.paymentId = result.paymentId;
+          this.qrCodeImage = result.codeUrl;
+          this.paymentStatus = 'pending';
+          
+          // 寮�濮嬭疆璇㈡敮浠樼姸鎬�
+          this.checkPaymentStatus();
+        }).catch(err => {
+          console.error('鐢熸垚鏀粯浜岀淮鐮佸け璐�', err);
+          this.$modal.showToast('鐢熸垚鏀粯浜岀淮鐮佸け璐�');
+          this.$refs.qrCodePopup.close();
+          this.selectedPaymentMethod = '';
+        });
       },
       
       // 璐圭敤绫诲瀷閫夋嫨
       onFeeTypeChange(e) {
-        this.selectedFeeTypeName = this.additionalFeeTypeNames[e.detail.value];
+        const index = e.detail.value
+        this.selectedFeeTypeName = this.additionalFeeTypes[index].dictLabel
+        this.selectedFeeTypeValue = this.additionalFeeTypes[index].dictValue
       },
       
+      // 杞妫�鏌ユ敮浠樼姸鎬�
       checkPaymentStatus() {
-        // 妯℃嫙鏀粯鐘舵�佹鏌ワ紝瀹為檯椤圭洰涓簲璇ラ�氳繃API杞妫�鏌ユ敮浠樼姸鎬�
-        setTimeout(() => {
-          // 妯℃嫙鏀粯鎴愬姛
-          this.paymentStatus = 'success';
-        }, 5000);
+        if (this.pollTimer) {
+          clearInterval(this.pollTimer);
+        }
+        
+        this.pollTimer = setInterval(() => {
+          getPaymentStatus(this.taskId, this.paymentId).then(res => {
+            const data = res.data;
+            if (data.payStatus === 'PAID') {
+              // 鏀粯鎴愬姛
+              this.paymentStatus = 'success';
+              clearInterval(this.pollTimer);
+              this.pollTimer = null;
+              
+              // 鍦ㄥ脊绐椾腑鏄剧ず鏀粯鎴愬姛鐘舵��
+              // 鐢ㄦ埛闇�瑕佺偣鍑�"纭畾"鎸夐挳鏉ュ叧闂脊绐楀苟鍒锋柊椤甸潰
+            }
+          }).catch(err => {
+            console.error('鏌ヨ鏀粯鐘舵�佸け璐�', err);
+          });
+        }, 2000); // 姣�2绉掕疆璇竴娆�
       },
       
       showAdditionalFees() {
@@ -293,76 +587,151 @@
           return;
         }
         
-        // 鏌ユ壘閫変腑鐨勮垂鐢ㄧ被鍨嬩俊鎭�
-        const selectedFeeType = this.additionalFeeTypes.find(fee => fee.name === this.selectedFeeTypeName);
-        
-        // 妫�鏌ユ槸鍚﹀凡瀛樺湪鍚屽悕璐圭敤
-        const existingFee = this.selectedAdditionalFees.find(fee => fee.name === this.selectedFeeTypeName);
-        if (existingFee) {
-          existingFee.quantity += 1;
-        } else {
-          this.selectedAdditionalFees.push({
-            name: this.selectedFeeTypeName,
-            price: parseFloat(this.newFeePrice),
-            quantity: 1
-          });
+        // 璋冪敤鎺ュ彛娣诲姞闄勫姞璐圭敤
+        const data = {
+          taskId: this.taskId,
+          feeType: this.selectedFeeTypeValue,
+          feeName: this.selectedFeeTypeName,
+          unitAmount: parseFloat(this.newFeePrice),
+          quantity: 1,
+          remark: ''
         }
         
-        // 娓呯┖杈撳叆妗�
-        this.selectedFeeTypeName = '';
-        this.newFeePrice = '';
-        
-        this.calculateAdditionalAmount();
-        this.$modal.showToast('璐圭敤娣诲姞鎴愬姛');
+        addAdditionalFee(data).then(res => {
+          this.$modal.showToast('璐圭敤娣诲姞鎴愬姛')
+          
+          // 娓呯┖杈撳叆妗�
+          this.selectedFeeTypeName = ''
+          this.selectedFeeTypeValue = ''
+          this.newFeePrice = ''
+          
+          // 閲嶆柊鍔犺浇鏀粯淇℃伅
+          this.loadPaymentInfo()
+        }).catch(err => {
+          console.error('娣诲姞璐圭敤澶辫触', err)
+          this.$modal.showToast('娣诲姞璐圭敤澶辫触')
+        })
       },
       
-      calculateAdditionalAmount() {
-        this.additionalAmount = this.selectedAdditionalFees.reduce((total, fee) => {
-          return total + (fee.price * fee.quantity);
-        }, 0);
+      // 鍒犻櫎闄勫姞璐圭敤
+      removeFee(feeId) {
+        this.$modal.confirm('纭畾瑕佸垹闄よ璐圭敤鍚楋紵').then(() => {
+          removeAdditionalFee({ taskId: this.taskId, feeId }).then(res => {
+            this.$modal.showToast('鍒犻櫎鎴愬姛')
+            // 閲嶆柊鍔犺浇鏀粯淇℃伅
+            this.loadPaymentInfo()
+          }).catch(err => {
+            console.error('鍒犻櫎璐圭敤澶辫触', err)
+            this.$modal.showToast('鍒犻櫎璐圭敤澶辫触')
+          })
+        }).catch(() => {})
       },
       
       confirmAdditionalFees() {
-        this.calculateAdditionalAmount();
         this.closeAdditionalFeesPopup();
+      },
+      
+      // 鑾峰彇鏀粯鏂瑰紡鏂囨湰
+      getPaymentMethodText(dictValue) {
+        const method = this.paymentMethodDict.find(item => item.dictValue === dictValue)
+        return method ? method.dictLabel : dictValue
+      },
+      
+      // 鏍煎紡鍖栨敮浠樻椂闂�
+      formatPaymentTime(time) {
+        if (!time) return '鏈煡'
+        const date = new Date(time)
+        const year = date.getFullYear()
+        const month = String(date.getMonth() + 1).padStart(2, '0')
+        const day = String(date.getDate()).padStart(2, '0')
+        const hour = String(date.getHours()).padStart(2, '0')
+        const minute = String(date.getMinutes()).padStart(2, '0')
+        return `${year}-${month}-${day} ${hour}:${minute}`
       },
       
       saveSettlement() {
         if (!this.settlementAmount) {
-          this.$modal.showToast('璇疯緭鍏ョ粨绠楅噾棰�');
-          return;
+          this.$modal.showToast('璇疯緭鍏ョ粨绠楅噾棰�')
+          return
         }
         
         if (!this.selectedPaymentMethod) {
-          this.$modal.showToast('璇烽�夋嫨鏀粯鏂瑰紡');
-          return;
+          this.$modal.showToast('璇烽�夋嫨鏀粯鏂瑰紡')
+          return
         }
         
-        // 妫�鏌ョ粨绠楅噾棰濇槸鍚﹀悎鐞�
-        if (parseFloat(this.settlementAmount) > this.totalAmount) {
-          this.$modal.showToast('缁撶畻閲戦涓嶈兘澶т簬鎬昏垂鐢�');
-          return;
+        const amount = parseFloat(this.settlementAmount)
+        
+        // 鏍¢獙缁撶畻閲戦蹇呴』澶т簬0
+        if (amount <= 0) {
+          this.$modal.showToast('缁撶畻閲戦蹇呴』澶т簬0')
+          return
         }
         
-        this.$modal.confirm('纭畾瑕佷繚瀛樼粨绠椾俊鎭悧锛�').then(() => {
-          // 杩欓噷搴旇璋冪敤API淇濆瓨缁撶畻淇℃伅
-          console.log('缁撶畻淇℃伅:', {
-            taskId: this.task.id,
-            baseAmount: this.baseAmount,
-            additionalAmount: this.additionalAmount,
-            totalAmount: this.totalAmount,
-            settlementAmount: this.settlementAmount,
-            paymentMethod: this.selectedPaymentMethod,
-            remark: this.remark,
-            additionalFees: this.selectedAdditionalFees
-          });
-          
-          this.$modal.showToast('缁撶畻淇℃伅淇濆瓨鎴愬姛');
-          // 杩斿洖浠诲姟鍒楄〃
-          this.$tab.navigateBack();
-        }).catch(() => {
-          // 鍙栨秷鎿嶄綔
-        });
+        // 鏍¢獙缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑閲戦
+        if (amount > this.remainingAmount) {
+          this.$modal.showToast(`缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑閲戦楼${this.remainingAmount}`)
+          return
+        }
+        
+        const dictValue = this.getPaymentMethodValue(this.selectedPaymentMethod)
+        
+        // 3-寰俊鏀粯, 4-鏀粯瀹� 宸茬粡鍦ㄩ�夋嫨鏃剁敓鎴愪簡浜岀淮鐮侊紝绛夊緟鏀粯瀹屾垚
+        if (dictValue === '3' || dictValue === '4') {
+          if (this.paymentStatus !== 'success') {
+            this.$modal.showToast('璇峰厛瀹屾垚鎵爜鏀粯')
+            return
+          }
+        }
+        
+        // 1-鐜伴噾, 2-閾惰杞处, 5-POS鏀舵, 6-鎸傝处, 7-鏄撳尰閫氭寕璐� 闇�瑕佸垱寤烘敮浠樿褰�
+        if (dictValue === '1' || dictValue === '2' || dictValue === '5' || dictValue === '6' || dictValue === '7') {
+          this.$modal.confirm('纭畾瑕佷繚瀛樼粨绠椾俊鎭悧锛�').then(() => {
+            const data = {
+              taskId: this.taskId,
+              paymentMethod: dictValue,
+              settlementAmount: amount,
+              remark: this.remark
+            }
+            
+            this.loading = true
+            createPayment(data).then(res => {
+              this.loading = false
+              const result = res.data
+              this.paymentId = result.paymentId
+              this.paymentStatus = 'success'
+              
+              // 閲嶆柊鍔犺浇鏀粯淇℃伅浠ヨ幏鍙栨渶鏂扮殑宸叉敮浠橀噾棰�
+              this.loadPaymentInfo()
+              
+              // 妫�鏌ユ槸鍚﹀叏棰濇敮浠橈紙浣跨敤鏈�鏂版暟鎹垽鏂級
+              setTimeout(() => {
+                if (this.remainingAmount <= 0) {
+                  this.paySuccess = true
+                  this.$modal.showToast('鏀粯鎴愬姛锛屽凡鍏ㄩ缁撶畻')
+                  setTimeout(() => {
+                    uni.navigateBack()
+                  }, 1500)
+                } else {
+                  this.$modal.showToast(`鏀粯鎴愬姛锛屽墿浣櫬�${this.remainingAmount.toFixed(2)}`)
+                  // 閲嶇疆琛ㄥ崟锛屽噯澶囦笅涓�绗旀敮浠�
+                  this.selectedPaymentMethod = ''
+                  this.remark = ''
+                }
+              }, 300) // 绛夊緟鏁版嵁鍔犺浇瀹屾垚
+            }).catch(err => {
+              this.loading = false
+              console.error('鍒涘缓鏀粯澶辫触', err)
+              this.$modal.showToast('鍒涘缓鏀粯澶辫触')
+            })
+          }).catch(() => {
+            // 鍙栨秷鎿嶄綔
+          })
+        } else {
+          // 鎵爜鏀粯锛堝井淇�/鏀粯瀹濓級鐨勬儏鍐典笉搴旇璧板埌杩欓噷
+          // 鍥犱负鎵爜鏀粯鍦� confirmPaymentSuccess 涓鐞�
+          this.$modal.showToast('璇峰厛瀹屾垚鎵爜鏀粯')
+        }
       }
     }
   }
@@ -505,6 +874,76 @@
       }
     }
     
+    .payment-history-section {
+      background-color: white;
+      border-radius: 15rpx;
+      padding: 30rpx;
+      margin-bottom: 20rpx;
+      box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
+      
+      .section-title {
+        font-size: 32rpx;
+        font-weight: bold;
+        margin-bottom: 20rpx;
+        color: #333;
+      }
+      
+      .payment-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 20rpx 0;
+        border-bottom: 1rpx solid #f0f0f0;
+        
+        &:last-child {
+          border-bottom: none;
+        }
+        
+        .payment-info {
+          flex: 1;
+          
+          .payment-method {
+            margin-bottom: 10rpx;
+            
+            .method-tag {
+              display: inline-block;
+              padding: 4rpx 12rpx;
+              border-radius: 6rpx;
+              font-size: 24rpx;
+              color: white;
+              
+              &.method-cash {
+                background-color: #34C759;
+              }
+              
+              &.method-on_account {
+                background-color: #ff9500;
+              }
+              
+              &.method-wechat {
+                background-color: #09BB07;
+              }
+              
+              &.method-alipay {
+                background-color: #1677FF;
+              }
+            }
+          }
+          
+          .payment-time {
+            font-size: 24rpx;
+            color: #999;
+          }
+        }
+        
+        .payment-amount {
+          font-size: 32rpx;
+          font-weight: bold;
+          color: #34C759;
+        }
+      }
+    }
+    
     .settlement-form {
       background-color: white;
       border-radius: 15rpx;
@@ -618,6 +1057,130 @@
     }
   }
   
+  // 鏀粯浜岀淮鐮佸脊绐楁牱寮�
+  .qr-popup-content {
+    width: 600rpx;
+    background-color: white;
+    border-radius: 20rpx;
+    overflow: hidden;
+    
+    .qr-popup-header {
+      padding: 40rpx 30rpx 30rpx;
+      text-align: center;
+      border-bottom: 1rpx solid #f0f0f0;
+      
+      .qr-popup-title {
+        font-size: 36rpx;
+        font-weight: bold;
+        color: #333;
+      }
+    }
+    
+    .qr-popup-body {
+      padding: 40rpx 30rpx;
+      text-align: center;
+      
+      .qr-code-box {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-bottom: 30rpx;
+        
+        .qr-image {
+          width: 400rpx;
+          height: 400rpx;
+          border: 2rpx solid #f0f0f0;
+          border-radius: 10rpx;
+          padding: 20rpx;
+          box-sizing: border-box;
+        }
+      }
+      
+      .qr-loading {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        height: 400rpx;
+        margin-bottom: 30rpx;
+        
+        .loading-text {
+          margin-top: 20rpx;
+          font-size: 28rpx;
+          color: #999;
+        }
+      }
+      
+      .qr-tip-text {
+        font-size: 28rpx;
+        color: #666;
+        margin-bottom: 20rpx;
+      }
+      
+      .qr-amount {
+        font-size: 48rpx;
+        font-weight: bold;
+        color: #e54d42;
+        margin-bottom: 30rpx;
+      }
+      
+      .payment-status-box {
+        padding: 20rpx;
+        border-radius: 10rpx;
+        
+        .status-waiting {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          gap: 10rpx;
+          font-size: 28rpx;
+          color: #ff9900;
+          
+          text {
+            margin-left: 10rpx;
+          }
+        }
+        
+        .status-paid {
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          gap: 10rpx;
+          font-size: 32rpx;
+          color: #4cd964;
+          font-weight: bold;
+          
+          text {
+            margin-left: 10rpx;
+          }
+        }
+      }
+    }
+    
+    .qr-popup-footer {
+      padding: 20rpx 30rpx 30rpx;
+      
+      .cancel-pay-btn,
+      .confirm-pay-btn {
+        width: 100%;
+        height: 80rpx;
+        border-radius: 10rpx;
+        font-size: 32rpx;
+        border: none;
+      }
+      
+      .cancel-pay-btn {
+        background-color: #f5f5f5;
+        color: #666;
+      }
+      
+      .confirm-pay-btn {
+        background-color: #4cd964;
+        color: white;
+      }
+    }
+  }
+  
   .popup-content {
     background-color: white;
     border-top-left-radius: 20rpx;
@@ -713,6 +1276,7 @@
         }
         
         .fee-info {
+          flex: 1;
           .fee-name {
             font-size: 28rpx;
             color: #333;
@@ -725,11 +1289,21 @@
           }
         }
         
+        .fee-actions {
+          display: flex;
+          align-items: center;
+          gap: 20rpx;
+        }
+        
         .fee-total {
           font-size: 28rpx;
           font-weight: bold;
           color: #e54d42;
         }
+        
+        .delete-btn {
+          padding: 10rpx;
+        }
       }
     }
     
diff --git a/app/plugins/dict.js b/app/plugins/dict.js
new file mode 100644
index 0000000..62142a5
--- /dev/null
+++ b/app/plugins/dict.js
@@ -0,0 +1,7 @@
+import { getDicts } from '@/api/dict'
+
+export default {
+  getDicts(dictType) {
+    return getDicts(dictType)
+  }
+}
diff --git a/app/plugins/index.js b/app/plugins/index.js
index efbae15..1ce4e16 100644
--- a/app/plugins/index.js
+++ b/app/plugins/index.js
@@ -1,6 +1,7 @@
 import tab from './tab'
 import auth from './auth'
 import modal from './modal'
+import dict from './dict'
 
 export default {
   install(Vue) {
@@ -10,5 +11,7 @@
     Vue.prototype.$auth = auth
     // 妯℃�佹瀵硅薄
     Vue.prototype.$modal = modal
+    // 瀛楀吀瀵硅薄
+    Vue.prototype.$dict = dict
   }
 }
diff --git "a/doc/\346\224\257\344\273\230\345\212\237\350\203\275\345\256\236\347\216\260\350\277\233\345\272\246.md" "b/doc/\346\224\257\344\273\230\345\212\237\350\203\275\345\256\236\347\216\260\350\277\233\345\272\246.md"
new file mode 100644
index 0000000..381d31f
--- /dev/null
+++ "b/doc/\346\224\257\344\273\230\345\212\237\350\203\275\345\256\236\347\216\260\350\277\233\345\272\246.md"
@@ -0,0 +1,137 @@
+# 杞繍浠诲姟鏀粯鍔熻兘瀹炵幇杩涘害
+
+## 宸插畬鎴愮殑宸ヤ綔
+
+### 1. 鏁版嵁搴撹璁� 鉁�
+- 鉁� 鍒涘缓 `sys_task_additional_fee` 闄勫姞璐圭敤琛�
+- 鉁� 鍒涘缓 `sys_task_payment` 鏀粯璁板綍琛�
+- 鉁� 鍒涘缓闄勫姞璐圭敤绫诲瀷瀛楀吀 `task_additional_fee_type`
+- 鉁� SQL鑴氭湰锛歚sql/task_payment_tables.sql`
+
+### 2. 鍚庣瀹炰綋绫� 鉁�
+- 鉁� SysTaskAdditionalFee.java - 闄勫姞璐圭敤瀹炰綋
+- 鉁� SysTaskPayment.java - 鏀粯璁板綍瀹炰綋
+- 鉁� TaskPaymentInfoVO.java - 鏀粯淇℃伅VO
+- 鉁� TaskPaymentCreateVO.java - 鍒涘缓鏀粯VO
+- 鉁� TaskPaymentResultVO.java - 鏀粯缁撴灉VO
+
+### 3. 鍚庣Mapper灞� 鉁�
+- 鉁� SysTaskAdditionalFeeMapper.java / SysTaskAdditionalFeeMapper.xml
+- 鉁� SysTaskPaymentMapper.java / SysTaskPaymentMapper.xml
+
+### 4. 鍚庣Service灞� 鉁�
+- 鉁� ISysTaskPaymentService.java - 浠诲姟鏀粯Service鎺ュ彛
+- 鉁� SysTaskPaymentServiceImpl.java - 浠诲姟鏀粯Service瀹炵幇
+- 鉁� IPaymentModuleService.java - 鏀粯妯″潡璋冪敤鎺ュ彛
+- 鉁� PaymentModuleServiceImpl.java - 鏀粯妯″潡璋冪敤瀹炵幇锛堟ā鎷燂級
+
+### 5. 鍚庣Controller灞� 鉁�
+- 鉁� SysTaskPaymentController.java - 浠诲姟鏀粯鎺у埗鍣�
+  - GET /task/payment/info - 鑾峰彇浠诲姟鏀粯淇℃伅
+  - POST /task/payment/additional-fee/add - 鏂板闄勫姞璐圭敤
+  - POST /task/payment/additional-fee/remove - 鍒犻櫎闄勫姞璐圭敤
+  - POST /task/payment/create - 鍒涘缓鏀粯
+  - GET /task/payment/status - 鏌ヨ鏀粯鐘舵��
+- 鉁� PaymentCallbackController.java - 鏀粯鍥炶皟鎺у埗鍣�
+  - POST /payment/callback/wechat - 寰俊鏀粯鍥炶皟
+  - POST /payment/callback/alipay - 鏀粯瀹濇敮浠樺洖璋�
+
+### 6. 鍓嶇APP绔� 鉁�
+- 鉁� app/api/payment.js - 鏀粯API璋冪敤
+- 鉁� app/pages/task/settlement.vue - 缁撶畻椤甸潰鏀归��
+  - 鏀寔鍔犺浇鏀粯淇℃伅
+  - 鏀寔闄勫姞璐圭敤绠$悊锛堟柊澧�/鍒犻櫎锛�
+  - 鏀寔鍥涚鏀粯鏂瑰紡锛堢幇閲戙�佹寕甯愩�佸井淇°�佹敮浠樺疂锛�
+  - 寰俊/鏀粯瀹濇樉绀轰簩缁寸爜骞惰疆璇㈡敮浠樼姸鎬�
+  - 閲戦鏍¢獙锛堢粨绠楅噾棰濆繀椤荤瓑浜庢�婚噾棰濓級
+
+## 寰呭畬鎴愮殑宸ヤ綔
+
+### 7. 鍓嶇APP绔� - 浠诲姟鍒楄〃鍜岃鎯呭鍔犵粨绠楀叆鍙� 鉁�
+宸插畬鎴愮殑淇敼锛�
+- 鉁� app/pages/task/detail.vue - 浠诲姟璇︽儏椤靛鍔�"缁撶畻"鎸夐挳
+  - 浠呰浆杩愪换鍔℃樉绀虹粨绠楁寜閽�
+  - 瀹屾垚/鍙栨秷鐘舵�佷笉鏄剧ず缁撶畻鎸夐挳
+  - 鐐瑰嚮璺宠浆鑷崇粨绠楅〉闈�
+
+寰呭畬鎴愶細
+- [ ] app/pages/task/list.vue - 浠诲姟鍒楄〃鍗$墖澧炲姞"缁撶畻"鎸夐挳锛堝彲閫夛級
+
+### 8. 鍚庡彴绠$悊UI - 浠诲姟璇︽儏椤垫樉绀烘敮浠樹俊鎭� 鉁�
+宸插畬鎴愮殑淇敼锛�
+- 鉁� ruoyi-ui/src/api/task.js - 澧炲姞鏀粯鐩稿叧API鎺ュ彛
+  - getPaymentInfo - 鑾峰彇浠诲姟鏀粯淇℃伅
+  - getAdditionalFees - 鏌ヨ闄勫姞璐圭敤鍒楄〃
+  - getLatestPayment - 鏌ヨ鏈�鏂版敮浠樿褰�
+- 鉁� ruoyi-ui/src/views/task/detail/index.vue - 浠诲姟璇︽儏椤靛鍔犳敮浠樹俊鎭睍绀�
+  - 浠呰浆杩愪换鍔℃樉绀烘敮浠樹俊鎭崱鐗�
+  - 鏄剧ず鎴愪氦浠枫�侀檮鍔犺垂鐢ㄣ�佹�婚噾棰�
+  - 鏄剧ず鏀粯鐘舵�併�佹敮浠樻柟寮忋�佺粨绠楅噾棰�
+  - 鏄剧ず浜ゆ槗鍙枫�佹敮浠樻椂闂�
+  - 鏄剧ず闄勫姞璐圭敤鏄庣粏琛ㄦ牸锛堣垂鐢ㄥ悕绉般�佸崟浠枫�佹暟閲忋�佸皬璁°�佸娉級
+  - 鍙灞曠ず锛屼笉鏀寔缂栬緫
+
+### 9. 閰嶇疆鏂囦欢 鈴�
+闇�瑕佹坊鍔犵殑閰嶇疆锛�
+- [ ] application.yml - 澧炲姞鏀粯妯″潡閰嶇疆
+  ```yaml
+  payment:
+    module:
+      url: http://localhost:8081/pay  # 鏀粯妯″潡鏈嶅姟鍦板潃
+    callback:
+      base-url: http://localhost:8080  # 鍥炶皟鍩虹URL
+  ```
+
+### 10. 闆嗘垚娴嬭瘯 鈴�
+- [ ] 娴嬭瘯闄勫姞璐圭敤鏂板/鍒犻櫎鍔熻兘
+- [ ] 娴嬭瘯鐜伴噾/鎸傚笎鏀粯娴佺▼
+- [ ] 娴嬭瘯寰俊/鏀粯瀹濅簩缁寸爜鐢熸垚
+- [ ] 娴嬭瘯鏀粯鐘舵�佽疆璇�
+- [ ] 娴嬭瘯鏀粯鍥炶皟澶勭悊
+- [ ] 娴嬭瘯閲戦鏍¢獙閫昏緫
+
+### 11. 鏀粯妯″潡瀵规帴 鈴�
+褰撳墠 PaymentModuleServiceImpl 鏄ā鎷熷疄鐜帮紝闇�瑕佹浛鎹负鐪熷疄鐨凥TTP璋冪敤锛�
+- [ ] 浣跨敤 RestTemplate 鎴� HttpClient 璋冪敤鏀粯妯″潡鎺ュ彛
+- [ ] 瀹炵幇绛惧悕楠岃瘉閫昏緫
+- [ ] 澶勭悊寮傚父鎯呭喌鍜岄噸璇曢�昏緫
+
+## 涓嬩竴姝ユ搷浣滃缓璁�
+
+馃帀 **鏍稿績鍔熻兘宸插叏閮ㄥ畬鎴愶紒**
+
+鎺ヤ笅鏉ラ渶瑕佸畬鎴愮殑宸ヤ綔锛�
+
+1. **浼樺厛绾ф渶楂橈細鏁版嵁搴撳垵濮嬪寲**
+   - 鎵ц `sql/task_payment_tables.sql` 鍒涘缓琛ㄥ拰瀛楀吀
+   - 纭闄勫姞璐圭敤绫诲瀷瀛楀吀姝g‘鍒涘缓
+
+2. **浼樺厛绾�2锛氶厤缃敮浠樻ā鍧�**
+   - 鍦� `application.yml` 涓厤缃敮浠樻ā鍧桿RL
+   - 閰嶇疆鍥炶皟鍩虹URL锛堝寘鎷煙鍚嶏級
+
+3. **浼樺厛绾�3锛氶泦鎴愭祴璇�**
+   - 娴嬭瘯闄勫姞璐圭敤绠$悊鍔熻兘
+   - 娴嬭瘯鐜伴噾/鎸傝处鏀粯娴佺▼
+   - 娴嬭瘯鏀粯淇℃伅灞曠ず锛圓PP绔拰鍚庡彴锛�
+   - 楠岃瘉閲戦璁$畻姝g‘鎬�
+
+4. **浼樺厛绾�4锛氬鎺ョ湡瀹炴敮浠樻ā鍧�**
+   - 鏍规嵁鏀粯妯″潡瀹為檯鎺ュ彛鏂囨。淇敼 `PaymentModuleServiceImpl.java`
+   - 鏇挎崲TODO鏍囪鐨勬ā鎷熶唬鐮佷负鐪熷疄鐨凥TTP璋冪敤
+   - 娴嬭瘯寰俊/鏀粯瀹濅簩缁寸爜鐢熸垚
+   - 娴嬭瘯鏀粯鐘舵�佽疆璇笌鍥炶皟
+   - 瀹炵幇绛惧悕楠岃瘉閫昏緫
+
+5. **鍙�夊姛鑳斤細浠诲姟鍒楄〃缁撶畻鎸夐挳**
+   - 鍦� `app/pages/task/list.vue` 浠诲姟鍗$墖澧炲姞鈥滅粨绠椻�濇寜閽�
+
+## 娉ㄦ剰浜嬮」
+
+1. **閲戦绮惧害**锛氭墍鏈夐噾棰濊绠椾娇鐢� BigDecimal锛屼繚鐣欎袱浣嶅皬鏁�
+2. **浜嬪姟绠$悊**锛氶檮鍔犺垂鐢ㄦ搷浣滃拰鏀粯鎿嶄綔宸叉坊鍔� @Transactional 娉ㄨВ
+3. **鏉冮檺鎺у埗**锛氭敮浠樼浉鍏虫帴鍙i渶瑕丣WT閴存潈锛岀‘淇濆彧鏈変换鍔$浉鍏充汉鍛樺彲鎿嶄綔
+4. **鏁版嵁鏉冮檺**锛氶伒寰幇鏈夐儴闂�/鍒嗗叕鍙搁殧绂昏鍒�
+5. **鍥炶皟瀹夊叏**锛氬疄闄呴」鐩腑闇�瑕佷弗鏍奸獙璇佸洖璋冪鍚�
+6. **浜岀淮鐮佽繃鏈�**锛氬墠绔簲鎻愮ず浜岀淮鐮佽繃鏈熸椂闂村苟鍏佽閲嶆柊鐢熸垚
+7. **鏀粯鐘舵�佷竴鑷存��**锛氫互鍚庣鏀粯鐘舵�佷负鍑嗭紝鍥炶皟涓庤疆璇繚鎸佷竴鑷�
diff --git "a/doc/\346\224\257\344\273\230\345\256\235\346\224\257\344\273\230\346\226\271\345\274\217\351\205\215\347\275\256\350\257\264\346\230\216.md" "b/doc/\346\224\257\344\273\230\345\256\235\346\224\257\344\273\230\346\226\271\345\274\217\351\205\215\347\275\256\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..ef7d589
--- /dev/null
+++ "b/doc/\346\224\257\344\273\230\345\256\235\346\224\257\344\273\230\346\226\271\345\274\217\351\205\215\347\275\256\350\257\264\346\230\216.md"
@@ -0,0 +1,85 @@
+# 鏀粯瀹濇敮浠樻柟寮忛厤缃鏄�
+
+## 姒傝堪
+
+鏈郴缁熸敮鎸佷袱绉嶆敮浠樺疂鏀粯鏂瑰紡锛�
+1. **瀹樻柟鏀粯瀹濆綋闈粯** - 浣跨敤鏀粯瀹濆畼鏂筍DK鐩存帴瀵规帴
+2. **绗笁鏂规敮浠樺疂鏀粯** - 閫氳繃鏃х郴缁熺殑绗笁鏂规帴鍙e鎺�
+
+## 閰嶇疆璇存槑
+
+### 1. 鏀粯鏂瑰紡閰嶇疆鍙傛暟
+
+鍦� `application.yml` 涓殑 `payment.alipay` 鑺傜偣涓嬫柊澧炰互涓嬮厤缃細
+
+```yaml
+# 鏀粯瀹濋厤缃�
+alipay:
+  # ... 鍏朵粬鍘熸湁閰嶇疆淇濇寔涓嶅彉 ...
+  
+  # 鏀粯鏂瑰紡: OFFICIAL(瀹樻柟鏀粯瀹�) 鎴� THIRD_PARTY(绗笁鏂规敮浠樺疂)
+  paymentMethod: OFFICIAL
+  
+  # 绗笁鏂规敮浠橀厤缃�
+  thirdParty:
+    enabled: true
+    url: https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php
+    defaultNotifyUrl: https://dsp.966120.com.cn/alipay/pay_notify
+    timeout: 30000  # 瓒呮椂鏃堕棿锛堟绉掞級
+```
+
+### 2. 閰嶇疆鍙傛暟璇﹁В
+
+| 鍙傛暟 | 榛樿鍊� | 璇存槑 |
+|------|--------|------|
+| paymentMethod | OFFICIAL | 鏀粯鏂瑰紡锛屽彲閫夊�硷細<br>- `OFFICIAL`: 瀹樻柟鏀粯瀹濆綋闈粯<br>- `THIRD_PARTY`: 绗笁鏂规敮浠樺疂鏀粯 |
+| thirdParty.enabled | true | 鏄惁鍚敤绗笁鏂规敮浠樺姛鑳� |
+| thirdParty.url | https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php | 绗笁鏂规敮浠樻帴鍙e湴鍧� |
+| thirdParty.defaultNotifyUrl | https://dsp.966120.com.cn/alipay/pay_notify | 榛樿鍥炶皟鍦板潃 |
+| thirdParty.timeout | 30000 | 璇锋眰瓒呮椂鏃堕棿锛堟绉掞級 |
+
+## 浣跨敤鏂瑰紡
+
+### 1. 浣跨敤瀹樻柟鏀粯瀹濆綋闈粯
+
+灏� `paymentMethod` 璁剧疆涓� `OFFICIAL`锛�
+
+```yaml
+payment:
+  alipay:
+    paymentMethod: OFFICIAL
+    # ... 鍏朵粬閰嶇疆
+```
+
+### 2. 浣跨敤绗笁鏂规敮浠樺疂鏀粯
+
+灏� `paymentMethod` 璁剧疆涓� `THIRD_PARTY`锛�
+
+```yaml
+payment:
+  alipay:
+    paymentMethod: THIRD_PARTY
+    # ... 鍏朵粬閰嶇疆
+```
+
+## 鍒囨崲娉ㄦ剰浜嬮」
+
+1. **鍒囨崲鏀粯鏂瑰紡鍚庨渶瑕侀噸鍚湇鍔�**鎵嶈兘鐢熸晥
+2. **宸插垱寤虹殑璁㈠崟涓嶅彈褰卞搷**锛屼粛浣跨敤鍒涘缓鏃剁殑鏀粯鏂瑰紡杩涜澶勭悊
+3. **寤鸿鍦ㄦ祴璇曠幆澧冧腑鍏呭垎娴嬭瘯**鍚庡啀鍒囨崲鍒扮敓浜х幆澧�
+
+## 鏁呴殰鎺掗櫎
+
+### 1. 鏀粯鏂瑰紡涓嶇敓鏁�
+
+妫�鏌ヤ互涓嬪嚑鐐癸細
+- 纭 `paymentMethod` 鍙傛暟鍊兼纭紙娉ㄦ剰澶у皬鍐欙級
+- 纭鏈嶅姟宸查噸鍚�
+- 鏌ョ湅鏃ュ織纭閰嶇疆鏄惁姝g‘鍔犺浇
+
+### 2. 绗笁鏂规敮浠樻帴鍙h皟鐢ㄥけ璐�
+
+妫�鏌ヤ互涓嬪嚑鐐癸細
+- 纭绗笁鏂规帴鍙e湴鍧�鏄惁鍙揪
+- 纭缃戠粶杩炴帴鏄惁姝e父
+- 妫�鏌ユ棩蹇椾腑鐨勯敊璇俊鎭�
\ No newline at end of file
diff --git "a/doc/\350\275\254\350\277\220\344\273\273\345\212\241\346\224\257\344\273\230\345\212\237\350\203\275\350\256\276\350\256\241\346\226\271\346\241\210.md" "b/doc/\350\275\254\350\277\220\344\273\273\345\212\241\346\224\257\344\273\230\345\212\237\350\203\275\350\256\276\350\256\241\346\226\271\346\241\210.md"
new file mode 100644
index 0000000..48c2b08
--- /dev/null
+++ "b/doc/\350\275\254\350\277\220\344\273\273\345\212\241\346\224\257\344\273\230\345\212\237\350\203\275\350\256\276\350\256\241\346\226\271\346\241\210.md"
@@ -0,0 +1,172 @@
+# 杞繍浠诲姟鏀粯鍔熻兘璁捐鏂规锛堟渶缁堢増锛�
+
+鏈柟妗堥拡瀵硅浆杩愪换鍔$殑"鎬婚涓�娆℃�ф敮浠�"鍦烘櫙锛氭�婚=鎴愪氦浠�+闄勫姞璐圭敤姹囨�伙紝鏀寔鐜伴噾銆佹寕甯愩�佸井淇°�佹敮浠樺疂鍥涚鏂瑰紡銆傚井淇�/鏀粯瀹濈敱"鐙珛鏀粯妯″潡"鐢熸垚浜岀淮鐮佷笌鍥炶皟锛屾垜鏂圭郴缁熶粎瀵规帴璇ユ敮浠樻ā鍧椼��
+
+## 涓�銆佹渶缁堢‘璁ょ偣
+
+- 缁撶畻閲戦蹇呴』涓庢�婚噾棰濅竴鑷达紙鎬婚噾棰�=鎴愪氦浠�+闄勫姞璐圭敤姹囨�伙級銆�
+- 鎸傚笎鏀粯浠呰褰曞娉ㄥ嵆鍙��
+- 闄勫姞璐圭敤绫诲瀷鐢卞悗鍙板瓧鍏哥淮鎶わ紙瀛楀吀绫诲瀷锛歵ask_additional_fee_type锛夈��
+- 寰俊銆佹敮浠樺疂鐢辩嫭绔嬫敮浠樻ā鍧楃敓鎴愭敮浠樹簩缁寸爜涓庢煡璇㈢粨鏋滐紝涓嶇洿鎺ラ泦鎴愬晢鎴峰彿閫昏緫銆�
+- 缁撶畻鍏ュ彛鍦� APP 鐨勪换鍔¤鎯呴〉鍜屼换鍔″垪琛ㄥ崱鐗囦笂閮借鏈夈��
+- 鍚庡彴 ruoyi-ui 鍙睍绀烘敮浠樹俊鎭笌闄勫姞璐圭敤鏄庣粏锛屼笉鍏佽淇敼銆�
+- 鍙睍绀�"鏈夋晥鏀粯"锛堟渶杩戜竴鏉″凡鏀粯鎴愬姛鐨勮褰曪級銆�
+- 浜ゆ槗鍗曞彿 outTradeNo 鏍煎紡锛歿taskCode}-{timestampMillis}锛宼imestamp 浣跨敤姣绾ф椂闂存埑銆�
+- 鍥炶皟璺緞 callbackUrl 鍦ㄥ垱寤轰簩缁寸爜鏃剁敱鎴戞柟浼犲叆锛屽繀椤讳负缁濆鍦板潃锛堝惈鍩熷悕涓庤矾寰勶級銆�
+- 閲戦鏍¢獙锛氭垜鏂瑰彂璧锋敮浠樺墠寮烘牎楠� settlementAmount==totalAmount锛涙敮浠樻ā鍧椾篃杩涜閲戦浜屾鏍¢獙銆�
+
+## 浜屻�佹�讳綋娴佺▼
+
+1. APP 鍦ㄤ换鍔″垪琛ㄤ笌浠诲姟璇︽儏澧炲姞"缁撶畻"鍏ュ彛锛岃烦杞粨绠楅〉銆�
+2. 缁撶畻椤垫媺鍙栨垚浜や环涓庨檮鍔犺垂鐢ㄥ垪琛紝鍏佽鏂板/鍒犻櫎闄勫姞璐圭敤锛屽疄鏃惰绠楁�婚噾棰濄��
+3. 閫夋嫨鏀粯鏂瑰紡骞跺彂璧锋敮浠橈細
+   - 鐜伴噾銆佹寕甯愶細鍚庣鐩存帴鏍囪宸叉敮浠樸��
+   - 寰俊銆佹敮浠樺疂锛氬悗绔皟鐢�"鏀粯妯″潡鍒涘缓浜岀淮鐮�"锛岃繑鍥� codeUrl 涓庤繃鏈熸椂闂寸粰鍓嶇灞曠ず锛涘墠绔疆璇㈡垜鏂�"鏀粯鐘舵�佹帴鍙�"銆�
+4. 鏀粯鎴愬姛鍚庯紝APP 鑷姩鎻愮ず骞跺睍绀�"鏀粯鎴愬姛"鐘舵�侊紱绂佺敤鍚庣画淇敼銆�
+5. ruoyi-ui 鍦ㄤ换鍔℃槑缁嗛〉鍙灞曠ず鏀粯淇℃伅涓庨檮鍔犺垂鐢ㄦ槑缁嗐��
+
+## 涓夈�佹暟鎹ā鍨�
+
+鏀粯涓庨檮鍔犺垂鐙珛寤鸿〃锛岄伩鍏嶆薄鏌撲换鍔′富琛細
+
+### sys_task_additional_fee锛堥檮鍔犺垂鐢ㄦ槑缁嗭級
+- 瀛楁锛歩d, task_id, fee_type(瀛楀吀), fee_name, unit_amount, quantity, total_amount, remark, created_by, created_time
+
+### sys_task_payment锛堜换鍔℃敮浠樿褰曪級
+- 瀛楁锛歩d, task_id, total_amount, settlement_amount(蹇呴』==total_amount), payment_method("CASH""ON_ACCOUNT""WECHAT""ALIPAY"), pay_status("UNPAID""PENDING""PAID""FAILED""REFUNDED"), pay_time, out_trade_no, trade_no, code_url, qr_expire_time, provider("WECHAT""ALIPAY"), payment_ref_id(鏀粯妯″潡杩斿洖鍞竴鏍囪瘑), callback_url, remark, created_by, created_time, update_time
+
+### 鎴愪氦浠锋潵婧�
+- SysTaskEmergency.transferPrice
+- 鎬婚噾棰�=transferPrice + sum(sys_task_additional_fee.total_amount)
+
+### 鏈夋晥鏀粯
+- 鍚屼竴浠诲姟灞曠ず鏈�杩戜竴鏉� pay_status="PAID"鐨勮褰曪紱鑻ヤ笉瀛樺湪鍒欐樉绀�"鏈敮浠�"
+
+## 鍥涖�佸瓧鍏镐笌閰嶇疆
+
+### 瀛楀吀绫诲瀷锛歵ask_additional_fee_type
+- 1锛氱瓑寰呰垂
+- 2锛氭媴鏋�
+- 3锛氬眳瀹禝CU
+- 4锛氬尰鐤楄澶�
+
+### 閰嶇疆椤�
+- payment.module.url锛氭敮浠樻ā鍧楁湇鍔″湴鍧�锛堥粯璁わ細http://localhost:8081/pay锛�
+- payment.callback.base-url锛氬洖璋冨熀纭�URL锛堥粯璁わ細http://localhost:8080锛�
+
+## 浜斻�佷笌鏀粯妯″潡鐨勫鎺ュ绾�
+
+### 鍒涘缓浜岀淮鐮侊紙鏀粯妯″潡锛�
+- 鎺ュ彛锛歅OST /pay/qrcode/create
+- 鍏ュ弬锛歰utTradeNo, amount, provider("WECHAT""ALIPAY"), subject, attach(濡� taskId/taskCode), callbackUrl锛堢粷瀵瑰湴鍧�锛�
+- 鍑哄弬锛歱aymentRefId, codeUrl, expireTime
+
+### 鏌ヨ鏀粯鐘舵�侊紙鏀粯妯″潡锛�
+- 鎺ュ彛锛欸ET /pay/status?paymentRefId=xxx 鎴� GET /pay/status?outTradeNo=xxx
+- 鍑哄弬锛歴tatus("PENDING""PAID""FAILED""CLOSED"), tradeNo, payTime
+
+### 鍥炶皟锛堟敮浠樻ā鍧� 鈫� 鎴戞柟锛�
+- 鎺ュ彛锛歅OST {callbackUrl}
+- 浣撳唴瀛楁锛歰utTradeNo, tradeNo, amount, status=PAID, sign 绛夛紱鎴戞柟楠岀鍚庢洿鏂颁负 PAID
+
+### 璁㈠崟鍙疯鑼�
+- outTradeNo锛歍ASK-{taskCode}-{timestampMillis}
+- subject锛�"杞繍浠诲姟缁撶畻锛坽taskCode}锛�"
+
+## 鍏�佹垜鏂瑰悗绔帴鍙o紙APP 鐢級
+
+### GET /task/payment/info
+- 鍏ュ弬锛歵askId
+- 鍑哄弬锛歵ransferPrice, additionalFees[], additionalAmount, totalAmount, latestPayment锛堝鏈夛級, paymentMethods["CASH""ON_ACCOUNT""WECHAT""ALIPAY"]
+
+### POST /task/additional-fee/add
+- 鍏ュ弬锛歵askId, feeType, feeName, unitAmount, quantity, remark
+- 鍑哄弬锛歛dditionalAmount, totalAmount
+
+### POST /task/additional-fee/remove
+- 鍏ュ弬锛歵askId, feeId
+- 鍑哄弬锛歛dditionalAmount, totalAmount
+
+### POST /task/payment/create
+- 鍏ュ弬锛歵askId, paymentMethod, settlementAmount(蹇呴』==totalAmount), remark
+- 琛屼负锛�
+  - CASH/ON_ACCOUNT锛氱洿鎺ュ垱寤烘敮浠樿褰曞苟缃负 PAID
+  - WECHAT/ALIPAY锛氱敓鎴� outTradeNo锛坱askCode-姣鏃堕棿鎴筹級銆佽绠� amount銆佸噯澶� subject/attach/callbackUrl锛涜皟鐢ㄦ敮浠樻ā鍧楀垱寤轰簩缁寸爜锛涗繚瀛� paymentRefId銆乧odeUrl銆乪xpireTime锛岀疆涓� PENDING 杩斿洖
+- 鍑哄弬锛歱aymentId, payStatus, codeUrl(浠呭井淇�/鏀粯瀹�), qrExpireTime
+
+### GET /task/payment/status
+- 鍏ュ弬锛歵askId 鎴� paymentId
+- 琛屼负锛氭牴鎹� paymentRefId 鎴� outTradeNo 璋冪敤鏀粯妯″潡鏌ヨ锛涜嫢杩斿洖 PAID锛屾垜鏂规洿鏂� sys_task_payment 涓� PAID 骞惰繑鍥炴渶鏂扮姸鎬�
+- 鍑哄弬锛歱ayStatus, tradeNo, payTime
+
+### POST /payment/callback/{provider}
+- 鏀粯妯″潡鍥炶皟鎺ュ彛锛岄獙绛惧悗鏇存柊鏀粯鐘舵�佷负 PAID
+
+## 涓冦�丄PP 鍓嶇鏀归��
+
+### 鍏ュ彛
+- 浠诲姟鍒楄〃鍗$墖涓庝换鍔¤鎯呴〉鍧囧鍔�"缁撶畻"鎸夐挳锛堣鎯呴〉閬靛惊鏃㈡湁鎸夐挳鏄剧ず瑙勫垯锛氫粎瀹屾垚/鍙栨秷鐘舵�侀殣钘忥級
+
+### 缁撶畻椤碉紙settlement.vue锛�
+- 鍒濆鍖栵細璋冪敤 /task/payment/info 鎷夊彇鎴愪氦浠枫�侀檮鍔犺垂鍒楄〃涓庢眹鎬�
+- 闄勫姞璐圭敤锛氭柊澧�/鍒犻櫎浣跨敤瀵瑰簲鎺ュ彛锛岃垂鐢ㄧ被鍨嬫潵鑷瓧鍏革紱鍒锋柊姹囨��
+- 鏀粯锛�
+  - 鐜伴噾/鎸傚笎锛氳皟鐢� /task/payment/create锛屾垚鍔熷悗鎻愮ず"鏀粯鎴愬姛"
+  - 寰俊/鏀粯瀹濓細璋冪敤 /task/payment/create 鑾峰彇 codeUrl 涓� qrExpireTime锛涘睍绀轰簩缁寸爜骞舵瘡 2~3 绉掕疆璇� /task/payment/status锛岀洿鍒� PAID 鎴栬秴鏃�
+- 鏍¢獙锛歴ettlementAmount 蹇呴』绛変簬 totalAmount锛涗簩缁寸爜杩囨湡鎻愮ず閲嶆柊鐢熸垚
+- 鎴愬姛鍚庯細绂佺敤闄勫姞璐圭敤涓庢敮浠樻搷浣滐紱鍙繑鍥炰换鍔¤鎯�
+
+## 鍏�乺uoyi-ui 鍚庡彴灞曠ず锛堝彧璇伙級
+
+### 浠诲姟鏄庣粏椤垫柊澧�"鏀粯淇℃伅"鍖哄潡
+- 灞曠ず锛氭敮浠樻柟寮忋�佺粨绠楅噾棰濄�佹�婚噾棰濄�佹敮浠樼姸鎬併�佷氦鏄撳彿銆佹敮浠樻椂闂�
+- 闄勫姞璐圭敤鏄庣粏鍒楄〃涓庢眹鎬�
+- 鑻ユ湁鍘嗗彶鏀粯璁板綍锛屼粎灞曠ず鏈�杩戜竴娆� PAID锛涗笉鎻愪緵缂栬緫鎴栭噸璇曞叆鍙�
+
+## 涔濄�佹潈闄愪笌瀹夊叏
+
+- APP 閴存潈锛欽WT锛涗粎浠诲姟褰掑睘鎴愬憳锛堝垱寤轰汉銆佹墽琛屼汉銆佽皟搴﹁鑹诧級鍙粨绠�
+- 鏁版嵁鏉冮檺锛氬欢缁幇鏈夐儴闂�/鍒嗗叕鍙搁殧绂昏鍒�
+- 鍥炶皟瀹夊叏锛歝allbackUrl 楠岀锛堢鍚嶇畻娉曠敱鏀粯妯″潡纭畾锛夛紝鍙姞婧� IP 鐧藉悕鍗�
+- 閲戦涓�鑷存�э細鍓嶅悗绔弻閲嶆牎楠岋紱浜岀淮鐮佸垱寤哄悗閲戦閿佸畾锛屽彉鏇撮檮鍔犺垂闇�閲嶆柊鍙戣捣鏀粯
+
+## 鍗併�佽竟鐣屽鐞�
+
+- 浜岀淮鐮佽繃鏈燂細鎻愮ず骞跺厑璁搁噸鏂板垱寤猴紱鏃ф敮浠樿褰曠疆涓� FAILED/CLOSED
+- 杞涓庡洖璋冪珵鎬侊細浠ユ垜鏂瑰悗绔敮浠樼姸鎬佷负鍑嗭紙鍥炶皟鎴栨煡璇㈡洿鏂帮級
+- 閫�娆�/鎾ら攢锛氭湰鏈熶笉瀹炵幇锛涘鍚庣画闇�瑕侊紝澧炲姞 REFUNDED 鐘舵�佷笌閫�娆炬帴鍙�
+
+## 鍗佷竴銆侀獙鏀舵爣鍑�
+
+- APP锛氶檮鍔犺垂鐢ㄧ淮鎶や笌鎬婚璁$畻姝g‘锛涘洓绉嶆敮浠樻祦绋嬮�氱晠锛涙壂鐮佹敮浠樻垚鍔熷悗鑷姩鎻愮ず涓庣鐢ㄤ慨鏀�
+- 鍚庡彴锛氬噯纭睍绀烘敮浠樹俊鎭笌闄勫姞璐圭敤鏄庣粏锛涘彧鏄剧ず鏈夋晥鏀粯
+- 鍚庣锛氭敮浠樹笌闄勫姞璐硅惤搴撴纭紱鍥炶皟涓庤疆璇㈠潎鑳藉噯纭洿鏂版敮浠樼姸鎬侊紱閲戦鏍¢獙涓ユ牸鐢熸晥
+
+## 鍗佷簩銆佸疄鐜版枃浠舵竻鍗�
+
+### 鏁版嵁搴�
+- sql/task_payment_tables.sql
+
+### 瀹炰綋绫�
+- SysTaskAdditionalFee.java
+- SysTaskPayment.java
+- TaskPaymentInfoVO.java
+- TaskPaymentCreateVO.java
+- TaskPaymentResultVO.java
+
+### Mapper
+- SysTaskAdditionalFeeMapper.java / SysTaskAdditionalFeeMapper.xml
+- SysTaskPaymentMapper.java / SysTaskPaymentMapper.xml
+
+### Service
+- ISysTaskPaymentService.java / SysTaskPaymentServiceImpl.java
+- IPaymentModuleService.java / PaymentModuleServiceImpl.java
+
+### Controller
+- SysTaskPaymentController.java
+- PaymentCallbackController.java
+
+### 鍓嶇锛堝緟瀹炵幇锛�
+- app/pages/task/settlement.vue锛堟敼閫狅級
+- app/api/payment.js锛堟柊澧烇級
+- ruoyi-ui/src/views/task/detail.vue锛堝鍔犳敮浠樹俊鎭睍绀猴級
diff --git a/dryad-payment/.gitignore b/dryad-payment/.gitignore
new file mode 100644
index 0000000..03075a4
--- /dev/null
+++ b/dryad-payment/.gitignore
@@ -0,0 +1,35 @@
+# Maven
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+
+# IDE
+.idea/
+*.iws
+*.iml
+*.ipr
+.vscode/
+*.swp
+*.swo
+*~
+
+# Logs
+logs/
+*.log
+log/
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Application
+application-local.yml
+application-dev.yml
+application-prod.yml
diff --git "a/dryad-payment/API\346\216\245\345\217\243\346\226\207\346\241\243.md" "b/dryad-payment/API\346\216\245\345\217\243\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..50ba25e
--- /dev/null
+++ "b/dryad-payment/API\346\216\245\345\217\243\346\226\207\346\241\243.md"
@@ -0,0 +1,470 @@
+# 鏀粯妯″潡 API 鎺ュ彛鏂囨。
+
+## 鍩虹淇℃伅
+
+- **鏈嶅姟鍦板潃**: `http://your-domain:8080`
+- **鎺ュ彛鍗忚**: HTTP/HTTPS
+- **鏁版嵁鏍煎紡**: JSON
+- **瀛楃缂栫爜**: UTF-8
+
+---
+
+## 1. 鍙戣捣寰俊Native鏀粯
+
+### 鎺ュ彛璇存槑
+鐢熸垚寰俊鏀粯浜岀淮鐮侊紝鐢ㄦ埛鎵爜鍚庡畬鎴愭敮浠樸��
+
+### 璇锋眰淇℃伅
+- **璇锋眰鏂瑰紡**: `POST`
+- **璇锋眰璺緞**: `/api/pay/wechat/native`
+- **Content-Type**: `application/json`
+
+### 璇锋眰鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 | 绀轰緥 |
+|--------|------|------|------|------|
+| bizOrderId | String | 鏄� | 涓氬姟璁㈠崟鍙凤紙鍞竴鏍囪瘑锛� | "ORDER20251123001" |
+| amount | Integer | 鏄� | 鏀粯閲戦锛堝崟浣嶏細鍒嗭級 | 10000 (琛ㄧず100鍏�) |
+| subject | String | 鏄� | 璁㈠崟鏍囬 | "鍟嗗搧璁㈠崟鏀粯" |
+| description | String | 鍚� | 璁㈠崟鎻忚堪 | "璐拱鍟嗗搧A脳1" |
+| callbackUrl | String | 鏄� | 涓氬姟鍥炶皟鍦板潃锛堟敮浠樻垚鍔熷悗閫氱煡锛� | "https://your-domain.com/notify" |
+
+### 璇锋眰绀轰緥
+
+```json
+{
+  "bizOrderId": "ORDER20251123001",
+  "amount": 10000,
+  "subject": "鍟嗗搧璁㈠崟鏀粯",
+  "description": "璐拱鍟嗗搧A脳1",
+  "callbackUrl": "https://your-domain.com/notify"
+}
+```
+
+### 鍝嶅簲鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| code | Integer | 鍝嶅簲鐮侊紝200琛ㄧず鎴愬姛 |
+| msg | String | 鍝嶅簲娑堟伅 |
+| data | Object | 鍝嶅簲鏁版嵁 |
+| data.orderId | Long | 鏀粯璁㈠崟ID |
+| data.transactionId | Long | 浜ゆ槗娴佹按ID |
+| data.status | String | 璁㈠崟鐘舵�侊紙PENDING-寰呮敮浠橈級 |
+| data.qrBase64 | String | 浜岀淮鐮佸浘鐗嘊ase64缂栫爜 |
+| data.expireAt | String | 杩囨湡鏃堕棿锛�2灏忔椂锛� |
+
+### 鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "orderId": 1234567890,
+    "transactionId": 9876543210,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
+    "expireAt": "2025-11-23 14:00:00"
+  }
+}
+```
+
+### 浣跨敤璇存槑
+
+1. 璋冪敤鎺ュ彛鑾峰彇 `qrBase64`
+2. 鍓嶇鐩存帴灏咮ase64鏄剧ず涓哄浘鐗囷細`<img src="{qrBase64}" />`
+3. 鐢ㄦ埛浣跨敤寰俊鎵爜鏀粯
+4. 鏀粯鎴愬姛鍚庯紝绯荤粺浼氳皟鐢ㄦ偍鎻愪緵鐨� `callbackUrl` 閫氱煡缁撴灉
+
+---
+
+## 2. 鍙戣捣鏀粯瀹濆綋闈粯
+
+### 鎺ュ彛璇存槑
+鐢熸垚鏀粯瀹濇敮浠樹簩缁寸爜锛岀敤鎴锋壂鐮佸悗瀹屾垚鏀粯銆�
+
+### 璇锋眰淇℃伅
+- **璇锋眰鏂瑰紡**: `POST`
+- **璇锋眰璺緞**: `/api/pay/alipay/precreate`
+- **Content-Type**: `application/json`
+
+### 璇锋眰鍙傛暟
+
+涓庡井淇℃敮浠樼浉鍚岋紝鍙傝�冧笂鏂硅〃鏍笺��
+
+### 璇锋眰绀轰緥
+
+```json
+{
+  "bizOrderId": "ORDER20251123002",
+  "amount": 10000,
+  "subject": "鍟嗗搧璁㈠崟鏀粯",
+  "description": "璐拱鍟嗗搧B脳1",
+  "callbackUrl": "https://your-domain.com/notify"
+}
+```
+
+### 鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "orderId": 1234567891,
+    "transactionId": 9876543211,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
+    "expireAt": "2025-11-23 14:00:00"
+  }
+}
+```
+
+---
+
+## 3. 鏌ヨ璁㈠崟鐘舵��
+
+### 鎺ュ彛璇存槑
+鏌ヨ鏀粯璁㈠崟鐨勫綋鍓嶇姸鎬併��
+
+### 璇锋眰淇℃伅
+- **璇锋眰鏂瑰紡**: `GET`
+- **璇锋眰璺緞**: `/api/pay/orders/{orderId}`
+
+### 璺緞鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| orderId | Long | 鏄� | 鏀粯璁㈠崟ID |
+
+### 璇锋眰绀轰緥
+
+```
+GET /api/pay/orders/1234567890
+```
+
+### 鍝嶅簲鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| code | Integer | 鍝嶅簲鐮� |
+| msg | String | 鍝嶅簲娑堟伅 |
+| data | Object | 璁㈠崟璇︽儏 |
+| data.id | Long | 璁㈠崟ID |
+| data.bizOrderId | String | 涓氬姟璁㈠崟鍙� |
+| data.amount | Integer | 閲戦锛堝垎锛� |
+| data.currency | String | 甯佺锛圕NY锛� |
+| data.channel | String | 鏀粯娓犻亾锛圵ECHAT/ALIPAY锛� |
+| data.status | String | 璁㈠崟鐘舵�� |
+| data.subject | String | 璁㈠崟鏍囬 |
+| data.channelTradeNo | String | 娓犻亾浜ゆ槗鍙� |
+| data.paidAt | String | 鏀粯瀹屾垚鏃堕棿 |
+| data.expireAt | String | 杩囨湡鏃堕棿 |
+| data.createdAt | String | 鍒涘缓鏃堕棿 |
+
+### 璁㈠崟鐘舵�佽鏄�
+
+| 鐘舵�佺爜 | 璇存槑 |
+|--------|------|
+| INIT | 鍒濆鍖� |
+| PENDING | 寰呮敮浠� |
+| SUCCEEDED | 鏀粯鎴愬姛 |
+| FAILED | 鏀粯澶辫触 |
+| CANCELED | 宸插叧闂� |
+| EXPIRED | 宸茶繃鏈� |
+
+### 鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "id": 1234567890,
+    "bizOrderId": "ORDER20251123001",
+    "amount": 10000,
+    "currency": "CNY",
+    "channel": "WECHAT",
+    "status": "SUCCEEDED",
+    "subject": "鍟嗗搧璁㈠崟鏀粯",
+    "channelTradeNo": "4200001234567890",
+    "paidAt": "2025-11-23 12:30:00",
+    "expireAt": "2025-11-23 14:00:00",
+    "createdAt": "2025-11-23 12:00:00"
+  }
+}
+```
+
+---
+
+## 4. 鏌ヨ鏈�鏂颁氦鏄�
+
+### 鎺ュ彛璇存槑
+鏌ヨ璁㈠崟鐨勬渶鏂颁氦鏄撹褰曪紙鍖呭惈浜岀淮鐮侊級銆�
+
+### 璇锋眰淇℃伅
+- **璇锋眰鏂瑰紡**: `GET`
+- **璇锋眰璺緞**: `/api/pay/orders/{orderId}/transactions/latest`
+
+### 璇锋眰绀轰緥
+
+```
+GET /api/pay/orders/1234567890/transactions/latest
+```
+
+### 鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "id": 9876543210,
+    "orderId": 1234567890,
+    "channel": "WECHAT",
+    "clientType": "NATIVE",
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
+    "createdAt": "2025-11-23 12:00:00"
+  }
+}
+```
+
+---
+
+## 5. 涓氬姟鍥炶皟閫氱煡锛堥噸瑕侊級
+
+### 鎺ュ彛璇存槑
+褰撴敮浠樻垚鍔熷悗锛岀郴缁熶細涓诲姩璋冪敤鎮ㄥ湪鍙戣捣鏀粯鏃舵彁渚涚殑 `callbackUrl`锛岄�氱煡鏀粯缁撴灉銆�
+
+### 鍥炶皟鏂瑰紡
+- **璇锋眰鏂瑰紡**: `POST`
+- **Content-Type**: `application/json`
+- **璇锋眰鍦板潃**: 鎮ㄦ彁渚涚殑 `callbackUrl`
+
+### 璇锋眰澶�
+
+| 鍙傛暟鍚� | 璇存槑 |
+|--------|------|
+| Content-Type | application/json |
+| X-Signature | HMAC-SHA256绛惧悕锛岀敤浜庨獙璇佽姹傛潵婧� |
+| X-Nonce | 闅忔満瀛楃涓� |
+| X-Timestamp | 鏃堕棿鎴筹紙姣锛� |
+
+### 鍥炶皟鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| tradeId | Long | 浜ゆ槗ID |
+| orderId | Long | 璁㈠崟ID |
+| bizOrderId | String | 涓氬姟璁㈠崟鍙� |
+| channel | String | 鏀粯娓犻亾锛圵ECHAT/ALIPAY锛� |
+| amount | Integer | 閲戦锛堝垎锛� |
+| currency | String | 甯佺锛圕NY锛� |
+| status | String | 璁㈠崟鐘舵�侊紙SUCCEEDED锛� |
+| channelTradeNo | String | 娓犻亾浜ゆ槗鍙� |
+| paidAt | String | 鏀粯瀹屾垚鏃堕棿 |
+| subject | String | 璁㈠崟鏍囬 |
+| description | String | 璁㈠崟鎻忚堪 |
+
+### 鍥炶皟绀轰緥
+
+```json
+{
+  "tradeId": 9876543210,
+  "orderId": 1234567890,
+  "bizOrderId": "ORDER20251123001",
+  "channel": "WECHAT",
+  "amount": 10000,
+  "currency": "CNY",
+  "status": "SUCCEEDED",
+  "channelTradeNo": "4200001234567890",
+  "paidAt": "2025-11-23 12:30:00",
+  "subject": "鍟嗗搧璁㈠崟鏀粯",
+  "description": "璐拱鍟嗗搧A脳1"
+}
+```
+
+### 绛惧悕楠岃瘉
+
+**绛惧悕绠楁硶**: HMAC-SHA256
+
+**绛惧悕鏁版嵁**: `payload + nonce + timestamp`
+
+**楠岃瘉姝ラ**:
+1. 鑾峰彇璇锋眰澶翠腑鐨� `X-Signature`銆乣X-Nonce`銆乣X-Timestamp`
+2. 鑾峰彇璇锋眰浣� JSON 瀛楃涓� `payload`
+3. 鎷兼帴瀛楃涓诧細`signData = payload + nonce + timestamp`
+4. 浣跨敤閰嶇疆鐨� `callbackSignSecret` 璁$畻 HMAC-SHA256
+5. 瀵规瘮璁$畻缁撴灉涓� `X-Signature` 鏄惁涓�鑷�
+
+**Java绀轰緥浠g爜**:
+```java
+String payload = "璇锋眰浣揓SON瀛楃涓�";
+String nonce = request.getHeader("X-Nonce");
+String timestamp = request.getHeader("X-Timestamp");
+String signature = request.getHeader("X-Signature");
+
+String signData = payload + nonce + timestamp;
+String calculated = SignUtil.hmacSha256(signData, callbackSignSecret);
+
+if (signature.equals(calculated)) {
+    // 绛惧悕楠岃瘉閫氳繃
+}
+```
+
+### 鍝嶅簲瑕佹眰
+
+鎮ㄧ殑鍥炶皟鎺ュ彛搴旇繑鍥烇細
+- **鎴愬姛**: HTTP 鐘舵�佺爜 200-299
+- **澶辫触**: 鍏朵粬鐘舵�佺爜锛堢郴缁熶細鑷姩閲嶈瘯锛�
+
+### 閲嶈瘯鏈哄埗
+
+濡傛灉鍥炶皟澶辫触锛岀郴缁熶細鎸変互涓嬮棿闅旇嚜鍔ㄩ噸璇曪紙鏈�澶�10娆★級锛�
+- 绔嬪嵆閲嶈瘯
+- 1鍒嗛挓鍚�
+- 5鍒嗛挓鍚�
+- 15鍒嗛挓鍚�
+- 60鍒嗛挓鍚�
+
+---
+
+## 6. 鍋ュ悍妫�鏌�
+
+### 鎺ュ彛璇存槑
+妫�鏌ユ湇鍔℃槸鍚︽甯歌繍琛屻��
+
+### 璇锋眰淇℃伅
+- **璇锋眰鏂瑰紡**: `GET`
+- **璇锋眰璺緞**: `/api/health`
+
+### 鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "status": "UP",
+    "service": "dryad-payment",
+    "time": "2025-11-23 12:00:00",
+    "message": "鏀粯妯″潡鏈嶅姟杩愯姝e父"
+  }
+}
+```
+
+---
+
+## 閿欒鐮佽鏄�
+
+| 閿欒鐮� | 璇存槑 |
+|--------|------|
+| 200 | 鎴愬姛 |
+| 500 | 鏈嶅姟鍣ㄥ唴閮ㄩ敊璇� |
+| 400 | 璇锋眰鍙傛暟閿欒 |
+| 404 | 璧勬簮涓嶅瓨鍦� |
+
+### 閿欒鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 500,
+  "msg": "鏀粯鍒涘缓澶辫触: 寰俊涓嬪崟澶辫触",
+  "data": null
+}
+```
+
+---
+
+## 闆嗘垚绀轰緥
+
+### cURL绀轰緥
+
+**鍙戣捣寰俊鏀粯**:
+```bash
+curl -X POST http://localhost:8080/api/pay/wechat/native \
+  -H "Content-Type: application/json" \
+  -d '{
+    "bizOrderId": "ORDER20251123001",
+    "amount": 10000,
+    "subject": "鍟嗗搧璁㈠崟鏀粯",
+    "description": "璐拱鍟嗗搧A脳1",
+    "callbackUrl": "https://your-domain.com/notify"
+  }'
+```
+
+**鏌ヨ璁㈠崟**:
+```bash
+curl http://localhost:8080/api/pay/orders/1234567890
+```
+
+### JavaScript绀轰緥
+
+```javascript
+// 鍙戣捣鏀粯
+async function createPayment() {
+  const response = await fetch('http://localhost:8080/api/pay/wechat/native', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json'
+    },
+    body: JSON.stringify({
+      bizOrderId: 'ORDER20251123001',
+      amount: 10000,
+      subject: '鍟嗗搧璁㈠崟鏀粯',
+      description: '璐拱鍟嗗搧A脳1',
+      callbackUrl: 'https://your-domain.com/notify'
+    })
+  });
+  
+  const result = await response.json();
+  if (result.code === 200) {
+    // 鏄剧ず浜岀淮鐮�
+    document.getElementById('qrcode').src = result.data.qrBase64;
+  }
+}
+
+// 鏌ヨ璁㈠崟鐘舵��
+async function queryOrder(orderId) {
+  const response = await fetch(`http://localhost:8080/api/pay/orders/${orderId}`);
+  const result = await response.json();
+  return result.data.status;
+}
+```
+
+### Java绀轰緥
+
+```java
+// 鍙戣捣鏀粯
+RestTemplate restTemplate = new RestTemplate();
+String url = "http://localhost:8080/api/pay/wechat/native";
+
+Map<String, Object> request = new HashMap<>();
+request.put("bizOrderId", "ORDER20251123001");
+request.put("amount", 10000);
+request.put("subject", "鍟嗗搧璁㈠崟鏀粯");
+request.put("callbackUrl", "https://your-domain.com/notify");
+
+ResponseEntity<Map> response = restTemplate.postForEntity(url, request, Map.class);
+Map<String, Object> data = (Map<String, Object>) response.getBody().get("data");
+String qrBase64 = (String) data.get("qrBase64");
+```
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+1. **骞傜瓑鎬�**: 鍚屼竴 `bizOrderId` + `channel` 閲嶅璇锋眰浼氳繑鍥炲悓涓�璁㈠崟鍜屼簩缁寸爜
+2. **杩囨湡鏃堕棿**: 璁㈠崟鍒涘缓鍚�2灏忔椂鍐呮湁鏁堬紝瓒呮椂鑷姩杩囨湡
+3. **骞跺彂鎺у埗**: 鍚屼竴璁㈠崟鍚屾椂鍙厑璁镐竴绗旇繘琛屼腑鐨勪氦鏄�
+4. **鍥炶皟绛惧悕**: 鍔″繀楠岃瘉鍥炶皟绛惧悕锛岄槻姝吉閫犺姹�
+5. **閲戦鍗曚綅**: 鎵�鏈夐噾棰濆崟浣嶅潎涓�**鍒�**锛堜緥濡傦細100鍏� = 10000鍒嗭級
+6. **鐜閰嶇疆**: 鐢熶骇鐜璇蜂娇鐢℉TTPS鍗忚
+
+---
+
+## 鎶�鏈敮鎸�
+
+濡傛湁闂锛岃鑱旂郴鎶�鏈敮鎸佸洟闃熴��
diff --git a/dryad-payment/README.md b/dryad-payment/README.md
new file mode 100644
index 0000000..b6fbf6a
--- /dev/null
+++ b/dryad-payment/README.md
@@ -0,0 +1,254 @@
+# 鏀粯妯″潡椤圭洰璇存槑
+
+## 椤圭洰姒傝堪
+鍩轰簬DDD鏋舵瀯鐨勬敮浠樻ā鍧楋紝鏀寔寰俊鏀粯Native鍜屾敮浠樺疂褰撻潰浠樹簩缁寸爜鏀粯銆�
+
+## 鎶�鏈爤
+- Java 1.8
+- Spring Boot 2.5.15
+- MyBatis Plus 3.4.3.4
+- MySQL
+- ZXing (浜岀淮鐮佺敓鎴�)
+
+## 椤圭洰缁撴瀯
+
+```
+dryad-payment/
+鈹溾攢鈹� src/main/java/com/ruoyi/payment/
+鈹�   鈹溾攢鈹� PaymentApplication.java              # 鍚姩绫�
+鈹�   鈹溾攢鈹� common/                              # 閫氱敤绫�
+鈹�   鈹�   鈹斺攢鈹� AjaxResult.java                 # 缁熶竴鍝嶅簲缁撴灉
+鈹�   鈹溾攢鈹� domain/                              # 棰嗗煙灞�
+鈹�   鈹�   鈹溾攢鈹� enums/                          # 鏋氫妇
+鈹�   鈹�   鈹�   鈹溾攢鈹� PayChannel.java             # 鏀粯娓犻亾
+鈹�   鈹�   鈹�   鈹溾攢鈹� OrderStatus.java            # 璁㈠崟鐘舵��
+鈹�   鈹�   鈹�   鈹溾攢鈹� TransactionStatus.java      # 浜ゆ槗鐘舵��
+鈹�   鈹�   鈹�   鈹斺攢鈹� ClientType.java             # 瀹㈡埛绔被鍨�
+鈹�   鈹�   鈹斺攢鈹� model/                          # 棰嗗煙妯″瀷
+鈹�   鈹�       鈹溾攢鈹� PaymentOrder.java           # 鏀粯璁㈠崟(鑱氬悎鏍�)
+鈹�   鈹�       鈹溾攢鈹� PaymentTransaction.java     # 鏀粯浜ゆ槗
+鈹�   鈹�       鈹溾攢鈹� NotifyLog.java              # 娓犻亾鍥炶皟鏃ュ織
+鈹�   鈹�       鈹溾攢鈹� BizCallbackLog.java         # 涓氬姟鍥炶皟鏃ュ織
+鈹�   鈹�       鈹斺攢鈹� OperationAudit.java         # 鎿嶄綔瀹¤
+鈹�   鈹溾攢鈹� application/                         # 搴旂敤灞�
+鈹�   鈹�   鈹斺攢鈹� service/
+鈹�   鈹�       鈹斺攢鈹� PaymentService.java         # 鏀粯搴旂敤鏈嶅姟
+鈹�   鈹溾攢鈹� infrastructure/                      # 鍩虹璁炬柦灞�
+鈹�   鈹�   鈹溾攢鈹� config/                         # 閰嶇疆
+鈹�   鈹�   鈹�   鈹溾攢鈹� WechatPayConfig.java        # 寰俊鏀粯閰嶇疆
+鈹�   鈹�   鈹�   鈹溾攢鈹� AlipayConfig.java           # 鏀粯瀹濋厤缃�
+鈹�   鈹�   鈹�   鈹溾攢鈹� BusinessCallbackConfig.java # 涓氬姟鍥炶皟閰嶇疆
+鈹�   鈹�   鈹�   鈹斺攢鈹� QrCodeConfig.java           # 浜岀淮鐮侀厤缃�
+鈹�   鈹�   鈹溾攢鈹� persistence/                    # 鎸佷箙鍖�
+鈹�   鈹�   鈹�   鈹斺攢鈹� mapper/                     # MyBatis Mapper
+鈹�   鈹�   鈹�       鈹溾攢鈹� PaymentOrderMapper.java
+鈹�   鈹�   鈹�       鈹溾攢鈹� PaymentTransactionMapper.java
+鈹�   鈹�   鈹�       鈹溾攢鈹� NotifyLogMapper.java
+鈹�   鈹�   鈹�       鈹溾攢鈹� BizCallbackLogMapper.java
+鈹�   鈹�   鈹�       鈹斺攢鈹� OperationAuditMapper.java
+鈹�   鈹�   鈹斺攢鈹� util/                           # 宸ュ叿绫�
+鈹�   鈹�       鈹溾攢鈹� QrCodeUtil.java             # 浜岀淮鐮佺敓鎴愬伐鍏�
+鈹�   鈹�       鈹斺攢鈹� SignUtil.java               # 绛惧悕宸ュ叿
+鈹�   鈹斺攢鈹� interfaces/                          # 鎺ュ彛灞�
+鈹�       鈹溾攢鈹� controller/                     # 鎺у埗鍣�
+鈹�       鈹�   鈹溾攢鈹� PaymentController.java      # 鏀粯鎺ュ彛
+鈹�       鈹�   鈹斺攢鈹� PaymentNotifyController.java# 鍥炶皟鎺ュ彛
+鈹�       鈹斺攢鈹� dto/                            # 鏁版嵁浼犺緭瀵硅薄
+鈹�           鈹溾攢鈹� PaymentRequest.java         # 鏀粯璇锋眰
+鈹�           鈹斺攢鈹� PaymentResponse.java        # 鏀粯鍝嶅簲
+鈹溾攢鈹� src/main/resources/
+鈹�   鈹溾攢鈹� application.yml                     # 閰嶇疆鏂囦欢
+鈹�   鈹溾攢鈹� mapper/                             # MyBatis XML
+鈹�   鈹�   鈹溾攢鈹� PaymentOrderMapper.xml
+鈹�   鈹�   鈹斺攢鈹� PaymentTransactionMapper.xml
+鈹�   鈹斺攢鈹� sql/
+鈹�       鈹斺攢鈹� schema.sql                      # 鏁版嵁搴撹〃缁撴瀯
+鈹溾攢鈹� doc/
+鈹�   鈹斺攢鈹� 璁捐鏂规.md                          # 璇︾粏璁捐鏂囨。
+鈹斺攢鈹� pom.xml                                  # Maven閰嶇疆
+
+```
+
+## 宸插疄鐜板姛鑳�
+
+### 1. 鍩虹妗嗘灦 鉁�
+- DDD鍒嗗眰鏋舵瀯
+- Spring Boot椤圭洰閰嶇疆
+- MyBatis Plus闆嗘垚
+- 鏁版嵁搴撹〃缁撴瀯
+
+### 2. 棰嗗煙妯″瀷 鉁�
+- PaymentOrder (鏀粯璁㈠崟鑱氬悎鏍�)
+- PaymentTransaction (鏀粯浜ゆ槗)
+- NotifyLog (娓犻亾鍥炶皟鏃ュ織)
+- BizCallbackLog (涓氬姟鍥炶皟鏃ュ織)
+- OperationAudit (鎿嶄綔瀹¤)
+
+### 3. 鏍稿績鎺ュ彛 鉁�
+- POST /api/pay/wechat/native - 鍙戣捣寰俊Native鏀粯
+- POST /api/pay/alipay/precreate - 鍙戣捣鏀粯瀹濆綋闈粯
+- GET /api/pay/orders/{orderId} - 鏌ヨ璁㈠崟
+- GET /api/pay/orders/{orderId}/transactions/latest - 鏌ヨ鏈�鏂颁氦鏄�
+- POST /api/pay/notify/wechat - 寰俊鍥炶皟(妗嗘灦)
+- POST /api/pay/notify/alipay - 鏀粯瀹濆洖璋�(妗嗘灦)
+
+### 4. 宸ュ叿绫� 鉁�
+- 浜岀淮鐮佺敓鎴�(300脳300 PNG Base64)
+- MD5绛惧悕
+- HMAC-SHA256绛惧悕
+
+## 寰呭畬鎴愬姛鑳�
+
+### 1. 娓犻亾瀹㈡埛绔疄鐜� 鈿狅笍
+闇�瑕佸畬鍠勪互涓嬪唴瀹癸細
+- `WxPayV2Client`: 寰俊v2缁熶竴涓嬪崟銆佹煡璇€�佸叧闂�佺鍚嶉獙璇�
+- `AlipayF2FClient`: 鏀粯瀹濆綋闈粯涓嬪崟銆佹煡璇€�佸叧闂�佺鍚嶉獙璇�
+
+褰撳墠PaymentService涓殑 `callWechatUnifiedOrder()` 鍜� `callAlipayPrecreate()` 鏄ā鎷熷疄鐜般��
+
+### 2. 鍥炶皟澶勭悊瀹屽杽 鈿狅笍
+闇�瑕佸畬鍠� PaymentNotifyController 涓殑TODO閮ㄥ垎锛�
+- 寰俊XML鎶ユ枃瑙f瀽涓庣鍚嶉獙璇�
+- 鏀粯瀹濆弬鏁伴獙璇佷笌绛惧悕楠岃瘉
+- 璁㈠崟鍜屼氦鏄撶姸鎬佹洿鏂伴�昏緫
+- 瑙﹀彂涓氬姟鍥炶皟閫昏緫
+- 璁板綍NotifyLog瀹炵幇骞傜瓑
+
+### 3. 涓氬姟鍥炶皟鏈嶅姟 馃摑
+闇�瑕佸疄鐜帮細
+- `BizCallbackService`: 澶栭儴涓氬姟鍥炶皟瑙﹀彂
+- HMAC-SHA256绛惧悕鐢熸垚
+- HTTP POST璋冪敤
+- 閲嶈瘯鏈哄埗(0/1/5/15/60鍒嗛挓)
+- 璁板綍BizCallbackLog
+
+### 4. 姣忔棩瀵硅处浠诲姟 馃摑
+闇�瑕佸疄鐜帮細
+- `ReconciliationTask`: @Scheduled瀹氭椂浠诲姟
+- 璋冪敤娓犻亾鏌ヨ鎺ュ彛瀵规瘮鐘舵��
+- 鑷姩淇鐘舵�佸樊寮�
+- 鐢熸垚瀵硅处鎶ュ憡
+
+### 5. 璁㈠崟杩囨湡澶勭悊 馃摑
+闇�瑕佸疄鐜帮細
+- 瀹氭椂浠诲姟妫�鏌ヨ繃鏈熻鍗�
+- 灏嗚秴杩�2灏忔椂鏈敮浠樼殑璁㈠崟鏍囪涓篍XPIRED
+
+### 6. 绠$悊绔帴鍙� 馃摑
+闇�瑕佸疄鐜帮細
+- 璁㈠崟鍒楄〃鏌ヨ
+- 浜ゆ槗娴佹按鏌ヨ
+- 鍥炶皟鏃ュ織鏌ヨ
+- 鎵嬪伐閲嶅彂涓氬姟鍥炶皟
+- 瀵硅处浠诲姟鏌ヨ
+- 鎿嶄綔瀹¤璁板綍
+
+## 蹇�熷紑濮�
+
+### 1. 鐜鍑嗗
+- JDK 1.8
+- MySQL 5.7+
+- Maven 3.6+
+
+### 2. 鏁版嵁搴撳垵濮嬪寲
+```bash
+# 鎵цSQL鑴氭湰鍒涘缓鏁版嵁搴撳拰琛�
+mysql -u root -p < src/main/resources/sql/schema.sql
+```
+
+### 3. 閰嶇疆淇敼
+淇敼 `src/main/resources/application.yml`:
+```yaml
+spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/dryad_payment?...
+    username: your_username
+    password: your_password
+
+payment:
+  wechat:
+    appId: your_wechat_appid
+    mchId: your_wechat_mchid
+    mchKey: your_wechat_mchkey
+  
+  alipay:
+    appId: your_alipay_appid
+    privateKey: your_alipay_private_key
+    alipayPublicKey: alipay_public_key
+```
+
+### 4. 缂栬瘧杩愯
+```bash
+# 缂栬瘧
+mvn clean package
+
+# 杩愯
+java -jar target/dryad-payment-1.0.0.jar
+
+# 鎴栫洿鎺ヨ繍琛�
+mvn spring-boot:run
+```
+
+### 5. 娴嬭瘯鎺ュ彛
+```bash
+# 鍙戣捣寰俊Native鏀粯
+curl -X POST http://localhost:8080/api/pay/wechat/native \
+  -H "Content-Type: application/json" \
+  -d '{
+    "bizOrderId": "TEST20251123001",
+    "amount": 100,
+    "subject": "娴嬭瘯璁㈠崟",
+    "description": "杩欐槸涓�涓祴璇曡鍗�",
+    "callbackUrl": "http://your-domain.com/callback"
+  }'
+
+# 鏌ヨ璁㈠崟
+curl http://localhost:8080/api/pay/orders/1
+```
+
+## 鏍稿績涓氬姟閫昏緫
+
+### 鍚屼竴璁㈠崟鍙厑璁镐竴绗旇繘琛屼腑鐨勪氦鏄�
+鍦� `PaymentService` 涓凡瀹炵幇锛�
+```java
+// 妫�鏌ユ槸鍚﹀瓨鍦ㄥ緟鏀粯浜ゆ槗
+PaymentTransaction existingTransaction = 
+    paymentTransactionMapper.selectPendingByOrderId(order.getId());
+if (existingTransaction != null) {
+    // 鐩存帴杩斿洖宸叉湁浜ゆ槗
+    return buildPaymentResponse(order, existingTransaction);
+}
+```
+
+### 璁㈠崟2灏忔椂杩囨湡
+鍒涘缓璁㈠崟鏃惰缃細
+```java
+order.setExpireAt(LocalDateTime.now().plusHours(2));
+```
+
+### 浜岀淮鐮丅ase64杩斿洖
+浣跨敤ZXing鐢熸垚300脳300 PNG浜岀淮鐮佸苟杞崲涓築ase64銆�
+
+## 鍚庣画寮�鍙戝缓璁�
+
+1. **浼樺厛瀹屾垚娓犻亾瀹㈡埛绔�**: 杩欐槸鏍稿績鍔熻兘锛屽缓璁弬鑰冨井淇℃敮浠樺拰鏀粯瀹濆畼鏂筍DK鏂囨。瀹炵幇
+2. **瀹屽杽鍥炶皟澶勭悊**: 瀹炵幇绛惧悕楠岃瘉鍜岀姸鎬佹洿鏂帮紝纭繚鏁版嵁涓�鑷存��
+3. **瀹炵幇涓氬姟鍥炶皟**: 纭繚澶栭儴绯荤粺鑳藉強鏃舵敹鍒版敮浠樼粨鏋�
+4. **娣诲姞鍗曞厓娴嬭瘯**: 瀵规牳蹇冧笟鍔¢�昏緫缂栧啓娴嬭瘯鐢ㄤ緥
+5. **鐩戞帶涓庡憡璀�**: 娣诲姞鏃ュ織鐩戞帶鍜屽紓甯稿憡璀�
+
+## 娉ㄦ剰浜嬮」
+
+1. 閰嶇疆鏂囦欢涓殑瀵嗛挜闇�瑕佸Ε鍠勪繚绠★紝涓嶈鎻愪氦鍒颁唬鐮佷粨搴�
+2. 鐢熶骇鐜闇�瑕侀厤缃瓾TTPS
+3. 鍥炶皟URL闇�瑕佽兘鍏綉璁块棶
+4. 寤鸿浣跨敤Redis缂撳瓨璁㈠崟鍜屼氦鏄撴暟鎹�
+5. 鐢熶骇鐜闇�瑕侀厤缃垎甯冨紡閿侀槻姝㈠苟鍙戝垱寤轰氦鏄�
+
+## 鍙傝�冩枃妗�
+- 璇︾粏璁捐鏂规: `doc/璁捐鏂规.md`
+- 寰俊鏀粯v2鏂囨。: https://pay.weixin.qq.com/wiki/doc/api/native.php
+- 鏀粯瀹濆綋闈粯鏂囨。: https://opendocs.alipay.com/open/194/105072
+
+## 璁稿彲璇�
+鏈」鐩粎渚涘涔犱娇鐢ㄣ��
diff --git "a/dryad-payment/doc/\344\273\243\347\240\201\347\224\237\346\210\220\346\200\273\347\273\223.md" "b/dryad-payment/doc/\344\273\243\347\240\201\347\224\237\346\210\220\346\200\273\347\273\223.md"
new file mode 100644
index 0000000..457db19
--- /dev/null
+++ "b/dryad-payment/doc/\344\273\243\347\240\201\347\224\237\346\210\220\346\200\273\347\273\223.md"
@@ -0,0 +1,268 @@
+# 鏀粯妯″潡浠g爜鐢熸垚瀹屾垚鎬荤粨
+
+## 鉁� 宸插畬鎴愬唴瀹�
+
+### 1. 椤圭洰鍩虹鏋舵瀯
+- 鉁� Maven椤圭洰閰嶇疆 (pom.xml)
+- 鉁� Spring Boot 2.5.15 鍚姩绫�
+- 鉁� application.yml 閰嶇疆鏂囦欢
+- 鉁� 鏁版嵁搴撹〃缁撴瀯 SQL (7寮犺〃)
+- 鉁� MyBatis Plus 闆嗘垚閰嶇疆
+- 鉁� .gitignore 閰嶇疆
+
+### 2. DDD鍒嗗眰鏋舵瀯
+
+#### Domain灞傦紙棰嗗煙灞傦級
+- 鉁� 鏋氫妇绫�
+  - PayChannel (鏀粯娓犻亾)
+  - OrderStatus (璁㈠崟鐘舵��)
+  - TransactionStatus (浜ゆ槗鐘舵��)
+  - ClientType (瀹㈡埛绔被鍨�)
+- 鉁� 棰嗗煙妯″瀷
+  - PaymentOrder (鏀粯璁㈠崟 - 鑱氬悎鏍�)
+  - PaymentTransaction (鏀粯浜ゆ槗)
+  - NotifyLog (娓犻亾鍥炶皟鏃ュ織)
+  - BizCallbackLog (涓氬姟鍥炶皟鏃ュ織)
+  - OperationAudit (鎿嶄綔瀹¤)
+
+#### Infrastructure灞傦紙鍩虹璁炬柦灞傦級
+- 鉁� 閰嶇疆绫�
+  - WechatPayConfig (寰俊鏀粯閰嶇疆)
+  - AlipayConfig (鏀粯瀹濋厤缃�)
+  - BusinessCallbackConfig (涓氬姟鍥炶皟閰嶇疆)
+  - QrCodeConfig (浜岀淮鐮侀厤缃�)
+- 鉁� Mapper鎺ュ彛
+  - PaymentOrderMapper + XML
+  - PaymentTransactionMapper + XML
+  - NotifyLogMapper
+  - BizCallbackLogMapper
+  - OperationAuditMapper
+- 鉁� 宸ュ叿绫�
+  - QrCodeUtil (浜岀淮鐮佺敓鎴� - 300脳300 PNG Base64)
+  - SignUtil (MD5 + HMAC-SHA256绛惧悕)
+
+#### Application灞傦紙搴旂敤灞傦級
+- 鉁� PaymentService
+  - 鍒涘缓寰俊Native鏀粯
+  - 鍒涘缓鏀粯瀹濆綋闈粯
+  - 鍚屼竴璁㈠崟鍙厑璁镐竴绗旇繘琛屼腑浜ゆ槗鐨勯�昏緫
+  - 璁㈠崟2灏忔椂杩囨湡鏃堕棿璁剧疆
+  - 鏌ヨ璁㈠崟鍜屼氦鏄�
+
+#### Interfaces灞傦紙鎺ュ彛灞傦級
+- 鉁� Controller
+  - PaymentController (鏀粯鎺ュ彛)
+    - POST /api/pay/wechat/native
+    - POST /api/pay/alipay/precreate
+    - GET /api/pay/orders/{orderId}
+    - GET /api/pay/orders/{orderId}/transactions/latest
+  - PaymentNotifyController (鍥炶皟鎺ュ彛妗嗘灦)
+    - POST /api/pay/notify/wechat
+    - POST /api/pay/notify/alipay
+  - HealthController (鍋ュ悍妫�鏌�)
+    - GET /api/health
+- 鉁� DTO
+  - PaymentRequest (鏀粯璇锋眰)
+  - PaymentResponse (鏀粯鍝嶅簲)
+
+#### Common灞傦紙閫氱敤灞傦級
+- 鉁� AjaxResult (缁熶竴鍝嶅簲缁撴灉)
+
+### 3. 鏂囨。
+- 鉁� doc/璁捐鏂规.md (瀹屾暣鐨凞DD璁捐鏂囨。)
+- 鉁� README.md (椤圭洰璇存槑鍜屼娇鐢ㄦ寚鍗�)
+
+## 馃搵 椤圭洰鐗规��
+
+### 宸插疄鐜扮殑鏍稿績鐗规��
+1. 鉁� **鍚屼竴璁㈠崟浠呬竴绗旇繘琛屼腑浜ゆ槗**: 鍦≒aymentService涓疄鐜帮紝妫�鏌ENDING鐘舵�佷氦鏄�
+2. 鉁� **璁㈠崟2灏忔椂鑷姩杩囨湡**: 鍒涘缓璁㈠崟鏃惰缃甧xpireAt
+3. 鉁� **浜岀淮鐮丅ase64杩斿洖**: 浣跨敤ZXing鐢熸垚300脳300 PNG骞惰浆Base64
+4. 鉁� **閰嶇疆缁熶竴绠$悊**: application.yml闆嗕腑閰嶇疆
+5. 鉁� **涔愯閿佸苟鍙戞帶鍒�**: PaymentOrder浣跨敤@Version
+6. 鉁� **鍙傛暟鏍¢獙**: 浣跨敤@Validated娉ㄨВ
+7. 鉁� **鏃ュ織璁板綍**: 浣跨敤@Slf4j
+
+### 寰呭疄鐜扮殑鍔熻兘锛堝凡棰勭暀TODO锛�
+1. 鈿狅笍 寰俊鏀粯v2瀹㈡埛绔� (WxPayV2Client)
+   - 缁熶竴涓嬪崟鎺ュ彛瀹炵幇
+   - MD5绛惧悕鐢熸垚涓庨獙璇�
+   - XML鎶ユ枃瑙f瀽
+   
+2. 鈿狅笍 鏀粯瀹濆鎴风 (AlipayF2FClient)
+   - 褰撻潰浠樹笅鍗曟帴鍙e疄鐜�
+   - RSA2绛惧悕楠岃瘉
+   
+3. 鈿狅笍 娓犻亾鍥炶皟瀹屾暣澶勭悊
+   - 寰俊XML鎶ユ枃瑙f瀽
+   - 鏀粯瀹濆弬鏁伴獙璇�
+   - 璁㈠崟鐘舵�佹洿鏂�
+   - 涓氬姟鍥炶皟瑙﹀彂
+   - NotifyLog璁板綍瀹炵幇骞傜瓑
+   
+4. 馃摑 涓氬姟鍥炶皟鏈嶅姟 (BizCallbackService)
+   - HMAC-SHA256绛惧悕
+   - HTTP POST璋冪敤
+   - 閲嶈瘯鏈哄埗
+   
+5. 馃摑 姣忔棩瀵硅处浠诲姟 (ReconciliationTask)
+   - @Scheduled瀹氭椂浠诲姟
+   - 娓犻亾鐘舵�佹煡璇�
+   - 鑷姩淇宸紓
+   
+6. 馃摑 璁㈠崟杩囨湡澶勭悊
+   - 瀹氭椂浠诲姟鏍囪EXPIRED
+
+7. 馃摑 绠$悊绔帴鍙�
+   - 璁㈠崟鍒楄〃/璇︽儏
+   - 浜ゆ槗娴佹按鏌ヨ
+   - 鍥炶皟鏃ュ織鏌ヨ
+   - 鎵嬪伐閲嶅彂鍥炶皟
+   - 瀵硅处缁撴灉鏌ヨ
+
+## 馃搨 椤圭洰鏂囦欢娓呭崟
+
+```
+dryad-payment/
+鈹溾攢鈹� pom.xml                                    鉁�
+鈹溾攢鈹� README.md                                  鉁�
+鈹溾攢鈹� .gitignore                                 鉁�
+鈹溾攢鈹� doc/
+鈹�   鈹斺攢鈹� 璁捐鏂规.md                             鉁�
+鈹溾攢鈹� src/main/java/com/ruoyi/payment/
+鈹�   鈹溾攢鈹� PaymentApplication.java                鉁�
+鈹�   鈹溾攢鈹� common/
+鈹�   鈹�   鈹斺攢鈹� AjaxResult.java                    鉁�
+鈹�   鈹溾攢鈹� domain/
+鈹�   鈹�   鈹溾攢鈹� enums/
+鈹�   鈹�   鈹�   鈹溾攢鈹� PayChannel.java                鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� OrderStatus.java               鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� TransactionStatus.java         鉁�
+鈹�   鈹�   鈹�   鈹斺攢鈹� ClientType.java                鉁�
+鈹�   鈹�   鈹斺攢鈹� model/
+鈹�   鈹�       鈹溾攢鈹� PaymentOrder.java              鉁�
+鈹�   鈹�       鈹溾攢鈹� PaymentTransaction.java        鉁�
+鈹�   鈹�       鈹溾攢鈹� NotifyLog.java                 鉁�
+鈹�   鈹�       鈹溾攢鈹� BizCallbackLog.java            鉁�
+鈹�   鈹�       鈹斺攢鈹� OperationAudit.java            鉁�
+鈹�   鈹溾攢鈹� application/service/
+鈹�   鈹�   鈹斺攢鈹� PaymentService.java                鉁�
+鈹�   鈹溾攢鈹� infrastructure/
+鈹�   鈹�   鈹溾攢鈹� config/
+鈹�   鈹�   鈹�   鈹溾攢鈹� WechatPayConfig.java           鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� AlipayConfig.java              鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� BusinessCallbackConfig.java    鉁�
+鈹�   鈹�   鈹�   鈹斺攢鈹� QrCodeConfig.java              鉁�
+鈹�   鈹�   鈹溾攢鈹� persistence/mapper/
+鈹�   鈹�   鈹�   鈹溾攢鈹� PaymentOrderMapper.java        鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� PaymentTransactionMapper.java  鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� NotifyLogMapper.java           鉁�
+鈹�   鈹�   鈹�   鈹溾攢鈹� BizCallbackLogMapper.java      鉁�
+鈹�   鈹�   鈹�   鈹斺攢鈹� OperationAuditMapper.java      鉁�
+鈹�   鈹�   鈹斺攢鈹� util/
+鈹�   鈹�       鈹溾攢鈹� QrCodeUtil.java                鉁�
+鈹�   鈹�       鈹斺攢鈹� SignUtil.java                  鉁�
+鈹�   鈹斺攢鈹� interfaces/
+鈹�       鈹溾攢鈹� controller/
+鈹�       鈹�   鈹溾攢鈹� PaymentController.java         鉁�
+鈹�       鈹�   鈹溾攢鈹� PaymentNotifyController.java   鉁�
+鈹�       鈹�   鈹斺攢鈹� HealthController.java          鉁�
+鈹�       鈹斺攢鈹� dto/
+鈹�           鈹溾攢鈹� PaymentRequest.java            鉁�
+鈹�           鈹斺攢鈹� PaymentResponse.java           鉁�
+鈹斺攢鈹� src/main/resources/
+    鈹溾攢鈹� application.yml                        鉁�
+    鈹溾攢鈹� mapper/
+    鈹�   鈹溾攢鈹� PaymentOrderMapper.xml             鉁�
+    鈹�   鈹斺攢鈹� PaymentTransactionMapper.xml       鉁�
+    鈹斺攢鈹� sql/
+        鈹斺攢鈹� schema.sql                         鉁�
+```
+
+**缁熻**: 
+- Java鏂囦欢: 32涓� 鉁�
+- XML鏂囦欢: 2涓� 鉁�
+- 閰嶇疆鏂囦欢: 2涓� 鉁�
+- SQL鏂囦欢: 1涓� 鉁�
+- 鏂囨。: 3涓� 鉁�
+- **鎬昏: 40涓枃浠�** 鉁�
+
+## 馃殌 蹇�熷惎鍔ㄦ楠�
+
+### 1. 鍒濆鍖栨暟鎹簱
+```bash
+mysql -u root -p < src/main/resources/sql/schema.sql
+```
+
+### 2. 淇敼閰嶇疆
+缂栬緫 `src/main/resources/application.yml`:
+- 鏁版嵁搴撹繛鎺ヤ俊鎭�
+- 寰俊鏀粯閰嶇疆锛坅ppId, mchId, mchKey锛�
+- 鏀粯瀹濋厤缃紙appId, privateKey, alipayPublicKey锛�
+
+### 3. 缂栬瘧杩愯
+```bash
+mvn clean package
+java -jar target/dryad-payment-1.0.0.jar
+```
+
+### 4. 娴嬭瘯鎺ュ彛
+```bash
+# 鍋ュ悍妫�鏌�
+curl http://localhost:8080/api/health
+
+# 鍒涘缓寰俊鏀粯
+curl -X POST http://localhost:8080/api/pay/wechat/native \
+  -H "Content-Type: application/json" \
+  -d '{"bizOrderId":"TEST001","amount":100,"subject":"娴嬭瘯","callbackUrl":"http://test.com"}'
+```
+
+## 鈿欙笍 鎶�鏈爤鐗堟湰
+
+| 鎶�鏈� | 鐗堟湰 |
+|------|------|
+| Java | 1.8 |
+| Spring Boot | 2.5.15 |
+| MyBatis Plus | 3.4.3.4 |
+| Druid | 1.2.8 |
+| FastJSON | 1.2.83 |
+| Alipay SDK | 4.22.110.ALL |
+| ZXing | 3.4.1 |
+
+## 馃幆 涓嬩竴姝ュ缓璁�
+
+### 浼樺厛绾�1锛堟牳蹇冨姛鑳斤級
+1. 瀹炵幇寰俊鏀粯v2瀹㈡埛绔紙鍙傝�冨畼鏂规枃妗o級
+2. 瀹炵幇鏀粯瀹濆綋闈粯瀹㈡埛绔紙浣跨敤瀹樻柟SDK锛�
+3. 瀹屽杽鍥炶皟澶勭悊閫昏緫锛堢鍚嶉獙璇�+鐘舵�佹洿鏂帮級
+
+### 浼樺厛绾�2锛堜笟鍔″畬鏁存�э級
+4. 瀹炵幇涓氬姟鍥炶皟鏈嶅姟
+5. 瀹炵幇璁㈠崟杩囨湡瀹氭椂浠诲姟
+6. 娣诲姞鍗曞厓娴嬭瘯
+
+### 浼樺厛绾�3锛堣繍缁存敮鎸侊級
+7. 瀹炵幇姣忔棩瀵硅处浠诲姟
+8. 瀹炵幇绠$悊绔帴鍙�
+9. 娣诲姞鐩戞帶鍜屽憡璀�
+
+## 馃摑 娉ㄦ剰浜嬮」
+
+1. **瀹夊叏**: 閰嶇疆鏂囦欢涓殑瀵嗛挜璇峰嬁鎻愪氦鍒颁唬鐮佷粨搴�
+2. **HTTPS**: 鐢熶骇鐜鍥炶皟URL蹇呴』浣跨敤HTTPS
+3. **骞跺彂**: 寤鸿浣跨敤Redis鍒嗗竷寮忛攣
+4. **鐩戞帶**: 娣诲姞鏃ュ織鐩戞帶鍜屽紓甯稿憡璀�
+5. **娴嬭瘯**: 鍏堝湪娌欑鐜娴嬭瘯
+
+## 馃摉 鍙傝�冩枃妗�
+
+- 璁捐鏂规: `doc/璁捐鏂规.md`
+- 椤圭洰璇存槑: `README.md`
+- 寰俊鏀粯v2: https://pay.weixin.qq.com/wiki/doc/api/native.php
+- 鏀粯瀹濆綋闈粯: https://opendocs.alipay.com/open/194/105072
+
+---
+
+**浠g爜鐢熸垚瀹屾垚鏃堕棿**: 2025-11-23
+**椤圭洰鐘舵��**: 鍩虹妗嗘灦瀹屾垚锛屾牳蹇冧笟鍔″緟瀹炵幇
+**鍙繍琛屾��**: 鉁� 椤圭洰鍙紪璇戣繍琛岋紝鎺ュ彛鍙祴璇曪紙妯℃嫙妯″紡锛�
diff --git "a/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243-\345\277\253\351\200\237\345\274\200\345\247\213.md" "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243-\345\277\253\351\200\237\345\274\200\345\247\213.md"
new file mode 100644
index 0000000..8bca554
--- /dev/null
+++ "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243-\345\277\253\351\200\237\345\274\200\345\247\213.md"
@@ -0,0 +1,171 @@
+# 鏀粯瀹濈涓夋柟鎺ュ彛 - 蹇�熷紑濮嬫寚鍗�
+
+## 馃搵 鍔熻兘姒傝堪
+
+鏂板鏀粯瀹濆綋闈粯绗笁鏂规帴鍙o紝閫氳繃璋冪敤鏃х郴缁烶HP鎺ュ彛鐢熸垚鏀粯URL鍜屼簩缁寸爜銆�
+
+## 馃殌 蹇�熷紑濮�
+
+### 1. 鎺ュ彛鍦板潃
+```
+POST /api/pay/alipay/thirdparty/precreate
+```
+
+### 2. 璇锋眰绀轰緥
+```bash
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "BF20250012-1",
+  "amount": 10000,
+  "subject": "鎬ユ晳杞繍鏈嶅姟璐�",
+  "description": "鎬ユ晳杞繍浠诲姟鏀粯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}'
+```
+
+### 3. 鍝嶅簲绀轰緥
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "orderId": 1234567890123456789,
+    "transactionId": 9876543210987654321,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
+    "expireAt": "2025-11-24T18:00:00"
+  }
+}
+```
+
+## 馃搧 鏂板鏂囦欢娓呭崟
+
+### 鏍稿績浠g爜
+- 鉁� `AlipayThirdPartyClient.java` - 绗笁鏂规帴鍙h皟鐢ㄥ鎴风
+- 鉁� `PaymentService.java` - 鏂板绗笁鏂规敮浠樻柟娉�
+- 鉁� `PaymentController.java` - 鏂板绗笁鏂规敮浠樻帴鍙�
+
+### 鏂囨。
+- 鉁� `鏀粯瀹濈涓夋柟鎺ュ彛浣跨敤璇存槑.md` - 璇︾粏浣跨敤鏂囨。
+- 鉁� `鏀粯瀹濈涓夋柟鎺ュ彛娴嬭瘯鏂囨。.md` - 娴嬭瘯鎸囧崡
+- 鉁� `鏀粯瀹濈涓夋柟鎺ュ彛寮�鍙戞�荤粨.md` - 寮�鍙戞�荤粨
+
+## 馃攽 鏍稿績鍙傛暟璇存槑
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| bizOrderId | String | 鏄� | 涓氬姟璁㈠崟鍙� |
+| amount | Integer | 鏄� | 閲戦锛堝崟浣嶏細鍒嗭級 |
+| subject | String | 鏄� | 璁㈠崟鏍囬 |
+| description | String | 鍚� | 璁㈠崟鎻忚堪 |
+| callbackUrl | String | 鏄� | 鏀粯鍥炶皟鍦板潃 |
+
+## 鈿欙笍 閰嶇疆璇存槑
+
+宸插湪 `application.yml` 涓坊鍔犵涓夋柟鎺ュ彛閰嶇疆锛�
+
+```yaml
+payment:
+  alipay:
+    thirdParty:
+      enabled: true
+      url: https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php
+      defaultNotifyUrl: https://dsp.966120.com.cn/alipay/pay_notify
+      timeout: 30000
+```
+
+## 馃И 蹇�熸祴璇�
+
+### Postman娴嬭瘯
+1. 鍒涘缓POST璇锋眰锛歚http://localhost:8080/api/pay/alipay/thirdparty/precreate`
+2. 璁剧疆Header锛歚Content-Type: application/json`
+3. 璁剧疆Body锛圝SON鏍煎紡锛夛細
+```json
+{
+  "bizOrderId": "TEST001",
+  "amount": 100,
+  "subject": "娴嬭瘯璁㈠崟",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}
+```
+4. 鍙戦�佽姹傦紝鑾峰彇浜岀淮鐮�
+
+### 鍓嶇灞曠ず浜岀淮鐮�
+```javascript
+const qrImage = document.getElementById('qrImage');
+qrImage.src = result.data.qrBase64;
+```
+
+## 馃攧 璋冪敤娴佺▼
+
+```
+鍓嶇 鈫� PaymentController 
+     鈫� PaymentService 
+     鈫� AlipayThirdPartyClient 
+     鈫� 绗笁鏂筆HP鎺ュ彛
+     鈫� 杩斿洖鏀粯URL 
+     鈫� 鐢熸垚浜岀淮鐮� 
+     鈫� 杩斿洖缁欏墠绔�
+```
+
+## 馃搳 涓庢爣鍑嗘帴鍙e姣�
+
+| 鎺ュ彛绫诲瀷 | 鎺ュ彛璺緞 | 璋冪敤鏂瑰紡 |
+|---------|---------|---------|
+| 鏍囧噯鎺ュ彛 | `/api/pay/alipay/precreate` | 鏀粯瀹漇DK |
+| 绗笁鏂规帴鍙� | `/api/pay/alipay/thirdparty/precreate` | HTTP POST |
+
+## 鈿狅笍 娉ㄦ剰浜嬮」
+
+1. **閲戦鍗曚綅**锛氭墍鏈夐噾棰濆弬鏁板崟浣嶄负**鍒�**锛�1鍏� = 100鍒嗭級
+2. **璁㈠崟杩囨湡**锛氳鍗曢粯璁�**2灏忔椂**鍚庤繃鏈�
+3. **閲嶅璋冪敤**锛氱浉鍚屼笟鍔¤鍗曞彿杩斿洖宸插瓨鍦ㄨ褰�
+4. **鍥炶皟鍦板潃**锛氬繀椤婚厤缃纭殑鍥炶皟鍦板潃
+
+## 馃悰 闂鎺掓煡
+
+### 绗笁鏂规帴鍙h皟鐢ㄥけ璐�
+```bash
+# 妫�鏌ョ綉缁滆繛鎺�
+ping sys.966120.com.cn
+
+# 鐩存帴娴嬭瘯绗笁鏂规帴鍙�
+curl --location --request POST 'https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php' \
+--header 'Cookie: CAMEName=' \
+--form 'notify_url="https://dsp.966120.com.cn/alipay/pay_notify"' \
+--form 'out_trade_no="TEST001"' \
+--form 'total_fee="100"' \
+--form 'ServiceOrdID="TEST001"'
+```
+
+### 鏌ョ湅鏃ュ織
+```bash
+# 鏌ョ湅鏈嶅姟鏃ュ織
+tail -f logs/dryad-payment.log
+
+# 鍏抽敭鏃ュ織
+- "璋冪敤绗笁鏂规敮浠樺疂褰撻潰浠樻帴鍙�"
+- "绗笁鏂规帴鍙e搷搴�"
+- "鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛夊垱寤烘垚鍔�"
+```
+
+## 馃摓 鎶�鏈敮鎸�
+
+璇︾粏鏂囨。鍙傝�冿細
+- `doc/鏀粯瀹濈涓夋柟鎺ュ彛浣跨敤璇存槑.md`
+- `doc/鏀粯瀹濈涓夋柟鎺ュ彛娴嬭瘯鏂囨。.md`
+- `doc/鏀粯瀹濈涓夋柟鎺ュ彛寮�鍙戞�荤粨.md`
+
+## 馃幆 涓嬩竴姝�
+
+- [ ] 娴嬭瘯绗笁鏂规帴鍙e彲鐢ㄦ��
+- [ ] 楠岃瘉杩斿洖URL鏍煎紡骞惰皟鏁磋В鏋愰�昏緫
+- [ ] 闆嗘垚鍒颁富搴旂敤
+- [ ] 閰嶇疆鐢熶骇鐜鍥炶皟鍦板潃
+- [ ] 杩涜瀹屾暣娴佺▼娴嬭瘯
+
+---
+
+**寮�鍙戝畬鎴愭椂闂�**: 2025-11-24  
+**鐗堟湰**: v1.0.0
diff --git "a/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\344\275\277\347\224\250\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..0e58d81
--- /dev/null
+++ "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\344\275\277\347\224\250\350\257\264\346\230\216.md"
@@ -0,0 +1,199 @@
+# 鏀粯瀹濈涓夋柟鎺ュ彛浣跨敤璇存槑
+
+## 姒傝堪
+
+鏈ā鍧楁柊澧炰簡鏀粯瀹濆綋闈粯绗笁鏂规帴鍙o紝鐢ㄤ簬璋冪敤鏃х郴缁熺殑鏀粯瀹濇敮浠樻帴鍙g敓鎴愭敮浠楿RL鍜屼簩缁寸爜銆�
+
+## 鍔熻兘璇存槑
+
+### 鎺ュ彛鍦板潃
+- **Controller鎺ュ彛**: `POST /api/pay/alipay/thirdparty/precreate`
+- **绗笁鏂规帴鍙�**: `https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php`
+
+### 瀹炵幇娴佺▼
+
+1. 鎺ユ敹鍓嶇鏀粯璇锋眰
+2. 鍒涘缓鎴栨煡璇㈣鍗曡褰�
+3. 璋冪敤绗笁鏂规敮浠樺疂鎺ュ彛鐢熸垚鏀粯URL
+4. 灏嗘敮浠楿RL鐢熸垚浜岀淮鐮侊紙Base64鏍煎紡锛�
+5. 鍒涘缓浜ゆ槗璁板綍
+6. 杩斿洖鏀粯淇℃伅缁欏墠绔�
+
+## 璇锋眰鍙傛暟
+
+### 璇锋眰绀轰緥
+
+```json
+{
+  "bizOrderId": "BF20250012-1",
+  "amount": 10000,
+  "subject": "鎬ユ晳杞繍鏈嶅姟璐�",
+  "description": "鎬ユ晳杞繍浠诲姟鏀粯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}
+```
+
+### 鍙傛暟璇存槑
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| bizOrderId | String | 鏄� | 涓氬姟璁㈠崟鍙凤紙濡傦細BF20250012-1锛� |
+| amount | Integer | 鏄� | 璁㈠崟閲戦锛屽崟浣嶏細鍒嗭紙濡傦細10000琛ㄧず100.00鍏冿級 |
+| subject | String | 鏄� | 璁㈠崟鏍囬 |
+| description | String | 鍚� | 璁㈠崟鎻忚堪 |
+| callbackUrl | String | 鏄� | 鏀粯鎴愬姛鍚庣殑鍥炶皟閫氱煡鍦板潃 |
+
+## 鍝嶅簲鍙傛暟
+
+### 鎴愬姛鍝嶅簲绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "orderId": 1234567890123456789,
+    "transactionId": 9876543210987654321,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
+    "expireAt": "2025-11-24T18:00:00"
+  }
+}
+```
+
+### 鍝嶅簲鍙傛暟璇存槑
+
+| 鍙傛暟鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| orderId | Long | 鏀粯璁㈠崟ID |
+| transactionId | Long | 浜ゆ槗娴佹按ID |
+| status | String | 璁㈠崟鐘舵�侊紙PENDING-寰呮敮浠橈級 |
+| qrBase64 | String | 浜岀淮鐮佸浘鐗嘊ase64缂栫爜 |
+| expireAt | DateTime | 璁㈠崟杩囨湡鏃堕棿锛�2灏忔椂鍚庯級 |
+
+## 璋冪敤绗笁鏂规帴鍙e弬鏁版槧灏�
+
+璋冪敤绗笁鏂规帴鍙f椂锛屽弬鏁版槧灏勫叧绯诲涓嬶細
+
+| 绗笁鏂瑰弬鏁� | 鏉ユ簮 | 璇存槑 |
+|-----------|------|------|
+| notify_url | callbackUrl | 寮傛鍥炶皟閫氱煡鍦板潃 |
+| out_trade_no | orderId | 鏀粯妯″潡鐢熸垚鐨勮鍗旾D |
+| total_fee | amount | 璁㈠崟閲戦锛堝垎锛� |
+| ServiceOrdID | bizOrderId | 涓氬姟璁㈠崟鍙� |
+
+### curl绀轰緥
+
+```bash
+curl --location --request POST 'https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php' \
+--header 'Cookie: CAMEName=' \
+--form 'notify_url="https://dsp.966120.com.cn/alipay/pay_notify"' \
+--form 'out_trade_no="1234567890123456789"' \
+--form 'total_fee="10000"' \
+--form 'ServiceOrdID="BF20250012-1"'
+```
+
+## 浠g爜瀹炵幇
+
+### 鏍稿績绫昏鏄�
+
+#### 1. AlipayThirdPartyClient
+- **浣嶇疆**: `com.ruoyi.payment.infrastructure.channel.alipay.AlipayThirdPartyClient`
+- **鍔熻兘**: 灏佽绗笁鏂规敮浠樺疂鎺ュ彛璋冪敤閫昏緫
+- **涓昏鏂规硶**: 
+  - `createQrCodeUrl()`: 璋冪敤绗笁鏂规帴鍙g敓鎴愭敮浠楿RL
+
+#### 2. PaymentService
+- **浣嶇疆**: `com.ruoyi.payment.application.service.PaymentService`
+- **鍔熻兘**: 鏀粯涓氬姟閫昏緫澶勭悊
+- **涓昏鏂规硶**:
+  - `createAlipayThirdPartyPrecreate()`: 鍙戣捣绗笁鏂规敮浠樺疂褰撻潰浠�
+
+#### 3. PaymentController
+- **浣嶇疆**: `com.ruoyi.payment.interfaces.controller.PaymentController`
+- **鍔熻兘**: 鎻愪緵HTTP鎺ュ彛
+- **鎺ュ彛璺緞**: `POST /api/pay/alipay/thirdparty/precreate`
+
+## 浣跨敤绀轰緥
+
+### 鍓嶇璋冪敤绀轰緥
+
+```javascript
+// 鍙戣捣鏀粯
+async function createPayment() {
+  const response = await fetch('/api/pay/alipay/thirdparty/precreate', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json'
+    },
+    body: JSON.stringify({
+      bizOrderId: 'BF20250012-1',
+      amount: 10000,
+      subject: '鎬ユ晳杞繍鏈嶅姟璐�',
+      description: '鎬ユ晳杞繍浠诲姟鏀粯',
+      callbackUrl: 'https://dsp.966120.com.cn/alipay/pay_notify'
+    })
+  });
+  
+  const result = await response.json();
+  
+  if (result.code === 200) {
+    // 鏄剧ず浜岀淮鐮�
+    const qrImage = document.getElementById('qrImage');
+    qrImage.src = result.data.qrBase64;
+  }
+}
+```
+
+## 娉ㄦ剰浜嬮」
+
+1. **閲戦鍗曚綅**: 鎵�鏈夐噾棰濆弬鏁板崟浣嶅潎涓哄垎锛屽墠绔渶瑕佸皢鍏冭浆鎹负鍒嗭紙涔樹互100锛�
+2. **璁㈠崟杩囨湡**: 璁㈠崟榛樿2灏忔椂鍚庤繃鏈燂紝闇�鍦ㄦ湁鏁堟湡鍐呭畬鎴愭敮浠�
+3. **閲嶅璋冪敤**: 鍚屼竴涓氬姟璁㈠崟鍙峰娆¤皟鐢ㄤ細杩斿洖宸插瓨鍦ㄧ殑鏀粯璁板綍锛屼笉浼氶噸澶嶅垱寤�
+4. **鍥炶皟鍦板潃**: 蹇呴』閰嶇疆姝g‘鐨勫洖璋冨湴鍧�锛岀敤浜庢帴鏀舵敮浠樻垚鍔熼�氱煡
+5. **绗笁鏂规帴鍙e搷搴旀牸寮�**: 闇�瑕佹牴鎹疄闄呰繑鍥炴牸寮忚皟鏁� `parseQrCodeUrl()` 鏂规硶
+
+## 涓庢爣鍑嗘敮浠樺疂褰撻潰浠樻帴鍙g殑鍖哄埆
+
+| 鐗规�� | 鏍囧噯鎺ュ彛 | 绗笁鏂规帴鍙� |
+|------|---------|-----------|
+| 鎺ュ彛鍦板潃 | 鏀粯瀹濆畼鏂笰PI | 鏃х郴缁烶HP鎺ュ彛 |
+| 璋冪敤鏂瑰紡 | 鏀粯瀹漇DK | HTTP POST multipart/form-data |
+| 杩斿洖鍐呭 | 鏀粯瀹漲r_code | 鏀粯URL |
+| 浼樺娍 | 瀹樻柟鏀寔銆佺ǔ瀹� | 鍏煎鏃х郴缁熴�佸揩閫熼泦鎴� |
+
+## 閰嶇疆璇存槑
+
+### 榛樿鍥炶皟鍦板潃
+濡傛灉璇锋眰涓湭鎸囧畾`callbackUrl`锛岀郴缁熶細浣跨敤榛樿鍥炶皟鍦板潃锛�
+```
+https://dsp.966120.com.cn/alipay/pay_notify
+```
+
+鍙湪 `PaymentService.callAlipayThirdPartyPrecreate()` 鏂规硶涓慨鏀归粯璁ゅ�笺��
+
+## 閿欒澶勭悊
+
+### 甯歌閿欒鐮�
+
+| 閿欒鐮� | 璇存槑 | 澶勭悊鏂瑰紡 |
+|--------|------|---------|
+| 500 | 绗笁鏂规帴鍙h皟鐢ㄥけ璐� | 妫�鏌ョ綉缁滆繛鎺ュ拰绗笁鏂规帴鍙e彲鐢ㄦ�� |
+| 500 | 鏈繑鍥炴湁鏁堢殑鏀粯URL | 妫�鏌ョ涓夋柟鎺ュ彛杩斿洖鏍煎紡 |
+| 400 | 鍙傛暟鏍¢獙澶辫触 | 妫�鏌ヨ姹傚弬鏁版槸鍚﹀畬鏁� |
+
+## 娴嬭瘯寤鸿
+
+1. 鍏堜娇鐢≒ostman鎴朿url娴嬭瘯绗笁鏂规帴鍙e彲鐢ㄦ��
+2. 楠岃瘉绗笁鏂规帴鍙h繑鍥炵殑URL鏍煎紡
+3. 娴嬭瘯灏忛鏀粯锛堝1鍏冿級楠岃瘉瀹屾暣娴佺▼
+4. 娴嬭瘯璁㈠崟閲嶅鍒涘缓鍦烘櫙
+5. 娴嬭瘯璁㈠崟杩囨湡鍦烘櫙
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **鍝嶅簲瑙f瀽**: 鏍规嵁绗笁鏂规帴鍙e疄闄呰繑鍥炴牸寮忥紝瀹屽杽 `parseQrCodeUrl()` 鏂规硶
+2. **閿欒閲嶈瘯**: 澧炲姞绗笁鏂规帴鍙h皟鐢ㄥけ璐ョ殑閲嶈瘯鏈哄埗
+3. **瓒呮椂鎺у埗**: 璁剧疆HTTP璇锋眰瓒呮椂鏃堕棿
+4. **鏃ュ織瀹屽杽**: 澧炲姞鏇磋缁嗙殑璋冪敤鏃ュ織锛屼究浜庨棶棰樻帓鏌�
+5. **鐩戞帶鍛婅**: 瀵规帴鍙h皟鐢ㄥけ璐ヨ繘琛岀洃鎺у拰鍛婅
diff --git "a/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\345\274\200\345\217\221\346\200\273\347\273\223.md" "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\345\274\200\345\217\221\346\200\273\347\273\223.md"
new file mode 100644
index 0000000..c715c21
--- /dev/null
+++ "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\345\274\200\345\217\221\346\200\273\347\273\223.md"
@@ -0,0 +1,248 @@
+# 鏀粯瀹濈涓夋柟鎺ュ彛寮�鍙戞�荤粨
+
+## 寮�鍙戞杩�
+
+鏈寮�鍙戝湪鏀粯妯″潡涓柊澧炰簡鏀粯瀹濆綋闈粯绗笁鏂规帴鍙e姛鑳斤紝閫氳繃璋冪敤鏃х郴缁熺殑PHP鎺ュ彛鐢熸垚鏀粯URL鍜屼簩缁寸爜銆�
+
+## 鏂板鏂囦欢娓呭崟
+
+### 1. 鏍稿績浠g爜鏂囦欢
+
+#### AlipayThirdPartyClient.java
+**璺緞**: `dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayThirdPartyClient.java`
+
+**鍔熻兘**: 
+- 灏佽绗笁鏂规敮浠樺疂鎺ュ彛璋冪敤
+- 浣跨敤Apache HttpClient鍙戦�乵ultipart/form-data璇锋眰
+- 瑙f瀽绗笁鏂规帴鍙e搷搴旓紝鎻愬彇鏀粯URL
+
+**鏍稿績鏂规硶**:
+```java
+public String createQrCodeUrl(String notifyUrl, String outTradeNo, Integer totalFee, String serviceOrdId)
+```
+
+### 2. 鏈嶅姟灞備慨鏀�
+
+#### PaymentService.java
+**璺緞**: `dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentService.java`
+
+**鏂板鍐呭**:
+- 娉ㄥ叆 `AlipayThirdPartyClient` Bean
+- 鏂板鏂规硶 `createAlipayThirdPartyPrecreate()` - 澶勭悊绗笁鏂规敮浠樺疂褰撻潰浠樹笟鍔¢�昏緫
+- 鏂板鏂规硶 `callAlipayThirdPartyPrecreate()` - 璋冪敤绗笁鏂规帴鍙g敓鎴愭敮浠楿RL
+
+### 3. 鎺у埗鍣ㄥ眰淇敼
+
+#### PaymentController.java
+**璺緞**: `dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentController.java`
+
+**鏂板鎺ュ彛**:
+- `POST /api/pay/alipay/thirdparty/precreate` - 鍙戣捣鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛�
+
+### 4. 鏂囨。鏂囦欢
+
+#### 鏀粯瀹濈涓夋柟鎺ュ彛浣跨敤璇存槑.md
+**璺緞**: `dryad-payment/doc/鏀粯瀹濈涓夋柟鎺ュ彛浣跨敤璇存槑.md`
+
+**鍐呭**:
+- 鍔熻兘璇存槑
+- 鎺ュ彛鍙傛暟鏂囨。
+- 浠g爜瀹炵幇璇存槑
+- 浣跨敤绀轰緥
+- 娉ㄦ剰浜嬮」
+
+#### 鏀粯瀹濈涓夋柟鎺ュ彛娴嬭瘯鏂囨。.md
+**璺緞**: `dryad-payment/doc/鏀粯瀹濈涓夋柟鎺ュ彛娴嬭瘯鏂囨。.md`
+
+**鍐呭**:
+- Postman娴嬭瘯姝ラ
+- cURL娴嬭瘯鍛戒护
+- 鍚勭娴嬭瘯鍦烘櫙
+- 鍓嶇闆嗘垚绀轰緥
+- 闂鎺掓煡鎸囧崡
+
+## 鎶�鏈疄鐜拌鐐�
+
+### 1. HTTP璇锋眰灏佽
+浣跨敤Apache HttpClient鍙戦�乵ultipart/form-data鏍煎紡鐨凱OST璇锋眰锛�
+```java
+HttpEntity entity = MultipartEntityBuilder.create()
+    .addTextBody("notify_url", notifyUrl)
+    .addTextBody("out_trade_no", outTradeNo)
+    .addTextBody("total_fee", String.valueOf(totalFee))
+    .addTextBody("ServiceOrdID", serviceOrdId)
+    .build();
+```
+
+### 2. 鍙傛暟鏄犲皠
+| 涓氬姟鍙傛暟 | 绗笁鏂瑰弬鏁� | 璇存槑 |
+|---------|-----------|------|
+| callbackUrl | notify_url | 鍥炶皟閫氱煡鍦板潃 |
+| orderId | out_trade_no | 璁㈠崟ID |
+| amount | total_fee | 閲戦锛堝垎锛� |
+| bizOrderId | ServiceOrdID | 涓氬姟璁㈠崟鍙� |
+
+### 3. URL瑙f瀽
+鎻愪緵浜嗙伒娲荤殑URL瑙f瀽鏂规硶锛屾敮鎸侊細
+- 鐩存帴杩斿洖URL瀛楃涓�
+- JSON鏍煎紡鍝嶅簲
+- 甯﹀紩鍙风殑URL瀛楃涓�
+
+鍙牴鎹疄闄呰繑鍥炴牸寮忚皟鏁� `parseQrCodeUrl()` 鏂规硶銆�
+
+### 4. 浜岀淮鐮佺敓鎴�
+澶嶇敤鐜版湁鐨� `QrCodeUtil` 宸ュ叿绫伙紝灏嗘敮浠楿RL杞崲涓築ase64鏍煎紡鐨勪簩缁寸爜鍥剧墖銆�
+
+## 鎺ュ彛璋冪敤娴佺▼
+
+```
+鍓嶇璇锋眰
+    鈫�
+PaymentController.createAlipayThirdPartyPrecreate()
+    鈫�
+PaymentService.createAlipayThirdPartyPrecreate()
+    鈫�
+callAlipayThirdPartyPrecreate()
+    鈫�
+AlipayThirdPartyClient.createQrCodeUrl()
+    鈫�
+HTTP POST 鈫� https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php
+    鈫�
+瑙f瀽鍝嶅簲寰楀埌鏀粯URL
+    鈫�
+QrCodeUtil.generateQrCodeBase64() - 鐢熸垚浜岀淮鐮�
+    鈫�
+淇濆瓨璁㈠崟鍜屼氦鏄撹褰�
+    鈫�
+杩斿洖鏀粯淇℃伅缁欏墠绔�
+```
+
+## 涓庢爣鍑嗘帴鍙g殑瀵规瘮
+
+| 瀵规瘮椤� | 鏍囧噯鏀粯瀹漇DK鎺ュ彛 | 绗笁鏂规帴鍙� |
+|-------|----------------|----------|
+| 瀹炵幇绫� | AlipayF2FClient | AlipayThirdPartyClient |
+| 璋冪敤鏂瑰紡 | 鏀粯瀹漇DK | HTTP POST |
+| 鎺ュ彛鍦板潃 | 鏀粯瀹濆畼鏂� | 鏃х郴缁烶HP鎺ュ彛 |
+| 杩斿洖鍐呭 | qr_code | 鏀粯URL |
+| 鎺ュ彛璺緞 | /api/pay/alipay/precreate | /api/pay/alipay/thirdparty/precreate |
+
+## 鏁版嵁搴撹〃璁捐
+
+### 璁㈠崟琛� (pay_order)
+- 璁板綍鏀粯璁㈠崟鍩烘湰淇℃伅
+- 鏀寔澶氭笭閬擄紙寰俊銆佹敮浠樺疂锛�
+- 2灏忔椂鑷姩杩囨湡
+
+### 浜ゆ槗琛� (pay_transaction)
+- 璁板綍姣忕瑪浜ゆ槗璇︽儏
+- 瀛樺偍鏀粯URL鍜屼簩缁寸爜
+- 鍏宠仈璁㈠崟ID
+
+## 閰嶇疆璇存槑
+
+### 榛樿閰嶇疆
+- 鍥炶皟鍦板潃: `https://dsp.966120.com.cn/alipay/pay_notify`
+- 浜岀淮鐮佸昂瀵�: 300x300
+- 璁㈠崟杩囨湡鏃堕棿: 2灏忔椂
+
+### 鍙厤缃」
+鍦� `PaymentService.callAlipayThirdPartyPrecreate()` 鏂规硶涓彲淇敼锛�
+- 榛樿鍥炶皟鍦板潃
+- 鍏朵粬涓氬姟鍙傛暟
+
+## 娴嬭瘯瑕佺偣
+
+### 鍔熻兘娴嬭瘯
+- [x] 姝e父鏀粯娴佺▼
+- [x] 閲嶅璁㈠崟澶勭悊
+- [x] 鍙傛暟鏍¢獙
+- [x] 璁㈠崟杩囨湡澶勭悊
+
+### 鎺ュ彛娴嬭瘯
+- [ ] 绗笁鏂规帴鍙e彲鐢ㄦ��
+- [ ] 缃戠粶寮傚父澶勭悊
+- [ ] 瓒呮椂澶勭悊
+- [ ] 杩斿洖鏍煎紡瑙f瀽
+
+### 闆嗘垚娴嬭瘯
+- [ ] 涓庝富搴旂敤闆嗘垚
+- [ ] 鏀粯鍥炶皟澶勭悊
+- [ ] 鍓嶇灞曠ず浜岀淮鐮�
+
+## 娉ㄦ剰浜嬮」
+
+### 1. 鍝嶅簲鏍煎紡閫傞厤
+绗笁鏂规帴鍙g殑瀹為檯杩斿洖鏍煎紡闇�瑕佹牴鎹疄闄呮儏鍐佃皟鏁� `parseQrCodeUrl()` 鏂规硶锛�
+
+```java
+private String parseQrCodeUrl(String responseBody) {
+    // 鏍规嵁瀹為檯杩斿洖鏍煎紡璋冩暣
+    // 濡傛灉鏄疛SON: JSONObject json = JSON.parseObject(responseBody);
+    // 濡傛灉鏄函鏂囨湰: return responseBody.trim();
+}
+```
+
+### 2. 閿欒澶勭悊
+寤鸿娣诲姞鏇磋缁嗙殑閿欒澶勭悊鍜屾棩蹇楄褰曪紝渚夸簬闂鎺掓煡銆�
+
+### 3. 鎬ц兘浼樺寲
+鑰冭檻娣诲姞锛�
+- HTTP杩炴帴姹�
+- 瓒呮椂璁剧疆
+- 閲嶈瘯鏈哄埗
+- 鐔旀柇闄嶇骇
+
+### 4. 瀹夊叏鎬�
+- 楠岃瘉鍥炶皟绛惧悕
+- HTTPS閫氫俊
+- 鏁忔劅淇℃伅鍔犲瘑
+
+## 鍚庣画浼樺寲寤鸿
+
+### 鐭湡浼樺寲
+1. 鏍规嵁瀹為檯杩斿洖鏍煎紡瀹屽杽URL瑙f瀽閫昏緫
+2. 娣诲姞鍗曞厓娴嬭瘯
+3. 瀹屽杽寮傚父澶勭悊
+4. 澧炲姞鎺ュ彛鏃ュ織
+
+### 闀挎湡浼樺寲
+1. 寮曞叆HTTP杩炴帴姹犵鐞�
+2. 瀹炵幇閲嶈瘯鍜岀啍鏂満鍒�
+3. 娣诲姞鎺ュ彛鐩戞帶鍜屽憡璀�
+4. 鎬ц兘浼樺寲鍜屽帇娴�
+5. 鏀寔寮傛澶勭悊
+
+## 渚濊禆璇存槑
+
+椤圭洰宸插寘鍚墍闇�渚濊禆锛屾棤闇�棰濆娣诲姞锛�
+- `org.apache.httpcomponents:httpclient:4.5.13`
+- `com.google.zxing:core:3.4.1`
+- `com.google.zxing:javase:3.4.1`
+
+## 閮ㄧ讲璇存槑
+
+### 寮�鍙戠幆澧�
+1. 纭繚鏁版嵁搴撻厤缃纭�
+2. 楠岃瘉绗笁鏂规帴鍙e彲璁块棶
+3. 鍚姩鏈嶅姟娴嬭瘯
+
+### 鐢熶骇鐜
+1. 閰嶇疆姝g‘鐨勫洖璋冨湴鍧�
+2. 璁剧疆鍚堢悊鐨勮秴鏃舵椂闂�
+3. 娣诲姞鐩戞帶鍜屽憡璀�
+4. 杩涜鍘嬪姏娴嬭瘯
+
+## 鑱旂郴鏂瑰紡
+
+濡傛湁闂锛岃鏌ラ槄锛�
+- 浣跨敤璇存槑鏂囨。: `doc/鏀粯瀹濈涓夋柟鎺ュ彛浣跨敤璇存槑.md`
+- 娴嬭瘯鏂囨。: `doc/鏀粯瀹濈涓夋柟鎺ュ彛娴嬭瘯鏂囨。.md`
+
+## 鐗堟湰鍘嗗彶
+
+### v1.0.0 (2025-11-24)
+- 鉁� 鏂板鏀粯瀹濈涓夋柟鎺ュ彛鍔熻兘
+- 鉁� 鏀寔璋冪敤鏃х郴缁烶HP鎺ュ彛
+- 鉁� 鐢熸垚鏀粯URL鍜屼簩缁寸爜
+- 鉁� 瀹屽杽鏂囨。鍜屾祴璇曠敤渚�
diff --git "a/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\265\213\350\257\225\346\226\207\346\241\243.md" "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\265\213\350\257\225\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..b24c4ff
--- /dev/null
+++ "b/dryad-payment/doc/\346\224\257\344\273\230\345\256\235\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\265\213\350\257\225\346\226\207\346\241\243.md"
@@ -0,0 +1,320 @@
+# 鏀粯瀹濈涓夋柟鎺ュ彛API娴嬭瘯鏂囨。
+
+## 娴嬭瘯鐜鍑嗗
+
+### 1. 鍚姩鏀粯妯″潡鏈嶅姟
+```bash
+cd dryad-payment
+mvn spring-boot:run
+```
+
+鏈嶅姟榛樿绔彛锛歚8080`锛堟牴鎹疄闄呴厤缃皟鏁达級
+
+## 鎺ュ彛娴嬭瘯
+
+### 鎺ュ彛淇℃伅
+- **璇锋眰鍦板潃**: `POST http://localhost:8080/api/pay/alipay/thirdparty/precreate`
+- **Content-Type**: `application/json`
+
+### Postman娴嬭瘯姝ラ
+
+#### 1. 鍒涘缓鏂拌姹�
+- 鏂规硶锛歚POST`
+- URL锛歚http://localhost:8080/api/pay/alipay/thirdparty/precreate`
+
+#### 2. 璁剧疆璇锋眰澶�
+```
+Content-Type: application/json
+```
+
+#### 3. 璁剧疆璇锋眰浣擄紙Body -> raw -> JSON锛�
+```json
+{
+  "bizOrderId": "BF20250012-1",
+  "amount": 10000,
+  "subject": "鎬ユ晳杞繍鏈嶅姟璐�",
+  "description": "鎬ユ晳杞繍浠诲姟鏀粯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}
+```
+
+#### 4. 鍙戦�佽姹�
+
+棰勬湡鍝嶅簲锛�
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "orderId": 1234567890123456789,
+    "transactionId": 9876543210987654321,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
+    "expireAt": "2025-11-24T18:00:00"
+  }
+}
+```
+
+## cURL娴嬭瘯鍛戒护
+
+### 鍩烘湰娴嬭瘯
+```bash
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "BF20250012-1",
+  "amount": 10000,
+  "subject": "鎬ユ晳杞繍鏈嶅姟璐�",
+  "description": "鎬ユ晳杞繍浠诲姟鏀粯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}'
+```
+
+### 娴嬭瘯涓嶅悓閲戦
+```bash
+# 娴嬭瘯1鍏冿紙100鍒嗭級
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "TEST001",
+  "amount": 100,
+  "subject": "娴嬭瘯璁㈠崟",
+  "description": "娴嬭瘯1鍏冩敮浠�",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}'
+```
+
+## 娴嬭瘯鍦烘櫙
+
+### 鍦烘櫙1锛氭甯告敮浠樻祦绋�
+1. 鍙戦�佹敮浠樿姹�
+2. 鑾峰彇璁㈠崟ID鍜屼簩缁寸爜
+3. 鍓嶇灞曠ず浜岀淮鐮�
+4. 鐢ㄦ埛鎵爜鏀粯
+5. 鎺ユ敹鏀粯鍥炶皟閫氱煡
+
+### 鍦烘櫙2锛氶噸澶嶈鍗曟祴璇�
+```bash
+# 绗竴娆¤姹�
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "DUPLICATE_TEST_001",
+  "amount": 100,
+  "subject": "閲嶅璁㈠崟娴嬭瘯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}'
+
+# 绗簩娆¤姹傦紙鐩稿悓bizOrderId锛�- 搴旇杩斿洖鐩稿悓鐨勮鍗曚俊鎭�
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "DUPLICATE_TEST_001",
+  "amount": 100,
+  "subject": "閲嶅璁㈠崟娴嬭瘯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}'
+```
+
+### 鍦烘櫙3锛氬弬鏁版牎楠屾祴璇�
+
+#### 缂哄皯蹇呭~鍙傛暟
+```bash
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "TEST001",
+  "subject": "娴嬭瘯璁㈠崟"
+}'
+```
+棰勬湡锛氳繑鍥�400閿欒锛屾彁绀�"閲戦涓嶈兘涓虹┖"
+
+#### 閲戦涓�0
+```bash
+curl --location --request POST 'http://localhost:8080/api/pay/alipay/thirdparty/precreate' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+  "bizOrderId": "TEST001",
+  "amount": 0,
+  "subject": "娴嬭瘯璁㈠崟",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}'
+```
+棰勬湡锛氳繑鍥�400閿欒锛屾彁绀�"閲戦蹇呴』澶т簬0"
+
+## 鏌ヨ璁㈠崟鎺ュ彛娴嬭瘯
+
+### 鏍规嵁璁㈠崟ID鏌ヨ
+```bash
+curl --location --request GET 'http://localhost:8080/api/pay/orders/{orderId}'
+```
+
+绀轰緥锛�
+```bash
+curl --location --request GET 'http://localhost:8080/api/pay/orders/1234567890123456789'
+```
+
+### 鏌ヨ鏈�鏂颁氦鏄撹褰�
+```bash
+curl --location --request GET 'http://localhost:8080/api/pay/orders/{orderId}/transactions/latest'
+```
+
+绀轰緥锛�
+```bash
+curl --location --request GET 'http://localhost:8080/api/pay/orders/1234567890123456789/transactions/latest'
+```
+
+## 绗笁鏂规帴鍙g洿鎺ユ祴璇�
+
+濡傛灉闇�瑕佸崟鐙祴璇曠涓夋柟鎺ュ彛鏄惁鍙敤锛�
+
+```bash
+curl --location --request POST 'https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php' \
+--header 'Cookie: CAMEName=' \
+--form 'notify_url="https://dsp.966120.com.cn/alipay/pay_notify"' \
+--form 'out_trade_no="T202511240001"' \
+--form 'total_fee="10000"' \
+--form 'ServiceOrdID="BF20250012-1"'
+```
+
+## 鏃ュ織鏌ョ湅
+
+鏌ョ湅鏈嶅姟鏃ュ織锛屽叧娉ㄤ互涓嬪叧閿棩蹇楋細
+
+```
+# 鎺ュ彛璋冪敤
+鍙戣捣鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛夛紝璇锋眰鍙傛暟: {...}
+
+# 绗笁鏂规帴鍙h皟鐢�
+璋冪敤绗笁鏂规敮浠樺疂褰撻潰浠樻帴鍙o紝璁㈠崟鍙�: xxx, 閲戦: xxx鍒�, 涓氬姟璁㈠崟ID: xxx
+鍙戦�佽姹傚埌绗笁鏂规帴鍙�: https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php
+
+# 绗笁鏂规帴鍙e搷搴�
+绗笁鏂规帴鍙e搷搴旓紝鐘舵�佺爜: 200, 鍝嶅簲鍐呭: xxx
+绗笁鏂规敮浠樺疂褰撻潰浠楿RL鐢熸垚鎴愬姛: xxx
+
+# 璁㈠崟鍒涘缓鎴愬姛
+鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛夊垱寤烘垚鍔燂紝璁㈠崟ID: xxx, 浜ゆ槗ID: xxx
+```
+
+## 甯歌闂鎺掓煡
+
+### 1. 绗笁鏂规帴鍙h皟鐢ㄥけ璐�
+- 妫�鏌ョ綉缁滆繛鎺�
+- 楠岃瘉绗笁鏂规帴鍙f槸鍚﹀彲璁块棶
+- 妫�鏌ヨ姹傚弬鏁版牸寮忔槸鍚︽纭�
+
+### 2. 鏈繑鍥炴湁鏁堢殑鏀粯URL
+- 妫�鏌ョ涓夋柟鎺ュ彛杩斿洖鍐呭
+- 璋冩暣 `parseQrCodeUrl()` 鏂规硶浠ラ�傞厤瀹為檯杩斿洖鏍煎紡
+
+### 3. 浜岀淮鐮佺敓鎴愬け璐�
+- 妫�鏌ユ敮浠楿RL鏍煎紡鏄惁姝g‘
+- 楠岃瘉ZXing搴撴槸鍚︽甯稿伐浣�
+
+## 鏁版嵁搴撻獙璇�
+
+### 鏌ヨ璁㈠崟琛�
+```sql
+SELECT * FROM pay_order 
+WHERE biz_order_id = 'BF20250012-1' 
+ORDER BY created_at DESC;
+```
+
+### 鏌ヨ浜ゆ槗琛�
+```sql
+SELECT * FROM pay_transaction 
+WHERE order_id = '璁㈠崟ID' 
+ORDER BY created_at DESC;
+```
+
+## 鎬ц兘娴嬭瘯
+
+### 骞跺彂娴嬭瘯锛堜娇鐢ˋpache Bench锛�
+```bash
+# 100涓姹傦紝10涓苟鍙�
+ab -n 100 -c 10 -p payload.json -T application/json \
+http://localhost:8080/api/pay/alipay/thirdparty/precreate
+```
+
+payload.json:
+```json
+{
+  "bizOrderId": "PERF_TEST_${RANDOM}",
+  "amount": 100,
+  "subject": "鎬ц兘娴嬭瘯",
+  "callbackUrl": "https://dsp.966120.com.cn/alipay/pay_notify"
+}
+```
+
+## 鍓嶇闆嗘垚绀轰緥
+
+### HTML + JavaScript
+```html
+<!DOCTYPE html>
+<html>
+<head>
+    <title>鏀粯瀹濇敮浠樻祴璇�</title>
+</head>
+<body>
+    <h1>鏀粯瀹濇敮浠樻祴璇�</h1>
+    <button onclick="createPayment()">鍙戣捣鏀粯</button>
+    <div id="qrcode" style="margin-top: 20px;"></div>
+    
+    <script>
+        async function createPayment() {
+            try {
+                const response = await fetch('http://localhost:8080/api/pay/alipay/thirdparty/precreate', {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json'
+                    },
+                    body: JSON.stringify({
+                        bizOrderId: 'WEB_TEST_' + Date.now(),
+                        amount: 100,
+                        subject: '娴嬭瘯鏀粯',
+                        description: '缃戦〉娴嬭瘯',
+                        callbackUrl: 'https://dsp.966120.com.cn/alipay/pay_notify'
+                    })
+                });
+                
+                const result = await response.json();
+                
+                if (result.code === 200) {
+                    // 鏄剧ず浜岀淮鐮�
+                    const qrcodeDiv = document.getElementById('qrcode');
+                    qrcodeDiv.innerHTML = `
+                        <p>璁㈠崟ID: ${result.data.orderId}</p>
+                        <p>浜ゆ槗ID: ${result.data.transactionId}</p>
+                        <p>杩囨湡鏃堕棿: ${result.data.expireAt}</p>
+                        <img src="${result.data.qrBase64}" alt="鏀粯浜岀淮鐮�" />
+                    `;
+                } else {
+                    alert('鏀粯鍒涘缓澶辫触: ' + result.msg);
+                }
+            } catch (error) {
+                alert('璇锋眰澶辫触: ' + error.message);
+            }
+        }
+    </script>
+</body>
+</html>
+```
+
+## 鐜閰嶇疆妫�鏌ユ竻鍗�
+
+- [ ] 鏀粯妯″潡鏈嶅姟宸插惎鍔�
+- [ ] 鏁版嵁搴撹繛鎺ユ甯�
+- [ ] 绗笁鏂规帴鍙e彲璁块棶
+- [ ] 鍥炶皟鍦板潃宸查厤缃�
+- [ ] 鏃ュ織绾у埆璁剧疆涓篋EBUG锛堝紑鍙戠幆澧冿級
+- [ ] 缃戠粶闃茬伀澧欏厑璁歌闂涓夋柟鎺ュ彛
+
+## 涓嬩竴姝�
+
+娴嬭瘯閫氳繃鍚庯紝鍙互杩涜浠ヤ笅宸ヤ綔锛�
+1. 闆嗘垚鍒颁富搴旂敤涓�
+2. 瀹屽杽閿欒澶勭悊
+3. 娣诲姞鐩戞帶鍜屽憡璀�
+4. 鎬ц兘浼樺寲
+5. 瀹夊叏鍔犲浐
diff --git "a/dryad-payment/doc/\350\256\276\350\256\241\346\226\271\346\241\210.md" "b/dryad-payment/doc/\350\256\276\350\256\241\346\226\271\346\241\210.md"
new file mode 100644
index 0000000..1fd77dc
--- /dev/null
+++ "b/dryad-payment/doc/\350\256\276\350\256\241\346\226\271\346\241\210.md"
@@ -0,0 +1,1067 @@
+# 鏀粯妯″潡璁捐鏂规锛圖DD鏋舵瀯锛�
+
+## 涓�銆佹暣浣撴灦鏋勪笌鎶�鏈爤
+
+### 鎶�鏈爤
+- **Java**: 1.8
+- **妗嗘灦**: Spring Boot 2.5.15 + ruoyi-framework
+- **鎸佷箙鍖�**: MyBatis / MyBatis-Plus
+- **鏋舵瀯妯″紡**: DDD锛堥鍩熼┍鍔ㄨ璁★級
+- **鏀粯娓犻亾**: 寰俊鏀粯v2銆佹敮浠樺疂褰撻潰浠�
+
+### 鏈嶅姟瀹氫綅
+- 鐙珛鏈嶅姟锛屽彲鍗曠嫭杩愯
+- 鍗曞晢鎴锋ā寮�
+- 閰嶇疆缁熶竴鍦� `application.yml` 绠$悊
+
+---
+
+## 浜屻�丏DD鍒嗗眰涓庡寘缁撴瀯
+
+### 鍒嗗眰鏄犲皠鑷� RuoYi 缁撴瀯
+
+#### 1. Interfaces 灞傦紙鎺ュ彛灞傦級
+**鍖呰矾寰�**: `com.ruoyi.payment.interfaces.controller`
+
+**鑱岃矗**:
+- 瀵瑰 REST API锛堝彂璧锋敮浠樸�佹煡璇㈣鍗曪級
+- 娓犻亾寮傛鍥炶皟 Webhook锛堝井淇�/鏀粯瀹濓級
+- 绠$悊绔搷浣滄帴鍙o紙鍏抽棴銆侀噸鍙戝洖璋冦�佸璐︽煡璇級
+
+#### 2. Application 灞傦紙搴旂敤灞傦級
+**鍖呰矾寰�**: `com.ruoyi.payment.application.service`
+
+**鑱岃矗**:
+- 鐢ㄤ緥缂栨帓锛堝彂璧锋敮浠樸�佸鐞嗘笭閬撳洖璋冦�佽Е鍙戜笟鍔″洖璋冿級
+- 浜嬪姟鎺у埗涓庤法鑱氬悎鍗忚皟
+- 瀹氭椂浠诲姟锛堟瘡鏃ュ璐︺�佽鍗曡繃鏈熷鐞嗭級
+
+#### 3. Domain 灞傦紙棰嗗煙灞傦級
+**鍖呰矾寰�**:
+- `com.ruoyi.payment.domain.model` - 鑱氬悎鏍广�佸疄浣撱�佸�煎璞�
+- `com.ruoyi.payment.domain.service` - 棰嗗煙鏈嶅姟
+- `com.ruoyi.payment.domain.repository` - 浠撳偍鎺ュ彛
+
+**鑱岃矗**:
+- 鏍稿績涓氬姟瑙勫垯涓庣姸鎬佹満
+- 鑱氬悎鏍瑰皝瑁呬笌涓嶅彉鎬х害鏉�
+- 棰嗗煙浜嬩欢瀹氫箟
+
+#### 4. Infrastructure 灞傦紙鍩虹璁炬柦灞傦級
+**鍖呰矾寰�**:
+- `com.ruoyi.payment.infrastructure.persistence` - Mapper 瀹炵幇
+- `com.ruoyi.payment.infrastructure.channel.wechat` - 寰俊瀹㈡埛绔�
+- `com.ruoyi.payment.infrastructure.channel.alipay` - 鏀粯瀹濆鎴风
+- `com.ruoyi.payment.infrastructure.config` - 閰嶇疆鍔犺浇
+- `com.ruoyi.payment.infrastructure.schedule` - 瀹氭椂璋冨害
+- `com.ruoyi.payment.infrastructure.audit` - 鎿嶄綔瀹¤
+
+**鑱岃矗**:
+- 浠撳偍鎺ュ彛瀹炵幇锛堟暟鎹簱璁块棶锛�
+- 娓犻亾瀹㈡埛绔皝瑁呬笌閫傞厤
+- 璇佷功涓庡瘑閽ョ鐞�
+- 瀹氭椂浠诲姟涓庢秷鎭彂甯�
+
+---
+
+## 涓夈�佹牳蹇冮鍩熸ā鍨�
+
+### 1. PaymentOrder锛堟敮浠樿鍗� - 鑱氬悎鏍癸級
+
+**瀛楁**:
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| id | Long | 鍐呴儴璁㈠崟ID锛堜富閿紝闆姳ID锛� |
+| bizOrderId | String | 澶栭儴涓氬姟璁㈠崟鍙� |
+| amount | Integer | 閲戦锛堝崟浣嶏細鍒嗭級 |
+| currency | String | 甯佺锛堝浐瀹� CNY锛� |
+| channel | Enum | 鏀粯娓犻亾锛圵ECHAT/ALIPAY锛� |
+| status | Enum | 璁㈠崟鐘舵�� |
+| subject | String | 璁㈠崟鏍囬 |
+| description | String | 璁㈠崟鎻忚堪 |
+| callbackUrl | String | 涓氬姟鍥炶皟鍦板潃 |
+| expireAt | DateTime | 杩囨湡鏃堕棿锛堝垱寤哄悗+2灏忔椂锛� |
+| latestTransactionId | Long | 鏈�鏂颁氦鏄揑D |
+| channelTradeNo | String | 娓犻亾浜ゆ槗鍙凤紙鏀粯鎴愬姛鍚庯級 |
+| paidAt | DateTime | 鏀粯鎴愬姛鏃堕棿 |
+| version | Integer | 涔愯閿佺増鏈彿 |
+| createdAt | DateTime | 鍒涘缓鏃堕棿 |
+| updatedAt | DateTime | 鏇存柊鏃堕棿 |
+
+**璁㈠崟鐘舵�佹灇涓�** (`status`):
+- `INIT`: 鍒濆鍖�
+- `PENDING`: 寰呮敮浠�
+- `SUCCEEDED`: 鏀粯鎴愬姛
+- `FAILED`: 鏀粯澶辫触
+- `CANCELED`: 宸插叧闂�
+- `EXPIRED`: 宸茶繃鏈�
+
+**涓氬姟瑙勫垯**:
+1. 閲戦蹇呴』 > 0
+2. 甯佺鍥哄畾涓� CNY
+3. 鍚屼竴璁㈠崟鍚屾椂鍙厑璁稿瓨鍦�**涓�绗旇繘琛屼腑鐨勪氦鏄�**锛圥ENDING锛�
+4. 璁㈠崟瓒呰繃2灏忔椂鏈敮浠樿嚜鍔ㄦ爣璁颁负 EXPIRED
+5. 璁㈠崟鎴愬姛鍚庤Е鍙戝閮ㄤ笟鍔″洖璋�
+
+### 2. PaymentTransaction锛堟敮浠樹氦鏄撴祦姘� - 瀹炰綋锛�
+
+**瀛楁**:
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| id | Long | 浜ゆ槗ID锛堜富閿級 |
+| orderId | Long | 鎵�灞炶鍗旾D |
+| channel | Enum | 鏀粯娓犻亾 |
+| clientType | Enum | 瀹㈡埛绔被鍨嬶紙NATIVE/ALIPAY_PRECREATE锛� |
+| status | Enum | 浜ゆ槗鐘舵�� |
+| codeOrQr | String | 娓犻亾杩斿洖鐨勪簩缁寸爜鍐呭锛坈ode_url/qr_code锛� |
+| qrBase64 | Text | 鏈嶅姟绔敓鎴愮殑Base64浜岀淮鐮佸浘鐗� |
+| requestParams | Text | 娓犻亾璇锋眰鍙傛暟蹇収 |
+| responseSnapshot | Text | 娓犻亾鍝嶅簲蹇収 |
+| channelTradeNo | String | 娓犻亾浜ゆ槗鍙� |
+| createdAt | DateTime | 鍒涘缓鏃堕棿 |
+| paidAt | DateTime | 鏀粯瀹屾垚鏃堕棿 |
+
+**浜ゆ槗鐘舵�佹灇涓�** (`status`):
+- `PENDING`: 寰呮敮浠�
+- `SUCCEEDED`: 鏀粯鎴愬姛
+- `FAILED`: 鏀粯澶辫触
+- `CANCELED`: 宸插彇娑�
+
+**涓氬姟瑙勫垯**:
+1. 姣忔鍙戣捣鏀粯鏃讹紝鑻ヨ鍗曞凡鏈� PENDING 浜ゆ槗锛屽垯澶嶇敤璇ヤ氦鏄撳苟杩斿洖鍏朵簩缁寸爜
+2. 鑻ユ棤 PENDING 浜ゆ槗锛屽垯鍒涘缓鏂颁氦鏄�
+3. 涓�鏃︿氦鏄撴垚鍔燂紝璁㈠崟鐘舵�佸悓姝ヤ负 SUCCEEDED
+
+### 3. NotifyLog锛堟笭閬撳洖璋冩棩蹇� - 瀹炰綋锛�
+
+**瀛楁**:
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| id | Long | 鏃ュ織ID |
+| channel | Enum | 鏀粯娓犻亾 |
+| notifyIdOrSerial | String | 娓犻亾閫氱煡鍞竴鏍囪瘑 |
+| orderId | Long | 璁㈠崟ID |
+| transactionId | Long | 浜ゆ槗ID |
+| payload | Text | 鍥炶皟鍘熷鎶ユ枃 |
+| verified | Boolean | 绛惧悕楠岃瘉鏄惁閫氳繃 |
+| processed | Boolean | 鏄惁宸插鐞� |
+| result | String | 澶勭悊缁撴灉 |
+| createdAt | DateTime | 鎺ユ敹鏃堕棿 |
+
+**骞傜瓑鎺у埗**:
+- 鍞竴绱㈠紩锛歚channel + notifyIdOrSerial`
+- 閲嶅閫氱煡鐩存帴杩斿洖鎴愬姛搴旂瓟
+
+### 4. BizCallbackLog锛堜笟鍔″洖璋冩棩蹇� - 瀹炰綋锛�
+
+**瀛楁**:
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| id | Long | 鏃ュ織ID |
+| orderId | Long | 璁㈠崟ID |
+| transactionId | Long | 浜ゆ槗ID |
+| callbackUrl | String | 鍥炶皟鍦板潃 |
+| payload | Text | 鍥炶皟璇锋眰浣� |
+| httpStatus | Integer | HTTP 鐘舵�佺爜 |
+| response | Text | 鍝嶅簲鍐呭 |
+| success | Boolean | 鏄惁鎴愬姛 |
+| retryCount | Integer | 閲嶈瘯娆℃暟 |
+| lastRetryAt | DateTime | 鏈�鍚庨噸璇曟椂闂� |
+| createdAt | DateTime | 鍒涘缓鏃堕棿 |
+
+**閲嶈瘯绛栫暐**:
+- 闂撮殧锛�0/1/5/15/60 鍒嗛挓
+- 鏈�澶氶噸璇曪細10娆�
+- 鏀寔绠$悊绔墜宸ラ噸鍙�
+
+### 5. OperationAudit锛堟搷浣滃璁� - 瀹炰綋锛�
+
+**瀛楁**:
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| id | Long | 瀹¤ID |
+| operator | String | 鎿嶄綔浜� |
+| operationType | Enum | 鎿嶄綔绫诲瀷 |
+| orderId | Long | 璁㈠崟ID锛堝彲閫夛級 |
+| transactionId | Long | 浜ゆ槗ID锛堝彲閫夛級 |
+| params | Text | 鎿嶄綔鍙傛暟 |
+| approved | Boolean | 鏄惁閫氳繃锛堣褰曪紝涓嶈蛋瀹℃壒娴佺▼锛� |
+| createdAt | DateTime | 鎿嶄綔鏃堕棿 |
+
+**鎿嶄綔绫诲瀷**:
+- `CLOSE_ORDER`: 鍏抽棴璁㈠崟
+- `RESEND_CALLBACK`: 閲嶅彂涓氬姟鍥炶皟
+- `MANUAL_FIX`: 鎵嬪伐淇瀵硅处宸紓
+- `UPDATE_CHANNEL_ACCOUNT`: 鏇存柊娓犻亾璐﹀彿
+
+### 6. 鍊煎璞�
+
+- **Money**: `{ amountInCents, currency }`
+- **BizOrderId**: 澶栭儴涓氬姟璁㈠崟鍙峰皝瑁�
+- **CallbackUrl**: 涓氬姟鍥炶皟鍦板潃灏佽
+- **ChannelTradeNo**: 娓犻亾浜ゆ槗鍙峰皝瑁�
+
+---
+
+## 鍥涖�佹牳蹇冪敤渚嬩笌娴佺▼
+
+### 1. 鍙戣捣浜岀淮鐮佹敮浠�
+
+**鍏ュ弬**:
+- `bizOrderId`: 澶栭儴涓氬姟璁㈠崟鍙�
+- `amount`: 閲戦锛堝垎锛�
+- `subject`: 璁㈠崟鏍囬
+- `description`: 璁㈠崟鎻忚堪
+- `channel`: 鏀粯娓犻亾锛圵ECHAT/ALIPAY锛�
+- `callbackUrl`: 涓氬姟鍥炶皟鍦板潃
+
+**娴佺▼**:
+```
+1. 鏌ヨ璁㈠崟鏄惁瀛樺湪
+   - 涓嶅瓨鍦� 鈫� 鍒涘缓璁㈠崟锛堢姸鎬� PENDING锛宔xpireAt = now + 2灏忔椂锛�
+   - 瀛樺湪 鈫� 鍔犺浇璁㈠崟
+
+2. 妫�鏌ヨ鍗曟槸鍚︽湁杩涜涓殑浜ゆ槗锛圥ENDING锛�
+   - 鏈� 鈫� 鐩存帴杩斿洖宸叉湁浜ゆ槗鐨勪簩缁寸爜 Base64
+   - 鏃� 鈫� 鍒涘缓鏂颁氦鏄�
+
+3. 璋冪敤娓犻亾涓嬪崟鎺ュ彛
+   銆愬井淇°��
+   - 鎺ュ彛锛歷2 unifiedorder
+   - trade_type: native
+   - 绛惧悕鏂瑰紡锛歁D5
+   - notify_url: https://api.966120.com/api/pay/notify/wechat
+   - 杩斿洖锛歝ode_url
+   
+   銆愭敮浠樺疂銆�
+   - 鎺ュ彛锛歛lipay.trade.precreate
+   - notify_url: https://api.966120.com/api/pay/notify/alipay
+   - 杩斿洖锛歲r_code
+
+4. 鐢熸垚浜岀淮鐮�
+   - 灏� code_url/qr_code 鐢熸垚 300脳300 PNG 浜岀淮鐮�
+   - 缂栫爜涓� Base64 瀛楃涓�
+   - 淇濆瓨鍒颁氦鏄撹褰曪紙qrBase64锛�
+
+5. 杩斿洖缁欏墠绔�
+   {
+     "orderId": xxx,
+     "transactionId": xxx,
+     "status": "PENDING",
+     "qrBase64": "data:image/png;base64,iVBORw0KG...",
+     "expireAt": "2025-11-23T12:00:00"
+   }
+```
+
+**骞傜瓑鎺у埗**:
+- 鍚屼竴璁㈠崟浠呭厑璁镐竴绗� PENDING 浜ゆ槗瀛樺湪
+- 閲嶅璇锋眰鐩存帴杩斿洖宸叉湁浜ゆ槗鏁版嵁
+
+### 2. 娓犻亾鍥炶皟澶勭悊锛圵ebhook锛�
+
+**寰俊v2鍥炶皟**:
+```
+1. 鎺ユ敹 XML 鎶ユ枃
+2. 楠岃瘉绛惧悕锛圡D5锛�
+3. 瑙f瀽鎶ユ枃锛屾彁鍙栦氦鏄撳彿涓庢敮浠樼粨鏋�
+4. 鏌ヨ璁㈠崟涓庝氦鏄�
+5. 鐘舵�佽浆鎹�
+   - 鎴愬姛 鈫� 浜ゆ槗鐘舵�� SUCCEEDED锛岃鍗曠姸鎬� SUCCEEDED
+   - 澶辫触 鈫� 浜ゆ槗鐘舵�� FAILED
+6. 鎸佷箙鍖栨洿鏂帮紙涔愯閿侊級
+7. 璁板綍 NotifyLog锛堝箓绛夋帶鍒讹級
+8. 瑙﹀彂澶栭儴涓氬姟鍥炶皟
+9. 杩斿洖寰俊瑕佹眰鐨� XML 搴旂瓟
+```
+
+**鏀粯瀹濆洖璋�**:
+```
+1. 鎺ユ敹琛ㄥ崟鍙傛暟
+2. 楠岃瘉绛惧悕锛圧SA2锛�
+3. 瑙f瀽浜ゆ槗鐘舵��
+4. 鍚屾璁㈠崟涓庝氦鏄撶姸鎬�
+5. 璁板綍 NotifyLog
+6. 瑙﹀彂澶栭儴涓氬姟鍥炶皟
+7. 杩斿洖 "success"
+```
+
+**骞傜瓑淇濋殰**:
+- 鍩轰簬 `channel + notifyIdOrSerial` 鍞竴绱㈠紩
+- 閲嶅閫氱煡鐩存帴杩斿洖鎴愬姛搴旂瓟锛屼笉閲嶅澶勭悊
+
+### 3. 澶栭儴涓氬姟鍥炶皟
+
+**瑙﹀彂鏃舵満**: 璁㈠崟鐘舵�佸彉鏇翠负 SUCCEEDED 鍚�
+
+**鍗忚**: HTTP POST JSON
+
+**璇锋眰澶�**:
+- `Content-Type: application/json`
+- `X-Signature`: HMAC-SHA256(payload + nonce + timestamp, callbackSignSecret)
+- `X-Nonce`: 闅忔満瀛楃涓�
+- `X-Timestamp`: 姣鏃堕棿鎴�
+
+**璇锋眰浣�**:
+```json
+{
+  "tradeId": 1234567890,
+  "orderId": 9876543210,
+  "bizOrderId": "BIZ20251123001",
+  "channel": "WECHAT",
+  "amount": 10000,
+  "currency": "CNY",
+  "status": "SUCCEEDED",
+  "channelTradeNo": "4200001234567890",
+  "paidAt": "2025-11-23T10:30:00",
+  "subject": "鍟嗗搧璁㈠崟鏀粯",
+  "description": "璁㈠崟璇︽儏"
+}
+```
+
+**閴存潈鏂瑰紡**:
+- 浣跨敤 HMAC-SHA256 绛惧悕
+- 瀵嗛挜锛氶厤缃枃浠朵腑鐨� `callbackSignSecret`
+- 绛惧悕鍐呭锛歚payload + nonce + timestamp`
+- 澶栭儴绯荤粺浣跨敤鐩稿悓瀵嗛挜楠岃瘉绛惧悕
+
+**閲嶈瘯绛栫暐**:
+- 澶辫触閲嶈瘯闂撮殧锛�0/1/5/15/60 鍒嗛挓
+- 鏈�澶氶噸璇曪細10娆�
+- 鏀寔绠$悊绔墜宸ラ噸鍙�
+
+### 4. 璁㈠崟杩囨湡澶勭悊
+
+**瑙﹀彂鏂瑰紡**: 瀹氭椂浠诲姟锛堝缓璁瘡10鍒嗛挓锛�
+
+**閫昏緫**:
+```
+1. 鏌ヨ鐘舵�佷负 PENDING 涓� expireAt < now 鐨勮鍗�
+2. 灏嗚鍗曠姸鎬佹洿鏂颁负 EXPIRED
+3. 璁板綍鎿嶄綔鏃ュ織
+```
+
+**杩囨湡鏃堕棿**:
+- 浠庤鍗曢娆″垱寤烘椂闂磋捣绠� +2灏忔椂
+- 鍙戣捣鏂颁氦鏄撲笉鍒锋柊杩囨湡鏃堕棿
+
+### 5. 姣忔棩瀵硅处锛堣嚜鍔ㄤ慨澶嶏級
+
+**璋冨害鏃堕棿**: 姣忓ぉ 02:00
+
+**娴佺▼**:
+```
+1. 纭畾瀵硅处鏃ユ湡锛圱-1锛�
+2. 鏌ヨ鏈湴璇ユ棩鎵�鏈夎鍗曚笌浜ゆ槗
+3. 璋冪敤娓犻亾鏌ヨ鎺ュ彛锛堟壒閲�/鍗曠瑪锛�
+   - 寰俊锛歰rderquery
+   - 鏀粯瀹濓細alipay.trade.query
+4. 瀵规瘮鏈湴鐘舵�佷笌娓犻亾鐘舵��
+5. 鑷姩淇
+   - 鏈湴 PENDING锛屾笭閬撳凡鎴愬姛 鈫� 淇涓� SUCCEEDED
+   - 鏈湴 PENDING锛屾笭閬撳凡鍏抽棴 鈫� 淇涓� FAILED
+6. 宸紓璁板綍
+   - 閲戦涓嶄竴鑷�
+   - 娓犻亾鏃犺褰曚絾鏈湴瀛樺湪
+   - 鍏朵粬寮傚父鎯呭喌
+7. 鐢熸垚瀵硅处鎶ュ憡
+   - 鎬昏鍗曟暟
+   - 鎴愬姛鏁�
+   - 澶辫触鏁�
+   - 宸紓鏁�
+   - 鑷姩淇鏁�
+8. 淇濆瓨瀵硅处浠诲姟涓庣粨鏋滄槑缁�
+```
+
+**宸紓澶勭悊**:
+- 鐘舵�佸樊寮傦細鑷姩淇骞惰褰�
+- 閲戦宸紓锛氫粎璁板綍锛屼笉鑷姩淇锛岄渶浜哄伐浠嬪叆
+- 涓ラ噸宸紓锛氬憡璀﹂�氱煡
+
+---
+
+## 浜斻�佹笭閬撻�傞厤涓庡鎴风灏佽
+
+### 1. 寰俊鏀粯 v2锛圢ative锛�
+
+**閰嶇疆椤�** (`application.yml`):
+```yaml
+payment:
+  wechat:
+    appId: wx70f6a7346ee842xx
+    mchId: 1573728xxx
+    mchKey: Xz0ClPK3f5sCeT6SGa1vpVmyUFcbpxxx
+    notifyUrl: https://api.966120.com/api/pay/notify/wechat
+    signType: MD5
+```
+
+**鎺ュ彛灏佽** (`WxPayV2Client`):
+- `createNativeOrder()`: 缁熶竴涓嬪崟锛岃繑鍥� code_url
+- `queryOrder()`: 鏌ヨ璁㈠崟鐘舵��
+- `closeOrder()`: 鍏抽棴璁㈠崟
+- `verifyNotify()`: 楠岃瘉鍥炶皟绛惧悕
+- `buildNotifyResponse()`: 鏋勯�犲簲绛旀姤鏂�
+
+**绛惧悕鏂瑰紡**: MD5
+
+**鍏抽敭娴佺▼**:
+1. 鍙傛暟鎸� ASCII 鎺掑簭鎷兼帴
+2. 杩藉姞 `&key=mchKey`
+3. MD5 鍔犲瘑骞惰浆澶у啓
+
+### 2. 鏀粯瀹濆綋闈粯锛圥recreate锛�
+
+**閰嶇疆椤�** (`application.yml`):
+```yaml
+payment:
+  alipay:
+    appId: 2021xxxxxxxxxxxxx
+    privateKey: MIIEvQIBADANBgkqhki...锛堝晢鎴稲SA2绉侀挜锛�
+    alipayPublicKey: MIIBIjANBgkqhki...锛堟敮浠樺疂RSA2鍏挜锛�
+    serverUrl: https://openapi.alipay.com/gateway.do
+    notifyUrl: https://api.966120.com/api/pay/notify/alipay
+    signType: RSA2
+```
+
+**鎺ュ彛灏佽** (`AlipayF2FClient`):
+- `precreate()`: 褰撻潰浠樹笅鍗曪紝杩斿洖 qr_code
+- `query()`: 鏌ヨ璁㈠崟鐘舵��
+- `close()`: 鍏抽棴璁㈠崟
+- `verifyNotify()`: 楠岃瘉鍥炶皟绛惧悕
+
+**绛惧悕鏂瑰紡**: RSA2
+
+**SDK**: 浣跨敤瀹樻柟 `alipay-sdk-java`
+
+### 3. 娓犻亾瀹㈡埛绔粺涓�鎺ュ彛
+
+```java
+public interface ChannelClient {
+    /**
+     * 鍒涘缓浜岀淮鐮佽鍗�
+     */
+    QrOrderResponse createQrOrder(QrOrderRequest request);
+    
+    /**
+     * 鏌ヨ璁㈠崟鐘舵��
+     */
+    OrderQueryResponse queryOrder(String channelTradeNo);
+    
+    /**
+     * 鍏抽棴璁㈠崟
+     */
+    void closeOrder(String channelTradeNo);
+    
+    /**
+     * 楠岃瘉鍥炶皟绛惧悕
+     */
+    boolean verifyNotify(Map<String, String> params);
+}
+```
+
+**宸ュ巶妯″紡閫夋嫨瀹炵幇**:
+- `WxPayV2Client implements ChannelClient`
+- `AlipayF2FClient implements ChannelClient`
+
+---
+
+## 鍏�佷簩缁寸爜鐢熸垚瑙勮寖
+
+**鎶�鏈柟妗�**: 浣跨敤 ZXing 搴�
+
+**鍙傛暟**:
+- 灏哄锛�300 脳 300
+- 鏍煎紡锛歅NG
+- 绾犻敊绛夌骇锛歁锛堥粯璁わ級
+- 缂栫爜锛歎TF-8
+
+**杈撳嚭鏍煎紡**:
+```
+data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
+```
+
+**瀹炵幇**:
+```java
+// 浼唬鐮�
+BufferedImage qrImage = QRCodeGenerator.generate(codeUrl, 300, 300);
+ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ImageIO.write(qrImage, "PNG", baos);
+String base64 = "data:image/png;base64," + Base64.getEncoder().encodeToString(baos.toByteArray());
+```
+
+---
+
+## 涓冦�佹暟鎹〃璁捐
+
+### 1. pay_order锛堟敮浠樿鍗曡〃锛�
+
+```sql
+CREATE TABLE `pay_order` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '璁㈠崟ID',
+  `biz_order_id` VARCHAR(64) NOT NULL COMMENT '涓氬姟璁㈠崟鍙�',
+  `amount` INT NOT NULL COMMENT '閲戦锛堝垎锛�',
+  `currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '甯佺',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `status` VARCHAR(16) NOT NULL COMMENT '璁㈠崟鐘舵��',
+  `subject` VARCHAR(128) NOT NULL COMMENT '璁㈠崟鏍囬',
+  `description` VARCHAR(512) COMMENT '璁㈠崟鎻忚堪',
+  `callback_url` VARCHAR(512) NOT NULL COMMENT '涓氬姟鍥炶皟鍦板潃',
+  `expire_at` DATETIME NOT NULL COMMENT '杩囨湡鏃堕棿',
+  `latest_transaction_id` BIGINT COMMENT '鏈�鏂颁氦鏄揑D',
+  `channel_trade_no` VARCHAR(64) COMMENT '娓犻亾浜ゆ槗鍙�',
+  `paid_at` DATETIME COMMENT '鏀粯鎴愬姛鏃堕棿',
+  `version` INT NOT NULL DEFAULT 0 COMMENT '涔愯閿佺増鏈彿',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+  INDEX `idx_biz_order_id` (`biz_order_id`),
+  INDEX `idx_channel_trade_no` (`channel_trade_no`),
+  INDEX `idx_status` (`status`),
+  INDEX `idx_expire_at` (`expire_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鏀粯璁㈠崟琛�';
+```
+
+### 2. pay_transaction锛堟敮浠樹氦鏄撴祦姘磋〃锛�
+
+```sql
+CREATE TABLE `pay_transaction` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '浜ゆ槗ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `client_type` VARCHAR(32) NOT NULL COMMENT '瀹㈡埛绔被鍨�',
+  `status` VARCHAR(16) NOT NULL COMMENT '浜ゆ槗鐘舵��',
+  `code_or_qr` VARCHAR(512) COMMENT '浜岀淮鐮佸唴瀹�',
+  `qr_base64` TEXT COMMENT 'Base64浜岀淮鐮佸浘鐗�',
+  `request_params` TEXT COMMENT '璇锋眰鍙傛暟蹇収',
+  `response_snapshot` TEXT COMMENT '鍝嶅簲蹇収',
+  `channel_trade_no` VARCHAR(64) COMMENT '娓犻亾浜ゆ槗鍙�',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  `paid_at` DATETIME COMMENT '鏀粯瀹屾垚鏃堕棿',
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_channel_trade_no` (`channel_trade_no`),
+  INDEX `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鏀粯浜ゆ槗娴佹按琛�';
+```
+
+### 3. notify_log锛堟笭閬撳洖璋冩棩蹇楄〃锛�
+
+```sql
+CREATE TABLE `notify_log` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏃ュ織ID',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `notify_id_or_serial` VARCHAR(64) NOT NULL COMMENT '娓犻亾閫氱煡鍞竴鏍囪瘑',
+  `order_id` BIGINT COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `payload` TEXT NOT NULL COMMENT '鍥炶皟鍘熷鎶ユ枃',
+  `verified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '绛惧悕楠岃瘉鏄惁閫氳繃',
+  `processed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁宸插鐞�',
+  `result` VARCHAR(128) COMMENT '澶勭悊缁撴灉',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鎺ユ敹鏃堕棿',
+  UNIQUE KEY `uk_channel_notify` (`channel`, `notify_id_or_serial`),
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_transaction_id` (`transaction_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='娓犻亾鍥炶皟鏃ュ織琛�';
+```
+
+### 4. biz_callback_log锛堜笟鍔″洖璋冩棩蹇楄〃锛�
+
+```sql
+CREATE TABLE `biz_callback_log` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏃ュ織ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT NOT NULL COMMENT '浜ゆ槗ID',
+  `callback_url` VARCHAR(512) NOT NULL COMMENT '鍥炶皟鍦板潃',
+  `payload` TEXT NOT NULL COMMENT '鍥炶皟璇锋眰浣�',
+  `http_status` INT COMMENT 'HTTP鐘舵�佺爜',
+  `response` TEXT COMMENT '鍝嶅簲鍐呭',
+  `success` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁鎴愬姛',
+  `retry_count` INT NOT NULL DEFAULT 0 COMMENT '閲嶈瘯娆℃暟',
+  `last_retry_at` DATETIME COMMENT '鏈�鍚庨噸璇曟椂闂�',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_success` (`success`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='涓氬姟鍥炶皟鏃ュ織琛�';
+```
+
+### 5. operation_audit锛堟搷浣滃璁¤〃锛�
+
+```sql
+CREATE TABLE `operation_audit` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '瀹¤ID',
+  `operator` VARCHAR(64) NOT NULL COMMENT '鎿嶄綔浜�',
+  `operation_type` VARCHAR(32) NOT NULL COMMENT '鎿嶄綔绫诲瀷',
+  `order_id` BIGINT COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `params` TEXT COMMENT '鎿嶄綔鍙傛暟',
+  `approved` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '鏄惁閫氳繃',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鎿嶄綔鏃堕棿',
+  INDEX `idx_operator` (`operator`),
+  INDEX `idx_operation_type` (`operation_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鎿嶄綔瀹¤琛�';
+```
+
+### 6. reconciliation_task锛堝璐︿换鍔¤〃锛�
+
+```sql
+CREATE TABLE `reconciliation_task` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '浠诲姟ID',
+  `task_date` DATE NOT NULL COMMENT '瀵硅处鏃ユ湡',
+  `status` VARCHAR(16) NOT NULL COMMENT '浠诲姟鐘舵��',
+  `total_count` INT NOT NULL DEFAULT 0 COMMENT '鎬昏鍗曟暟',
+  `success_count` INT NOT NULL DEFAULT 0 COMMENT '鎴愬姛鏁�',
+  `failed_count` INT NOT NULL DEFAULT 0 COMMENT '澶辫触鏁�',
+  `diff_count` INT NOT NULL DEFAULT 0 COMMENT '宸紓鏁�',
+  `fixed_count` INT NOT NULL DEFAULT 0 COMMENT '鑷姩淇鏁�',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  `finished_at` DATETIME COMMENT '瀹屾垚鏃堕棿',
+  UNIQUE KEY `uk_task_date` (`task_date`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀵硅处浠诲姟琛�';
+```
+
+### 7. reconciliation_result锛堝璐﹀樊寮傛槑缁嗚〃锛�
+
+```sql
+CREATE TABLE `reconciliation_result` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏄庣粏ID',
+  `task_id` BIGINT NOT NULL COMMENT '浠诲姟ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `local_status` VARCHAR(16) COMMENT '鏈湴鐘舵��',
+  `channel_status` VARCHAR(16) COMMENT '娓犻亾鐘舵��',
+  `diff_type` VARCHAR(32) NOT NULL COMMENT '宸紓绫诲瀷',
+  `fixed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁宸蹭慨澶�',
+  `note` VARCHAR(512) COMMENT '澶囨敞',
+  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  INDEX `idx_task_id` (`task_id`),
+  INDEX `idx_order_id` (`order_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀵硅处宸紓鏄庣粏琛�';
+```
+
+---
+
+## 鍏�丷ESTful API 鎺ュ彛娓呭崟
+
+### 1. 鍙戣捣寰俊 Native 鏀粯
+```
+POST /api/pay/wechat/native
+```
+**璇锋眰浣�**:
+```json
+{
+  "bizOrderId": "BIZ20251123001",
+  "amount": 10000,
+  "subject": "鍟嗗搧璁㈠崟鏀粯",
+  "description": "璐拱鍟嗗搧A",
+  "callbackUrl": "https://your-business.com/notify"
+}
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "success",
+  "data": {
+    "orderId": 1234567890,
+    "transactionId": 9876543210,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KG...",
+    "expireAt": "2025-11-23T12:00:00"
+  }
+}
+```
+
+### 2. 鍙戣捣鏀粯瀹濆綋闈粯
+```
+POST /api/pay/alipay/precreate
+```
+**璇锋眰浣�/鍝嶅簲**: 鍚屼笂
+
+### 3. 寰俊鍥炶皟閫氱煡
+```
+POST /api/pay/notify/wechat
+```
+**璇存槑**: 鎺ユ敹寰俊 XML 鎶ユ枃锛岄獙绛惧悗澶勭悊锛岃繑鍥� XML 搴旂瓟
+
+### 4. 鏀粯瀹濆洖璋冮�氱煡
+```
+POST /api/pay/notify/alipay
+```
+**璇存槑**: 鎺ユ敹琛ㄥ崟鍙傛暟锛岄獙绛惧悗澶勭悊锛岃繑鍥� "success"
+
+### 5. 鏌ヨ璁㈠崟
+```
+GET /api/pay/orders/{orderId}
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "success",
+  "data": {
+    "orderId": 1234567890,
+    "bizOrderId": "BIZ20251123001",
+    "amount": 10000,
+    "currency": "CNY",
+    "channel": "WECHAT",
+    "status": "SUCCEEDED",
+    "subject": "鍟嗗搧璁㈠崟鏀粯",
+    "channelTradeNo": "4200001234567890",
+    "paidAt": "2025-11-23T10:30:00",
+    "expireAt": "2025-11-23T12:00:00",
+    "createdAt": "2025-11-23T10:00:00"
+  }
+}
+```
+
+### 6. 鏌ヨ鏈�鏂颁氦鏄�
+```
+GET /api/pay/orders/{orderId}/transactions/latest
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "success",
+  "data": {
+    "transactionId": 9876543210,
+    "orderId": 1234567890,
+    "status": "PENDING",
+    "qrBase64": "data:image/png;base64,iVBORw0KG...",
+    "createdAt": "2025-11-23T10:00:00"
+  }
+}
+```
+
+### 7. 鍏抽棴璁㈠崟
+```
+POST /api/pay/orders/{orderId}/close
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "璁㈠崟宸插叧闂�"
+}
+```
+
+### 8. 閲嶅彂涓氬姟鍥炶皟
+```
+POST /api/pay/orders/{orderId}/callback/resend
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "鍥炶皟宸查噸鏂板彂閫�"
+}
+```
+
+### 9. 鏌ヨ瀵硅处浠诲姟鍒楄〃
+```
+GET /api/pay/reconciliation/tasks?date=2025-11-22
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "success",
+  "data": {
+    "taskId": 12345,
+    "taskDate": "2025-11-22",
+    "status": "FINISHED",
+    "totalCount": 1000,
+    "successCount": 980,
+    "failedCount": 15,
+    "diffCount": 5,
+    "fixedCount": 3,
+    "createdAt": "2025-11-23T02:00:00",
+    "finishedAt": "2025-11-23T02:15:00"
+  }
+}
+```
+
+### 10. 鏌ヨ瀵硅处宸紓鏄庣粏
+```
+GET /api/pay/reconciliation/results?taskId=12345
+```
+**鍝嶅簲**:
+```json
+{
+  "code": 200,
+  "msg": "success",
+  "data": [
+    {
+      "orderId": 1234567890,
+      "transactionId": 9876543210,
+      "localStatus": "PENDING",
+      "channelStatus": "SUCCEEDED",
+      "diffType": "STATUS_DIFF",
+      "fixed": true,
+      "note": "宸茶嚜鍔ㄤ慨澶�"
+    }
+  ]
+}
+```
+
+---
+
+## 涔濄�侀厤缃枃浠剁ず渚�
+
+**application.yml**:
+```yaml
+spring:
+  application:
+    name: dryad-payment
+
+# 鏀粯閰嶇疆
+payment:
+  # 寰俊鏀粯閰嶇疆
+  wechat:
+    appId: wx70f6a7346ee842xx
+    mchId: 1573728xxx
+    mchKey: Xz0ClPK3f5sCeT6SGa1vpVmyUFcbpxxx
+    notifyUrl: https://api.966120.com/api/pay/notify/wechat
+    signType: MD5
+  
+  # 鏀粯瀹濋厤缃�
+  alipay:
+    appId: 2021xxxxxxxxxxxxx
+    privateKey: MIIEvQIBADANBgkqhki...
+    alipayPublicKey: MIIBIjANBgkqhki...
+    serverUrl: https://openapi.alipay.com/gateway.do
+    notifyUrl: https://api.966120.com/api/pay/notify/alipay
+    signType: RSA2
+  
+  # 涓氬姟鍥炶皟閰嶇疆
+  business:
+    callbackSignSecret: your-hmac-secret-key-here
+    callbackRetryMaxCount: 10
+    callbackRetryIntervals: 0,1,5,15,60  # 鍒嗛挓
+  
+  # 浜岀淮鐮侀厤缃�
+  qrcode:
+    size: 300
+    format: PNG
+  
+  # 瀵硅处閰嶇疆
+  reconciliation:
+    enabled: true
+    cron: "0 0 2 * * ?"  # 姣忓ぉ鍑屾櫒2鐐�
+```
+
+---
+
+## 鍗併�佺鐞嗙椤甸潰鍔熻兘娓呭崟
+
+### 1. 鏀粯璁㈠崟绠$悊
+**璺緞**: `/payment/orders`
+
+**鍔熻兘**:
+- 鍒楄〃灞曠ず锛堟敮鎸佸垎椤碉級
+- 鏉′欢妫�绱細涓氬姟璁㈠崟鍙枫�佹笭閬撱�佺姸鎬併�佹椂闂磋寖鍥�
+- 璇︽儏鏌ョ湅锛氳鍗曚俊鎭�佷氦鏄撹褰曘�佸洖璋冩棩蹇�
+- 鎿嶄綔锛氭墜宸ュ叧闂鍗�
+
+### 2. 浜ゆ槗娴佹按绠$悊
+**璺緞**: `/payment/transactions`
+
+**鍔熻兘**:
+- 鍒楄〃灞曠ず锛堟敮鎸佸垎椤碉級
+- 鏌ョ湅浜岀淮鐮侊紙Base64鍥剧墖锛�
+- 鏌ョ湅娓犻亾璇锋眰/鍝嶅簲蹇収
+- 鎸夎鍗曡繃婊�
+
+### 3. 娓犻亾鍥炶皟鏃ュ織
+**璺緞**: `/payment/notify-logs`
+
+**鍔熻兘**:
+- 鍒楄〃灞曠ず锛堟敮鎸佸垎椤碉級
+- 鏌ョ湅鍘熷鎶ユ枃
+- 楠岀缁撴灉灞曠ず
+- 澶勭悊鐘舵�佷笌缁撴灉
+
+### 4. 涓氬姟鍥炶皟鏃ュ織
+**璺緞**: `/payment/callback-logs`
+
+**鍔熻兘**:
+- 鍒楄〃灞曠ず锛堟敮鎸佸垎椤碉級
+- 鏌ョ湅鍥炶皟璇锋眰/鍝嶅簲
+- 閲嶈瘯娆℃暟涓庣姸鎬�
+- 鎵嬪伐閲嶅彂鍥炶皟
+
+### 5. 瀵硅处绠$悊
+**璺緞**: `/payment/reconciliation`
+
+**鍔熻兘**:
+- 瀵硅处浠诲姟鍒楄〃锛堟寜鏃ユ湡锛�
+- 鏌ョ湅瀵硅处缁熻
+- 宸紓鏄庣粏鍒楄〃
+- 鑷姩淇璁板綍鏌ョ湅
+
+### 6. 鎿嶄綔瀹¤
+**璺緞**: `/payment/audit`
+
+**鍔熻兘**:
+- 瀹¤鏃ュ織鍒楄〃锛堟敮鎸佸垎椤碉級
+- 鎸夋搷浣滀汉銆佹搷浣滅被鍨嬭繃婊�
+- 鏌ョ湅鎿嶄綔鍙傛暟涓庢椂闂�
+
+**璇存槑**: 涓嶆彁渚涘鍑哄姛鑳斤紝鎵�鏈夋暟鎹粎鍦ㄧ嚎鏌ョ湅
+
+---
+
+## 鍗佷竴銆佸畨鍏ㄤ笌鍚堣
+
+### 1. 瀵嗛挜绠$悊
+- 閰嶇疆鏂囦欢鏉冮檺鍙楁帶锛堜粎鏈嶅姟鍣ㄥ彲璇伙級
+- 鏃ュ織鑴辨晱锛堝瘑閽ャ�佽瘉涔﹀唴瀹逛笉杈撳嚭锛�
+- 瀹氭湡鏇存崲瀵嗛挜鏈哄埗锛堥鐣欐帴鍙o級
+
+### 2. 绛惧悕楠岃瘉
+- 鎵�鏈夋笭閬撳洖璋冨繀椤婚獙绛�
+- 澶栭儴涓氬姟鍥炶皟閲囩敤 HMAC-SHA256
+- 绛惧悕澶辫触璁板綍鍛婅
+
+### 3. 骞傜瓑涓庨槻閲�
+- 娓犻亾鍥炶皟锛歯otify 鍞竴閿�
+- 鍙戣捣鏀粯锛氳鍗曠骇鍒帶鍒�
+- 涓氬姟鍥炶皟锛氶噸璇曟満鍒� + 鏃ュ織璁板綍
+
+### 4. 鏁版嵁瀹夊叏
+- 鏁忔劅瀛楁鍔犲瘑瀛樺偍锛堝鏈夐渶瑕侊級
+- 浼犺緭灞� HTTPS 寮哄埗
+- 鍥炶皟 URL 鐧藉悕鍗曟牎楠岋紙鍙�夛級
+
+### 5. 鎿嶄綔瀹¤
+- 鎵�鏈夊叧閿搷浣滆褰曞璁℃棩蹇�
+- 鎿嶄綔浜恒�佹椂闂淬�佸弬鏁板畬鏁磋褰�
+- 鏀寔鍥炴函涓庤拷璐�
+
+---
+
+## 鍗佷簩銆佺洃鎺т笌鍛婅
+
+### 1. 鍏抽敭鎸囨爣
+- 璁㈠崟鏀粯鎴愬姛鐜�
+- 娓犻亾鍥炶皟楠岀澶辫触鐜�
+- 涓氬姟鍥炶皟鎴愬姛鐜�
+- 瀵硅处宸紓鏁伴噺
+- 璁㈠崟杩囨湡鐜�
+
+### 2. 鍛婅瑙勫垯
+- 鍥炶皟楠岀澶辫触 > 闃堝��
+- 涓氬姟鍥炶皟澶辫触鐜� > 闃堝��
+- 瀵硅处宸紓鏁� > 闃堝��
+- 娓犻亾鎺ュ彛寮傚父锛堣秴鏃�/閿欒鐮侊級
+
+### 3. 鏃ュ織
+- 缁熶竴 traceId 璐┛鍏ㄩ摼璺�
+- 鍏抽敭鑺傜偣鏃ュ織杈撳嚭
+- 閿欒鍫嗘爤瀹屾暣璁板綍
+
+---
+
+## 鍗佷笁銆佸悗缁墿灞曡鍒�
+
+### 1. 閫�娆惧姛鑳�
+- RefundOrder 鑱氬悎鏍�
+- 閮ㄥ垎閫�娆炬敮鎸�
+- 閫�娆惧璐�
+
+### 2. 鍒嗚处鍔熻兘
+- 鏀寔寰俊/鏀粯瀹濆垎璐�
+- 鍒嗚处鎺ユ敹鏂圭鐞�
+- 鍒嗚处鏄庣粏涓庡璐�
+
+### 3. 澶氬晢鎴锋敮鎸�
+- ChannelAccount 瀹炰綋婵�娲�
+- 鎸夊晢鎴风淮搴︾鐞嗗瘑閽�
+- 澶氱鎴烽殧绂�
+
+### 4. 鏇村鏀粯鏂瑰紡
+- 寰俊 H5/APP/灏忕▼搴�
+- 鏀粯瀹� APP/WAP
+- 閾惰鍗″揩鎹锋敮浠�
+
+### 5. 瀵硅处浼樺寲
+- 鏀寔涓嬭浇娓犻亾瀵硅处鏂囦欢
+- 鑷姩瑙f瀽涓庢瘮瀵�
+- 宸紓鑷姩淇绛栫暐鍗囩骇
+
+---
+
+## 鍗佸洓銆佸紑鍙戜笌浜や粯璁″垝
+
+### 闃舵涓�锛氭牳蹇冩敮浠樺姛鑳斤紙棰勮 2 鍛級
+- 棰嗗煙妯″瀷涓庢暟鎹簱琛�
+- 寰俊 Native 鏀粯
+- 鏀粯瀹濆綋闈粯
+- 娓犻亾鍥炶皟澶勭悊
+- 浜岀淮鐮佺敓鎴愪笌 Base64 杩斿洖
+
+### 闃舵浜岋細涓氬姟鍥炶皟涓庡璁★紙棰勮 1 鍛級
+- 澶栭儴涓氬姟鍥炶皟閫昏緫
+- HMAC 閴存潈瀹炵幇
+- 閲嶈瘯鏈哄埗
+- 鎿嶄綔瀹¤璁板綍
+
+### 闃舵涓夛細瀵硅处涓庣鐞嗙锛堥璁� 1.5 鍛級
+- 姣忔棩瀵硅处浠诲姟
+- 鑷姩淇閫昏緫
+- 绠$悊绔〉闈㈠紑鍙�
+- 鏉冮檺鑿滃崟闆嗘垚
+
+### 闃舵鍥涳細娴嬭瘯涓庝紭鍖栵紙棰勮 1 鍛級
+- 鍗曞厓娴嬭瘯
+- 闆嗘垚娴嬭瘯锛堟矙绠辩幆澧冿級
+- 鎬ц兘娴嬭瘯涓庝紭鍖�
+- 瀹夊叏娴嬭瘯
+
+---
+
+## 鍗佷簲銆佹妧鏈闄╀笌搴斿
+
+### 1. 骞跺彂鎺у埗
+**椋庨櫓**: 鍚屼竴璁㈠崟骞跺彂鍒涘缓澶氱瑪浜ゆ槗
+**搴斿**: 璁㈠崟绾у埆涔愯閿� + 鏁版嵁搴撳敮涓�绾︽潫
+
+### 2. 鍥炶皟涓㈠け
+**椋庨櫓**: 娓犻亾鍥炶皟鏈垚鍔熼�佽揪
+**搴斿**: 姣忔棩瀵硅处琛ュ伩 + 涓诲姩鏌ヨ鏈哄埗
+
+### 3. 涓氬姟鍥炶皟澶辫触
+**椋庨櫓**: 澶栭儴绯荤粺涓嶅彲鐢ㄥ鑷村洖璋冨け璐�
+**搴斿**: 閲嶈瘯鏈哄埗 + 鎵嬪伐閲嶅彂
+
+### 4. 瀵硅处宸紓
+**椋庨櫓**: 鏈湴涓庢笭閬撶姸鎬佷笉涓�鑷�
+**搴斿**: 鑷姩淇 + 宸紓鍛婅 + 浜哄伐浠嬪叆
+
+### 5. 瀵嗛挜娉勯湶
+**椋庨櫓**: 閰嶇疆鏂囦欢娉勯湶瀵艰嚧瀵嗛挜鏆撮湶
+**搴斿**: 鏂囦欢鏉冮檺鎺у埗 + 鏃ュ織鑴辨晱 + 瀹氭湡鏇存崲
+
+---
+
+## 鍗佸叚銆佹�荤粨
+
+鏈璁℃柟妗堝熀浜� DDD 鏋舵瀯锛屽厖鍒嗚�冭檻浜嗘敮浠樹笟鍔$殑澶嶆潅鎬т笌绋冲仴鎬ч渶姹傦細
+
+1. **娓呮櫚鐨勯鍩熸ā鍨�**: 鑱氬悎鏍广�佸疄浣撱�佸�煎璞¤亴璐f槑纭�
+2. **涓ユ牸鐨勭姸鎬佹帶鍒�**: 璁㈠崟涓庝氦鏄撶姸鎬佹満銆佽繃鏈熸満鍒�
+3. **鍙潬鐨勫洖璋冩満鍒�**: 骞傜瓑銆侀噸璇曘�侀壌鏉�
+4. **鑷姩鍖栧璐�**: 姣忔棩淇銆佸樊寮傚憡璀�
+5. **瀹屾暣鐨勫璁¤拷婧�**: 鎿嶄綔鏃ュ織銆佹笭閬撴棩蹇椼�佷笟鍔℃棩蹇�
+6. **鍙墿灞曟灦鏋�**: 棰勭暀閫�娆俱�佸垎璐︺�佸鍟嗘埛绛夋墿灞曠偣
+
+璇ユ柟妗堝凡瀵归綈锛�
+- 鉁� Java 1.8 + Spring Boot 2.5.15 + ruoyi-framework
+- 鉁� 寰俊鏀粯 v2 缁熶竴涓嬪崟锛圡D5绛惧悕锛�
+- 鉁� 鏀粯瀹濆綋闈粯锛圧SA2绛惧悕锛�
+- 鉁� 鏈嶅姟绔繑鍥� 300脳300 Base64 浜岀淮鐮�
+- 鉁� 澶栭儴涓氬姟鍥炶皟 HMAC 閴存潈
+- 鉁� 鍚屼竴璁㈠崟浠呬竴绗旇繘琛屼腑浜ゆ槗
+- 鉁� 璁㈠崟 2 灏忔椂鑷姩杩囨湡
+- 鉁� 姣忔棩 2 鐐硅嚜鍔ㄥ璐︿慨澶�
+- 鉁� 鍗曞晢鎴烽厤缃枃浠跺姞杞�
+- 鉁� 绠$悊绔〉闈紙涓嶅鍑猴級
+
+**鏂规宸茬‘璁わ紝鍙繘鍏ヤ唬鐮佸疄鐜伴樁娈点��**
diff --git a/dryad-payment/pom.xml b/dryad-payment/pom.xml
new file mode 100644
index 0000000..165e949
--- /dev/null
+++ b/dryad-payment/pom.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
+         http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.ruoyi</groupId>
+    <artifactId>dryad-payment</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+
+    <name>dryad-payment</name>
+    <description>鏀粯妯″潡鏈嶅姟锛堝彲鐙珛杩愯鎴栦綔涓虹粍浠堕泦鎴愶級</description>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <spring-boot.version>2.5.15</spring-boot.version>
+        <mybatis-plus.version>3.4.3.4</mybatis-plus.version>
+        <druid.version>1.2.8</druid.version>
+        <fastjson.version>1.2.83</fastjson.version>
+        <commons-lang3.version>3.12.0</commons-lang3.version>
+        <httpclient.version>4.5.13</httpclient.version>
+        <alipay-sdk.version>4.22.110.ALL</alipay-sdk.version>
+        <zxing.version>3.4.1</zxing.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <!-- Spring Boot Starter Web -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- Spring Boot Starter AOP -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!-- Spring Boot Starter Validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!-- MyBatis -->
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.2.2</version>
+        </dependency>
+
+        <!-- Druid 鏁版嵁搴撹繛鎺ユ睜 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+
+        <!-- MySQL Driver -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- FastJSON -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+        <!-- Commons Lang3 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>${commons-lang3.version}</version>
+        </dependency>
+
+        <!-- HttpClient -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+
+        <!-- HttpClient Mime (鏀寔 multipart/form-data) -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+
+        <!-- Commons Codec -->
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+
+        <!-- 鏀粯瀹漇DK -->
+        <dependency>
+            <groupId>com.alipay.sdk</groupId>
+            <artifactId>alipay-sdk-java</artifactId>
+            <version>${alipay-sdk.version}</version>
+        </dependency>
+
+        <!-- ZXing 浜岀淮鐮佺敓鎴� -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>${zxing.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>${zxing.version}</version>
+        </dependency>
+
+        <!-- Lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- Spring Boot Configuration Processor -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common</artifactId>
+            <version>3.9.0</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <!-- 鏀寔鎵撳寘鎴愬彲鎵цjar锛堢嫭绔嬭繍琛岋級 -->
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <!-- 鍙�夛細涓嶅皢渚濊禆鎵撳寘鍒癹ar涓紝浣滀负缁勪欢鏃舵洿杞婚噺 -->
+                    <skip>false</skip>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>repackage</id>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                        <configuration>
+                            <!-- 鐢熸垚鍙墽琛宩ar -->
+                            <classifier>exec</classifier>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            
+            <!-- 鐢熸垚sources jar渚涘叾浠栭」鐩紩鐢� -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>3.2.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/PaymentApplication.java b/dryad-payment/src/main/java/com/ruoyi/payment/PaymentApplication.java
new file mode 100644
index 0000000..5bf77a6
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/PaymentApplication.java
@@ -0,0 +1,29 @@
+package com.ruoyi.payment;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * 鏀粯妯″潡鍚姩绫�
+ * 
+ * 浣跨敤鏂瑰紡锛�
+ * 1. 鐙珛杩愯锛氱洿鎺ヨ繍琛屾绫荤殑 main 鏂规硶
+ * 2. 浣滀负缁勪欢闆嗘垚锛�
+ *    - 鍦ㄤ富椤圭洰 pom.xml 涓坊鍔犱緷璧�
+ *    - Spring Boot 浼氳嚜鍔ㄦ壂鎻� PaymentAutoConfiguration
+ *    - 鏃犻渶棰濆閰嶇疆锛屽嵆鍙娇鐢ㄦ敮浠樺姛鑳�
+ * 
+ * @author ruoyi
+ */
+@SpringBootApplication
+@EnableScheduling
+@MapperScan("com.ruoyi.payment.infrastructure.persistence.mapper")
+public class PaymentApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(PaymentApplication.class, args);
+        System.out.println("(鈾モ棤鈥库棤)銉庯豢 鏀粯妯″潡鍚姩鎴愬姛  醿�(麓凇`醿�)锘�");
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/application/service/BizCallbackService.java b/dryad-payment/src/main/java/com/ruoyi/payment/application/service/BizCallbackService.java
new file mode 100644
index 0000000..5e2d931
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/application/service/BizCallbackService.java
@@ -0,0 +1,247 @@
+package com.ruoyi.payment.application.service;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.payment.domain.event.PaymentSuccessEvent;
+import com.ruoyi.payment.domain.model.BizCallbackLog;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import com.ruoyi.payment.infrastructure.config.BusinessCallbackConfig;
+import com.ruoyi.payment.infrastructure.persistence.mapper.BizCallbackLogMapper;
+import com.ruoyi.payment.infrastructure.util.SignUtil;
+import com.ruoyi.payment.infrastructure.util.SnowflakeIdGenerator;
+import com.ruoyi.payment.interfaces.callback.PaymentCallback;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * 涓氬姟鍥炶皟鏈嶅姟
+ * 
+ * 鏀寔涓夌鍥炶皟鏂瑰紡锛�
+ * 1. Spring浜嬩欢锛氬彂甯� PaymentSuccessEvent 浜嬩欢锛堟帹鑽愮敤浜巎ar鍖呴泦鎴愶級
+ * 2. 鎺ュ彛鍥炶皟锛氳皟鐢ㄦ墍鏈夊疄鐜颁簡 PaymentCallback 鎺ュ彛鐨凚ean锛堟帹鑽愮敤浜巎ar鍖呴泦鎴愶級
+ * 3. HTTP鍥炶皟锛氬悜鎸囧畾URL鍙戦�丳OST璇锋眰锛堢敤浜庣嫭绔嬮儴缃叉垨璺ㄦ湇鍔¤皟鐢級
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Service
+public class BizCallbackService {
+
+    @Autowired
+    private BizCallbackLogMapper bizCallbackLogMapper;
+
+    @Autowired
+    private BusinessCallbackConfig businessCallbackConfig;
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    /**
+     * 瑙﹀彂涓氬姟鍥炶皟锛堝紓姝ワ級
+     * 
+     * 浼樺厛绾э細
+     * 1. 鍙戝竷Spring浜嬩欢锛堝悓姝ワ紝鍦ㄥ悓涓�浜嬪姟涓級
+     * 2. 璋冪敤PaymentCallback鎺ュ彛瀹炵幇锛堝悓姝ワ紝鍦ㄥ悓涓�浜嬪姟涓級
+     * 3. HTTP鍥炶皟锛堝紓姝ワ紝鏀寔閲嶈瘯锛�
+     */
+    @Async
+    public void triggerCallback(PaymentOrder order, PaymentTransaction transaction) {
+        log.info("瑙﹀彂涓氬姟鍥炶皟锛岃鍗旾D: {}, bizOrderId: {}", order.getId(), order.getBizOrderId());
+
+        // 鏂瑰紡1: 鍙戝竷Spring浜嬩欢锛坖ar鍖呴泦鎴愭椂锛屼富椤圭洰鍙互鐩戝惉姝や簨浠讹級
+        publishPaymentEvent(order, transaction);
+
+        // 鏂瑰紡2: 璋冪敤PaymentCallback鎺ュ彛瀹炵幇锛坖ar鍖呴泦鎴愭椂锛屼富椤圭洰瀹炵幇姝ゆ帴鍙o級
+        invokeCallbackInterface(order, transaction);
+
+        // 鏂瑰紡3: HTTP鍥炶皟锛堢嫭绔嬮儴缃叉椂浣跨敤锛岄渶瑕侀厤缃甤allbackUrl锛�
+        if (StringUtils.hasText(order.getCallbackUrl())) {
+            executeHttpCallback(order, transaction);
+        } else {
+            log.info("鏈厤缃瓾TTP鍥炶皟URL锛岃烦杩嘓TTP鍥炶皟");
+        }
+    }
+
+    /**
+     * 鍙戝竷鏀粯鎴愬姛浜嬩欢
+     */
+    private void publishPaymentEvent(PaymentOrder order, PaymentTransaction transaction) {
+        try {
+            PaymentSuccessEvent event = new PaymentSuccessEvent(this, order, transaction);
+            applicationContext.publishEvent(event);
+            log.info("鍙戝竷鏀粯鎴愬姛浜嬩欢锛岃鍗旾D: {}", order.getId());
+        } catch (Exception e) {
+            log.error("鍙戝竷鏀粯浜嬩欢澶辫触", e);
+        }
+    }
+
+    /**
+     * 璋冪敤PaymentCallback鎺ュ彛瀹炵幇
+     */
+    private void invokeCallbackInterface(PaymentOrder order, PaymentTransaction transaction) {
+        try {
+            Map<String, PaymentCallback> callbacks = applicationContext.getBeansOfType(PaymentCallback.class);
+            if (callbacks.isEmpty()) {
+                log.info("鏈壘鍒癙aymentCallback鎺ュ彛瀹炵幇锛岃烦杩囨帴鍙e洖璋�");
+                return;
+            }
+
+            for (Map.Entry<String, PaymentCallback> entry : callbacks.entrySet()) {
+                try {
+                    log.info("璋冪敤PaymentCallback: {}", entry.getKey());
+                    entry.getValue().onPaymentSuccess(order, transaction);
+                } catch (Exception e) {
+                    log.error("璋冪敤PaymentCallback澶辫触: {}", entry.getKey(), e);
+                }
+            }
+        } catch (Exception e) {
+            log.error("璋冪敤PaymentCallback鎺ュ彛澶辫触", e);
+        }
+    }
+
+    /**
+     * 鎵цHTTP鍥炶皟
+     */
+    private void executeHttpCallback(PaymentOrder order, PaymentTransaction transaction) {
+        log.info("鎵цHTTP鍥炶皟锛岃鍗旾D: {}, 鍥炶皟URL: {}", order.getId(), order.getCallbackUrl());
+
+        // 鏋勯�犲洖璋冨弬鏁�
+        Map<String, Object> callbackData = new HashMap<>();
+        callbackData.put("tradeId", transaction.getId());
+        callbackData.put("orderId", order.getId());
+        callbackData.put("bizOrderId", order.getBizOrderId());
+        callbackData.put("channel", order.getChannel());
+        callbackData.put("amount", order.getAmount());
+        callbackData.put("currency", order.getCurrency());
+        callbackData.put("status", order.getStatus());
+        callbackData.put("channelTradeNo", order.getChannelTradeNo());
+        callbackData.put("paidAt", order.getPaidAt() != null ? order.getPaidAt().toString() : null);
+        callbackData.put("subject", order.getSubject());
+        callbackData.put("description", order.getDescription());
+
+        String payload = JSON.toJSONString(callbackData);
+
+        // 鐢熸垚绛惧悕
+        String nonce = UUID.randomUUID().toString().replace("-", "");
+        String timestamp = String.valueOf(System.currentTimeMillis());
+        String signData = payload + nonce + timestamp;
+        String signature = SignUtil.hmacSha256(signData, businessCallbackConfig.getCallbackSignSecret());
+
+        // 璁板綍鍥炶皟鏃ュ織
+        BizCallbackLog callbackLog = new BizCallbackLog();
+        callbackLog.setId(SnowflakeIdGenerator.generateId());
+        callbackLog.setOrderId(order.getId());
+        callbackLog.setTransactionId(transaction.getId());
+        callbackLog.setCallbackUrl(order.getCallbackUrl());
+        callbackLog.setPayload(payload);
+        callbackLog.setSuccess(false);
+        callbackLog.setRetryCount(0);
+        callbackLog.setCreatedAt(LocalDateTime.now());
+        bizCallbackLogMapper.insert(callbackLog);
+
+        // 鎵цHTTP鍥炶皟
+        executeHttpRequest(callbackLog, payload, signature, nonce, timestamp, 0);
+    }
+
+    /**
+     * 鎵цHTTP鍥炶皟璇锋眰
+     */
+    private void executeHttpRequest(BizCallbackLog callbackLog, String payload, String signature, 
+                                  String nonce, String timestamp, int retryCount) {
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            HttpPost httpPost = new HttpPost(callbackLog.getCallbackUrl());
+            
+            // 璁剧疆璇锋眰澶�
+            httpPost.setHeader("Content-Type", "application/json");
+            httpPost.setHeader("X-Signature", signature);
+            httpPost.setHeader("X-Nonce", nonce);
+            httpPost.setHeader("X-Timestamp", timestamp);
+            
+            // 璁剧疆璇锋眰浣�
+            httpPost.setEntity(new StringEntity(payload, "UTF-8"));
+            
+            // 鍙戦�佽姹�
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                int statusCode = response.getStatusLine().getStatusCode();
+                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
+                
+                log.info("涓氬姟鍥炶皟鍝嶅簲锛岀姸鎬佺爜: {}, 鍝嶅簲: {}", statusCode, responseBody);
+                
+                // 鏇存柊鍥炶皟鏃ュ織
+                callbackLog.setHttpStatus(statusCode);
+                callbackLog.setResponse(responseBody);
+                callbackLog.setRetryCount(retryCount);
+                callbackLog.setLastRetryAt(LocalDateTime.now());
+                
+                if (statusCode >= 200 && statusCode < 300) {
+                    callbackLog.setSuccess(true);
+                    bizCallbackLogMapper.update(callbackLog);
+                    log.info("涓氬姟鍥炶皟鎴愬姛锛岃鍗旾D: {}", callbackLog.getOrderId());
+                } else {
+                    callbackLog.setSuccess(false);
+                    bizCallbackLogMapper.update(callbackLog);
+                    
+                    // 閲嶈瘯閫昏緫
+                    scheduleRetry(callbackLog, payload, signature, nonce, timestamp, retryCount);
+                }
+            }
+        } catch (Exception e) {
+            log.error("涓氬姟鍥炶皟寮傚父锛岃鍗旾D: {}", callbackLog.getOrderId(), e);
+            
+            // 鏇存柊澶辫触璁板綍
+            callbackLog.setSuccess(false);
+            callbackLog.setResponse("寮傚父: " + e.getMessage());
+            callbackLog.setRetryCount(retryCount);
+            callbackLog.setLastRetryAt(LocalDateTime.now());
+            bizCallbackLogMapper.update(callbackLog);
+            
+            // 閲嶈瘯閫昏緫
+            scheduleRetry(callbackLog, payload, signature, nonce, timestamp, retryCount);
+        }
+    }
+
+    /**
+     * 瀹夋帓閲嶈瘯
+     */
+    private void scheduleRetry(BizCallbackLog callbackLog, String payload, String signature,
+                               String nonce, String timestamp, int retryCount) {
+        int maxRetry = businessCallbackConfig.getCallbackRetryMaxCount();
+        if (retryCount >= maxRetry) {
+            log.warn("涓氬姟鍥炶皟閲嶈瘯娆℃暟宸茶揪涓婇檺锛岃鍗旾D: {}", callbackLog.getOrderId());
+            return;
+        }
+
+        int[] intervals = businessCallbackConfig.getRetryIntervalsArray();
+        int nextRetry = retryCount + 1;
+        int delayMinutes = nextRetry < intervals.length ? intervals[nextRetry] : intervals[intervals.length - 1];
+
+        log.info("瀹夋帓涓氬姟鍥炶皟閲嶈瘯锛岃鍗旾D: {}, 绗瑊}娆¢噸璇曪紝寤惰繜{}鍒嗛挓", 
+                 callbackLog.getOrderId(), nextRetry, delayMinutes);
+
+        // TODO: 浣跨敤瀹氭椂浠诲姟鎴栧欢杩熼槦鍒楀疄鐜伴噸璇�
+        // 杩欓噷绠�鍖栧鐞嗭紝瀹為檯搴斾娇鐢� @Scheduled 鎴栨秷鎭槦鍒�
+    }
+
+    /**
+     * 鎵嬪伐閲嶅彂鍥炶皟
+     */
+    public void resendCallback(Long orderId) {
+        // TODO: 瀹炵幇鎵嬪伐閲嶅彂閫昏緫
+        log.info("鎵嬪伐閲嶅彂涓氬姟鍥炶皟锛岃鍗旾D: {}", orderId);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentNotifyService.java b/dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentNotifyService.java
new file mode 100644
index 0000000..c4a8ff4
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentNotifyService.java
@@ -0,0 +1,218 @@
+package com.ruoyi.payment.application.service;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.payment.domain.model.NotifyLog;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import com.ruoyi.payment.infrastructure.persistence.mapper.NotifyLogMapper;
+import com.ruoyi.payment.infrastructure.persistence.mapper.PaymentOrderMapper;
+import com.ruoyi.payment.infrastructure.persistence.mapper.PaymentTransactionMapper;
+import com.ruoyi.payment.infrastructure.util.SnowflakeIdGenerator;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.Map;
+
+/**
+ * 鏀粯鍥炶皟澶勭悊鏈嶅姟
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Service
+public class PaymentNotifyService {
+
+    @Autowired
+    private PaymentOrderMapper paymentOrderMapper;
+
+    @Autowired
+    private PaymentTransactionMapper paymentTransactionMapper;
+
+    @Autowired
+    private NotifyLogMapper notifyLogMapper;
+
+    @Autowired
+    private BizCallbackService bizCallbackService;
+
+    /**
+     * 澶勭悊寰俊鏀粯鍥炶皟
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void processWechatNotify(Map<String, String> params, String rawXml) {
+        String outTradeNo = params.get("out_trade_no"); // 鍟嗘埛璁㈠崟鍙�
+        String transactionId = params.get("transaction_id"); // 寰俊浜ゆ槗鍙�
+        String resultCode = params.get("result_code");
+        String returnCode = params.get("return_code");
+
+        log.info("澶勭悊寰俊鍥炶皟锛屽晢鎴疯鍗曞彿: {}, 寰俊浜ゆ槗鍙�: {}, 缁撴灉: {}", outTradeNo, transactionId, resultCode);
+
+        // 妫�鏌ュ箓绛夋��
+        if (isNotifyProcessed("WECHAT", transactionId)) {
+            log.info("寰俊鍥炶皟宸插鐞嗚繃锛屼氦鏄撳彿: {}", transactionId);
+            return;
+        }
+
+        // 璁板綍鍥炶皟鏃ュ織
+        NotifyLog notifyLog = saveNotifyLog("WECHAT", transactionId, rawXml, true);
+
+        try {
+            // 閫氫俊鎴愬姛涓斾笟鍔℃垚鍔�
+            if ("SUCCESS".equals(returnCode) && "SUCCESS".equals(resultCode)) {
+                // 鏌ヨ璁㈠崟鍜屼氦鏄擄紙浣跨敤涓氬姟璁㈠崟鍙锋煡璇級
+                PaymentOrder order = paymentOrderMapper.selectByBizOrderIdAndChannel(outTradeNo, "WECHAT");
+                if (order == null) {
+                    log.error("璁㈠崟涓嶅瓨鍦�: {}", outTradeNo);
+                    updateNotifyLog(notifyLog.getId(), false, "璁㈠崟涓嶅瓨鍦�");
+                    return;
+                }
+
+                PaymentTransaction transaction = paymentTransactionMapper.selectPendingByOrderId(order.getId());
+                if (transaction == null) {
+                    log.error("寰呮敮浠樹氦鏄撲笉瀛樺湪锛岃鍗旾D: {}", order.getId());
+                    updateNotifyLog(notifyLog.getId(), false, "浜ゆ槗涓嶅瓨鍦�");
+                    return;
+                }
+
+                // 鏇存柊浜ゆ槗鐘舵��
+                transaction.setStatus("SUCCEEDED");
+                transaction.setChannelTradeNo(transactionId);
+                transaction.setPaidAt(LocalDateTime.now());
+                transaction.setResponseSnapshot(JSON.toJSONString(params));
+                paymentTransactionMapper.update(transaction);
+
+                // 鏇存柊璁㈠崟鐘舵��
+                order.setStatus("SUCCEEDED");
+                order.setChannelTradeNo(transactionId);
+                order.setPaidAt(LocalDateTime.now());
+                order.setLatestTransactionId(transaction.getId());
+                paymentOrderMapper.update(order);
+
+                // 鏇存柊閫氱煡鏃ュ織
+                notifyLog.setOrderId(order.getId());
+                notifyLog.setTransactionId(transaction.getId());
+                updateNotifyLog(notifyLog.getId(), true, "澶勭悊鎴愬姛");
+
+                // 瑙﹀彂涓氬姟鍥炶皟
+                bizCallbackService.triggerCallback(order, transaction);
+
+                log.info("寰俊鏀粯鍥炶皟澶勭悊鎴愬姛锛岃鍗旾D: {}, 浜ゆ槗ID: {}", order.getId(), transaction.getId());
+            } else {
+                log.warn("寰俊鏀粯澶辫触锛宺eturnCode: {}, resultCode: {}", returnCode, resultCode);
+                updateNotifyLog(notifyLog.getId(), true, "鏀粯澶辫触");
+            }
+        } catch (Exception e) {
+            log.error("澶勭悊寰俊鍥炶皟寮傚父", e);
+            updateNotifyLog(notifyLog.getId(), false, "澶勭悊寮傚父: " + e.getMessage());
+            throw e;
+        }
+    }
+
+    /**
+     * 澶勭悊鏀粯瀹濆洖璋�
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void processAlipayNotify(Map<String, String> params) {
+        String outTradeNo = params.get("out_trade_no"); // 鍟嗘埛璁㈠崟鍙�
+        String tradeNo = params.get("trade_no"); // 鏀粯瀹濅氦鏄撳彿
+        String tradeStatus = params.get("trade_status");
+
+        log.info("澶勭悊鏀粯瀹濆洖璋冿紝鍟嗘埛璁㈠崟鍙�: {}, 鏀粯瀹濅氦鏄撳彿: {}, 鐘舵��: {}", outTradeNo, tradeNo, tradeStatus);
+
+        // 妫�鏌ュ箓绛夋��
+        if (isNotifyProcessed("ALIPAY", tradeNo)) {
+            log.info("鏀粯瀹濆洖璋冨凡澶勭悊杩囷紝浜ゆ槗鍙�: {}", tradeNo);
+            return;
+        }
+
+        // 璁板綍鍥炶皟鏃ュ織
+        NotifyLog notifyLog = saveNotifyLog("ALIPAY", tradeNo, JSON.toJSONString(params), true);
+
+        try {
+            // 浜ゆ槗鎴愬姛
+            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
+                // 鏌ヨ璁㈠崟鍜屼氦鏄擄紙浣跨敤涓氬姟璁㈠崟鍙锋煡璇級
+                PaymentOrder order = paymentOrderMapper.selectByBizOrderIdAndChannel(outTradeNo, "ALIPAY");
+                if (order == null) {
+                    log.error("璁㈠崟涓嶅瓨鍦�: {}", outTradeNo);
+                    updateNotifyLog(notifyLog.getId(), false, "璁㈠崟涓嶅瓨鍦�");
+                    return;
+                }
+
+                PaymentTransaction transaction = paymentTransactionMapper.selectPendingByOrderId(order.getId());
+                if (transaction == null) {
+                    log.error("寰呮敮浠樹氦鏄撲笉瀛樺湪锛岃鍗旾D: {}", order.getId());
+                    updateNotifyLog(notifyLog.getId(), false, "浜ゆ槗涓嶅瓨鍦�");
+                    return;
+                }
+
+                // 鏇存柊浜ゆ槗鐘舵��
+                transaction.setStatus("SUCCEEDED");
+                transaction.setChannelTradeNo(tradeNo);
+                transaction.setPaidAt(LocalDateTime.now());
+                transaction.setResponseSnapshot(JSON.toJSONString(params));
+                paymentTransactionMapper.update(transaction);
+
+                // 鏇存柊璁㈠崟鐘舵��
+                order.setStatus("SUCCEEDED");
+                order.setChannelTradeNo(tradeNo);
+                order.setPaidAt(LocalDateTime.now());
+                order.setLatestTransactionId(transaction.getId());
+                paymentOrderMapper.update(order);
+
+                // 鏇存柊閫氱煡鏃ュ織
+                notifyLog.setOrderId(order.getId());
+                notifyLog.setTransactionId(transaction.getId());
+                updateNotifyLog(notifyLog.getId(), true, "澶勭悊鎴愬姛");
+
+                // 瑙﹀彂涓氬姟鍥炶皟
+                bizCallbackService.triggerCallback(order, transaction);
+
+                log.info("鏀粯瀹濆洖璋冨鐞嗘垚鍔燂紝璁㈠崟ID: {}, 浜ゆ槗ID: {}", order.getId(), transaction.getId());
+            } else {
+                log.warn("鏀粯瀹濅氦鏄撶姸鎬佸紓甯�: {}", tradeStatus);
+                updateNotifyLog(notifyLog.getId(), true, "鐘舵��: " + tradeStatus);
+            }
+        } catch (Exception e) {
+            log.error("澶勭悊鏀粯瀹濆洖璋冨紓甯�", e);
+            updateNotifyLog(notifyLog.getId(), false, "澶勭悊寮傚父: " + e.getMessage());
+            throw e;
+        }
+    }
+
+    /**
+     * 妫�鏌ラ�氱煡鏄惁宸插鐞嗭紙骞傜瓑鎬э級
+     */
+    private boolean isNotifyProcessed(String channel, String notifyId) {
+        return notifyLogMapper.selectProcessedCount(channel, notifyId) > 0;
+    }
+
+    /**
+     * 淇濆瓨閫氱煡鏃ュ織
+     */
+    private NotifyLog saveNotifyLog(String channel, String notifyId, String payload, boolean verified) {
+        NotifyLog log = new NotifyLog();
+        log.setId(SnowflakeIdGenerator.generateId());
+        log.setChannel(channel);
+        log.setNotifyIdOrSerial(notifyId);
+        log.setPayload(payload);
+        log.setVerified(verified);
+        log.setProcessed(false);
+        log.setCreatedAt(LocalDateTime.now());
+        notifyLogMapper.insert(log);
+        return log;
+    }
+
+    /**
+     * 鏇存柊閫氱煡鏃ュ織
+     */
+    private void updateNotifyLog(Long id, boolean processed, String result) {
+        NotifyLog log = new NotifyLog();
+        log.setId(id);
+        log.setProcessed(processed);
+        log.setResult(result);
+        notifyLogMapper.update(log);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentService.java b/dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentService.java
new file mode 100644
index 0000000..3b44a9b
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentService.java
@@ -0,0 +1,338 @@
+package com.ruoyi.payment.application.service;
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.payment.domain.enums.ClientType;
+import com.ruoyi.payment.domain.enums.OrderStatus;
+import com.ruoyi.payment.domain.enums.PayChannel;
+import com.ruoyi.payment.domain.enums.TransactionStatus;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import com.ruoyi.payment.infrastructure.channel.alipay.AlipayF2FClient;
+import com.ruoyi.payment.infrastructure.channel.alipay.AlipayThirdPartyClient;
+import com.ruoyi.payment.infrastructure.channel.wechat.WxPayV2Client;
+import com.ruoyi.payment.infrastructure.config.AlipayConfig;
+import com.ruoyi.payment.infrastructure.config.QrCodeConfig;
+import com.ruoyi.payment.infrastructure.persistence.mapper.PaymentOrderMapper;
+import com.ruoyi.payment.infrastructure.persistence.mapper.PaymentTransactionMapper;
+import com.ruoyi.payment.infrastructure.util.QrCodeUtil;
+import com.ruoyi.payment.infrastructure.util.SnowflakeIdGenerator;
+import com.ruoyi.payment.interfaces.dto.PaymentRequest;
+import com.ruoyi.payment.interfaces.dto.PaymentResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鏀粯搴旂敤鏈嶅姟
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Service
+public class PaymentService {
+
+    @Autowired
+    private PaymentOrderMapper paymentOrderMapper;
+
+    @Autowired
+    private PaymentTransactionMapper paymentTransactionMapper;
+
+    @Autowired
+    private QrCodeUtil qrCodeUtil;
+
+    @Autowired
+    private QrCodeConfig qrCodeConfig;
+
+    @Autowired
+    private WxPayV2Client wxPayV2Client;
+
+    @Autowired
+    private AlipayF2FClient alipayF2FClient;
+
+    @Autowired
+    private AlipayThirdPartyClient alipayThirdPartyClient;
+
+    @Autowired
+    private AlipayConfig alipayConfig;
+
+    /**
+     * 鍙戣捣寰俊Native鏀粯
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public PaymentResponse createWechatNativePayment(PaymentRequest request) {
+        log.info("鍙戣捣寰俊Native鏀粯锛岃姹傚弬鏁�: {}", JSON.toJSONString(request));
+
+        // 1. 鏌ヨ鎴栧垱寤鸿鍗�
+        PaymentOrder order = getOrCreateOrder(request, PayChannel.WECHAT.getCode());
+
+        // 2. 妫�鏌ユ槸鍚﹀瓨鍦ㄥ緟鏀粯浜ゆ槗锛堝悓涓�璁㈠崟鍙厑璁镐竴绗旇繘琛屼腑锛�
+        PaymentTransaction existingTransaction = paymentTransactionMapper.selectPendingByOrderId(order.getId());
+        if (existingTransaction != null) {
+            log.info("璁㈠崟{}宸插瓨鍦ㄥ緟鏀粯浜ゆ槗{}锛岀洿鎺ヨ繑鍥�", order.getId(), existingTransaction.getId());
+            return buildPaymentResponse(order, existingTransaction);
+        }
+
+        // 3. 璋冪敤寰俊涓嬪崟鎺ュ彛锛堣繖閲屽厛妯℃嫙锛�
+        String codeUrl = callWechatUnifiedOrder(order);
+
+        // 4. 鐢熸垚浜岀淮鐮丅ase64
+        String qrBase64 = qrCodeUtil.generateQrCodeBase64(codeUrl, qrCodeConfig.getSize());
+
+        // 5. 鍒涘缓浜ゆ槗璁板綍
+        PaymentTransaction transaction = new PaymentTransaction();
+        transaction.setId(SnowflakeIdGenerator.generateId());
+        transaction.setOrderId(order.getId());
+        transaction.setChannel(PayChannel.WECHAT.getCode());
+        transaction.setClientType(ClientType.NATIVE.getCode());
+        transaction.setStatus(TransactionStatus.PENDING.getCode());
+        transaction.setCodeOrQr(codeUrl);
+        transaction.setQrBase64(qrBase64);
+        transaction.setCreatedAt(LocalDateTime.now());
+
+        // 鏋勯�犺姹傚弬鏁板揩鐓�
+        Map<String, Object> requestParams = new HashMap<>();
+        requestParams.put("bizOrderId", request.getBizOrderId());
+        requestParams.put("amount", request.getAmount());
+        requestParams.put("subject", request.getSubject());
+        transaction.setRequestParams(JSON.toJSONString(requestParams));
+
+        paymentTransactionMapper.insert(transaction);
+
+        // 6. 鏇存柊璁㈠崟鏈�鏂颁氦鏄揑D
+        order.setLatestTransactionId(transaction.getId());
+        paymentOrderMapper.update(order);
+
+        log.info("寰俊Native鏀粯鍒涘缓鎴愬姛锛岃鍗旾D: {}, 浜ゆ槗ID: {}", order.getId(), transaction.getId());
+
+        return buildPaymentResponse(order, transaction);
+    }
+
+    /**
+     * 鍙戣捣鏀粯瀹濆綋闈粯
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public PaymentResponse createAlipayPrecreate(PaymentRequest request) {
+        log.info("鍙戣捣鏀粯瀹濆綋闈粯锛岃姹傚弬鏁�: {}", JSON.toJSONString(request));
+
+        // 1. 鏌ヨ鎴栧垱寤鸿鍗�
+        PaymentOrder order = getOrCreateOrder(request, PayChannel.ALIPAY.getCode());
+
+        // 2. 妫�鏌ユ槸鍚﹀瓨鍦ㄥ緟鏀粯浜ゆ槗
+        PaymentTransaction existingTransaction = paymentTransactionMapper.selectPendingByOrderId(order.getId());
+        if (existingTransaction != null) {
+            log.info("璁㈠崟{}宸插瓨鍦ㄥ緟鏀粯浜ゆ槗{}锛岀洿鎺ヨ繑鍥�", order.getId(), existingTransaction.getId());
+            return buildPaymentResponse(order, existingTransaction);
+        }
+
+        // 3. 璋冪敤鏀粯瀹濅笅鍗曟帴鍙o紙杩欓噷鍏堟ā鎷燂級
+        String qrCode = callAlipayPrecreate(order);
+
+        // 4. 鐢熸垚浜岀淮鐮丅ase64
+        String qrBase64 = qrCodeUtil.generateQrCodeBase64(qrCode, qrCodeConfig.getSize());
+
+        // 5. 鍒涘缓浜ゆ槗璁板綍
+        PaymentTransaction transaction = new PaymentTransaction();
+        transaction.setId(SnowflakeIdGenerator.generateId());
+        transaction.setOrderId(order.getId());
+        transaction.setChannel(PayChannel.ALIPAY.getCode());
+        transaction.setClientType(ClientType.ALIPAY_PRECREATE.getCode());
+        transaction.setStatus(TransactionStatus.PENDING.getCode());
+        transaction.setCodeOrQr(qrCode);
+        transaction.setQrBase64(qrBase64);
+        transaction.setCreatedAt(LocalDateTime.now());
+
+        Map<String, Object> requestParams = new HashMap<>();
+        requestParams.put("bizOrderId", request.getBizOrderId());
+        requestParams.put("amount", request.getAmount());
+        requestParams.put("subject", request.getSubject());
+        transaction.setRequestParams(JSON.toJSONString(requestParams));
+
+        paymentTransactionMapper.insert(transaction);
+
+        // 6. 鏇存柊璁㈠崟
+        order.setLatestTransactionId(transaction.getId());
+        paymentOrderMapper.update(order);
+
+        log.info("鏀粯瀹濆綋闈粯鍒涘缓鎴愬姛锛岃鍗旾D: {}, 浜ゆ槗ID: {}", order.getId(), transaction.getId());
+
+        return buildPaymentResponse(order, transaction);
+    }
+
+    /**
+     * 鍙戣捣鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛�
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public PaymentResponse createAlipayThirdPartyPrecreate(PaymentRequest request) {
+        log.info("鍙戣捣鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛夛紝璇锋眰鍙傛暟: {}", JSON.toJSONString(request));
+
+        // 1. 鏌ヨ鎴栧垱寤鸿鍗�
+        PaymentOrder order = getOrCreateOrder(request, PayChannel.ALIPAY.getCode());
+
+        // 2. 妫�鏌ユ槸鍚﹀瓨鍦ㄥ緟鏀粯浜ゆ槗
+        PaymentTransaction existingTransaction = paymentTransactionMapper.selectPendingByOrderId(order.getId());
+        if (existingTransaction != null) {
+            log.info("璁㈠崟{}宸插瓨鍦ㄥ緟鏀粯浜ゆ槗{}锛岀洿鎺ヨ繑鍥�", order.getId(), existingTransaction.getId());
+            return buildPaymentResponse(order, existingTransaction);
+        }
+
+        // 3. 璋冪敤绗笁鏂规敮浠樺疂鎺ュ彛鐢熸垚鏀粯URL
+        String payUrl = callAlipayThirdPartyPrecreate(order, request);
+
+        // 4. 鐢熸垚浜岀淮鐮丅ase64
+        String qrBase64 = qrCodeUtil.generateQrCodeBase64(payUrl, qrCodeConfig.getSize());
+
+        // 5. 鍒涘缓浜ゆ槗璁板綍
+        PaymentTransaction transaction = new PaymentTransaction();
+        transaction.setId(SnowflakeIdGenerator.generateId());
+        transaction.setOrderId(order.getId());
+        transaction.setChannel(PayChannel.ALIPAY.getCode());
+        transaction.setClientType(ClientType.ALIPAY_PRECREATE.getCode());
+        transaction.setStatus(TransactionStatus.PENDING.getCode());
+        transaction.setCodeOrQr(payUrl);
+        transaction.setQrBase64(qrBase64);
+        transaction.setCreatedAt(LocalDateTime.now());
+
+        Map<String, Object> requestParams = new HashMap<>();
+        requestParams.put("bizOrderId", request.getBizOrderId());
+        requestParams.put("amount", request.getAmount());
+        requestParams.put("subject", request.getSubject());
+        requestParams.put("thirdParty", true);
+        transaction.setRequestParams(JSON.toJSONString(requestParams));
+
+        paymentTransactionMapper.insert(transaction);
+
+        // 6. 鏇存柊璁㈠崟
+        order.setLatestTransactionId(transaction.getId());
+        paymentOrderMapper.update(order);
+
+        log.info("鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛夊垱寤烘垚鍔燂紝璁㈠崟ID: {}, 浜ゆ槗ID: {}", order.getId(), transaction.getId());
+
+        return buildPaymentResponse(order, transaction);
+    }
+
+    /**
+     * 鏌ヨ鎴栧垱寤鸿鍗�
+     */
+    private PaymentOrder getOrCreateOrder(PaymentRequest request, String channel) {
+        // 鍏堟煡璇㈡槸鍚﹀瓨鍦�
+        PaymentOrder existingOrder = paymentOrderMapper.selectByBizOrderIdAndChannel(
+                request.getBizOrderId(), channel);
+
+        if (existingOrder != null) {
+            // 濡傛灉璁㈠崟宸茶繃鏈燂紝鏇存柊鐘舵��
+            if (existingOrder.isExpired() && OrderStatus.PENDING.getCode().equals(existingOrder.getStatus())) {
+                existingOrder.setStatus(OrderStatus.EXPIRED.getCode());
+                paymentOrderMapper.update(existingOrder);
+            }
+            return existingOrder;
+        }
+
+        // 鍒涘缓鏂拌鍗�
+        PaymentOrder order = new PaymentOrder();
+        order.setId(SnowflakeIdGenerator.generateId());
+        order.setBizOrderId(request.getBizOrderId());
+        order.setAmount(request.getAmount());
+        order.setCurrency("CNY");
+        order.setChannel(channel);
+        order.setStatus(OrderStatus.PENDING.getCode());
+        order.setSubject(request.getSubject());
+        order.setDescription(request.getDescription());
+        order.setCallbackUrl(request.getCallbackUrl());
+        order.setExpireAt(LocalDateTime.now().plusHours(2)); // 2灏忔椂杩囨湡
+        order.setVersion(0);
+        order.setCreatedAt(LocalDateTime.now());
+        order.setUpdatedAt(LocalDateTime.now());
+
+        paymentOrderMapper.insert(order);
+
+        return order;
+    }
+
+    /**
+     * 璋冪敤寰俊缁熶竴涓嬪崟鎺ュ彛
+     */
+    private String callWechatUnifiedOrder(PaymentOrder order) {
+        try {
+            return wxPayV2Client.unifiedOrder(order);
+        } catch (Exception e) {
+            log.error("璋冪敤寰俊缁熶竴涓嬪崟鎺ュ彛澶辫触", e);
+            throw new RuntimeException("寰俊涓嬪崟澶辫触: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 璋冪敤鏀粯瀹濆綋闈粯鎺ュ彛
+     */
+    private String callAlipayPrecreate(PaymentOrder order) {
+        try {
+            return alipayF2FClient.precreate(order);
+        } catch (Exception e) {
+            log.error("璋冪敤鏀粯瀹濆綋闈粯鎺ュ彛澶辫触", e);
+            throw new RuntimeException("鏀粯瀹濅笅鍗曞け璐�: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 璋冪敤绗笁鏂规敮浠樺疂鎺ュ彛鐢熸垚鏀粯URL
+     */
+    private String callAlipayThirdPartyPrecreate(PaymentOrder order, PaymentRequest request) {
+        try {
+            // 浣跨敤AlipayConfig涓厤缃殑鍥炶皟鍦板潃
+            String notifyUrl = alipayConfig.getNotifyUrl();
+            String outTradeNo = String.valueOf(order.getId());
+            Integer totalFee = order.getAmount(); // 鍗曚綅锛氬垎
+            String serviceOrdId = request.getBizOrderId(); // 涓氬姟璁㈠崟ID
+            
+            return alipayThirdPartyClient.createQrCodeUrl(notifyUrl, outTradeNo, totalFee, serviceOrdId);
+        } catch (Exception e) {
+            log.error("璋冪敤绗笁鏂规敮浠樺疂鎺ュ彛澶辫触", e);
+            throw new RuntimeException("绗笁鏂规敮浠樺疂涓嬪崟澶辫触: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 鏋勯�犳敮浠樺搷搴�
+     */
+    private PaymentResponse buildPaymentResponse(PaymentOrder order, PaymentTransaction transaction) {
+        PaymentResponse response = new PaymentResponse();
+        response.setOrderId(order.getId());
+        response.setTransactionId(transaction.getId());
+        response.setStatus(order.getStatus());
+        response.setQrBase64(transaction.getQrBase64());
+        response.setExpireAt(order.getExpireAt());
+        return response;
+    }
+
+    /**
+     * 鏌ヨ璁㈠崟
+     */
+    public PaymentOrder getOrder(Long orderId) {
+        return paymentOrderMapper.selectById(orderId);
+    }
+
+    /**
+     * 鏌ヨ鏈�鏂颁氦鏄�
+     */
+    public PaymentTransaction getLatestTransaction(Long orderId) {
+        return paymentTransactionMapper.selectLatestByOrderId(orderId);
+    }
+
+    /**
+     * 鏌ヨ鏀粯瀹濈涓夋柟浜ゆ槗鐘舵��
+     */
+    public String queryAlipayThirdPartyTradeStatus(Long orderId) {
+        try {
+            // 浣跨敤璁㈠崟ID浣滀负鍟嗘埛璁㈠崟鍙�
+            String outTradeNo = String.valueOf(orderId);
+            return alipayThirdPartyClient.queryTradeStatus(outTradeNo);
+        } catch (Exception e) {
+            log.error("鏌ヨ鏀粯瀹濈涓夋柟浜ゆ槗鐘舵�佸け璐ワ紝璁㈠崟ID: {}", orderId, e);
+            throw new RuntimeException("鏌ヨ浜ゆ槗鐘舵�佸け璐�: " + e.getMessage(), e);
+        }
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/common/AjaxResult.java b/dryad-payment/src/main/java/com/ruoyi/payment/common/AjaxResult.java
new file mode 100644
index 0000000..02d7796
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/common/AjaxResult.java
@@ -0,0 +1,87 @@
+package com.ruoyi.payment.common;
+
+import java.io.Serializable;
+
+/**
+ * 缁熶竴鍝嶅簲缁撴灉
+ * 
+ * @author ruoyi
+ */
+public class AjaxResult implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 鐘舵�佺爜 */
+    private int code;
+
+    /** 杩斿洖娑堟伅 */
+    private String msg;
+
+    /** 杩斿洖鏁版嵁 */
+    private Object data;
+
+    public AjaxResult() {
+    }
+
+    public AjaxResult(int code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public AjaxResult(int code, String msg, Object data) {
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+    }
+
+    public static AjaxResult success() {
+        return new AjaxResult(200, "鎿嶄綔鎴愬姛");
+    }
+
+    public static AjaxResult success(String msg) {
+        return new AjaxResult(200, msg);
+    }
+
+    public static AjaxResult success(Object data) {
+        return new AjaxResult(200, "鎿嶄綔鎴愬姛", data);
+    }
+
+    public static AjaxResult success(String msg, Object data) {
+        return new AjaxResult(200, msg, data);
+    }
+
+    public static AjaxResult error() {
+        return new AjaxResult(500, "鎿嶄綔澶辫触");
+    }
+
+    public static AjaxResult error(String msg) {
+        return new AjaxResult(500, msg);
+    }
+
+    public static AjaxResult error(int code, String msg) {
+        return new AjaxResult(code, msg);
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/config/PaymentAutoConfiguration.java b/dryad-payment/src/main/java/com/ruoyi/payment/config/PaymentAutoConfiguration.java
new file mode 100644
index 0000000..60ffce3
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/config/PaymentAutoConfiguration.java
@@ -0,0 +1,48 @@
+package com.ruoyi.payment.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+
+/**
+ * 鏀粯妯″潡鑷姩閰嶇疆绫�
+ * 
+ * 浣跨敤鏂瑰紡锛�
+ * 1. 浣滀负缁勪欢闆嗘垚鍒板叾浠栭」鐩椂锛屽湪涓婚」鐩殑 pom.xml 涓坊鍔犱緷璧栵細
+ *    <dependency>
+ *        <groupId>com.ruoyi</groupId>
+ *        <artifactId>dryad-payment</artifactId>
+ *        <version>1.0.0</version>
+ *    </dependency>
+ * 
+ * 2. 鍦ㄤ富椤圭洰鐨� application.yml 涓厤缃細
+ *    payment:
+ *      enabled: true  # 鍚敤鏀粯妯″潡
+ *      wechat: ...    # 寰俊閰嶇疆
+ *      alipay: ...    # 鏀粯瀹濋厤缃�
+ * 
+ * @author ruoyi
+ */
+@Configuration
+@ConditionalOnProperty(prefix = "payment", name = "enabled", havingValue = "true", matchIfMissing = true)
+@ComponentScan(
+    basePackages = {
+        "com.ruoyi.payment.interfaces.controller",
+        "com.ruoyi.payment.application.service",
+        "com.ruoyi.payment.domain.service",
+        "com.ruoyi.payment.infrastructure"
+    },
+    excludeFilters = @ComponentScan.Filter(
+        type = FilterType.REGEX,
+        pattern = "com\\.ruoyi\\.payment\\.example\\..*"
+    )
+)
+public class PaymentAutoConfiguration {
+    
+    public PaymentAutoConfiguration() {
+        System.out.println("=================================");
+        System.out.println("鏀粯妯″潡宸插惎鐢�");
+        System.out.println("=================================");
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/ClientType.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/ClientType.java
new file mode 100644
index 0000000..915d882
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/ClientType.java
@@ -0,0 +1,40 @@
+package com.ruoyi.payment.domain.enums;
+
+/**
+ * 瀹㈡埛绔被鍨嬫灇涓�
+ * 
+ * @author ruoyi
+ */
+public enum ClientType {
+    
+    /** 寰俊Native */
+    NATIVE("NATIVE", "寰俊Native"),
+    
+    /** 鏀粯瀹濆綋闈粯 */
+    ALIPAY_PRECREATE("ALIPAY_PRECREATE", "鏀粯瀹濆綋闈粯");
+
+    private final String code;
+    private final String desc;
+
+    ClientType(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public static ClientType fromCode(String code) {
+        for (ClientType type : values()) {
+            if (type.code.equals(code)) {
+                return type;
+            }
+        }
+        throw new IllegalArgumentException("鏈煡鐨勫鎴风绫诲瀷: " + code);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/OrderStatus.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/OrderStatus.java
new file mode 100644
index 0000000..8d38c78
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/OrderStatus.java
@@ -0,0 +1,52 @@
+package com.ruoyi.payment.domain.enums;
+
+/**
+ * 璁㈠崟鐘舵�佹灇涓�
+ * 
+ * @author ruoyi
+ */
+public enum OrderStatus {
+    
+    /** 鍒濆鍖� */
+    INIT("INIT", "鍒濆鍖�"),
+    
+    /** 寰呮敮浠� */
+    PENDING("PENDING", "寰呮敮浠�"),
+    
+    /** 鏀粯鎴愬姛 */
+    SUCCEEDED("SUCCEEDED", "鏀粯鎴愬姛"),
+    
+    /** 鏀粯澶辫触 */
+    FAILED("FAILED", "鏀粯澶辫触"),
+    
+    /** 宸插叧闂� */
+    CANCELED("CANCELED", "宸插叧闂�"),
+    
+    /** 宸茶繃鏈� */
+    EXPIRED("EXPIRED", "宸茶繃鏈�");
+
+    private final String code;
+    private final String desc;
+
+    OrderStatus(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public static OrderStatus fromCode(String code) {
+        for (OrderStatus status : values()) {
+            if (status.code.equals(code)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("鏈煡鐨勮鍗曠姸鎬�: " + code);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/PayChannel.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/PayChannel.java
new file mode 100644
index 0000000..189c3b8
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/PayChannel.java
@@ -0,0 +1,40 @@
+package com.ruoyi.payment.domain.enums;
+
+/**
+ * 鏀粯娓犻亾鏋氫妇
+ * 
+ * @author ruoyi
+ */
+public enum PayChannel {
+    
+    /** 寰俊鏀粯 */
+    WECHAT("WECHAT", "寰俊鏀粯"),
+    
+    /** 鏀粯瀹� */
+    ALIPAY("ALIPAY", "鏀粯瀹�");
+
+    private final String code;
+    private final String desc;
+
+    PayChannel(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public static PayChannel fromCode(String code) {
+        for (PayChannel channel : values()) {
+            if (channel.code.equals(code)) {
+                return channel;
+            }
+        }
+        throw new IllegalArgumentException("鏈煡鐨勬敮浠樻笭閬�: " + code);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/TransactionStatus.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/TransactionStatus.java
new file mode 100644
index 0000000..4cd29bb
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/enums/TransactionStatus.java
@@ -0,0 +1,46 @@
+package com.ruoyi.payment.domain.enums;
+
+/**
+ * 浜ゆ槗鐘舵�佹灇涓�
+ * 
+ * @author ruoyi
+ */
+public enum TransactionStatus {
+    
+    /** 寰呮敮浠� */
+    PENDING("PENDING", "寰呮敮浠�"),
+    
+    /** 鏀粯鎴愬姛 */
+    SUCCEEDED("SUCCEEDED", "鏀粯鎴愬姛"),
+    
+    /** 鏀粯澶辫触 */
+    FAILED("FAILED", "鏀粯澶辫触"),
+    
+    /** 宸插彇娑� */
+    CANCELED("CANCELED", "宸插彇娑�");
+
+    private final String code;
+    private final String desc;
+
+    TransactionStatus(String code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public static TransactionStatus fromCode(String code) {
+        for (TransactionStatus status : values()) {
+            if (status.code.equals(code)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("鏈煡鐨勪氦鏄撶姸鎬�: " + code);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/event/PaymentSuccessEvent.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/event/PaymentSuccessEvent.java
new file mode 100644
index 0000000..907123a
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/event/PaymentSuccessEvent.java
@@ -0,0 +1,50 @@
+package com.ruoyi.payment.domain.event;
+
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import lombok.Getter;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * 鏀粯鎴愬姛浜嬩欢
+ * 
+ * 浣跨敤鏂瑰紡锛�
+ * 1. 浣滀负jar鍖呴泦鎴愭椂锛屽湪涓婚」鐩腑鐩戝惉姝や簨浠讹細
+ *    @EventListener
+ *    public void handlePaymentSuccess(PaymentSuccessEvent event) {
+ *        PaymentOrder order = event.getOrder();
+ *        PaymentTransaction transaction = event.getTransaction();
+ *        // 澶勭悊涓氬姟閫昏緫
+ *    }
+ * 
+ * 2. 鎴栬�呭疄鐜� PaymentCallback 鎺ュ彛杩涜鍥炶皟
+ * 
+ * @author ruoyi
+ */
+@Getter
+public class PaymentSuccessEvent extends ApplicationEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鏀粯璁㈠崟
+     */
+    private final PaymentOrder order;
+
+    /**
+     * 鏀粯浜ゆ槗
+     */
+    private final PaymentTransaction transaction;
+
+    /**
+     * 鏀粯娓犻亾锛圵ECHAT/ALIPAY锛�
+     */
+    private final String channel;
+
+    public PaymentSuccessEvent(Object source, PaymentOrder order, PaymentTransaction transaction) {
+        super(source);
+        this.order = order;
+        this.transaction = transaction;
+        this.channel = order.getChannel();
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/BizCallbackLog.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/BizCallbackLog.java
new file mode 100644
index 0000000..39a11db
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/BizCallbackLog.java
@@ -0,0 +1,49 @@
+package com.ruoyi.payment.domain.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 涓氬姟鍥炶皟鏃ュ織
+ * 
+ * @author ruoyi
+ */
+@Data
+public class BizCallbackLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 鏃ュ織ID */
+    private Long id;
+
+    /** 璁㈠崟ID */
+    private Long orderId;
+
+    /** 浜ゆ槗ID */
+    private Long transactionId;
+
+    /** 鍥炶皟鍦板潃 */
+    private String callbackUrl;
+
+    /** 鍥炶皟璇锋眰浣� */
+    private String payload;
+
+    /** HTTP鐘舵�佺爜 */
+    private Integer httpStatus;
+
+    /** 鍝嶅簲鍐呭 */
+    private String response;
+
+    /** 鏄惁鎴愬姛 */
+    private Boolean success;
+
+    /** 閲嶈瘯娆℃暟 */
+    private Integer retryCount;
+
+    /** 鏈�鍚庨噸璇曟椂闂� */
+    private LocalDateTime lastRetryAt;
+
+    /** 鍒涘缓鏃堕棿 */
+    private LocalDateTime createdAt;
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/GoodsDetail.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/GoodsDetail.java
new file mode 100644
index 0000000..1eeede4
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/GoodsDetail.java
@@ -0,0 +1,51 @@
+package com.ruoyi.payment.domain.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 鍟嗗搧鏄庣粏
+ * 
+ * @author ruoyi
+ */
+@Data
+public class GoodsDetail implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 鍟嗗搧ID */
+    private String goodsId;
+
+    /** 鍟嗗搧鍚嶇О */
+    private String goodsName;
+
+    /** 鍟嗗搧鏁伴噺 */
+    private Integer quantity;
+
+    /** 鍟嗗搧鍗曚环锛堝垎锛� */
+    private Integer price;
+
+    /** 鍟嗗搧绫诲埆 */
+    private String goodsCategory;
+
+    /** 鍟嗗搧鎻忚堪 */
+    private String body;
+    
+    public GoodsDetail() {}
+    
+    public GoodsDetail(String goodsId, String goodsName, Integer quantity, Integer price) {
+        this.goodsId = goodsId;
+        this.goodsName = goodsName;
+        this.quantity = quantity;
+        this.price = price;
+    }
+    
+    public GoodsDetail(String goodsId, String goodsName, Integer quantity, Integer price, String goodsCategory, String body) {
+        this.goodsId = goodsId;
+        this.goodsName = goodsName;
+        this.quantity = quantity;
+        this.price = price;
+        this.goodsCategory = goodsCategory;
+        this.body = body;
+    }
+}
\ No newline at end of file
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/NotifyLog.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/NotifyLog.java
new file mode 100644
index 0000000..6975aa6
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/NotifyLog.java
@@ -0,0 +1,46 @@
+package com.ruoyi.payment.domain.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 娓犻亾鍥炶皟鏃ュ織
+ * 
+ * @author ruoyi
+ */
+@Data
+public class NotifyLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 鏃ュ織ID */
+    private Long id;
+
+    /** 鏀粯娓犻亾 */
+    private String channel;
+
+    /** 娓犻亾閫氱煡鍞竴鏍囪瘑 */
+    private String notifyIdOrSerial;
+
+    /** 璁㈠崟ID */
+    private Long orderId;
+
+    /** 浜ゆ槗ID */
+    private Long transactionId;
+
+    /** 鍥炶皟鍘熷鎶ユ枃 */
+    private String payload;
+
+    /** 绛惧悕楠岃瘉鏄惁閫氳繃 */
+    private Boolean verified;
+
+    /** 鏄惁宸插鐞� */
+    private Boolean processed;
+
+    /** 澶勭悊缁撴灉 */
+    private String result;
+
+    /** 鎺ユ敹鏃堕棿 */
+    private LocalDateTime createdAt;
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/OperationAudit.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/OperationAudit.java
new file mode 100644
index 0000000..35ebdf3
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/OperationAudit.java
@@ -0,0 +1,40 @@
+package com.ruoyi.payment.domain.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鎿嶄綔瀹¤
+ * 
+ * @author ruoyi
+ */
+@Data
+public class OperationAudit implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 瀹¤ID */
+    private Long id;
+
+    /** 鎿嶄綔浜� */
+    private String operator;
+
+    /** 鎿嶄綔绫诲瀷 */
+    private String operationType;
+
+    /** 璁㈠崟ID */
+    private Long orderId;
+
+    /** 浜ゆ槗ID */
+    private Long transactionId;
+
+    /** 鎿嶄綔鍙傛暟 */
+    private String params;
+
+    /** 鏄惁閫氳繃 */
+    private Boolean approved;
+
+    /** 鎿嶄綔鏃堕棿 */
+    private LocalDateTime createdAt;
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentOrder.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentOrder.java
new file mode 100644
index 0000000..0050670
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentOrder.java
@@ -0,0 +1,88 @@
+package com.ruoyi.payment.domain.model;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 鏀粯璁㈠崟 - 鑱氬悎鏍�
+ * 
+ * @author ruoyi
+ */
+@Data
+public class PaymentOrder implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 璁㈠崟ID */
+    private Long id;
+
+    /** 涓氬姟璁㈠崟鍙� */
+    private String bizOrderId;
+
+    /** 閲戦锛堝垎锛� */
+    private Integer amount;
+
+    /** 甯佺 */
+    private String currency;
+
+    /** 鏀粯娓犻亾 */
+    private String channel;
+
+    /** 璁㈠崟鐘舵�� */
+    private String status;
+
+    /** 璁㈠崟鏍囬 */
+    private String subject;
+
+    /** 璁㈠崟鎻忚堪 */
+    private String description;
+
+    /** 涓氬姟鍥炶皟鍦板潃 */
+    private String callbackUrl;
+
+    /** 杩囨湡鏃堕棿 */
+    private LocalDateTime expireAt;
+
+    /** 鏈�鏂颁氦鏄揑D */
+    private Long latestTransactionId;
+
+    /** 娓犻亾浜ゆ槗鍙� */
+    private String channelTradeNo;
+
+    /** 鏀粯鎴愬姛鏃堕棿 */
+    private LocalDateTime paidAt;
+
+    /** 涔愯閿佺増鏈彿 */
+    private Integer version;
+
+    /** 鍒涘缓鏃堕棿 */
+    private LocalDateTime createdAt;
+
+    /** 鏇存柊鏃堕棿 */
+    private LocalDateTime updatedAt;
+    
+    /** 鍟嗗搧鏄庣粏鍒楄〃 */
+    private List<GoodsDetail> goodsDetails;
+
+    /**
+     * 鍒ゆ柇璁㈠崟鏄惁宸茶繃鏈�
+     */
+    public boolean isExpired() {
+        return expireAt != null && LocalDateTime.now().isAfter(expireAt);
+    }
+
+    /**
+     * 鍒ゆ柇璁㈠崟鏄惁鍙互鏀粯
+     */
+    public boolean canPay() {
+        return "PENDING".equals(status) && !isExpired();
+    }
+
+    /**
+     * 鍒ゆ柇璁㈠崟鏄惁宸叉垚鍔�
+     */
+    public boolean isSuccess() {
+        return "SUCCEEDED".equals(status);
+    }
+}
\ No newline at end of file
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentTransaction.java b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentTransaction.java
new file mode 100644
index 0000000..143a93a
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/domain/model/PaymentTransaction.java
@@ -0,0 +1,66 @@
+package com.ruoyi.payment.domain.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鏀粯浜ゆ槗娴佹按
+ * 
+ * @author ruoyi
+ */
+@Data
+public class PaymentTransaction implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 浜ゆ槗ID */
+    private Long id;
+
+    /** 璁㈠崟ID */
+    private Long orderId;
+
+    /** 鏀粯娓犻亾 */
+    private String channel;
+
+    /** 瀹㈡埛绔被鍨� */
+    private String clientType;
+
+    /** 浜ゆ槗鐘舵�� */
+    private String status;
+
+    /** 浜岀淮鐮佸唴瀹� */
+    private String codeOrQr;
+
+    /** Base64浜岀淮鐮佸浘鐗� */
+    private String qrBase64;
+
+    /** 璇锋眰鍙傛暟蹇収 */
+    private String requestParams;
+
+    /** 鍝嶅簲蹇収 */
+    private String responseSnapshot;
+
+    /** 娓犻亾浜ゆ槗鍙� */
+    private String channelTradeNo;
+
+    /** 鍒涘缓鏃堕棿 */
+    private LocalDateTime createdAt;
+
+    /** 鏀粯瀹屾垚鏃堕棿 */
+    private LocalDateTime paidAt;
+
+    /**
+     * 鍒ゆ柇浜ゆ槗鏄惁寰呮敮浠�
+     */
+    public boolean isPending() {
+        return "PENDING".equals(status);
+    }
+
+    /**
+     * 鍒ゆ柇浜ゆ槗鏄惁宸叉垚鍔�
+     */
+    public boolean isSuccess() {
+        return "SUCCEEDED".equals(status);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/example/PaymentIntegrationExample.java b/dryad-payment/src/main/java/com/ruoyi/payment/example/PaymentIntegrationExample.java
new file mode 100644
index 0000000..4c4a5eb
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/example/PaymentIntegrationExample.java
@@ -0,0 +1,140 @@
+package com.ruoyi.payment.example;
+
+import com.ruoyi.payment.domain.event.PaymentSuccessEvent;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import com.ruoyi.payment.interfaces.callback.PaymentCallback;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鏀粯妯″潡闆嗘垚浣跨敤绀轰緥
+ * 
+ * 褰撴敮浠樻ā鍧椾綔涓簀ar鍖呴泦鎴愬埌涓婚」鐩椂锛屼富椤圭洰鍙互閫氳繃浠ヤ笅涓夌鏂瑰紡鎺ユ敹鏀粯鎴愬姛閫氱煡锛�
+ * 
+ * 鏂瑰紡1锛氱洃鍚琒pring浜嬩欢锛堟帹鑽愶級
+ * 鏂瑰紡2锛氬疄鐜癙aymentCallback鎺ュ彛锛堟帹鑽愶級
+ * 鏂瑰紡3锛氭彁渚汬TTP鍥炶皟URL锛堢敤浜庤法鏈嶅姟璋冪敤锛�
+ * 
+ * 娉ㄦ剰锛氭鏂囦欢浠呬綔涓虹ず渚嬶紝瀹為檯浣跨敤鏃跺簲鍦ㄤ富椤圭洰涓垱寤虹被浼肩殑瀹炵幇銆�
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class PaymentIntegrationExample implements PaymentCallback {
+
+    // ==================== 鏂瑰紡1锛氱洃鍚琒pring浜嬩欢 ====================
+    
+    /**
+     * 鐩戝惉鏀粯鎴愬姛浜嬩欢
+     * 
+     * 浼樼偣锛�
+     * - Spring鏍囧噯浜嬩欢鏈哄埗锛岃В鑰︽�уソ
+     * - 鍙互鏈夊涓洃鍚櫒
+     * - 鏀寔寮傛澶勭悊锛堟坊鍔燖Async锛�
+     * 
+     * 浣跨敤鏂瑰紡锛�
+     * 鍦ㄤ富椤圭洰鐨勪换鎰廆Component绫讳腑娣诲姞姝ゆ柟娉�
+     */
+    @EventListener
+    public void handlePaymentSuccess(PaymentSuccessEvent event) {
+        PaymentOrder order = event.getOrder();
+        PaymentTransaction transaction = event.getTransaction();
+        
+        log.info("銆愪簨浠剁洃鍚�戞敹鍒版敮浠樻垚鍔熼�氱煡");
+        log.info("涓氬姟璁㈠崟鍙�: {}", order.getBizOrderId());
+        log.info("鏀粯閲戦: {} 鍒�", order.getAmount());
+        log.info("鏀粯娓犻亾: {}", order.getChannel());
+        log.info("娓犻亾浜ゆ槗鍙�: {}", order.getChannelTradeNo());
+        log.info("鏀粯鏃堕棿: {}", order.getPaidAt());
+        
+        // 澶勭悊涓氬姟閫昏緫
+        processOrderPaymentSuccess(order, transaction);
+    }
+
+    // ==================== 鏂瑰紡2锛氬疄鐜癙aymentCallback鎺ュ彛 ====================
+    
+    /**
+     * 鏀粯鎴愬姛鍥炶皟
+     * 
+     * 浼樼偣锛�
+     * - 鎺ュ彛绾︽潫锛屾槑纭洖璋冩柟娉�
+     * - 绫诲瀷瀹夊叏
+     * - IDE鏅鸿兘鎻愮ず
+     * 
+     * 浣跨敤鏂瑰紡锛�
+     * 鍦ㄤ富椤圭洰涓垱寤虹被瀹炵幇PaymentCallback鎺ュ彛骞舵敞鍐屼负Bean
+     */
+    @Override
+    public void onPaymentSuccess(PaymentOrder order, PaymentTransaction transaction) {
+        log.info("銆愭帴鍙e洖璋冦�戞敹鍒版敮浠樻垚鍔熼�氱煡");
+        log.info("涓氬姟璁㈠崟鍙�: {}", order.getBizOrderId());
+        log.info("鏀粯閲戦: {} 鍒�", order.getAmount());
+        
+        // 澶勭悊涓氬姟閫昏緫
+        processOrderPaymentSuccess(order, transaction);
+    }
+
+    // ==================== 鏂瑰紡3锛欻TTP鍥炶皟URL ====================
+    
+    /**
+     * HTTP鍥炶皟鏂瑰紡
+     * 
+     * 鍦ㄥ垱寤烘敮浠樻椂浼犲叆callbackUrl锛�
+     * 
+     * PaymentRequest request = new PaymentRequest();
+     * request.setCallbackUrl("https://your-domain.com/api/payment/notify");
+     * 
+     * 鐒跺悗鍦ㄤ富椤圭洰涓垱寤烘帴鏀禜TTP鍥炶皟鐨勬帴鍙o細
+     * 
+     * @RestController
+     * @RequestMapping("/api/payment")
+     * public class PaymentNotifyController {
+     *     
+     *     @PostMapping("/notify")
+     *     public String receiveNotify(@RequestBody String payload,
+     *                                  @RequestHeader("X-Signature") String signature,
+     *                                  @RequestHeader("X-Nonce") String nonce,
+     *                                  @RequestHeader("X-Timestamp") String timestamp) {
+     *         // 1. 楠岃瘉绛惧悕
+     *         String signData = payload + nonce + timestamp;
+     *         String calculated = SignUtil.hmacSha256(signData, "your-secret-key");
+     *         if (!signature.equals(calculated)) {
+     *             return "绛惧悕楠岃瘉澶辫触";
+     *         }
+     *         
+     *         // 2. 瑙f瀽鏁版嵁
+     *         JSONObject data = JSON.parseObject(payload);
+     *         String bizOrderId = data.getString("bizOrderId");
+     *         Integer amount = data.getInteger("amount");
+     *         
+     *         // 3. 澶勭悊涓氬姟閫昏緫
+     *         processOrderPayment(bizOrderId, amount);
+     *         
+     *         return "success";
+     *     }
+     * }
+     */
+
+    // ==================== 涓氬姟澶勭悊绀轰緥 ====================
+    
+    /**
+     * 澶勭悊璁㈠崟鏀粯鎴愬姛鐨勪笟鍔¢�昏緫
+     */
+    private void processOrderPaymentSuccess(PaymentOrder order, PaymentTransaction transaction) {
+        String bizOrderId = order.getBizOrderId();
+        
+        // 绀轰緥锛氭洿鏂颁笟鍔¤鍗曠姸鎬�
+        // orderService.updateOrderStatus(bizOrderId, "PAID");
+        
+        // 绀轰緥锛氬彂閫佹敮浠樻垚鍔熼�氱煡
+        // notificationService.sendPaymentSuccessNotification(bizOrderId);
+        
+        // 绀轰緥锛氳Е鍙戝悗缁笟鍔℃祦绋�
+        // fulfillmentService.startFulfillment(bizOrderId);
+        
+        log.info("璁㈠崟 {} 鏀粯鎴愬姛锛屼笟鍔″鐞嗗畬鎴�", bizOrderId);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayF2FClient.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayF2FClient.java
new file mode 100644
index 0000000..3b30836
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayF2FClient.java
@@ -0,0 +1,173 @@
+package com.ruoyi.payment.infrastructure.channel.alipay;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.request.AlipayTradePrecreateRequest;
+import com.alipay.api.request.AlipayTradeQueryRequest;
+import com.alipay.api.request.AlipayTradeCloseRequest;
+import com.alipay.api.response.AlipayTradePrecreateResponse;
+import com.alipay.api.response.AlipayTradeQueryResponse;
+import com.alipay.api.response.AlipayTradeCloseResponse;
+import com.ruoyi.payment.domain.model.GoodsDetail;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.infrastructure.config.AlipayConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鏀粯瀹濆綋闈粯瀹㈡埛绔�
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class AlipayF2FClient {
+
+    @Autowired
+    private AlipayConfig alipayConfig;
+
+    private AlipayClient alipayClient;
+
+    /**
+     * 鍒濆鍖栨敮浠樺疂瀹㈡埛绔�
+     */
+    @PostConstruct
+    public void init() {
+        alipayClient = new DefaultAlipayClient(
+            alipayConfig.getServerUrl(),
+            alipayConfig.getAppId(),
+            alipayConfig.getPrivateKey(),
+            "json",
+            "UTF-8",
+            alipayConfig.getAlipayPublicKey(),
+            alipayConfig.getSignType()
+        );
+        log.info("鏀粯瀹濆鎴风鍒濆鍖栨垚鍔�");
+    }
+
+    /**
+     * 褰撻潰浠樹笅鍗� - 鐢熸垚浜岀淮鐮�
+     */
+    public String precreate(PaymentOrder order) throws AlipayApiException {
+        log.info("璋冪敤鏀粯瀹濆綋闈粯涓嬪崟鎺ュ彛锛岃鍗旾D: {}", order.getId());
+
+        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
+        request.setNotifyUrl(alipayConfig.getNotifyUrl());
+
+        // 鏋勯�犱笟鍔″弬鏁�
+        StringBuilder bizContent = new StringBuilder();
+        bizContent.append("{");
+        bizContent.append("\"out_trade_no\":\"").append(order.getId()).append("\","); // 鍟嗘埛璁㈠崟鍙�
+        bizContent.append("\"total_amount\":\"").append(formatAmount(order.getAmount())).append("\","); // 璁㈠崟閲戦锛屽崟浣嶏細鍏�
+        bizContent.append("\"subject\":\"").append(order.getSubject()).append("\""); // 璁㈠崟鏍囬
+        
+        // 娣诲姞鍟嗗搧鏄庣粏鍒楄〃
+        if (order.getGoodsDetails() != null && !order.getGoodsDetails().isEmpty()) {
+            bizContent.append(",\"goods_detail\":[");
+            for (int i = 0; i < order.getGoodsDetails().size(); i++) {
+                if (i > 0) {
+                    bizContent.append(",");
+                }
+                bizContent.append("{");
+                bizContent.append("\"goods_id\":\"").append(order.getGoodsDetails().get(i).getGoodsId()).append("\",");
+                bizContent.append("\"goods_name\":\"").append(order.getGoodsDetails().get(i).getGoodsName()).append("\",");
+                bizContent.append("\"quantity\":").append(order.getGoodsDetails().get(i).getQuantity()).append(",");
+                bizContent.append("\"price\":\"").append(formatAmount(order.getGoodsDetails().get(i).getPrice())).append("\"");
+                
+                // 娣诲姞鍙�夌殑鍟嗗搧绫诲埆鍜屾弿杩�
+                if (order.getGoodsDetails().get(i).getGoodsCategory() != null && !order.getGoodsDetails().get(i).getGoodsCategory().isEmpty()) {
+                    bizContent.append(",\"goods_category\":\"").append(order.getGoodsDetails().get(i).getGoodsCategory()).append("\"");
+                }
+                
+                if (order.getGoodsDetails().get(i).getBody() != null && !order.getGoodsDetails().get(i).getBody().isEmpty()) {
+                    bizContent.append(",\"body\":\"").append(order.getGoodsDetails().get(i).getBody()).append("\"");
+                }
+                
+                bizContent.append("}");
+            }
+            bizContent.append("]");
+        }
+        
+        if (order.getDescription() != null && !order.getDescription().isEmpty()) {
+            bizContent.append(",\"body\":\"").append(order.getDescription()).append("\"");
+        }
+        
+        // 璁剧疆瓒呮椂鏃堕棿
+        bizContent.append(",\"timeout_express\":\"30m\"");
+        
+        bizContent.append("}");
+
+        request.setBizContent(bizContent.toString());
+        log.info("鏀粯瀹濆綋闈粯璇锋眰鍙傛暟: {}", bizContent.toString());
+
+        // 璋冪敤SDK
+        AlipayTradePrecreateResponse response = alipayClient.execute(request);
+
+        if (!response.isSuccess()) {
+            log.error("鏀粯瀹濆綋闈粯涓嬪崟澶辫触: {}, {}", response.getSubCode(), response.getSubMsg());
+            throw new AlipayApiException("鏀粯瀹濆綋闈粯涓嬪崟澶辫触: " + response.getSubMsg());
+        }
+
+        String qrCode = response.getQrCode();
+        if (qrCode == null || qrCode.isEmpty()) {
+            throw new AlipayApiException("鏀粯瀹濇湭杩斿洖浜岀淮鐮�");
+        }
+
+        log.info("鏀粯瀹濆綋闈粯涓嬪崟鎴愬姛锛宷rCode: {}", qrCode);
+        return qrCode;
+    }
+
+    /**
+     * 鏌ヨ璁㈠崟
+     */
+    public AlipayTradeQueryResponse queryOrder(String outTradeNo) throws AlipayApiException {
+        log.info("鏌ヨ鏀粯瀹濊鍗曪紝鍟嗘埛璁㈠崟鍙�: {}", outTradeNo);
+
+        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
+        request.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");
+
+        AlipayTradeQueryResponse response = alipayClient.execute(request);
+
+        if (!response.isSuccess()) {
+            log.error("鏌ヨ鏀粯瀹濊鍗曞け璐�: {}, {}", response.getSubCode(), response.getSubMsg());
+            throw new AlipayApiException("鏌ヨ璁㈠崟澶辫触: " + response.getSubMsg());
+        }
+
+        log.info("鏌ヨ鏀粯瀹濊鍗曟垚鍔燂紝浜ゆ槗鐘舵��: {}", response.getTradeStatus());
+        return response;
+    }
+
+    /**
+     * 鍏抽棴璁㈠崟
+     */
+    public void closeOrder(String outTradeNo) throws AlipayApiException {
+        log.info("鍏抽棴鏀粯瀹濊鍗曪紝鍟嗘埛璁㈠崟鍙�: {}", outTradeNo);
+
+        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
+        request.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");
+
+        AlipayTradeCloseResponse response = alipayClient.execute(request);
+
+        if (!response.isSuccess()) {
+            log.error("鍏抽棴鏀粯瀹濊鍗曞け璐�: {}, {}", response.getSubCode(), response.getSubMsg());
+            throw new AlipayApiException("鍏抽棴璁㈠崟澶辫触: " + response.getSubMsg());
+        }
+
+        log.info("鍏抽棴鏀粯瀹濊鍗曟垚鍔�");
+    }
+
+    /**
+     * 鏍煎紡鍖栭噾棰濓細鍒嗚浆鍏冿紝淇濈暀涓や綅灏忔暟
+     */
+    private String formatAmount(Integer amountInCents) {
+        BigDecimal amount = new BigDecimal(amountInCents).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
+        return amount.toString();
+    }
+}
\ No newline at end of file
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayThirdPartyClient.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayThirdPartyClient.java
new file mode 100644
index 0000000..81c1363
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayThirdPartyClient.java
@@ -0,0 +1,196 @@
+package com.ruoyi.payment.infrastructure.channel.alipay;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鏀粯瀹濈涓夋柟鎺ュ彛瀹㈡埛绔�
+ * 璋冪敤鏃х郴缁熺殑鏀粯瀹濆綋闈粯鎺ュ彛
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class AlipayThirdPartyClient {
+
+    /**
+     * 绗笁鏂规敮浠樺疂褰撻潰浠樻帴鍙e湴鍧�
+     */
+    private static final String THIRD_PARTY_ALIPAY_URL = "https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php";
+
+    /**
+     * 绗笁鏂规敮浠樺疂鏌ヨ鎺ュ彛鍦板潃
+     */
+    private static final String THIRD_PARTY_QUERY_URL = "https://sys.966120.com.cn/alipay_pay_query.php";
+
+    /**
+     * 璋冪敤绗笁鏂规帴鍙g敓鎴愭敮浠樺疂褰撻潰浠楿RL
+     * 
+     * @param notifyUrl 寮傛鍥炶皟閫氱煡鍦板潃
+     * @param outTradeNo 鍟嗘埛璁㈠崟鍙�
+     * @param totalFee 璁㈠崟閲戦锛堝崟浣嶏細鍒嗭級
+     * @param serviceOrdId 涓氬姟璁㈠崟ID
+     * @return 鏀粯瀹濆綋闈粯URL
+     * @throws Exception 璋冪敤寮傚父
+     */
+    public String createQrCodeUrl(String notifyUrl, String outTradeNo, Integer totalFee, String serviceOrdId) 
+            throws Exception {
+        log.info("璋冪敤绗笁鏂规敮浠樺疂褰撻潰浠樻帴鍙o紝璁㈠崟鍙�: {}, 閲戦: {}鍒�, 涓氬姟璁㈠崟ID: {}", 
+                outTradeNo, totalFee, serviceOrdId);
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            HttpPost httpPost = new HttpPost(THIRD_PARTY_ALIPAY_URL);
+            
+            // 璁剧疆Cookie澶�
+            httpPost.setHeader("Cookie", "CAMEName=");
+            
+            // 鏋勫缓multipart/form-data璇锋眰浣�
+            HttpEntity entity = MultipartEntityBuilder.create()
+                    .addTextBody("notify_url", notifyUrl)
+                    .addTextBody("out_trade_no", outTradeNo)
+                    .addTextBody("total_fee", String.valueOf(totalFee))
+                    .addTextBody("ServiceOrdID", serviceOrdId)
+                    .build();
+            
+            httpPost.setEntity(entity);
+            
+            log.info("鍙戦�佽姹傚埌绗笁鏂规帴鍙�: {}", THIRD_PARTY_ALIPAY_URL);
+            
+            // 鍙戦�佽姹�
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                int statusCode = response.getStatusLine().getStatusCode();
+                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
+                
+                log.info("绗笁鏂规帴鍙e搷搴旓紝鐘舵�佺爜: {}, 鍝嶅簲鍐呭: {}", statusCode, responseBody);
+                
+                if (statusCode >= 200 && statusCode < 300) {
+                    // 鍝嶅簲鎴愬姛锛岃В鏋愯繑鍥炵殑URL
+                    String qrCodeUrl = parseQrCodeUrl(responseBody);
+                    
+                    if (qrCodeUrl == null || qrCodeUrl.isEmpty()) {
+                        throw new Exception("绗笁鏂规帴鍙f湭杩斿洖鏈夋晥鐨勬敮浠楿RL锛屽搷搴�: " + responseBody);
+                    }
+                    
+                    log.info("绗笁鏂规敮浠樺疂褰撻潰浠楿RL鐢熸垚鎴愬姛: {}", qrCodeUrl);
+                    return qrCodeUrl;
+                } else {
+                    throw new Exception("绗笁鏂规帴鍙h皟鐢ㄥけ璐ワ紝鐘舵�佺爜: " + statusCode + ", 鍝嶅簲: " + responseBody);
+                }
+            }
+        } catch (Exception e) {
+            log.error("璋冪敤绗笁鏂规敮浠樺疂褰撻潰浠樻帴鍙eけ璐�", e);
+            throw new Exception("璋冪敤绗笁鏂规敮浠樺疂褰撻潰浠樻帴鍙eけ璐�: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 瑙f瀽绗笁鏂规帴鍙e搷搴旓紝鎻愬彇鏀粯URL
+     * 鏍规嵁瀹為檯杩斿洖鏍煎紡璋冩暣瑙f瀽閫昏緫
+     * 
+     * @param responseBody 鍝嶅簲鍐呭
+     * @return 鏀粯URL
+     */
+    private String parseQrCodeUrl(String responseBody) {
+        // TODO: 鏍规嵁瀹為檯杩斿洖鏍煎紡璋冩暣瑙f瀽閫昏緫
+        // 杩欓噷鍋囪鐩存帴杩斿洖URL瀛楃涓诧紝鎴栬�呰繑鍥濲SON鏍煎紡
+        
+        if (responseBody == null || responseBody.isEmpty()) {
+            return null;
+        }
+        
+        // 鍘婚櫎鍙兘鐨勫紩鍙峰拰绌虹櫧瀛楃
+        String url = responseBody.trim();
+        if (url.startsWith("\"") && url.endsWith("\"")) {
+            url = url.substring(1, url.length() - 1);
+        }
+        
+        // 濡傛灉鏄疛SON鏍煎紡锛屽彲浠ヤ娇鐢‵astJSON瑙f瀽
+        // 绀轰緥锛歿"status": "success", "qr_code": "https://..."}
+        // JSONObject json = JSON.parseObject(responseBody);
+        // return json.getString("qr_code");
+        
+        return url;
+    }
+
+    /**
+     * 鏌ヨ鏀粯瀹濅氦鏄撶姸鎬�
+     * 
+     * @param outTradeNo 鍟嗘埛璁㈠崟鍙�
+     * @return 浜ゆ槗鐘舵�侊紙SUCCESS-鎴愬姛锛屽叾浠�-澶辫触鎴栧鐞嗕腑锛�
+     * @throws Exception 璋冪敤寮傚父
+     */
+    public String queryTradeStatus(String outTradeNo) throws Exception {
+        log.info("璋冪敤绗笁鏂规敮浠樺疂鏌ヨ鎺ュ彛锛岃鍗曞彿: {}", outTradeNo);
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            HttpPost httpPost = new HttpPost(THIRD_PARTY_QUERY_URL);
+            
+            // 璁剧疆Cookie澶�
+            httpPost.setHeader("Cookie", "CAMEName=");
+            
+            // 鏋勫缓multipart/form-data璇锋眰浣�
+            HttpEntity entity = MultipartEntityBuilder.create()
+                    .addTextBody("out_trade_no", outTradeNo)
+                    .build();
+            
+            httpPost.setEntity(entity);
+            
+            log.info("鍙戦�佹煡璇㈣姹傚埌绗笁鏂规帴鍙�: {}", THIRD_PARTY_QUERY_URL);
+            
+            // 鍙戦�佽姹�
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                int statusCode = response.getStatusLine().getStatusCode();
+                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
+                
+                log.info("绗笁鏂规煡璇㈡帴鍙e搷搴旓紝鐘舵�佺爜: {}, 鍝嶅簲鍐呭: {}", statusCode, responseBody);
+                
+                if (statusCode >= 200 && statusCode < 300) {
+                    // 鍝嶅簲鎴愬姛锛岃В鏋愪氦鏄撶姸鎬�
+                    String tradeStatus = parseTradeStatus(responseBody);
+                    
+                    log.info("绗笁鏂规敮浠樺疂浜ゆ槗鏌ヨ鎴愬姛锛岃鍗曞彿: {}, 鐘舵��: {}", outTradeNo, tradeStatus);
+                    return tradeStatus;
+                } else {
+                    throw new Exception("绗笁鏂规煡璇㈡帴鍙h皟鐢ㄥけ璐ワ紝鐘舵�佺爜: " + statusCode + ", 鍝嶅簲: " + responseBody);
+                }
+            }
+        } catch (Exception e) {
+            log.error("璋冪敤绗笁鏂规敮浠樺疂鏌ヨ鎺ュ彛澶辫触", e);
+            throw new Exception("璋冪敤绗笁鏂规敮浠樺疂鏌ヨ鎺ュ彛澶辫触: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 瑙f瀽浜ゆ槗鐘舵��
+     * 
+     * @param responseBody 鍝嶅簲鍐呭
+     * @return 浜ゆ槗鐘舵��
+     */
+    private String parseTradeStatus(String responseBody) {
+        if (responseBody == null || responseBody.isEmpty()) {
+            return "UNKNOWN";
+        }
+        
+        // 鍘婚櫎绌虹櫧瀛楃
+        String status = responseBody.trim();
+        
+        // 鍘婚櫎鍙兘鐨勫紩鍙�
+        if (status.startsWith("\"") && status.endsWith("\"")) {
+            status = status.substring(1, status.length() - 1);
+        }
+        
+        // 杞崲涓哄ぇ鍐�
+        status = status.toUpperCase();
+        
+        log.info("瑙f瀽浜ゆ槗鐘舵��: {}", status);
+        
+        return status;
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayUtil.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayUtil.java
new file mode 100644
index 0000000..4483a4b
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/alipay/AlipayUtil.java
@@ -0,0 +1,43 @@
+package com.ruoyi.payment.infrastructure.channel.alipay;
+
+import com.alipay.api.internal.util.AlipaySignature;
+import com.ruoyi.payment.infrastructure.config.AlipayConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 鏀粯瀹濆伐鍏风被
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class AlipayUtil {
+
+    @Autowired
+    private AlipayConfig alipayConfig;
+
+    /**
+     * 楠岃瘉鏀粯瀹濆洖璋冪鍚�
+     */
+    public boolean verifySign(Map<String, String> params) {
+        try {
+            if(!alipayConfig.getCheckSign()){
+                log.info("寮�濮嬩笉楠岃瘉鍥炶皟绛惧悕");
+                return true;
+            }
+            return AlipaySignature.rsaCheckV1(
+                params,
+                alipayConfig.getAlipayPublicKey(),
+                "UTF-8",
+                alipayConfig.getSignType()
+            );
+        } catch (Exception e) {
+            log.error("鏀粯瀹濈鍚嶉獙璇佸け璐�", e);
+            return false;
+        }
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayUtil.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayUtil.java
new file mode 100644
index 0000000..fc386ad
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayUtil.java
@@ -0,0 +1,129 @@
+package com.ruoyi.payment.infrastructure.channel.wechat;
+
+import com.ruoyi.payment.infrastructure.config.WechatPayConfig;
+import com.ruoyi.payment.infrastructure.util.SignUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.*;
+
+/**
+ * 寰俊鏀粯宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class WxPayUtil {
+
+    @Autowired
+    private WechatPayConfig wechatPayConfig;
+
+    /**
+     * XML杞琈ap
+     */
+    public Map<String, String> xmlToMap(String xml) throws Exception {
+        Map<String, String> data = new HashMap<>();
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
+        Document doc = builder.parse(is);
+        doc.getDocumentElement().normalize();
+        NodeList nodeList = doc.getDocumentElement().getChildNodes();
+        
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Node node = nodeList.item(i);
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                data.put(node.getNodeName(), node.getTextContent());
+            }
+        }
+        return data;
+    }
+
+    /**
+     * Map杞琗ML
+     */
+    public String mapToXml(Map<String, String> data) {
+        StringBuilder xml = new StringBuilder("<xml>");
+        for (Map.Entry<String, String> entry : data.entrySet()) {
+            xml.append("<").append(entry.getKey()).append(">");
+            xml.append("<![CDATA[").append(entry.getValue()).append("]]>");
+            xml.append("</").append(entry.getKey()).append(">");
+        }
+        xml.append("</xml>");
+        return xml.toString();
+    }
+
+    /**
+     * 鐢熸垚绛惧悕
+     */
+    public String generateSign(Map<String, String> data) {
+        // 1. 鍙傛暟鍚岮SCII鐮佷粠灏忓埌澶ф帓搴�
+        Set<String> keySet = data.keySet();
+        String[] keyArray = keySet.toArray(new String[0]);
+        Arrays.sort(keyArray);
+        
+        // 2. 鎷兼帴鍙傛暟
+        StringBuilder sb = new StringBuilder();
+        for (String k : keyArray) {
+            if ("sign".equals(k)) {
+                continue;
+            }
+            String value = data.get(k);
+            if (value != null && value.trim().length() > 0) {
+                sb.append(k).append("=").append(value).append("&");
+            }
+        }
+        
+        // 3. 鎷兼帴瀵嗛挜
+        sb.append("key=").append(wechatPayConfig.getMchKey());
+        
+        // 4. MD5鍔犲瘑骞惰浆澶у啓
+        return SignUtil.md5(sb.toString());
+    }
+
+    /**
+     * 楠岃瘉绛惧悕
+     */
+    public boolean verifySign(Map<String, String> data) {
+        if(!wechatPayConfig.getCheckSign()){
+            log.info("寰俊鍥炶皟涓嶆娴嬮獙璇佺鍚�");
+            return true;
+        }
+        String sign = data.get("sign");
+        if (sign == null || sign.isEmpty()) {
+            return false;
+        }
+        
+        String calculatedSign = generateSign(data);
+        return sign.equals(calculatedSign);
+    }
+
+    /**
+     * 鏋勯�犳垚鍔熷簲绛�
+     */
+    public String buildSuccessResponse() {
+        Map<String, String> response = new HashMap<>();
+        response.put("return_code", "SUCCESS");
+        response.put("return_msg", "OK");
+        return mapToXml(response);
+    }
+
+    /**
+     * 鏋勯�犲け璐ュ簲绛�
+     */
+    public String buildFailResponse(String msg) {
+        Map<String, String> response = new HashMap<>();
+        response.put("return_code", "FAIL");
+        response.put("return_msg", msg);
+        return mapToXml(response);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayV2Client.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayV2Client.java
new file mode 100644
index 0000000..238f0d0
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/channel/wechat/WxPayV2Client.java
@@ -0,0 +1,179 @@
+package com.ruoyi.payment.infrastructure.channel.wechat;
+
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.infrastructure.config.WechatPayConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 寰俊鏀粯v2瀹㈡埛绔�
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@Component
+public class WxPayV2Client {
+
+    private static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
+    private static final String ORDER_QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";
+    private static final String CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder";
+
+    @Autowired
+    private WechatPayConfig wechatPayConfig;
+
+    @Autowired
+    private WxPayUtil wxPayUtil;
+
+    /**
+     * 缁熶竴涓嬪崟 - Native鏀粯
+     */
+    public String unifiedOrder(PaymentOrder order) throws Exception {
+        log.info("璋冪敤寰俊缁熶竴涓嬪崟鎺ュ彛锛岃鍗旾D: {}", order.getId());
+
+        // 鏋勯�犺姹傚弬鏁�
+        Map<String, String> params = new HashMap<>();
+        params.put("appid", wechatPayConfig.getAppId());
+        params.put("mch_id", wechatPayConfig.getMchId());
+        params.put("nonce_str", generateNonceStr());
+        params.put("body", order.getSubject());
+        params.put("out_trade_no", String.valueOf(order.getId())); // 浣跨敤璁㈠崟ID浣滀负鍟嗘埛璁㈠崟鍙�
+        params.put("total_fee", String.valueOf(order.getAmount())); // 鍗曚綅锛氬垎
+        params.put("spbill_create_ip", "127.0.0.1");
+        params.put("notify_url", wechatPayConfig.getNotifyUrl());
+        params.put("trade_type", "NATIVE");
+        
+        if (order.getDescription() != null && !order.getDescription().isEmpty()) {
+            params.put("detail", order.getDescription());
+        }
+
+        // 鐢熸垚绛惧悕
+        String sign = wxPayUtil.generateSign(params);
+        params.put("sign", sign);
+
+        // 杞崲涓篨ML
+        String requestXml = wxPayUtil.mapToXml(params);
+        log.info("寰俊缁熶竴涓嬪崟璇锋眰: {}", requestXml);
+
+        // 鍙戦�丠TTP璇锋眰
+        String responseXml = doPost(UNIFIED_ORDER_URL, requestXml);
+        log.info("寰俊缁熶竴涓嬪崟鍝嶅簲: {}", responseXml);
+
+        // 瑙f瀽鍝嶅簲
+        Map<String, String> response = wxPayUtil.xmlToMap(responseXml);
+
+        // 楠岃瘉鍝嶅簲绛惧悕
+        if (!wxPayUtil.verifySign(response)) {
+            throw new RuntimeException("寰俊杩斿洖绛惧悕楠岃瘉澶辫触");
+        }
+
+        // 妫�鏌ヨ繑鍥炵姸鎬�
+        if (!"SUCCESS".equals(response.get("return_code"))) {
+            throw new RuntimeException("寰俊缁熶竴涓嬪崟澶辫触: " + response.get("return_msg"));
+        }
+
+        if (!"SUCCESS".equals(response.get("result_code"))) {
+            throw new RuntimeException("寰俊缁熶竴涓嬪崟涓氬姟澶辫触: " + response.get("err_code_des"));
+        }
+
+        // 杩斿洖code_url
+        String codeUrl = response.get("code_url");
+        if (codeUrl == null || codeUrl.isEmpty()) {
+            throw new RuntimeException("寰俊鏈繑鍥瀋ode_url");
+        }
+
+        log.info("寰俊缁熶竴涓嬪崟鎴愬姛锛宑ode_url: {}", codeUrl);
+        return codeUrl;
+    }
+
+    /**
+     * 鏌ヨ璁㈠崟
+     */
+    public Map<String, String> queryOrder(String outTradeNo) throws Exception {
+        log.info("鏌ヨ寰俊璁㈠崟锛屽晢鎴疯鍗曞彿: {}", outTradeNo);
+
+        Map<String, String> params = new HashMap<>();
+        params.put("appid", wechatPayConfig.getAppId());
+        params.put("mch_id", wechatPayConfig.getMchId());
+        params.put("out_trade_no", outTradeNo);
+        params.put("nonce_str", generateNonceStr());
+
+        String sign = wxPayUtil.generateSign(params);
+        params.put("sign", sign);
+
+        String requestXml = wxPayUtil.mapToXml(params);
+        String responseXml = doPost(ORDER_QUERY_URL, requestXml);
+
+        Map<String, String> response = wxPayUtil.xmlToMap(responseXml);
+
+        if (!wxPayUtil.verifySign(response)) {
+            throw new RuntimeException("鏌ヨ璁㈠崟鍝嶅簲绛惧悕楠岃瘉澶辫触");
+        }
+
+        if (!"SUCCESS".equals(response.get("return_code"))) {
+            throw new RuntimeException("鏌ヨ璁㈠崟澶辫触: " + response.get("return_msg"));
+        }
+
+        return response;
+    }
+
+    /**
+     * 鍏抽棴璁㈠崟
+     */
+    public void closeOrder(String outTradeNo) throws Exception {
+        log.info("鍏抽棴寰俊璁㈠崟锛屽晢鎴疯鍗曞彿: {}", outTradeNo);
+
+        Map<String, String> params = new HashMap<>();
+        params.put("appid", wechatPayConfig.getAppId());
+        params.put("mch_id", wechatPayConfig.getMchId());
+        params.put("out_trade_no", outTradeNo);
+        params.put("nonce_str", generateNonceStr());
+
+        String sign = wxPayUtil.generateSign(params);
+        params.put("sign", sign);
+
+        String requestXml = wxPayUtil.mapToXml(params);
+        String responseXml = doPost(CLOSE_ORDER_URL, requestXml);
+
+        Map<String, String> response = wxPayUtil.xmlToMap(responseXml);
+
+        if (!"SUCCESS".equals(response.get("return_code"))) {
+            throw new RuntimeException("鍏抽棴璁㈠崟澶辫触: " + response.get("return_msg"));
+        }
+
+        log.info("鍏抽棴寰俊璁㈠崟鎴愬姛");
+    }
+
+    /**
+     * 鍙戦�丳OST璇锋眰
+     */
+    private String doPost(String url, String xmlData) throws Exception {
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            HttpPost httpPost = new HttpPost(url);
+            httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
+            httpPost.setEntity(new StringEntity(xmlData, "UTF-8"));
+
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                HttpEntity entity = response.getEntity();
+                return EntityUtils.toString(entity, "UTF-8");
+            }
+        }
+    }
+
+    /**
+     * 鐢熸垚闅忔満瀛楃涓�
+     */
+    private String generateNonceStr() {
+        return java.util.UUID.randomUUID().toString().replace("-", "");
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/AlipayConfig.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/AlipayConfig.java
new file mode 100644
index 0000000..1a22b6f
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/AlipayConfig.java
@@ -0,0 +1,55 @@
+package com.ruoyi.payment.infrastructure.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鏀粯瀹濋厤缃�
+ * 
+ * @author ruoyi
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "payment.alipay")
+public class AlipayConfig {
+
+    /** 搴旂敤ID */
+    private String appId;
+
+    /** 鍟嗘埛绉侀挜 */
+    private String privateKey;
+
+    /** 鏀粯瀹濆叕閽� */
+    private String alipayPublicKey;
+
+    /** 鏈嶅姟鍣ㄥ湴鍧� */
+    private String serverUrl;
+
+    /** 鍥炶皟鍦板潃 */
+    private String notifyUrl;
+
+    /** 鍦ㄥ洖璋冩椂 鏄惁妫�鏌ョ鍚� */
+    private Boolean checkSign = true;
+
+    /** 绛惧悕绫诲瀷 */
+    private String signType = "RSA2";
+    
+    /** 鏀粯鏂瑰紡: OFFICIAL(瀹樻柟) 鎴� THIRD_PARTY(绗笁鏂�) */
+    private String paymentMethod = "OFFICIAL";
+    
+    /** 绗笁鏂规敮浠橀厤缃� */
+    private ThirdPartyConfig thirdParty = new ThirdPartyConfig();
+    
+    @Data
+    public static class ThirdPartyConfig {
+        /** 鏄惁鍚敤 */
+        private boolean enabled = false;
+        /** 绗笁鏂规帴鍙RL */
+        private String url = "https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php";
+        /** 榛樿鍥炶皟鍦板潃 */
+        private String defaultNotifyUrl = "https://dsp.966120.com.cn/alipay/pay_notify";
+        /** 瓒呮椂鏃堕棿锛堟绉掞級 */
+        private int timeout = 30000;
+    }
+}
\ No newline at end of file
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/BusinessCallbackConfig.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/BusinessCallbackConfig.java
new file mode 100644
index 0000000..208973c
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/BusinessCallbackConfig.java
@@ -0,0 +1,37 @@
+package com.ruoyi.payment.infrastructure.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 涓氬姟鍥炶皟閰嶇疆
+ * 
+ * @author ruoyi
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "payment.business")
+public class BusinessCallbackConfig {
+
+    /** 鍥炶皟绛惧悕瀵嗛挜 */
+    private String callbackSignSecret;
+
+    /** 鏈�澶ч噸璇曟鏁� */
+    private Integer callbackRetryMaxCount = 10;
+
+    /** 閲嶈瘯闂撮殧锛堝垎閽燂級 */
+    private String callbackRetryIntervals = "0,1,5,15,60";
+
+    /**
+     * 鑾峰彇閲嶈瘯闂撮殧鏁扮粍
+     */
+    public int[] getRetryIntervalsArray() {
+        String[] parts = callbackRetryIntervals.split(",");
+        int[] intervals = new int[parts.length];
+        for (int i = 0; i < parts.length; i++) {
+            intervals[i] = Integer.parseInt(parts[i].trim());
+        }
+        return intervals;
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/QrCodeConfig.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/QrCodeConfig.java
new file mode 100644
index 0000000..f396c9f
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/QrCodeConfig.java
@@ -0,0 +1,22 @@
+package com.ruoyi.payment.infrastructure.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 浜岀淮鐮侀厤缃�
+ * 
+ * @author ruoyi
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "payment.qrcode")
+public class QrCodeConfig {
+
+    /** 浜岀淮鐮佸昂瀵� */
+    private Integer size = 300;
+
+    /** 鍥剧墖鏍煎紡 */
+    private String format = "PNG";
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/WechatPayConfig.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/WechatPayConfig.java
new file mode 100644
index 0000000..7232142
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/config/WechatPayConfig.java
@@ -0,0 +1,36 @@
+package com.ruoyi.payment.infrastructure.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 寰俊鏀粯閰嶇疆
+ * 
+ * @author ruoyi
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "payment.wechat")
+public class WechatPayConfig {
+
+    /** 搴旂敤ID */
+    private String appId;
+
+    /** 鍟嗘埛鍙� */
+    private String mchId;
+
+    /** 鍟嗘埛瀵嗛挜 */
+    private String mchKey;
+
+    /** 鍥炶皟鍦板潃 */
+    private String notifyUrl;
+
+    /**
+     * 鍥炶皟鏄惁妫�鏌ョ鍚�
+     */
+    private Boolean checkSign=true;
+
+    /** 绛惧悕绫诲瀷 */
+    private String signType = "MD5";
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/BizCallbackLogMapper.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/BizCallbackLogMapper.java
new file mode 100644
index 0000000..43e290a
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/BizCallbackLogMapper.java
@@ -0,0 +1,29 @@
+package com.ruoyi.payment.infrastructure.persistence.mapper;
+
+import com.ruoyi.payment.domain.model.BizCallbackLog;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 涓氬姟鍥炶皟鏃ュ織Mapper
+ * 
+ * @author ruoyi
+ */
+@Mapper
+public interface BizCallbackLogMapper {
+
+    /**
+     * 鎻掑叆涓氬姟鍥炶皟鏃ュ織
+     */
+    int insert(BizCallbackLog bizCallbackLog);
+
+    /**
+     * 鏇存柊涓氬姟鍥炶皟鏃ュ織
+     */
+    int update(BizCallbackLog bizCallbackLog);
+
+    /**
+     * 鏍规嵁ID鏌ヨ
+     */
+    BizCallbackLog selectById(@Param("id") Long id);
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/NotifyLogMapper.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/NotifyLogMapper.java
new file mode 100644
index 0000000..d5dd215
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/NotifyLogMapper.java
@@ -0,0 +1,35 @@
+package com.ruoyi.payment.infrastructure.persistence.mapper;
+
+import com.ruoyi.payment.domain.model.NotifyLog;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 娓犻亾鍥炶皟鏃ュ織Mapper
+ * 
+ * @author ruoyi
+ */
+@Mapper
+public interface NotifyLogMapper {
+
+    /**
+     * 鎻掑叆鍥炶皟鏃ュ織
+     */
+    int insert(NotifyLog notifyLog);
+
+    /**
+     * 鏇存柊鍥炶皟鏃ュ織
+     */
+    int update(NotifyLog notifyLog);
+
+    /**
+     * 鏍规嵁ID鏌ヨ
+     */
+    NotifyLog selectById(@Param("id") Long id);
+
+    /**
+     * 鏌ヨ宸插鐞嗙殑鍥炶皟璁板綍鏁伴噺锛堝箓绛夋�ф鏌ワ級
+     */
+    int selectProcessedCount(@Param("channel") String channel, 
+                             @Param("notifyIdOrSerial") String notifyIdOrSerial);
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/OperationAuditMapper.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/OperationAuditMapper.java
new file mode 100644
index 0000000..3036aa5
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/OperationAuditMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.payment.infrastructure.persistence.mapper;
+
+import com.ruoyi.payment.domain.model.OperationAudit;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 鎿嶄綔瀹¤Mapper
+ * 
+ * @author ruoyi
+ */
+@Mapper
+public interface OperationAuditMapper {
+
+    /**
+     * 鎻掑叆瀹¤璁板綍
+     */
+    int insert(OperationAudit operationAudit);
+
+    /**
+     * 鏍规嵁ID鏌ヨ
+     */
+    OperationAudit selectById(@Param("id") Long id);
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentOrderMapper.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentOrderMapper.java
new file mode 100644
index 0000000..693fc35
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentOrderMapper.java
@@ -0,0 +1,40 @@
+package com.ruoyi.payment.infrastructure.persistence.mapper;
+
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 鏀粯璁㈠崟Mapper
+ * 
+ * @author ruoyi
+ */
+@Mapper
+public interface PaymentOrderMapper {
+
+    /**
+     * 鎻掑叆鏀粯璁㈠崟
+     */
+    int insert(PaymentOrder order);
+
+    /**
+     * 鏇存柊鏀粯璁㈠崟
+     */
+    int update(PaymentOrder order);
+
+    /**
+     * 鏍规嵁ID鏌ヨ璁㈠崟
+     */
+    PaymentOrder selectById(@Param("id") Long id);
+
+    /**
+     * 鏍规嵁涓氬姟璁㈠崟鍙峰拰娓犻亾鏌ヨ璁㈠崟
+     */
+    PaymentOrder selectByBizOrderIdAndChannel(@Param("bizOrderId") String bizOrderId, 
+                                               @Param("channel") String channel);
+
+    /**
+     * 鏍规嵁娓犻亾浜ゆ槗鍙锋煡璇㈣鍗�
+     */
+    PaymentOrder selectByChannelTradeNo(@Param("channelTradeNo") String channelTradeNo);
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentTransactionMapper.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentTransactionMapper.java
new file mode 100644
index 0000000..264f242
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/persistence/mapper/PaymentTransactionMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.payment.infrastructure.persistence.mapper;
+
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 鏀粯浜ゆ槗Mapper
+ * 
+ * @author ruoyi
+ */
+@Mapper
+public interface PaymentTransactionMapper {
+
+    /**
+     * 鎻掑叆浜ゆ槗璁板綍
+     */
+    int insert(PaymentTransaction transaction);
+
+    /**
+     * 鏇存柊浜ゆ槗璁板綍
+     */
+    int update(PaymentTransaction transaction);
+
+    /**
+     * 鏍规嵁ID鏌ヨ浜ゆ槗
+     */
+    PaymentTransaction selectById(@Param("id") Long id);
+
+    /**
+     * 鏌ヨ璁㈠崟鐨勫緟鏀粯浜ゆ槗
+     */
+    PaymentTransaction selectPendingByOrderId(@Param("orderId") Long orderId);
+
+    /**
+     * 鏍规嵁娓犻亾浜ゆ槗鍙锋煡璇�
+     */
+    PaymentTransaction selectByChannelTradeNo(@Param("channelTradeNo") String channelTradeNo);
+
+    /**
+     * 鏌ヨ璁㈠崟鐨勬渶鏂颁氦鏄�
+     */
+    PaymentTransaction selectLatestByOrderId(@Param("orderId") Long orderId);
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/QrCodeUtil.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/QrCodeUtil.java
new file mode 100644
index 0000000..e3df5b3
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/QrCodeUtil.java
@@ -0,0 +1,61 @@
+package com.ruoyi.payment.infrastructure.util;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.springframework.stereotype.Component;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 浜岀淮鐮佺敓鎴愬伐鍏�
+ * 
+ * @author ruoyi
+ */
+@Component
+public class QrCodeUtil {
+
+    /**
+     * 鐢熸垚浜岀淮鐮丅ase64瀛楃涓�
+     * 
+     * @param content 浜岀淮鐮佸唴瀹�
+     * @param size 灏哄
+     * @return Base64瀛楃涓�
+     */
+    public String generateQrCodeBase64(String content, int size) {
+        try {
+            // 閰嶇疆鍙傛暟
+            Map<EncodeHintType, Object> hints = new HashMap<>();
+            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
+            hints.put(EncodeHintType.MARGIN, 1);
+
+            // 鐢熸垚浜岀淮鐮�
+            QRCodeWriter qrCodeWriter = new QRCodeWriter();
+            BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);
+
+            // 杞崲涓哄浘鐗�
+            BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
+
+            // 杞崲涓築ase64
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, "PNG", baos);
+            byte[] bytes = baos.toByteArray();
+            String base64String = Base64.getEncoder().encodeToString(bytes);
+
+            return "data:image/png;base64," + base64String;
+        } catch (WriterException | IOException e) {
+            throw new RuntimeException("浜岀淮鐮佺敓鎴愬け璐�", e);
+        }
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SignUtil.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SignUtil.java
new file mode 100644
index 0000000..69118d3
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SignUtil.java
@@ -0,0 +1,63 @@
+package com.ruoyi.payment.infrastructure.util;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+/**
+ * 绛惧悕宸ュ叿绫�
+ * 
+ * @author ruoyi
+ */
+public class SignUtil {
+
+    /**
+     * MD5绛惧悕
+     * 
+     * @param data 寰呯鍚嶆暟鎹�
+     * @return 绛惧悕缁撴灉
+     */
+    public static String md5(String data) {
+        return DigestUtils.md5Hex(data).toUpperCase();
+    }
+
+    /**
+     * HMAC-SHA256绛惧悕
+     * 
+     * @param data 寰呯鍚嶆暟鎹�
+     * @param secret 瀵嗛挜
+     * @return 绛惧悕缁撴灉锛圔ase64缂栫爜锛�
+     */
+    public static String hmacSha256(String data, String secret) {
+        try {
+            Mac mac = Mac.getInstance("HmacSHA256");
+            SecretKeySpec secretKeySpec = new SecretKeySpec(
+                    secret.getBytes(StandardCharsets.UTF_8), 
+                    "HmacSHA256"
+            );
+            mac.init(secretKeySpec);
+            byte[] bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
+            return Base64.getEncoder().encodeToString(bytes);
+        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+            throw new RuntimeException("HMAC-SHA256绛惧悕澶辫触", e);
+        }
+    }
+
+    /**
+     * 楠岃瘉HMAC-SHA256绛惧悕
+     * 
+     * @param data 鍘熷鏁版嵁
+     * @param secret 瀵嗛挜
+     * @param signature 绛惧悕
+     * @return 鏄惁楠岃瘉閫氳繃
+     */
+    public static boolean verifyHmacSha256(String data, String secret, String signature) {
+        String calculated = hmacSha256(data, secret);
+        return calculated.equals(signature);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SnowflakeIdGenerator.java b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SnowflakeIdGenerator.java
new file mode 100644
index 0000000..0c0674c
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/infrastructure/util/SnowflakeIdGenerator.java
@@ -0,0 +1,96 @@
+package com.ruoyi.payment.infrastructure.util;
+
+/**
+ * 闆姳绠楁硶ID鐢熸垚鍣�
+ * 
+ * @author ruoyi
+ */
+public class SnowflakeIdGenerator {
+
+    // 璧峰鏃堕棿鎴� (2020-01-01)
+    private static final long START_TIMESTAMP = 1577808000000L;
+
+    // 姣忛儴鍒嗗崰鐢ㄧ殑浣嶆暟
+    private static final long SEQUENCE_BIT = 12;   // 搴忓垪鍙峰崰鐢ㄧ殑浣嶆暟
+    private static final long MACHINE_BIT = 5;     // 鏈哄櫒鏍囪瘑鍗犵敤鐨勪綅鏁�
+    private static final long DATACENTER_BIT = 5;  // 鏁版嵁涓績鍗犵敤鐨勪綅鏁�
+
+    // 姣忛儴鍒嗙殑鏈�澶у��
+    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
+    private static final long MAX_MACHINE_NUM = ~(-1L << MACHINE_BIT);
+    private static final long MAX_DATACENTER_NUM = ~(-1L << DATACENTER_BIT);
+
+    // 姣忛儴鍒嗗悜宸︾殑浣嶇Щ
+    private static final long MACHINE_LEFT = SEQUENCE_BIT;
+    private static final long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
+    private static final long TIMESTAMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
+
+    private static long datacenterId = 1;  // 鏁版嵁涓績ID
+    private static long machineId = 1;     // 鏈哄櫒ID
+    private static long sequence = 0L;     // 搴忓垪鍙�
+    private static long lastTimestamp = -1L;  // 涓婁竴娆℃椂闂存埑
+
+    private SnowflakeIdGenerator() {}
+
+    /**
+     * 鐢熸垚鍞竴ID
+     */
+    public static synchronized long generateId() {
+        long currTimestamp = getCurrentTimestamp();
+
+        if (currTimestamp < lastTimestamp) {
+            throw new RuntimeException("鏃堕挓鍥炴嫧锛屾嫆缁濈敓鎴怚D");
+        }
+
+        if (currTimestamp == lastTimestamp) {
+            // 鐩稿悓姣鍐咃紝搴忓垪鍙疯嚜澧�
+            sequence = (sequence + 1) & MAX_SEQUENCE;
+            // 鍚屼竴姣鐨勫簭鍒楁暟宸茬粡杈惧埌鏈�澶�
+            if (sequence == 0L) {
+                currTimestamp = getNextTimestamp();
+            }
+        } else {
+            // 涓嶅悓姣鍐咃紝搴忓垪鍙风疆涓�0
+            sequence = 0L;
+        }
+
+        lastTimestamp = currTimestamp;
+
+        return (currTimestamp - START_TIMESTAMP) << TIMESTAMP_LEFT  // 鏃堕棿鎴抽儴鍒�
+                | datacenterId << DATACENTER_LEFT                     // 鏁版嵁涓績閮ㄥ垎
+                | machineId << MACHINE_LEFT                           // 鏈哄櫒鏍囪瘑閮ㄥ垎
+                | sequence;                                           // 搴忓垪鍙烽儴鍒�
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿鎴�
+     */
+    private static long getCurrentTimestamp() {
+        return System.currentTimeMillis();
+    }
+
+    /**
+     * 鑾峰彇涓嬩竴涓椂闂存埑
+     */
+    private static long getNextTimestamp() {
+        long timestamp = getCurrentTimestamp();
+        while (timestamp <= lastTimestamp) {
+            timestamp = getCurrentTimestamp();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 璁剧疆鏁版嵁涓績ID鍜屾満鍣↖D
+     */
+    public static void setWorker(long datacenterId, long machineId) {
+        if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
+            throw new IllegalArgumentException("datacenterId 涓嶈兘澶т簬 " + MAX_DATACENTER_NUM + " 鎴栧皬浜� 0");
+        }
+        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
+            throw new IllegalArgumentException("machineId 涓嶈兘澶т簬 " + MAX_MACHINE_NUM + " 鎴栧皬浜� 0");
+        }
+        SnowflakeIdGenerator.datacenterId = datacenterId;
+        SnowflakeIdGenerator.machineId = machineId;
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/callback/PaymentCallback.java b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/callback/PaymentCallback.java
new file mode 100644
index 0000000..523c71f
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/callback/PaymentCallback.java
@@ -0,0 +1,32 @@
+package com.ruoyi.payment.interfaces.callback;
+
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+
+/**
+ * 鏀粯鍥炶皟鎺ュ彛
+ * 
+ * 浣跨敤鏂瑰紡锛�
+ * 鍦ㄤ富椤圭洰涓疄鐜版鎺ュ彛骞舵敞鍐屼负Spring Bean锛屾敮浠樻垚鍔熷悗浼氳嚜鍔ㄨ皟鐢細
+ * 
+ * @Component
+ * public class MyPaymentCallback implements PaymentCallback {
+ *     @Override
+ *     public void onPaymentSuccess(PaymentOrder order, PaymentTransaction transaction) {
+ *         // 澶勭悊鏀粯鎴愬姛涓氬姟閫昏緫
+ *         log.info("璁㈠崟鏀粯鎴愬姛: {}", order.getBizOrderId());
+ *     }
+ * }
+ * 
+ * @author ruoyi
+ */
+public interface PaymentCallback {
+
+    /**
+     * 鏀粯鎴愬姛鍥炶皟
+     * 
+     * @param order 鏀粯璁㈠崟
+     * @param transaction 鏀粯浜ゆ槗
+     */
+    void onPaymentSuccess(PaymentOrder order, PaymentTransaction transaction);
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/HealthController.java b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/HealthController.java
new file mode 100644
index 0000000..6d42535
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/HealthController.java
@@ -0,0 +1,38 @@
+package com.ruoyi.payment.interfaces.controller;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.payment.common.AjaxResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鍋ュ悍妫�鏌ユ帶鍒跺櫒
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/pay/health")
+public class HealthController {
+
+    /**
+     * 鍋ュ悍妫�鏌�
+     */
+    @Anonymous
+    @GetMapping("/health")
+    public AjaxResult health() {
+        Map<String, Object> data = new HashMap<>();
+        data.put("status", "UP");
+        data.put("service", "dryad-payment");
+        data.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+        data.put("message", "鏀粯妯″潡鏈嶅姟杩愯姝e父");
+        return AjaxResult.success(data);
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentController.java b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentController.java
new file mode 100644
index 0000000..311f0bd
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentController.java
@@ -0,0 +1,122 @@
+package com.ruoyi.payment.interfaces.controller;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.payment.application.service.PaymentService;
+import com.ruoyi.payment.common.AjaxResult;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import com.ruoyi.payment.interfaces.dto.PaymentRequest;
+import com.ruoyi.payment.interfaces.dto.PaymentResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 鏀粯鎺ュ彛鎺у埗鍣�
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/pay/payment")
+public class PaymentController {
+
+    @Autowired
+    private PaymentService paymentService;
+
+    @Anonymous()
+    @GetMapping("/hello")
+    public String hello() {
+        return "Hello, World!";
+    }
+    /**
+     * 鍙戣捣寰俊Native鏀粯
+     */
+    @PostMapping("/wechat/native")
+    public AjaxResult createWechatNativePayment(@Validated @RequestBody PaymentRequest request) {
+        try {
+            PaymentResponse response = paymentService.createWechatNativePayment(request);
+            return AjaxResult.success(response);
+        } catch (Exception e) {
+            log.error("鍙戣捣寰俊Native鏀粯澶辫触", e);
+            return AjaxResult.error("鏀粯鍒涘缓澶辫触: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 鍙戣捣鏀粯瀹濆綋闈粯
+     */
+    @PostMapping("/alipay/precreate")
+    public AjaxResult createAlipayPrecreate(@Validated @RequestBody PaymentRequest request) {
+        try {
+            PaymentResponse response = paymentService.createAlipayPrecreate(request);
+            return AjaxResult.success(response);
+        } catch (Exception e) {
+            log.error("鍙戣捣鏀粯瀹濆綋闈粯澶辫触", e);
+            return AjaxResult.error("鏀粯鍒涘缓澶辫触: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 鍙戣捣鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛�
+     */
+    @PostMapping("/alipay/thirdparty/precreate")
+    public AjaxResult createAlipayThirdPartyPrecreate(@Validated @RequestBody PaymentRequest request) {
+        try {
+            PaymentResponse response = paymentService.createAlipayThirdPartyPrecreate(request);
+            return AjaxResult.success(response);
+        } catch (Exception e) {
+            log.error("鍙戣捣鏀粯瀹濆綋闈粯锛堢涓夋柟鎺ュ彛锛夊け璐�", e);
+            return AjaxResult.error("鏀粯鍒涘缓澶辫触: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 鏌ヨ璁㈠崟
+     */
+    @GetMapping("/orders/{orderId}")
+    public AjaxResult getOrder(@PathVariable Long orderId) {
+        try {
+            PaymentOrder order = paymentService.getOrder(orderId);
+            if (order == null) {
+                return AjaxResult.error("璁㈠崟涓嶅瓨鍦�");
+            }
+            return AjaxResult.success(order);
+        } catch (Exception e) {
+            log.error("鏌ヨ璁㈠崟澶辫触", e);
+            return AjaxResult.error("鏌ヨ澶辫触: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 鏌ヨ鏈�鏂颁氦鏄�
+     */
+    @GetMapping("/orders/{orderId}/transactions/latest")
+    public AjaxResult getLatestTransaction(@PathVariable Long orderId) {
+        try {
+            PaymentTransaction transaction = paymentService.getLatestTransaction(orderId);
+            if (transaction == null) {
+                return AjaxResult.error("浜ゆ槗涓嶅瓨鍦�");
+            }
+            return AjaxResult.success(transaction);
+        } catch (Exception e) {
+            log.error("鏌ヨ浜ゆ槗澶辫触", e);
+            return AjaxResult.error("鏌ヨ澶辫触: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 鏌ヨ鏀粯瀹濈涓夋柟浜ゆ槗鐘舵��
+     */
+    @GetMapping("/alipay/thirdparty/query/{orderId}")
+    public AjaxResult queryAlipayThirdPartyTradeStatus(@PathVariable Long orderId) {
+        try {
+            String tradeStatus = paymentService.queryAlipayThirdPartyTradeStatus(orderId);
+            return AjaxResult.success(tradeStatus);
+        } catch (Exception e) {
+            log.error("鏌ヨ鏀粯瀹濈涓夋柟浜ゆ槗鐘舵�佸け璐�", e);
+            return AjaxResult.error("鏌ヨ澶辫触: " + e.getMessage());
+        }
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentNotifyController.java b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentNotifyController.java
new file mode 100644
index 0000000..c8721a8
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/controller/PaymentNotifyController.java
@@ -0,0 +1,128 @@
+package com.ruoyi.payment.interfaces.controller;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.payment.application.service.PaymentNotifyService;
+import com.ruoyi.payment.infrastructure.channel.alipay.AlipayUtil;
+import com.ruoyi.payment.infrastructure.channel.wechat.WxPayUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 娓犻亾鍥炶皟鎺ュ彛鎺у埗鍣�
+ * 
+ * @author ruoyi
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/pay/notify")
+public class PaymentNotifyController {
+
+    @Autowired
+    private WxPayUtil wxPayUtil;
+
+    @Autowired
+    private AlipayUtil alipayUtil;
+
+    @Autowired
+    private PaymentNotifyService paymentNotifyService;
+
+    /**
+     * 寰俊鏀粯鍥炶皟
+     */
+    @Anonymous
+    @PostMapping("/wechat")
+    public String wechatNotify(HttpServletRequest request) {
+        try {
+            log.info("鎺ユ敹鍒板井淇℃敮浠樺洖璋�");
+            
+            // 1. 璇诲彇XML鎶ユ枃
+            String xmlData = readRequestBody(request);
+            log.info("寰俊鍥炶皟鎶ユ枃: {}", xmlData);
+            
+            // 2. 瑙f瀽XML涓篗ap
+            Map<String, String> params = wxPayUtil.xmlToMap(xmlData);
+            
+            // 3. 楠岃瘉绛惧悕
+            if (!wxPayUtil.verifySign(params)) {
+                log.error("寰俊鍥炶皟绛惧悕楠岃瘉澶辫触");
+                return wxPayUtil.buildFailResponse("绛惧悕楠岃瘉澶辫触");
+            }
+            
+            log.info("寰俊鍥炶皟绛惧悕楠岃瘉閫氳繃");
+            
+            // 4. 澶勭悊鍥炶皟锛堟洿鏂拌鍗曠姸鎬併�佽Е鍙戜笟鍔″洖璋冿級
+            paymentNotifyService.processWechatNotify(params, xmlData);
+            
+            // 5. 杩斿洖寰俊瑕佹眰鐨刋ML搴旂瓟
+            return wxPayUtil.buildSuccessResponse();
+        } catch (Exception e) {
+            log.error("澶勭悊寰俊鍥炶皟澶辫触", e);
+            return wxPayUtil.buildFailResponse("澶勭悊澶辫触");
+        }
+    }
+
+    @Anonymous
+    @GetMapping("/hello")
+    public String hello() {
+        return "hello";
+    }
+
+    /**
+     * 鏀粯瀹濆洖璋�
+     */
+    @Anonymous
+    @PostMapping("/alipay")
+    public String alipayNotify(HttpServletRequest request) {
+        try {
+            log.info("鎺ユ敹鍒版敮浠樺疂鍥炶皟");
+            
+            // 1. 鑾峰彇鎵�鏈夊弬鏁�
+            Map<String, String> params = new HashMap<>();
+            Enumeration<String> parameterNames = request.getParameterNames();
+            while (parameterNames.hasMoreElements()) {
+                String name = parameterNames.nextElement();
+                params.put(name, request.getParameter(name));
+            }
+            
+            log.info("鏀粯瀹濆洖璋冨弬鏁�: {}", params);
+            
+            // 2. 楠岃瘉绛惧悕
+            if (!alipayUtil.verifySign(params)) {
+                log.error("鏀粯瀹濆洖璋冪鍚嶉獙璇佸け璐�");
+                return "fail";
+            }
+            
+            log.info("鏀粯瀹濆洖璋冪鍚嶉獙璇侀�氳繃");
+            
+            // 3. 澶勭悊鍥炶皟锛堟洿鏂拌鍗曠姸鎬併�佽Е鍙戜笟鍔″洖璋冿級
+            paymentNotifyService.processAlipayNotify(params);
+            
+            // 4. 杩斿洖鏀粯瀹濊姹傜殑搴旂瓟
+            return "success";
+        } catch (Exception e) {
+            log.error("澶勭悊鏀粯瀹濆洖璋冨け璐�", e);
+            return "fail";
+        }
+    }
+
+    /**
+     * 璇诲彇璇锋眰浣�
+     */
+    private String readRequestBody(HttpServletRequest request) throws Exception {
+        StringBuilder sb = new StringBuilder();
+        try (BufferedReader reader = request.getReader()) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentRequest.java b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentRequest.java
new file mode 100644
index 0000000..ec9f5fd
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentRequest.java
@@ -0,0 +1,38 @@
+package com.ruoyi.payment.interfaces.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * 鍙戣捣鏀粯璇锋眰
+ * 
+ * @author ruoyi
+ */
+@Data
+public class PaymentRequest implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 涓氬姟璁㈠崟鍙� */
+    @NotBlank(message = "涓氬姟璁㈠崟鍙蜂笉鑳戒负绌�")
+    private String bizOrderId;
+
+    /** 閲戦锛堝垎锛� */
+    @NotNull(message = "閲戦涓嶈兘涓虹┖")
+    @Min(value = 1, message = "閲戦蹇呴』澶т簬0")
+    private Integer amount;
+
+    /** 璁㈠崟鏍囬 */
+    @NotBlank(message = "璁㈠崟鏍囬涓嶈兘涓虹┖")
+    private String subject;
+
+    /** 璁㈠崟鎻忚堪 */
+    private String description;
+
+    /** 涓氬姟鍥炶皟鍦板潃 */
+    @NotBlank(message = "鍥炶皟鍦板潃涓嶈兘涓虹┖")
+    private String callbackUrl;
+}
diff --git a/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentResponse.java b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentResponse.java
new file mode 100644
index 0000000..b676b38
--- /dev/null
+++ b/dryad-payment/src/main/java/com/ruoyi/payment/interfaces/dto/PaymentResponse.java
@@ -0,0 +1,33 @@
+package com.ruoyi.payment.interfaces.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鏀粯鍝嶅簲
+ * 
+ * @author ruoyi
+ */
+@Data
+public class PaymentResponse implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 璁㈠崟ID */
+    private Long orderId;
+
+    /** 浜ゆ槗ID */
+    private Long transactionId;
+
+    /** 璁㈠崟鐘舵�� */
+    private String status;
+
+    /** Base64浜岀淮鐮� */
+    private String qrBase64;
+
+    /** 杩囨湡鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime expireAt;
+}
diff --git a/dryad-payment/src/main/resources/META-INF/spring.factories b/dryad-payment/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..5b5c043
--- /dev/null
+++ b/dryad-payment/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.ruoyi.payment.config.PaymentAutoConfiguration
diff --git a/dryad-payment/src/main/resources/application.yml b/dryad-payment/src/main/resources/application.yml
new file mode 100644
index 0000000..a8f3351
--- /dev/null
+++ b/dryad-payment/src/main/resources/application.yml
@@ -0,0 +1,98 @@
+server:
+  port: 8080
+  servlet:
+    context-path: /
+
+spring:
+  application:
+    name: dryad-payment
+  
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://localhost:3306/dryad_payment?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+    username: root
+    password: abcd1234
+    druid:
+      initial-size: 5
+      min-idle: 5
+      max-active: 20
+      max-wait: 60000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      validation-query: SELECT 1 FROM DUAL
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+
+# MyBatis Plus閰嶇疆
+mybatis-plus:
+  mapper-locations: classpath*:mapper/**/*Mapper.xml
+  type-aliases-package: com.ruoyi.payment.domain.model
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+  global-config:
+    db-config:
+      id-type: ASSIGN_ID
+      logic-delete-field: deleted
+      logic-delete-value: 1
+      logic-not-delete-value: 0
+
+# 鏃ュ織閰嶇疆
+logging:
+  level:
+    root: INFO
+    com.ruoyi.payment: DEBUG
+  pattern:
+    console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n'
+
+# 鏀粯閰嶇疆
+payment:
+  # 鏄惁鍚敤鏀粯妯″潡锛堜綔涓虹粍浠堕泦鎴愭椂鍙�氳繃姝ゅ紑鍏虫帶鍒讹級
+  enabled: true
+  
+  # 寰俊鏀粯閰嶇疆
+  wechat:
+    appId: wx70f6a7346ee842c0
+    mchId: 1573728151
+    appName: 姘戣埅鍖荤枟蹇嚎
+    mchKey: Xz0ClPK3f5sCeT6SGTaha1vpVmyUFcbp
+    notifyUrl: https://api.966120.com/api/pay/notify/wechat
+    signType: MD5
+    checkSign: false
+  
+  # 鏀粯瀹濋厤缃�
+  alipay:
+    appId: 2018060160299486
+    privateKey: MIIEpgIBAAKCAQEArt273bWTEPXPjCsUYwFx7CNjhcQlm1NtbNjfeIsZ2g9sbFCQP9qpyufp6zkBv6eq+6WEztkC1KwSsuDjP5LvgY/1pmGFlr8r7cjeZI4bTeIe9jG5UaHolnzbdXUlSoInzgWRvbYXxuQZciwVpokwviW27YK9wPIzz9OTiRquL8b3YWPZLO7xK0gBMa2KfFfUXxCB8gHJtidQ+FjjYXb2WpnScKLJdKfWcGWFnyGiZOknyFR9kI8cm0cYPNHtecQId0bQ1ee7YDLD8dBPd2Pd/JBC4Wn6HuOvZOLqZvIpIj+8q0zGXjUUns6MsjNL3MUKuhKy6hQGwP5sGrPcVcwqiwIDAQABAoIBAQCTeW9iSSsRx61VUlOsN+DDPQlHHCh3OcH0ZWb6e52+2Pkg1EUDhT9jX3lZJsfBwf8iofJCnKSVhdVzRNSCnkIdq7KJsn9+phW/QYPFnE+MvKJOEZtwLDNDD2PqSHS9xM0bJHlIXNTqqR6IuoM740HXa2k+H+A2ZE2r/YzUuUqkASwAYPKYzWa1wivg4CZrvoPZ5bXvYOHoV0jZEtyUQB9dHuCz+bghbR+28vGkYwEGInLsOCe6Gl5D61F0l2qAXRQky3P0jXxIPXPFmhBYutAAUufLpryruQgL3MDDm5dhBJpwp89qwFDjc8fWVS/FFYJ0KDQOpAxAI800YHgaJ4VBAoGBAOdCcoYS49Q9Iula7gFGVXeto7QSUsP0CnQZM/tsAU6TiX3XG5pxBYoVmYSIQPylgagRTBZHD5t/LGa+I+KYMHSVAH/kndPdgTO7EiwfUCzi1DmGZVWs7XJ2zRfTmYRVdsElPy3Z8Pm802jd7mhffw/5p6y9pzNJqOjmGOUbYGrrAoGBAMGS1CGHkK4nD2BsIWJoKW2Lxph3Bq5hN1iaE8ZjOAvFT9drNqfwRa6BVGyfYEXPZTvUT0FUNMdukcTCM6O3FRU8EABJIcVue2QA+BvkfwPEU3JxMA8DrWHO7IcgtG9wjbxretDsf+SZmkQgK0ZUPod5ZZSycFxM3/GiXDQjGhbhAoGBAL/Y/+j6AscvcKbmKEwmbQC7q/LWwJKPAZ0Oy3DoSK1G9+jNarjUyiOjh5fK8R6mrskekGBq0yfMeKlDU8HHP2t3sNJodgYs2+JubsTrtTeHdUfDlo1cyB8NL1d00wZVYA8bNy5yftavLzLv6bfsgRxfoBpNu0dw9A9B06U88N/BAoGBAKCN/nEJFlG8iB570Xzj1GjOJJzVLK96ZwOQWJKWPShWMhEFFkJZIhLJppKp5ppAmUD0qgAPre80oKdIRLin5E7GkKcMAXzWVHXv79qCvW8MagJkK25oqGiVzs2NrNs5yfXcV/PuFW4wkSmsXPhqa6rGYCDjmBqWkLDE8CE2dC9BAoGBAJ2+QfAAvB27mr48+vY4HxZyPRrCBA1YkokraWQ0IlfD0MKsFw0Af4Iu3oy7V6NlE2GwL/AcObyHeGZt7DLbViAQOgmb9BpUrjUZ4bXSBuGPfRe11HCu6j6W67qa76TAoy3A0Dfm0OE/m9r4H99NaLzeBm1KluySKkfYXoqyueQw
+    alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8BjXYaudmGT+sEos0AXEUrKl6+wyw6++hBoJDdY7P+P7poa34GN4YSkkavTA/HplmRM1wTLcY+NqhxhLpNrcgy08AbC/GGcLM2wxQGFa+L+DQLz34uBAShXDK8yN6O49UdbbJ2RRaJSAb+nW4ZVCPMGtMu4S3lXTymQgizM1IYo9L92U5QPRzZRSP8+AmQPzwofRqEgvkO02s66xU2G5AAdkVg5BQm34eM0Io2CmcWF9jSoWQTJdyd7tw3oec9NqD7x3CfcsN3NAJOQLz4+bWWqDWelyviyAr2reeH6AuBVjaWwAvAJx3yuLevKMXTzPC95Ja7w4XYSB9Fg2+aKmwIDAQAB
+    serverUrl: https://openapi.alipay.com/gateway.do
+    notifyUrl: https://api.966120.com/api/pay/notify/alipay
+    signType: RSA2
+    checkSign: true
+    # 鏀粯鏂瑰紡: OFFICIAL(瀹樻柟鏀粯瀹�) 鎴� THIRD_PARTY(绗笁鏂规敮浠樺疂)
+    paymentMethod: OFFICIAL
+    # 绗笁鏂规敮浠橀厤缃�
+    thirdParty:
+      enabled: true
+      url: https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php
+      defaultNotifyUrl: https://dsp.966120.com.cn/alipay/pay_notify
+      timeout: 30000  # 瓒呮椂鏃堕棿锛堟绉掞級
+  
+  # 涓氬姟鍥炶皟閰嶇疆
+  business:
+    callbackSignSecret: your-hmac-secret-key-here
+    callbackRetryMaxCount: 10
+    callbackRetryIntervals: 0,1,5,15,60
+  
+  # 浜岀淮鐮侀厤缃�
+  qrcode:
+    size: 300
+    format: PNG
+  
+  # 瀵硅处閰嶇疆
+  reconciliation:
+    enabled: true
+    cron: "0 0 2 * * ?"
\ No newline at end of file
diff --git a/dryad-payment/src/main/resources/mapper/BizCallbackLogMapper.xml b/dryad-payment/src/main/resources/mapper/BizCallbackLogMapper.xml
new file mode 100644
index 0000000..7a4e249
--- /dev/null
+++ b/dryad-payment/src/main/resources/mapper/BizCallbackLogMapper.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.payment.infrastructure.persistence.mapper.BizCallbackLogMapper">
+
+    <resultMap id="BizCallbackLogResult" type="com.ruoyi.payment.domain.model.BizCallbackLog">
+        <id property="id" column="id"/>
+        <result property="orderId" column="order_id"/>
+        <result property="transactionId" column="transaction_id"/>
+        <result property="callbackUrl" column="callback_url"/>
+        <result property="payload" column="payload"/>
+        <result property="httpStatus" column="http_status"/>
+        <result property="response" column="response"/>
+        <result property="success" column="success"/>
+        <result property="retryCount" column="retry_count"/>
+        <result property="lastRetryAt" column="last_retry_at"/>
+        <result property="createdAt" column="created_at"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.ruoyi.payment.domain.model.BizCallbackLog">
+        INSERT INTO pay_biz_callback_log (
+            id, order_id, transaction_id, callback_url, payload,
+            http_status, response, success, retry_count, last_retry_at, created_at
+        ) VALUES (
+            #{id}, #{orderId}, #{transactionId}, #{callbackUrl}, #{payload},
+            #{httpStatus}, #{response}, #{success}, #{retryCount}, #{lastRetryAt}, #{createdAt}
+        )
+    </insert>
+
+    <update id="update" parameterType="com.ruoyi.payment.domain.model.BizCallbackLog">
+        UPDATE pay_biz_callback_log
+        <set>
+            <if test="orderId != null">order_id = #{orderId},</if>
+            <if test="transactionId != null">transaction_id = #{transactionId},</if>
+            <if test="callbackUrl != null">callback_url = #{callbackUrl},</if>
+            <if test="payload != null">payload = #{payload},</if>
+            <if test="httpStatus != null">http_status = #{httpStatus},</if>
+            <if test="response != null">response = #{response},</if>
+            <if test="success != null">success = #{success},</if>
+            <if test="retryCount != null">retry_count = #{retryCount},</if>
+            <if test="lastRetryAt != null">last_retry_at = #{lastRetryAt},</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <select id="selectById" resultMap="BizCallbackLogResult">
+        SELECT * FROM pay_biz_callback_log
+        WHERE id = #{id}
+    </select>
+
+</mapper>
diff --git a/dryad-payment/src/main/resources/mapper/NotifyLogMapper.xml b/dryad-payment/src/main/resources/mapper/NotifyLogMapper.xml
new file mode 100644
index 0000000..47db5a7
--- /dev/null
+++ b/dryad-payment/src/main/resources/mapper/NotifyLogMapper.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.payment.infrastructure.persistence.mapper.NotifyLogMapper">
+
+    <resultMap id="NotifyLogResult" type="com.ruoyi.payment.domain.model.NotifyLog">
+        <id property="id" column="id"/>
+        <result property="channel" column="channel"/>
+        <result property="notifyIdOrSerial" column="notify_id_or_serial"/>
+        <result property="orderId" column="order_id"/>
+        <result property="transactionId" column="transaction_id"/>
+        <result property="payload" column="payload"/>
+        <result property="verified" column="verified"/>
+        <result property="processed" column="processed"/>
+        <result property="result" column="result"/>
+        <result property="createdAt" column="created_at"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.ruoyi.payment.domain.model.NotifyLog">
+        INSERT INTO pay_notify_log (
+            id, channel, notify_id_or_serial, order_id, transaction_id,
+            payload, verified, processed, result, created_at
+        ) VALUES (
+            #{id}, #{channel}, #{notifyIdOrSerial}, #{orderId}, #{transactionId},
+            #{payload}, #{verified}, #{processed}, #{result}, #{createdAt}
+        )
+    </insert>
+
+    <update id="update" parameterType="com.ruoyi.payment.domain.model.NotifyLog">
+        UPDATE pay_notify_log
+        <set>
+            <if test="channel != null">channel = #{channel},</if>
+            <if test="notifyIdOrSerial != null">notify_id_or_serial = #{notifyIdOrSerial},</if>
+            <if test="orderId != null">order_id = #{orderId},</if>
+            <if test="transactionId != null">transaction_id = #{transactionId},</if>
+            <if test="payload != null">payload = #{payload},</if>
+            <if test="verified != null">verified = #{verified},</if>
+            <if test="processed != null">processed = #{processed},</if>
+            <if test="result != null">result = #{result},</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <select id="selectById" resultMap="NotifyLogResult">
+        SELECT * FROM pay_notify_log
+        WHERE id = #{id}
+    </select>
+
+    <select id="selectProcessedCount" resultType="int">
+        SELECT COUNT(*) FROM pay_notify_log
+        WHERE channel = #{channel}
+        AND notify_id_or_serial = #{notifyIdOrSerial}
+        AND processed = 1
+    </select>
+
+</mapper>
diff --git a/dryad-payment/src/main/resources/mapper/OperationAuditMapper.xml b/dryad-payment/src/main/resources/mapper/OperationAuditMapper.xml
new file mode 100644
index 0000000..70ad48f
--- /dev/null
+++ b/dryad-payment/src/main/resources/mapper/OperationAuditMapper.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.payment.infrastructure.persistence.mapper.OperationAuditMapper">
+
+    <resultMap id="OperationAuditResult" type="com.ruoyi.payment.domain.model.OperationAudit">
+        <id property="id" column="id"/>
+        <result property="operator" column="operator"/>
+        <result property="operationType" column="operation_type"/>
+        <result property="orderId" column="order_id"/>
+        <result property="transactionId" column="transaction_id"/>
+        <result property="params" column="params"/>
+        <result property="approved" column="approved"/>
+        <result property="createdAt" column="created_at"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.ruoyi.payment.domain.model.OperationAudit">
+        INSERT INTO pay_operation_audit (
+            id, operator, operation_type, order_id, transaction_id,
+            params, approved, created_at
+        ) VALUES (
+            #{id}, #{operator}, #{operationType}, #{orderId}, #{transactionId},
+            #{params}, #{approved}, #{createdAt}
+        )
+    </insert>
+
+    <select id="selectById" resultMap="OperationAuditResult">
+        SELECT * FROM pay_operation_audit
+        WHERE id = #{id}
+    </select>
+
+</mapper>
diff --git a/dryad-payment/src/main/resources/mapper/PaymentOrderMapper.xml b/dryad-payment/src/main/resources/mapper/PaymentOrderMapper.xml
new file mode 100644
index 0000000..063c689
--- /dev/null
+++ b/dryad-payment/src/main/resources/mapper/PaymentOrderMapper.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.payment.infrastructure.persistence.mapper.PaymentOrderMapper">
+
+    <resultMap id="PaymentOrderResult" type="com.ruoyi.payment.domain.model.PaymentOrder">
+        <id property="id" column="id"/>
+        <result property="bizOrderId" column="biz_order_id"/>
+        <result property="amount" column="amount"/>
+        <result property="currency" column="currency"/>
+        <result property="channel" column="channel"/>
+        <result property="status" column="status"/>
+        <result property="subject" column="subject"/>
+        <result property="description" column="description"/>
+        <result property="callbackUrl" column="callback_url"/>
+        <result property="expireAt" column="expire_at"/>
+        <result property="latestTransactionId" column="latest_transaction_id"/>
+        <result property="channelTradeNo" column="channel_trade_no"/>
+        <result property="paidAt" column="paid_at"/>
+        <result property="version" column="version"/>
+        <result property="createdAt" column="created_at"/>
+        <result property="updatedAt" column="updated_at"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.ruoyi.payment.domain.model.PaymentOrder">
+        INSERT INTO pay_order (
+            id, biz_order_id, amount, currency, channel, status,
+            subject, description, callback_url, expire_at,
+            latest_transaction_id, channel_trade_no, paid_at,
+            version, created_at, updated_at
+        ) VALUES (
+            #{id}, #{bizOrderId}, #{amount}, #{currency}, #{channel}, #{status},
+            #{subject}, #{description}, #{callbackUrl}, #{expireAt},
+            #{latestTransactionId}, #{channelTradeNo}, #{paidAt},
+            #{version}, #{createdAt}, #{updatedAt}
+        )
+    </insert>
+
+    <update id="update" parameterType="com.ruoyi.payment.domain.model.PaymentOrder">
+        UPDATE pay_order
+        <set>
+            <if test="bizOrderId != null">biz_order_id = #{bizOrderId},</if>
+            <if test="amount != null">amount = #{amount},</if>
+            <if test="currency != null">currency = #{currency},</if>
+            <if test="channel != null">channel = #{channel},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="subject != null">subject = #{subject},</if>
+            <if test="description != null">description = #{description},</if>
+            <if test="callbackUrl != null">callback_url = #{callbackUrl},</if>
+            <if test="expireAt != null">expire_at = #{expireAt},</if>
+            <if test="latestTransactionId != null">latest_transaction_id = #{latestTransactionId},</if>
+            <if test="channelTradeNo != null">channel_trade_no = #{channelTradeNo},</if>
+            <if test="paidAt != null">paid_at = #{paidAt},</if>
+            <if test="version != null">version = #{version},</if>
+            <if test="updatedAt != null">updated_at = #{updatedAt},</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <select id="selectById" resultMap="PaymentOrderResult">
+        SELECT * FROM pay_order
+        WHERE id = #{id}
+    </select>
+
+    <select id="selectByBizOrderIdAndChannel" resultMap="PaymentOrderResult">
+        SELECT * FROM pay_order
+        WHERE biz_order_id = #{bizOrderId}
+        AND channel = #{channel}
+        LIMIT 1
+    </select>
+
+    <select id="selectByChannelTradeNo" resultMap="PaymentOrderResult">
+        SELECT * FROM pay_order
+        WHERE channel_trade_no = #{channelTradeNo}
+        LIMIT 1
+    </select>
+
+</mapper>
diff --git a/dryad-payment/src/main/resources/mapper/PaymentTransactionMapper.xml b/dryad-payment/src/main/resources/mapper/PaymentTransactionMapper.xml
new file mode 100644
index 0000000..6f721f7
--- /dev/null
+++ b/dryad-payment/src/main/resources/mapper/PaymentTransactionMapper.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.payment.infrastructure.persistence.mapper.PaymentTransactionMapper">
+
+    <resultMap id="PaymentTransactionResult" type="com.ruoyi.payment.domain.model.PaymentTransaction">
+        <id property="id" column="id"/>
+        <result property="orderId" column="order_id"/>
+        <result property="channel" column="channel"/>
+        <result property="clientType" column="client_type"/>
+        <result property="status" column="status"/>
+        <result property="codeOrQr" column="code_or_qr"/>
+        <result property="qrBase64" column="qr_base64"/>
+        <result property="requestParams" column="request_params"/>
+        <result property="responseSnapshot" column="response_snapshot"/>
+        <result property="channelTradeNo" column="channel_trade_no"/>
+        <result property="createdAt" column="created_at"/>
+        <result property="paidAt" column="paid_at"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.ruoyi.payment.domain.model.PaymentTransaction">
+        INSERT INTO pay_transaction (
+            id, order_id, channel, client_type, status,
+            code_or_qr, qr_base64, request_params, response_snapshot,
+            channel_trade_no, created_at, paid_at
+        ) VALUES (
+            #{id}, #{orderId}, #{channel}, #{clientType}, #{status},
+            #{codeOrQr}, #{qrBase64}, #{requestParams}, #{responseSnapshot},
+            #{channelTradeNo}, #{createdAt}, #{paidAt}
+        )
+    </insert>
+
+    <update id="update" parameterType="com.ruoyi.payment.domain.model.PaymentTransaction">
+        UPDATE pay_transaction
+        <set>
+            <if test="orderId != null">order_id = #{orderId},</if>
+            <if test="channel != null">channel = #{channel},</if>
+            <if test="clientType != null">client_type = #{clientType},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="codeOrQr != null">code_or_qr = #{codeOrQr},</if>
+            <if test="qrBase64 != null">qr_base64 = #{qrBase64},</if>
+            <if test="requestParams != null">request_params = #{requestParams},</if>
+            <if test="responseSnapshot != null">response_snapshot = #{responseSnapshot},</if>
+            <if test="channelTradeNo != null">channel_trade_no = #{channelTradeNo},</if>
+            <if test="paidAt != null">paid_at = #{paidAt},</if>
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <select id="selectById" resultMap="PaymentTransactionResult">
+        SELECT * FROM pay_transaction
+        WHERE id = #{id}
+    </select>
+
+    <select id="selectPendingByOrderId" resultMap="PaymentTransactionResult">
+        SELECT * FROM pay_transaction
+        WHERE order_id = #{orderId}
+        AND status = 'PENDING'
+        LIMIT 1
+    </select>
+
+    <select id="selectByChannelTradeNo" resultMap="PaymentTransactionResult">
+        SELECT * FROM pay_transaction
+        WHERE channel_trade_no = #{channelTradeNo}
+        LIMIT 1
+    </select>
+
+    <select id="selectLatestByOrderId" resultMap="PaymentTransactionResult">
+        SELECT * FROM pay_transaction
+        WHERE order_id = #{orderId}
+        ORDER BY created_at DESC
+        LIMIT 1
+    </select>
+
+</mapper>
diff --git a/dryad-payment/src/main/resources/sql/schema.sql b/dryad-payment/src/main/resources/sql/schema.sql
new file mode 100644
index 0000000..4f2047f
--- /dev/null
+++ b/dryad-payment/src/main/resources/sql/schema.sql
@@ -0,0 +1,134 @@
+-- 鍒涘缓鏁版嵁搴�
+CREATE DATABASE IF NOT EXISTS `dryad_payment` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
+USE `dryad_payment`;
+
+-- 鍒犻櫎宸插瓨鍦ㄧ殑琛�
+DROP TABLE IF EXISTS `pay_reconciliation_result`;
+DROP TABLE IF EXISTS `pay_reconciliation_task`;
+DROP TABLE IF EXISTS `pay_operation_audit`;
+DROP TABLE IF EXISTS `pay_biz_callback_log`;
+DROP TABLE IF EXISTS `pay_notify_log`;
+DROP TABLE IF EXISTS `pay_transaction`;
+DROP TABLE IF EXISTS `pay_order`;
+
+-- 鏀粯璁㈠崟琛�
+CREATE TABLE `pay_order` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '璁㈠崟ID',
+  `biz_order_id` VARCHAR(64) NOT NULL COMMENT '涓氬姟璁㈠崟鍙�',
+  `amount` INT NOT NULL COMMENT '閲戦锛堝垎锛�',
+  `currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '甯佺',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `status` VARCHAR(16) NOT NULL COMMENT '璁㈠崟鐘舵��',
+  `subject` VARCHAR(128) NOT NULL COMMENT '璁㈠崟鏍囬',
+  `description` VARCHAR(512) COMMENT '璁㈠崟鎻忚堪',
+  `callback_url` VARCHAR(512) NOT NULL COMMENT '涓氬姟鍥炶皟鍦板潃',
+  `expire_at` DATETIME NOT NULL COMMENT '杩囨湡鏃堕棿',
+  `latest_transaction_id` BIGINT COMMENT '鏈�鏂颁氦鏄揑D',
+  `channel_trade_no` VARCHAR(64) COMMENT '娓犻亾浜ゆ槗鍙�',
+  `paid_at` DATETIME COMMENT '鏀粯鎴愬姛鏃堕棿',
+  `version` INT NOT NULL DEFAULT 0 COMMENT '涔愯閿佺増鏈彿',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  `updated_at` DATETIME NOT NULL COMMENT '鏇存柊鏃堕棿',
+  INDEX `idx_biz_order_id` (`biz_order_id`),
+  INDEX `idx_channel_trade_no` (`channel_trade_no`),
+  INDEX `idx_status` (`status`),
+  INDEX `idx_expire_at` (`expire_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鏀粯璁㈠崟琛�';
+
+-- 鏀粯浜ゆ槗娴佹按琛�
+CREATE TABLE `pay_transaction` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '浜ゆ槗ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `client_type` VARCHAR(32) NOT NULL COMMENT '瀹㈡埛绔被鍨�',
+  `status` VARCHAR(16) NOT NULL COMMENT '浜ゆ槗鐘舵��',
+  `code_or_qr` VARCHAR(512) COMMENT '浜岀淮鐮佸唴瀹�',
+  `qr_base64` TEXT COMMENT 'Base64浜岀淮鐮佸浘鐗�',
+  `request_params` TEXT COMMENT '璇锋眰鍙傛暟蹇収',
+  `response_snapshot` TEXT COMMENT '鍝嶅簲蹇収',
+  `channel_trade_no` VARCHAR(64) COMMENT '娓犻亾浜ゆ槗鍙�',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  `paid_at` DATETIME COMMENT '鏀粯瀹屾垚鏃堕棿',
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_channel_trade_no` (`channel_trade_no`),
+  INDEX `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鏀粯浜ゆ槗娴佹按琛�';
+
+-- 娓犻亾鍥炶皟鏃ュ織琛�
+CREATE TABLE `pay_notify_log` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏃ュ織ID',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `notify_id_or_serial` VARCHAR(64) NOT NULL COMMENT '娓犻亾閫氱煡鍞竴鏍囪瘑',
+  `order_id` BIGINT COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `payload` TEXT NOT NULL COMMENT '鍥炶皟鍘熷鎶ユ枃',
+  `verified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '绛惧悕楠岃瘉鏄惁閫氳繃',
+  `processed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁宸插鐞�',
+  `result` VARCHAR(128) COMMENT '澶勭悊缁撴灉',
+  `created_at` DATETIME NOT NULL COMMENT '鎺ユ敹鏃堕棿',
+  UNIQUE KEY `uk_channel_notify` (`channel`, `notify_id_or_serial`),
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_transaction_id` (`transaction_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='娓犻亾鍥炶皟鏃ュ織琛�';
+
+-- 涓氬姟鍥炶皟鏃ュ織琛�
+CREATE TABLE `pay_biz_callback_log` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏃ュ織ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT NOT NULL COMMENT '浜ゆ槗ID',
+  `callback_url` VARCHAR(512) NOT NULL COMMENT '鍥炶皟鍦板潃',
+  `payload` TEXT NOT NULL COMMENT '鍥炶皟璇锋眰浣�',
+  `http_status` INT COMMENT 'HTTP鐘舵�佺爜',
+  `response` TEXT COMMENT '鍝嶅簲鍐呭',
+  `success` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁鎴愬姛',
+  `retry_count` INT NOT NULL DEFAULT 0 COMMENT '閲嶈瘯娆℃暟',
+  `last_retry_at` DATETIME COMMENT '鏈�鍚庨噸璇曟椂闂�',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_success` (`success`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='涓氬姟鍥炶皟鏃ュ織琛�';
+
+-- 鎿嶄綔瀹¤琛�
+CREATE TABLE `pay_operation_audit` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '瀹¤ID',
+  `operator` VARCHAR(64) NOT NULL COMMENT '鎿嶄綔浜�',
+  `operation_type` VARCHAR(32) NOT NULL COMMENT '鎿嶄綔绫诲瀷',
+  `order_id` BIGINT COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `params` TEXT COMMENT '鎿嶄綔鍙傛暟',
+  `approved` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '鏄惁閫氳繃',
+  `created_at` DATETIME NOT NULL COMMENT '鎿嶄綔鏃堕棿',
+  INDEX `idx_operator` (`operator`),
+  INDEX `idx_operation_type` (`operation_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鎿嶄綔瀹¤琛�';
+
+-- 瀵硅处浠诲姟琛�
+CREATE TABLE `pay_reconciliation_task` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '浠诲姟ID',
+  `task_date` DATE NOT NULL COMMENT '瀵硅处鏃ユ湡',
+  `status` VARCHAR(16) NOT NULL COMMENT '浠诲姟鐘舵��',
+  `total_count` INT NOT NULL DEFAULT 0 COMMENT '鎬昏鍗曟暟',
+  `success_count` INT NOT NULL DEFAULT 0 COMMENT '鎴愬姛鏁�',
+  `failed_count` INT NOT NULL DEFAULT 0 COMMENT '澶辫触鏁�',
+  `diff_count` INT NOT NULL DEFAULT 0 COMMENT '宸紓鏁�',
+  `fixed_count` INT NOT NULL DEFAULT 0 COMMENT '鑷姩淇鏁�',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  `finished_at` DATETIME COMMENT '瀹屾垚鏃堕棿',
+  UNIQUE KEY `uk_task_date` (`task_date`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀵硅处浠诲姟琛�';
+
+-- 瀵硅处宸紓鏄庣粏琛�
+CREATE TABLE `pay_reconciliation_result` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏄庣粏ID',
+  `task_id` BIGINT NOT NULL COMMENT '浠诲姟ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `local_status` VARCHAR(16) COMMENT '鏈湴鐘舵��',
+  `channel_status` VARCHAR(16) COMMENT '娓犻亾鐘舵��',
+  `diff_type` VARCHAR(32) NOT NULL COMMENT '宸紓绫诲瀷',
+  `fixed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁宸蹭慨澶�',
+  `note` VARCHAR(512) COMMENT '澶囨敞',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  INDEX `idx_task_id` (`task_id`),
+  INDEX `idx_order_id` (`order_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀵硅处宸紓鏄庣粏琛�';
diff --git "a/dryad-payment/\351\233\206\346\210\220\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/dryad-payment/\351\233\206\346\210\220\344\275\277\347\224\250\346\214\207\345\215\227.md"
new file mode 100644
index 0000000..90c5142
--- /dev/null
+++ "b/dryad-payment/\351\233\206\346\210\220\344\275\277\347\224\250\346\214\207\345\215\227.md"
@@ -0,0 +1,317 @@
+# 鏀粯妯″潡闆嗘垚浣跨敤鎸囧崡
+
+鏈敮浠樻ā鍧楁敮鎸佷袱绉嶄娇鐢ㄦ柟寮忥細**鐙珛杩愯** 鍜� **缁勪欢闆嗘垚**銆�
+
+---
+
+## 鏂瑰紡涓�锛氱嫭绔嬭繍琛�
+
+### 1. 缂栬瘧鎵撳寘
+
+```bash
+cd dryad-payment
+mvn clean package
+```
+
+缂栬瘧鍚庝細鐢熸垚涓や釜jar鏂囦欢锛�
+- `dryad-payment-1.0.0.jar` - 鏅�歫ar锛屼緵鍏朵粬椤圭洰渚濊禆
+- `dryad-payment-1.0.0-exec.jar` - 鍙墽琛宩ar锛岀敤浜庣嫭绔嬭繍琛�
+
+### 2. 杩愯鏈嶅姟
+
+```bash
+java -jar target/dryad-payment-1.0.0-exec.jar
+```
+
+### 3. 璁块棶鎺ュ彛
+
+鏈嶅姟鍚姩鍚庯紝鍙互鐩存帴璁块棶锛�
+- 鍋ュ悍妫�鏌�: `http://localhost:8080/api/health`
+- 寰俊鏀粯: `http://localhost:8080/api/pay/wechat/native`
+- 鏀粯瀹濇敮浠�: `http://localhost:8080/api/pay/alipay/precreate`
+
+---
+
+## 鏂瑰紡浜岋細浣滀负缁勪欢闆嗘垚鍒板叾浠栭」鐩�
+
+### 1. 瀹夎鍒版湰鍦癕aven浠撳簱
+
+棣栧厛灏嗘敮浠樻ā鍧楀畨瑁呭埌鏈湴浠撳簱锛�
+
+```bash
+cd dryad-payment
+mvn clean install
+```
+
+### 2. 鍦ㄤ富椤圭洰涓坊鍔犱緷璧�
+
+鍦ㄤ綘鐨勪富椤圭洰 `pom.xml` 涓坊鍔狅細
+
+```xml
+<dependencies>
+    <!-- 鏀粯妯″潡 -->
+    <dependency>
+        <groupId>com.ruoyi</groupId>
+        <artifactId>dryad-payment</artifactId>
+        <version>1.0.0</version>
+    </dependency>
+</dependencies>
+```
+
+### 3. 閰嶇疆鏀粯鍙傛暟
+
+鍦ㄤ富椤圭洰鐨� `application.yml` 涓坊鍔犳敮浠橀厤缃細
+
+```yaml
+# 鏀粯妯″潡閰嶇疆
+payment:
+  # 鍚敤鏀粯妯″潡
+  enabled: true
+  
+  # 寰俊鏀粯閰嶇疆
+  wechat:
+    appId: wx70f6a7346ee842xx
+    mchId: 1573728xxx
+    mchKey: Xz0ClPK3f5sCeT6SGa1vpVmyUFcbpxxx
+    notifyUrl: https://api.966120.com/api/pay/notify/wechat
+    signType: MD5
+  
+  # 鏀粯瀹濋厤缃�
+  alipay:
+    appId: 2021xxxxxxxxxxxxx
+    privateKey: MIIEvQIBADANBgkqhki...
+    alipayPublicKey: MIIBIjANBgkqhki...
+    serverUrl: https://openapi.alipay.com/gateway.do
+    notifyUrl: https://api.966120.com/api/pay/notify/alipay
+    signType: RSA2
+  
+  # 涓氬姟鍥炶皟閰嶇疆
+  business:
+    callbackSignSecret: your-hmac-secret-key-here
+    callbackRetryMaxCount: 10
+    callbackRetryIntervals: 0,1,5,15,60
+  
+  # 浜岀淮鐮侀厤缃�
+  qrcode:
+    size: 300
+    format: PNG
+  
+  # 瀵硅处閰嶇疆
+  reconciliation:
+    enabled: true
+    cron: "0 0 2 * * ?"
+```
+
+### 4. 閰嶇疆鏁版嵁搴�
+
+鍦ㄤ富椤圭洰鐨� `application.yml` 涓厤缃暟鎹簱杩炴帴锛�
+
+```yaml
+spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/dryad_payment?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+    username: root
+    password: root
+```
+
+鎵ц鏀粯妯″潡鐨勬暟鎹簱鑴氭湰锛�
+
+```bash
+mysql -u root -p < dryad-payment/src/main/resources/sql/schema.sql
+```
+
+### 5. 鍚姩涓婚」鐩�
+
+鍚姩浣犵殑涓婚」鐩紝鎺у埗鍙颁細鏄剧ず锛�
+
+```
+=================================
+鏀粯妯″潡宸插惎鐢�
+=================================
+```
+
+### 6. 浣跨敤鏀粯鍔熻兘
+
+鏀粯妯″潡鐨勬墍鏈夋帴鍙d細鑷姩娉ㄥ唽鍒颁富椤圭洰涓紝鍙互鐩存帴璋冪敤锛�
+
+```java
+@RestController
+@RequestMapping("/order")
+public class OrderController {
+    
+    @Autowired
+    private PaymentService paymentService;
+    
+    @PostMapping("/pay")
+    public AjaxResult createPayment(@RequestBody OrderDTO order) {
+        PaymentRequest request = new PaymentRequest();
+        request.setBizOrderId(order.getOrderNo());
+        request.setAmount(order.getAmount());
+        request.setSubject(order.getSubject());
+        request.setCallbackUrl("https://your-domain.com/order/notify");
+        
+        PaymentResponse response = paymentService.createWechatNativePayment(request);
+        return AjaxResult.success(response);
+    }
+}
+```
+
+---
+
+## 鍙�夐厤缃�
+
+### 绂佺敤鏀粯妯″潡
+
+濡傛灉鏌愪釜鐜涓嶉渶瑕佹敮浠樺姛鑳斤紝鍙互閫氳繃閰嶇疆绂佺敤锛�
+
+```yaml
+payment:
+  enabled: false  # 绂佺敤鏀粯妯″潡
+```
+
+### 鑷畾涔夋帴鍙h矾寰�
+
+濡傛灉闇�瑕佷慨鏀规帴鍙h矾寰勶紝鍙互鍦ㄤ富椤圭洰涓厤缃細
+
+```yaml
+server:
+  servlet:
+    context-path: /api  # 涓婚」鐩粺涓�鍓嶇紑
+```
+
+鏀粯鎺ュ彛浼氳嚜鍔ㄦ坊鍔犳鍓嶇紑锛屼緥濡傦細
+- `/api/api/pay/wechat/native`
+
+### 瑕嗙洊榛樿閰嶇疆
+
+涓婚」鐩殑閰嶇疆浼氳鐩栨敮浠樻ā鍧楃殑榛樿閰嶇疆锛屼緥濡備慨鏀圭鍙o細
+
+```yaml
+server:
+  port: 9090  # 涓婚」鐩鍙�
+```
+
+---
+
+## 鎵撳寘璇存槑
+
+### 鐢熸垚鐨勬枃浠�
+
+鎵ц `mvn clean package` 鍚庝細鐢熸垚锛�
+
+1. **dryad-payment-1.0.0.jar**
+   - 鏅�歫ar鍖�
+   - 鐢ㄤ簬琚叾浠栭」鐩緷璧�
+   - 涓嶅寘鍚玈pring Boot鍚姩鍣�
+
+2. **dryad-payment-1.0.0-exec.jar**
+   - 鍙墽琛宩ar鍖�
+   - 鐢ㄤ簬鐙珛杩愯
+   - 鍖呭惈鎵�鏈変緷璧�
+
+3. **dryad-payment-1.0.0-sources.jar**
+   - 婧愮爜jar鍖�
+   - 渚夸簬寮�鍙戞椂鏌ョ湅婧愮爜
+
+### Maven鍛戒护
+
+```bash
+# 缂栬瘧
+mvn clean compile
+
+# 鎵撳寘锛堢敓鎴恓ar锛�
+mvn clean package
+
+# 瀹夎鍒版湰鍦颁粨搴�
+mvn clean install
+
+# 璺宠繃娴嬭瘯鎵撳寘
+mvn clean package -DskipTests
+
+# 閮ㄧ讲鍒拌繙绋嬩粨搴擄紙闇�閰嶇疆锛�
+mvn clean deploy
+```
+
+---
+
+## 鏈�浣冲疄璺�
+
+### 1. 閰嶇疆绠$悊
+
+寤鸿灏嗘晱鎰熼厤缃紙瀵嗛挜绛夛級鏀惧湪閰嶇疆涓績鎴栫幆澧冨彉閲忎腑锛�
+
+```yaml
+payment:
+  wechat:
+    mchKey: ${WECHAT_MCH_KEY}  # 浠庣幆澧冨彉閲忚鍙�
+  alipay:
+    privateKey: ${ALIPAY_PRIVATE_KEY}
+```
+
+### 2. 澶氱幆澧冮厤缃�
+
+鍒涘缓涓嶅悓鐜鐨勯厤缃枃浠讹細
+
+- `application-dev.yml` - 寮�鍙戠幆澧冿紙娌欑锛�
+- `application-prod.yml` - 鐢熶骇鐜
+
+```yaml
+# application-dev.yml
+payment:
+  alipay:
+    serverUrl: https://openapi.alipaydev.com/gateway.do  # 娌欑鐜
+```
+
+### 3. 鏃ュ織閰嶇疆
+
+鍦ㄤ富椤圭洰涓彲浠ュ崟鐙厤缃敮浠樻ā鍧楃殑鏃ュ織绾у埆锛�
+
+```yaml
+logging:
+  level:
+    com.ruoyi.payment: DEBUG  # 鏀粯妯″潡璇︾粏鏃ュ織
+```
+
+### 4. 鏁版嵁搴撻殧绂�
+
+濡傛灉涓婚」鐩拰鏀粯妯″潡浣跨敤涓嶅悓鏁版嵁搴擄紝闇�瑕侀厤缃鏁版嵁婧愩��
+
+---
+
+## 甯歌闂
+
+### Q1: 闆嗘垚鍚庢彁绀烘壘涓嶅埌Bean锛�
+
+**A**: 纭繚涓婚」鐩殑鍚姩绫诲寘璺緞鍦� `com.ruoyi` 鎴栧叾瀛愬寘涓嬶紝鎴栬�呮墜鍔ㄦ坊鍔犳壂鎻忥細
+
+```java
+@SpringBootApplication
+@ComponentScan(basePackages = {"com.ruoyi.main", "com.ruoyi.payment"})
+public class MainApplication {
+    // ...
+}
+```
+
+### Q2: 鎺ュ彛璺緞鍐茬獊锛�
+
+**A**: 濡傛灉涓婚」鐩篃鏈� `/api/pay` 璺緞锛屽缓璁慨鏀规敮浠樻ā鍧楃殑 `@RequestMapping` 璺緞銆�
+
+### Q3: 閰嶇疆涓嶇敓鏁堬紵
+
+**A**: 妫�鏌ラ厤缃枃浠舵牸寮忥紝纭繚锛�
+- YAML缂╄繘姝g‘锛�2涓┖鏍硷級
+- 灞炴�у悕绉版纭�
+- 閰嶇疆鏂囦欢鍚嶇О姝g‘锛坅pplication.yml锛�
+
+### Q4: 鏁版嵁搴撹〃鍐茬獊锛�
+
+**A**: 鏀粯妯″潡鐨勮〃閮戒互 `pay_` 寮�澶达紝涓�鑸笉浼氬啿绐併�傚闇�淇敼琛ㄥ悕锛岃淇敼瀹炰綋绫荤殑 `@TableName` 娉ㄨВ銆�
+
+---
+
+## 鎶�鏈敮鎸�
+
+濡傛湁闂锛岃鏌ョ湅锛�
+- 鎺ュ彛鏂囨。: `API鎺ュ彛鏂囨。.md`
+- 璁捐鏂囨。: `doc/璁捐鏂规.md`
+- 婧愮爜娉ㄩ噴: 浠g爜涓寘鍚缁嗘敞閲�
diff --git a/pom.xml b/pom.xml
index 1978da3..8470f4d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -242,6 +242,7 @@
         <module>ruoyi-quartz</module>
         <module>ruoyi-generator</module>
         <module>ruoyi-common</module>
+        <module>dryad-payment</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git "a/prd/\345\210\206\345\205\254\345\217\270\351\273\230\350\256\244\345\207\272\345\217\221\345\234\260\351\205\215\347\275\256\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/prd/\345\210\206\345\205\254\345\217\270\351\273\230\350\256\244\345\207\272\345\217\221\345\234\260\351\205\215\347\275\256\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..7079032
--- /dev/null
+++ "b/prd/\345\210\206\345\205\254\345\217\270\351\273\230\350\256\244\345\207\272\345\217\221\345\234\260\351\205\215\347\275\256\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,189 @@
+# 鍒嗗叕鍙搁粯璁ゅ嚭鍙戝湴閰嶇疆鍔熻兘璇存槑
+
+## 鍔熻兘姒傝堪
+
+涓哄垱寤鸿浆杩愪换鍔¢〉闈㈠鍔犱簡鍑哄彂鍦拌緭鍏ュ姛鑳斤紝鏀寔浠庡垎鍏徃閰嶇疆涓嚜鍔ㄥ姞杞介粯璁ゅ嚭鍙戝湴锛岀敤鎴蜂篃鍙互鎵嬪姩淇敼銆�
+
+## 鏁版嵁搴撳彉鏇�
+
+### sys_dept 琛ㄦ柊澧炲瓧娈�
+
+鍦� `sys_dept` 琛ㄤ腑鏂板浜�3涓瓧娈电敤浜庡瓨鍌ㄥ垎鍏徃鐨勯粯璁ゅ嚭杞﹀湴鍧�锛�
+
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| `departure_address` | VARCHAR(500) | 榛樿鍑鸿溅鍦板潃 |
+| `departure_longitude` | DECIMAL(10, 6) | 鍑鸿溅鍦板潃缁忓害 |
+| `departure_latitude` | DECIMAL(10, 6) | 鍑鸿溅鍦板潃绾害 |
+
+**SQL鑴氭湰浣嶇疆**: `sql/sys_dept_add_departure_fields.sql`
+
+## 鍚庣淇敼
+
+### 1. SysDept 瀹炰綋绫� (SysDept.java)
+
+鏂板灞炴�э細
+```java
+private String departureAddress;
+private java.math.BigDecimal departureLongitude;
+private java.math.BigDecimal departureLatitude;
+```
+
+### 2. SysDeptMapper.xml
+
+- 鏇存柊 `resultMap`锛屽鍔犳柊瀛楁鏄犲皠
+- 鏇存柊 `selectDeptVo`锛屾煡璇㈡椂鍖呭惈鏂板瓧娈�
+- 鏇存柊 `insertDept`锛屾彃鍏ユ椂鏀寔鏂板瓧娈�
+- 鏇存柊 `updateDept`锛屾洿鏂版椂鏀寔鏂板瓧娈�
+
+## 鍓嶇淇敼
+
+### 1. OrganizationSelector 缁勪欢
+
+淇敼 `emitChange` 鏂规硶锛屽湪閫夋嫨褰掑睘鏈烘瀯鏃惰繑鍥炲嚭鍙戝湴淇℃伅锛�
+
+```javascript
+this.$emit('change', {
+  deptId: organization.deptId,
+  deptName: organization.deptName,
+  serviceOrderClass: organization.serviceOrderClass || '',
+  region: region,
+  // 鍑哄彂鍦颁俊鎭�
+  departureAddress: organization.departureAddress || '',
+  departureLongitude: organization.departureLongitude || null,
+  departureLatitude: organization.departureLatitude || null
+})
+```
+
+### 2. create-emergency.vue 椤甸潰
+
+#### 鏂板鏁版嵁瀛楁
+
+```javascript
+data() {
+  return {
+    departureAddress: '', // 鍑哄彂鍦板湴鍧�
+    departureLongitude: null, // 鍑哄彂鍦扮粡搴�
+    departureLatitude: null, // 鍑哄彂鍦扮含搴�
+    // ... 鍏朵粬瀛楁
+  }
+}
+```
+
+#### 褰掑睘鏈烘瀯鍙樺寲澶勭悊
+
+鍦� `onOrganizationChange` 鏂规硶涓嚜鍔ㄥ~鍏呭嚭鍙戝湴锛�
+
+```javascript
+onOrganizationChange(orgData) {
+  this.selectedOrganizationId = orgData.deptId
+  this.selectedOrganizationServiceOrderClass = orgData.serviceOrderClass
+  this.selectedRegion = orgData.region
+  
+  // 鑷姩濉厖鍑哄彂鍦颁俊鎭�
+  this.departureAddress = orgData.departureAddress || ''
+  this.departureLongitude = orgData.departureLongitude || null
+  this.departureLatitude = orgData.departureLatitude || null
+}
+```
+
+#### 鐣岄潰鏂板鍑哄彂鍦拌緭鍏ユ
+
+鍦ㄥ綊灞炴満鏋勯�夋嫨鍣ㄤ箣鍚庡鍔狅細
+
+```vue
+<view class="form-item">
+  <view class="form-label">鍑哄彂鍦�</view>
+  <input 
+    class="form-input" 
+    placeholder="璇疯緭鍏ュ嚭鍙戝湴鍦板潃" 
+    v-model="departureAddress"
+  />
+  <view class="form-tip" v-if="departureAddress">
+    <text>鎻愮ず锛氬彲淇敼榛樿鍑哄彂鍦板湴鍧�</text>
+  </view>
+</view>
+```
+
+#### 鎻愪氦鏁版嵁澶勭悊
+
+鍦� `buildSubmitData` 鏂规硶涓細
+
+```javascript
+const submitData = {
+  // 浼樺厛浣跨敤鑷畾涔夌殑鍑哄彂鍦帮紝濡傛灉涓虹┖鍒欎娇鐢ㄨ浆鍑哄尰闄㈠湴鍧�
+  departureAddress: this.departureAddress || this.taskForm.hospitalOut.address || '',
+  // ... 鍏朵粬瀛楁
+}
+
+// 鍑哄彂鍦癎PS鍧愭爣锛堜紭鍏堜娇鐢ㄨ嚜瀹氫箟鐨勫嚭鍙戝湴鍧愭爣锛�
+if (this.departureLongitude && this.departureLatitude) {
+  submitData.departureLongitude = this.departureLongitude
+  submitData.departureLatitude = this.departureLatitude
+} else if (this.addressCoordinates.hospitalOutAddress) {
+  // 鍏滃簳锛氫娇鐢ㄨ浆鍑哄尰闄㈢殑鍧愭爣
+  submitData.departureLongitude = this.addressCoordinates.hospitalOutAddress.lng
+  submitData.departureLatitude = this.addressCoordinates.hospitalOutAddress.lat
+}
+```
+
+## 浣跨敤娴佺▼
+
+### 1. 閰嶇疆鍒嗗叕鍙搁粯璁ゅ嚭鍙戝湴
+
+鍦ㄥ悗鍙扮鐞嗙郴缁熺殑閮ㄩ棬绠$悊涓紝涓哄悇鍒嗗叕鍙搁厤缃粯璁ゅ嚭杞﹀湴鍧�鍙奊PS鍧愭爣锛�
+
+1. 杩涘叆"绯荤粺绠$悊" -> "閮ㄩ棬绠$悊"
+2. 閫夋嫨闇�瑕侀厤缃殑鍒嗗叕鍙革紙parent_id=100鐨勯儴闂級
+3. 鐐瑰嚮"淇敼"
+4. 濉啓浠ヤ笅淇℃伅锛�
+   - **榛樿鍑鸿溅鍦板潃**: 濡�"骞垮窞甯傚ぉ娌冲尯XXX璺疿XX鍙�"
+   - **鍑鸿溅鍦板潃缁忓害**: 濡� 113.123456
+   - **鍑鸿溅鍦板潃绾害**: 濡� 23.123456
+
+### 2. 鍒涘缓杞繍浠诲姟鏃朵娇鐢�
+
+1. 鍦ˋPP绔墦寮�"鍒涘缓杞繍浠诲姟"椤甸潰
+2. 閫夋嫨"褰掑睘鏈烘瀯"锛堝垎鍏徃锛�
+3. 绯荤粺鑷姩濉厖璇ュ垎鍏徃閰嶇疆鐨勯粯璁ゅ嚭鍙戝湴
+4. 鐢ㄦ埛鍙互鎵嬪姩淇敼鍑哄彂鍦板湴鍧�
+5. 鎻愪氦鏃讹紝浼樺厛浣跨敤鑷畾涔夌殑鍑哄彂鍦帮紝濡備负绌哄垯浣跨敤杞嚭鍖婚櫌鍦板潃
+
+## 浼樺厛绾ц鍒�
+
+鍑哄彂鍦扮殑浼樺厛绾т粠楂樺埌浣庝负锛�
+
+1. **鐢ㄦ埛鎵嬪姩淇敼鐨勫嚭鍙戝湴** - 鏈�楂樹紭鍏堢骇
+2. **鍒嗗叕鍙搁厤缃殑榛樿鍑哄彂鍦�** - 閫夋嫨褰掑睘鏈烘瀯鏃惰嚜鍔ㄥ~鍏�
+3. **杞嚭鍖婚櫌鍦板潃** - 濡傛灉鍓嶄袱鑰呴兘涓虹┖锛屼娇鐢ㄨ浆鍑哄尰闄㈠湴鍧�
+
+GPS鍧愭爣鐨勪紭鍏堢骇锛�
+
+1. **鍒嗗叕鍙搁厤缃殑鍑哄彂鍦板潗鏍�** - 濡傛灉鏈夐厤缃�
+2. **杞嚭鍖婚櫌鍦板潃鐨勫潗鏍�** - 鍏滃簳鏂规
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁搴撳崌绾�**: 棣栨閮ㄧ讲闇�瑕佹墽琛� `sql/sys_dept_add_departure_fields.sql` 鑴氭湰
+2. **鏉冮檺閰嶇疆**: 纭繚閮ㄩ棬绠$悊鐨勭紪杈戞潈闄愬寘鍚柊澧炵殑瀛楁
+3. **鍏煎鎬�**: 鏈厤缃嚭鍙戝湴鐨勫垎鍏徃锛岀郴缁熶細鑷姩浣跨敤杞嚭鍖婚櫌鍦板潃锛屼笉褰卞搷鐜版湁鍔熻兘
+4. **鏁版嵁鏍¢獙**: 缁忕含搴﹀瓧娈垫敮鎸丯ULL锛屽彲浠ュ彧濉啓鍦板潃涓嶅~鍐欏潗鏍�
+
+## 鐩稿叧鏂囦欢
+
+### 鏁版嵁搴撹剼鏈�
+- `sql/sys_dept_add_departure_fields.sql`
+
+### 鍚庣鏂囦欢
+- `ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java`
+- `ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml`
+
+### 鍓嶇鏂囦欢
+- `app/components/OrganizationSelector.vue`
+- `app/pages/task/create-emergency.vue`
+
+## 鍚庣画浼樺寲寤鸿
+
+1. 鍙湪鍚庡彴绠$悊绯荤粺鐨勯儴闂ㄧ紪杈戦〉闈㈠鍔犲湴鍥鹃�夌偣鍔熻兘锛屾柟渚块厤缃粡绾害
+2. 鍙鍔犲嚭鍙戝湴鐨勫湴鍧�寤鸿鍔熻兘锛岀被浼煎尰闄㈠湴鍧�杈撳叆
+3. 鍙�冭檻涓烘瘡涓垎鍏徃閰嶇疆澶氫釜甯哥敤鍑哄彂鍦帮紝渚涚敤鎴峰揩閫熼�夋嫨
diff --git "a/prd/\346\224\257\344\273\230\344\277\241\346\201\257\345\217\214\345\220\221\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/prd/\346\224\257\344\273\230\344\277\241\346\201\257\345\217\214\345\220\221\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..54a7d72
--- /dev/null
+++ "b/prd/\346\224\257\344\273\230\344\277\241\346\201\257\345\217\214\345\220\221\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,276 @@
+# 鏀粯淇℃伅鍙屽悜鍚屾鍔熻兘璇存槑
+
+## 鍔熻兘姒傝堪
+
+瀹炵幇鏂扮郴缁� `sys_task_payment` 琛ㄤ笌鏃х郴缁� `PaidMoney` 琛ㄤ箣闂寸殑鏀粯淇℃伅鍙屽悜鍚屾锛岀‘淇濅袱涓郴缁熺殑鏀粯鏁版嵁淇濇寔涓�鑷淬��
+
+## 鎶�鏈灦鏋�
+
+### 鏍稿績瀹炰綋
+
+#### 1. SysTaskPayment锛堟柊绯荤粺鏀粯璁板綍锛�
+- **琛ㄥ悕**: `sys_task_payment`
+- **鏂板瀛楁**:
+  - `pid`: 鏃х郴缁熸敮浠樿褰旾D锛圥aidMoney.id锛�
+  - `sync_status`: 鍚屾鐘舵�侊紙0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触锛�
+  - `sync_time`: 鍚屾鏃堕棿
+
+#### 2. PaidMoney锛堟棫绯荤粺鏀粯璁板綍锛�
+- **琛ㄥ悕**: `PaidMoney`
+- **鍏抽敭瀛楁**:
+  - `id`: 涓婚敭
+  - `ServiceOrdIDDt`: 鏈嶅姟璁㈠崟ID
+  - `DispatchOrdIDDt`: 璋冨害璁㈠崟ID
+  - `PaidMoney`: 鏀粯閲戦
+  - `PaidMoneyType`: 鏀粯绫诲瀷
+  - `PaidMoneyMono`: 鏀粯鍗曞彿
+  - `PaidMoneyTime`: 鏀粯鏃堕棿
+  - `PaidMoneyOaID`: 鏀粯浜篛AID
+
+### 鍏抽敭鍏宠仈
+
+閫氳繃 `SysTaskEmergency` 琛ㄨ幏鍙栦换鍔′笌鏃х郴缁熻鍗曠殑鏄犲皠鍏崇郴锛�
+- `legacy_service_ord_id` 鈫� `ServiceOrdIDDt`
+- `legacy_dispatch_ord_id` 鈫� `DispatchOrdIDDt`
+
+## 鍚屾閫昏緫
+
+### 1. 鏂扮郴缁� 鈫� 鏃х郴缁熷悓姝�
+
+#### 瑙﹀彂鏃舵満
+- 鏂扮郴缁熸敮浠樻垚鍔熷悗鑷姩瑙﹀彂
+- 鍖呮嫭锛氱幇閲戞敮浠樸�佹寕璐︺�佸井淇℃敮浠樻垚鍔熴�佹敮浠樺疂鏀粯鎴愬姛
+
+#### 鍚屾娴佺▼
+1. 鏀粯鎴愬姛鍚庯紝璋冪敤 `PaymentSyncService.syncPaymentToLegacy(paymentId)`
+2. 鏌ヨ鏂扮郴缁熸敮浠樿褰曞拰浠诲姟淇℃伅
+3. 鑾峰彇 `ServiceOrdIDDt` 鍜� `DispatchOrdIDDt`
+4. 杞崲鏀粯鏂瑰紡锛堟柊绯荤粺 鈫� 鏃х郴缁燂級
+5. 鏋勫缓 `PaidMoney` 瀵硅薄骞舵彃鍏ユ棫绯荤粺
+6. 鏇存柊鏂扮郴缁熸敮浠樿褰曠殑 `pid`銆乣sync_status`銆乣sync_time`
+
+#### 鏀粯鏂瑰紡鏄犲皠锛堟柊 鈫� 鏃э級
+| 鏂扮郴缁熸敮浠樻柟寮� | 鏃х郴缁熸敮浠樼被鍨� | 璇存槑 |
+|--------------|--------------|------|
+| CASH | 1 | 鐜伴噾 |
+| ON_ACCOUNT | 6 | 鎸傝处 |
+| WECHAT | 3 | 寰俊鏀粯 |
+| ALIPAY | 4 | 鏀粯瀹� |
+
+#### 鏁版嵁鏄犲皠
+
+```java
+PaidMoney.PaidMoneyClass = "FI"  // 榛樿FI
+PaidMoney.ServiceOrdIDDt = emergency.legacyServiceOrdId
+PaidMoney.DispatchOrdIDDt = emergency.legacyDispatchOrdId
+PaidMoney.PaidMoney = payment.settlementAmount
+PaidMoney.PaidMoneyType = convertPaymentMethodToLegacy(payment.paymentMethod)
+PaidMoney.PaidMoneyMono = payment.tradeNo 鎴� payment.outTradeNo
+PaidMoney.PaidMoneyTime = payment.payTime
+PaidMoney.PaidMoneyOaID = user.oaUserId
+PaidMoney.PaidMoneyUnitID = 0  // 榛樿0
+PaidMoney.PaidMoneyAPCheck = 1  // 宸茬‘璁�
+PaidMoney.PaidMoneyAPTime = now()
+```
+
+### 2. 鏃х郴缁� 鈫� 鏂扮郴缁熷悓姝�
+
+#### 瑙﹀彂鏃舵満
+- 瀹氭椂浠诲姟锛堝緟瀹炵幇锛�
+- 鎵嬪姩璋冪敤 `PaymentSyncService.syncPaymentFromLegacy(paidMoneyId)`
+
+#### 鍚屾娴佺▼
+1. 鏌ヨ鏃х郴缁� `PaidMoney` 璁板綍
+2. 妫�鏌ユ槸鍚﹀凡鍚屾锛堥�氳繃 `pid` 瀛楁锛�
+3. 鏍规嵁 `ServiceOrdIDDt` 鏌ヨ鏂扮郴缁熶换鍔�
+4. 杞崲鏀粯鏂瑰紡锛堟棫绯荤粺 鈫� 鏂扮郴缁燂級
+5. 鏋勫缓 `SysTaskPayment` 瀵硅薄骞舵彃鍏ユ柊绯荤粺
+6. 璁剧疆 `pid`銆乣sync_status=2`銆乣sync_time`
+
+#### 鏀粯鏂瑰紡鏄犲皠锛堟棫 鈫� 鏂帮級
+| 鏃х郴缁熸敮浠樼被鍨� | 鏂扮郴缁熸敮浠樻柟寮� | 璇存槑 |
+|--------------|--------------|------|
+| 1 | CASH | 鐜伴噾 |
+| 6, 7 | ON_ACCOUNT | 鎸傝处銆佹槗鍖婚�氭寕璐� |
+| 3 | WECHAT | 寰俊鏀粯 |
+| 4 | ALIPAY | 鏀粯瀹� |
+
+#### 鏁版嵁鏄犲皠
+
+```java
+SysTaskPayment.taskId = task.taskId
+SysTaskPayment.totalAmount = paidMoney.paidMoney
+SysTaskPayment.settlementAmount = paidMoney.paidMoney
+SysTaskPayment.paymentMethod = convertPaymentMethodFromLegacy(paidMoney.paidMoneyType)
+SysTaskPayment.payStatus = "PAID"
+SysTaskPayment.payTime = paidMoney.paidMoneyTime
+SysTaskPayment.outTradeNo = taskCode + "-" + paidMoneyId
+SysTaskPayment.tradeNo = paidMoney.paidMoneyMono
+SysTaskPayment.pid = paidMoneyId
+SysTaskPayment.syncStatus = 2
+SysTaskPayment.syncTime = now()
+```
+
+## 鏍稿績浠g爜瀹炵幇
+
+### 鏂囦欢娓呭崟
+
+#### 鏂板鏂囦欢
+1. **瀹炰綋绫�**
+   - `PaidMoney.java` - 鏃х郴缁熸敮浠樿褰曞疄浣�
+
+2. **Mapper鎺ュ彛**
+   - `PaidMoneyMapper.java` - 鏃х郴缁熸敮浠樿褰昅apper鎺ュ彛
+
+3. **Mapper XML**
+   - `PaidMoneyMapper.xml` - 鏃х郴缁熸敮浠樿褰昐QL鏄犲皠
+
+4. **Service鎺ュ彛**
+   - `IPaymentSyncService.java` - 鏀粯鍚屾鏈嶅姟鎺ュ彛
+
+5. **Service瀹炵幇**
+   - `PaymentSyncServiceImpl.java` - 鏀粯鍚屾鏈嶅姟瀹炵幇
+
+6. **鏁版嵁搴撹剼鏈�**
+   - `payment_sync_update.sql` - 鏁版嵁琛ㄦ洿鏂拌剼鏈�
+
+#### 淇敼鏂囦欢
+1. **瀹炰綋绫�**
+   - `SysTaskPayment.java` - 鏂板 pid銆乻yncStatus銆乻yncTime 瀛楁
+
+2. **Mapper鎺ュ彛**
+   - `SysTaskPaymentMapper.java` - 鏂板 selectByPid銆乽pdateSyncInfo 鏂规硶
+
+3. **Mapper XML**
+   - `SysTaskPaymentMapper.xml` - 鏇存柊鏄犲皠鍜屾柊澧炴煡璇㈡柟娉�
+
+4. **Service瀹炵幇**
+   - `SysTaskPaymentServiceImpl.java` - 鏀粯鎴愬姛鍚庤Е鍙戝悓姝�
+
+## 鏁版嵁婧愰厤缃�
+
+浣跨敤 `@DataSource` 娉ㄨВ鍒囨崲鏁版嵁婧愶細
+
+```java
+// 璁块棶鏂扮郴缁熸暟鎹簱锛堥粯璁わ級
+public void processNewSystem() {
+    // 榛樿浣跨敤涓绘暟鎹簮
+}
+
+// 璁块棶鏃х郴缁熸暟鎹簱
+@DataSource(DataSourceType.SQLSERVER)
+public void processLegacySystem() {
+    // 浣跨敤SQL Server鏁版嵁婧�
+}
+```
+
+## 鍚屾鐘舵�佺鐞�
+
+### sync_status 鐘舵�佸��
+- **0 - 鏈悓姝�**: 鏂板垱寤虹殑鏀粯璁板綍锛屽皻鏈悓姝ュ埌鏃х郴缁�
+- **1 - 鍚屾涓�**: 姝e湪鎵ц鍚屾鎿嶄綔
+- **2 - 鍚屾鎴愬姛**: 宸叉垚鍔熷悓姝ュ埌鏃х郴缁�
+- **3 - 鍚屾澶辫触**: 鍚屾杩囩▼涓彂鐢熼敊璇�
+
+### 鐘舵�佹祦杞�
+```
+鏂版敮浠樿褰� 鈫� 0(鏈悓姝�) 鈫� 1(鍚屾涓�) 鈫� 2(鍚屾鎴愬姛) 鎴� 3(鍚屾澶辫触)
+                                    鈫�
+                                 鍙噸璇�
+```
+
+## 寮傚父澶勭悊
+
+### 鍚屾澶辫触鍦烘櫙
+1. 浠诲姟鏈悓姝ュ埌鏃х郴缁燂紙缂哄皯 ServiceOrdID/DispatchOrdID锛�
+2. 鏃х郴缁熸暟鎹簱杩炴帴澶辫触
+3. 鏁版嵁鎻掑叆鍐茬獊鎴栫害鏉熻繚鍙�
+4. 缃戠粶寮傚父
+
+### 澶勭悊绛栫暐
+1. 鍚屾澶辫触鏃舵爣璁� `sync_status=3`
+2. 璁板綍璇︾粏閿欒鏃ュ織
+3. 涓嶅奖鍝嶄富涓氬姟娴佺▼锛堝紓姝ュ悓姝ワ級
+4. 鍙�氳繃瀹氭椂浠诲姟鎴栨墜鍔ㄨЕ鍙戦噸璇�
+
+## 浣跨敤绀轰緥
+
+### 鎵嬪姩瑙﹀彂鍚屾
+
+```java
+@Autowired
+private IPaymentSyncService paymentSyncService;
+
+// 鍚屾鍗曟潯鏀粯璁板綍鍒版棫绯荤粺
+boolean success = paymentSyncService.syncPaymentToLegacy(paymentId);
+
+// 浠庢棫绯荤粺鍚屾鏀粯璁板綍
+boolean success = paymentSyncService.syncPaymentFromLegacy(paidMoneyId);
+
+// 鎵归噺鍚屾锛堝緟瀹炵幇锛�
+int count = paymentSyncService.batchSyncPaymentToLegacy();
+int count = paymentSyncService.batchSyncPaymentFromLegacy();
+```
+
+## 鏁版嵁搴撴洿鏂�
+
+鎵ц SQL 鑴氭湰锛�
+```sql
+source sql/payment_sync_update.sql
+```
+
+鎴栨墜鍔ㄦ墽琛岋細
+```sql
+ALTER TABLE sys_task_payment ADD COLUMN pid BIGINT COMMENT '鏃х郴缁熸敮浠樿褰旾D(PaidMoney.id)';
+ALTER TABLE sys_task_payment ADD COLUMN sync_status INT DEFAULT 0 COMMENT '鍚屾鐘舵�侊細0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触';
+ALTER TABLE sys_task_payment ADD COLUMN sync_time DATETIME COMMENT '鍚屾鏃堕棿';
+CREATE INDEX idx_pid ON sys_task_payment(pid);
+CREATE INDEX idx_sync_status ON sys_task_payment(sync_status);
+```
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **鎵归噺鍚屾瀹炵幇**
+   - 瀹炵幇瀹氭椂浠诲姟鎵归噺鍚屾鏈悓姝ョ殑鏀粯璁板綍
+   - 瀹炵幇浠庢棫绯荤粺瀹氭湡鎷夊彇鏂板鏀粯璁板綍
+
+2. **閲嶈瘯鏈哄埗**
+   - 瀵瑰悓姝ュけ璐ョ殑璁板綍瀹炵幇鑷姩閲嶈瘯
+   - 璁剧疆鏈�澶ч噸璇曟鏁板拰閲嶈瘯闂撮殧
+
+3. **鐩戞帶鍛婅**
+   - 鐩戞帶鍚屾澶辫触鐜�
+   - 鍚屾寤惰繜鍛婅
+   - 鏁版嵁涓�鑷存�ф牎楠�
+
+4. **鎬ц兘浼樺寲**
+   - 鑰冭檻浣跨敤娑堟伅闃熷垪寮傛澶勭悊
+   - 鎵归噺鎿嶄綔浼樺寲鏁版嵁搴撴�ц兘
+
+## 娉ㄦ剰浜嬮」
+
+1. **鍓嶇疆鏉′欢**: 浠诲姟蹇呴』鍏堝悓姝ュ埌鏃х郴缁燂紙鏈� ServiceOrdID 鍜� DispatchOrdID锛�
+2. **骞傜瓑鎬�**: 閲嶅鍚屾浼氳妫�娴嬪苟璺宠繃
+3. **浜嬪姟澶勭悊**: 鍚屾鎿嶄綔浣跨敤鐙珛浜嬪姟锛屽け璐ヤ笉褰卞搷涓讳笟鍔�
+4. **鏁版嵁涓�鑷存��**: 閫氳繃 pid 瀛楁寤虹珛鍙屽悜鍏宠仈锛岄伩鍏嶉噸澶嶅悓姝�
+5. **鏀粯鏂瑰紡鏄犲皠**: 纭繚鏂版棫绯荤粺鏀粯鏂瑰紡姝g‘鏄犲皠
+
+## 娴嬭瘯寤鸿
+
+1. **鍗曞厓娴嬭瘯**
+   - 娴嬭瘯鏀粯鏂瑰紡杞崲閫昏緫
+   - 娴嬭瘯鏁版嵁鏄犲皠姝g‘鎬�
+   - 娴嬭瘯寮傚父澶勭悊
+
+2. **闆嗘垚娴嬭瘯**
+   - 娴嬭瘯瀹屾暣鍚屾娴佺▼
+   - 娴嬭瘯骞傜瓑鎬�
+   - 娴嬭瘯澶辫触閲嶈瘯
+
+3. **鏁版嵁鏍¢獙**
+   - 瀵规瘮鏂版棫绯荤粺鏀粯鏁版嵁
+   - 楠岃瘉閲戦銆佹椂闂淬�佺姸鎬佷竴鑷存��
+
+---
+鏇存柊鏃堕棿: 2025-01-15
+鐗堟湰: v1.0
diff --git "a/prd/\351\231\204\345\212\240\350\264\271\347\224\250\345\217\214\345\220\221\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/prd/\351\231\204\345\212\240\350\264\271\347\224\250\345\217\214\345\220\221\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..06b6860
--- /dev/null
+++ "b/prd/\351\231\204\345\212\240\350\264\271\347\224\250\345\217\214\345\220\221\345\220\214\346\255\245\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,285 @@
+# 闄勫姞璐圭敤鍙屽悜鍚屾鍔熻兘璇存槑
+
+## 鍔熻兘姒傝堪
+
+瀹炵幇鏂扮郴缁� `sys_task_additional_fee` 琛ㄤ笌鏃х郴缁� `PaidMoney_Add` 琛ㄤ箣闂寸殑闄勫姞璐圭敤鍙屽悜鍚屾锛岀‘淇濅袱涓郴缁熺殑闄勫姞璐圭敤鏁版嵁淇濇寔涓�鑷淬��
+
+## 鎶�鏈灦鏋�
+
+### 鏍稿績瀹炰綋
+
+#### 1. SysTaskAdditionalFee锛堟柊绯荤粺闄勫姞璐圭敤璁板綍锛�
+- **琛ㄥ悕**: `sys_task_additional_fee`
+- **鏂板瀛楁**:
+  - `pid`: 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰旾D锛圥aidMoney_Add.id锛�
+  - `sync_status`: 鍚屾鐘舵�侊紙0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触锛�
+  - `sync_time`: 鍚屾鏃堕棿
+
+#### 2. PaidMoneyAdd锛堟棫绯荤粺闄勫姞璐圭敤璁板綍锛�
+- **琛ㄥ悕**: `PaidMoney_Add`
+- **鍏抽敭瀛楁**:
+  - `id`: 涓婚敭
+  - `ToServiceOrdID`: 鏈嶅姟鍗旾D
+  - `ToDispatchOrdID`: 璋冨害鍗旾D
+  - `AddMoneyType`: 闄勫姞璐圭敤绫诲瀷
+  - `AddMoney`: 闄勫姞璐圭敤閲戦
+  - `AddMoneyExplain`: 闄勫姞璐圭敤璇存槑
+  - `AddMoneyTime`: 闄勫姞璐圭敤鏃堕棿
+  - `AddMoneyOAID`: 娣诲姞鐢ㄦ埛鐨凮AID
+
+### 鍏抽敭鍏宠仈
+
+閫氳繃 `SysTaskEmergency` 琛ㄨ幏鍙栦换鍔′笌鏃х郴缁熻鍗曠殑鏄犲皠鍏崇郴锛�
+- `legacy_service_ord_id` 鈫� `ToServiceOrdID`
+- `legacy_dispatch_ord_id` 鈫� `ToDispatchOrdID`
+
+## 鍚屾閫昏緫
+
+### 1. 鏂扮郴缁� 鈫� 鏃х郴缁熷悓姝�
+
+#### 瑙﹀彂鏃舵満
+- 鏂扮郴缁熸坊鍔犻檮鍔犺垂鐢ㄥ悗鑷姩瑙﹀彂
+
+#### 鍚屾娴佺▼
+1. 娣诲姞闄勫姞璐圭敤鍚庯紝璋冪敤 `AdditionalFeeSyncService.syncAdditionalFeeToLegacy(feeId)`
+2. 鏌ヨ鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曞拰浠诲姟淇℃伅
+3. 鑾峰彇 `ToServiceOrdID` 鍜� `ToDispatchOrdID`
+4. 杞崲璐圭敤绫诲瀷锛堟柊绯荤粺 鈫� 鏃х郴缁燂級
+5. 鏋勫缓 `PaidMoneyAdd` 瀵硅薄骞舵彃鍏ユ棫绯荤粺
+6. 鏇存柊鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曠殑 `pid`銆乣sync_status`銆乣sync_time`
+
+#### 璐圭敤绫诲瀷鏄犲皠锛堟柊 鈫� 鏃э級
+| 鏂扮郴缁熷瓧鍏稿�� | 鏃х郴缁烝ddMoneyType | 璇存槑 |
+|------------|------------------|------|
+| 1 | 1 | 绛夊緟璐� |
+| 2 | 2 | 鎷呮灦 |
+| 3 | 3 | 灞呭ICU |
+| 4 | 4 | 鍖荤枟璁惧 |
+
+#### 鏁版嵁鏄犲皠
+
+```java
+PaidMoneyAdd.ToServiceOrdID = emergency.legacyServiceOrdId
+PaidMoneyAdd.ToDispatchOrdID = emergency.legacyDispatchOrdId
+PaidMoneyAdd.AddMoneyType = Integer.parseInt(fee.feeType)
+PaidMoneyAdd.AddMoney = fee.totalAmount
+PaidMoneyAdd.AddMoneyExplain = fee.feeName + (澶囨敞)
+PaidMoneyAdd.AddMoneyTime = fee.createdTime
+PaidMoneyAdd.AddMoneyOAID = user.oaUserId
+```
+
+### 2. 鏃х郴缁� 鈫� 鏂扮郴缁熷悓姝�
+
+#### 瑙﹀彂鏃舵満
+- 瀹氭椂浠诲姟锛堟瘡15鍒嗛挓鎵ц涓�娆★級
+- 鎵嬪姩璋冪敤 `AdditionalFeeSyncService.syncAdditionalFeeFromLegacy(paidMoneyAddId)`
+
+#### 鍚屾娴佺▼
+1. 鏌ヨ鏃х郴缁� `PaidMoney_Add` 璁板綍
+2. 妫�鏌ユ槸鍚﹀凡鍚屾锛堥�氳繃 `pid` 瀛楁锛�
+3. 鏍规嵁 `ToServiceOrdID` 鏌ヨ鏂扮郴缁熶换鍔�
+4. 楠岃瘉 `ToDispatchOrdID` 鏄惁鍖归厤
+5. 杞崲璐圭敤绫诲瀷锛堟棫绯荤粺 鈫� 鏂扮郴缁燂級
+6. 鏋勫缓 `SysTaskAdditionalFee` 瀵硅薄骞舵彃鍏ユ柊绯荤粺
+7. 璁剧疆 `pid`銆乣sync_status=2`銆乣sync_time`
+
+#### 璐圭敤绫诲瀷鏄犲皠锛堟棫 鈫� 鏂帮級
+| 鏃х郴缁烝ddMoneyType | 鏂扮郴缁熷瓧鍏稿�� | 璇存槑 |
+|------------------|-----------|------|
+| 1 | 1 | 绛夊緟璐� |
+| 2 | 2 | 鎷呮灦 |
+| 3 | 3 | 灞呭ICU |
+| 4 | 4 | 鍖荤枟璁惧 |
+
+#### 鏁版嵁鏄犲皠
+
+```java
+SysTaskAdditionalFee.taskId = emergency.taskId
+SysTaskAdditionalFee.feeType = String.valueOf(paidMoneyAdd.addMoneyType)
+SysTaskAdditionalFee.feeName = getFeeTypeName(feeType)
+SysTaskAdditionalFee.unitAmount = paidMoneyAdd.addMoney
+SysTaskAdditionalFee.quantity = 1
+SysTaskAdditionalFee.totalAmount = paidMoneyAdd.addMoney
+SysTaskAdditionalFee.remark = paidMoneyAdd.addMoneyExplain
+SysTaskAdditionalFee.pid = paidMoneyAddId
+SysTaskAdditionalFee.syncStatus = 2
+SysTaskAdditionalFee.syncTime = now()
+```
+
+## 鏍稿績浠g爜瀹炵幇
+
+### 鏂囦欢娓呭崟
+
+#### 鏂板鏂囦欢
+1. **瀹炰綋绫�**
+   - `PaidMoneyAdd.java` - 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曞疄浣�
+
+2. **Mapper鎺ュ彛**
+   - `PaidMoneyAddMapper.java` - 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰昅apper鎺ュ彛
+
+3. **Mapper XML**
+   - `PaidMoneyAddMapper.xml` - 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰昐QL鏄犲皠
+
+4. **Service鎺ュ彛**
+   - `IAdditionalFeeSyncService.java` - 闄勫姞璐圭敤鍚屾鏈嶅姟鎺ュ彛
+
+5. **Service瀹炵幇**
+   - `AdditionalFeeSyncServiceImpl.java` - 闄勫姞璐圭敤鍚屾鏈嶅姟瀹炵幇
+
+6. **鏁版嵁搴撹剼鏈�**
+   - `additional_fee_sync_update.sql` - 鏁版嵁琛ㄦ洿鏂拌剼鏈�
+
+#### 淇敼鏂囦欢
+1. **瀹炰綋绫�**
+   - `SysTaskAdditionalFee.java` - 鏂板 pid銆乻yncStatus銆乻yncTime 瀛楁
+
+2. **Mapper鎺ュ彛**
+   - `SysTaskAdditionalFeeMapper.java` - 鏂板 selectByPid銆乽pdateSyncInfo銆乻electUnsyncedFees 鏂规硶
+
+3. **Mapper XML**
+   - `SysTaskAdditionalFeeMapper.xml` - 鏇存柊鏄犲皠鍜屾柊澧炴煡璇㈡柟娉�
+
+4. **Service瀹炵幇**
+   - `SysTaskPaymentServiceImpl.java` - 娣诲姞闄勫姞璐圭敤鍚庤Е鍙戝悓姝�
+
+5. **瀹氭椂浠诲姟**
+   - `LegacySystemSyncTask.java` - 鏂板闄勫姞璐圭敤鍚屾瀹氭椂浠诲姟鏂规硶
+
+## 鏁版嵁婧愰厤缃�
+
+浣跨敤 `@DataSource` 娉ㄨВ鍒囨崲鏁版嵁婧愶細
+
+```java
+// 璁块棶鏂扮郴缁熸暟鎹簱锛堥粯璁わ級
+public void processNewSystem() {
+    // 榛樿浣跨敤涓绘暟鎹簮
+}
+
+// 璁块棶鏃х郴缁熸暟鎹簱
+@DataSource(DataSourceType.SQLSERVER)
+public void processLegacySystem() {
+    // 浣跨敤SQL Server鏁版嵁婧�
+}
+```
+
+## 鍚屾鐘舵�佺鐞�
+
+### sync_status 鐘舵�佸��
+- **0 - 鏈悓姝�**: 鏂板垱寤虹殑闄勫姞璐圭敤璁板綍锛屽皻鏈悓姝ュ埌鏃х郴缁�
+- **1 - 鍚屾涓�**: 姝e湪鎵ц鍚屾鎿嶄綔
+- **2 - 鍚屾鎴愬姛**: 宸叉垚鍔熷悓姝ュ埌鏃х郴缁�
+- **3 - 鍚屾澶辫触**: 鍚屾杩囩▼涓彂鐢熼敊璇�
+
+### 鐘舵�佹祦杞�
+```
+鏂伴檮鍔犺垂鐢ㄨ褰� 鈫� 0(鏈悓姝�) 鈫� 1(鍚屾涓�) 鈫� 2(鍚屾鎴愬姛) 鎴� 3(鍚屾澶辫触)
+                                         鈫�
+                                      鍙噸璇�
+```
+
+## 寮傚父澶勭悊
+
+### 鍚屾澶辫触鍦烘櫙
+1. 浠诲姟鏈悓姝ュ埌鏃х郴缁燂紙缂哄皯 ToServiceOrdID/ToDispatchOrdID锛�
+2. 鏃х郴缁熸暟鎹簱杩炴帴澶辫触
+3. 鏁版嵁鎻掑叆鍐茬獊鎴栫害鏉熻繚鍙�
+4. 缃戠粶寮傚父
+
+### 澶勭悊绛栫暐
+1. 鍚屾澶辫触鏃舵爣璁� `sync_status=3`
+2. 璁板綍璇︾粏閿欒鏃ュ織
+3. 涓嶅奖鍝嶄富涓氬姟娴佺▼锛堝紓姝ュ悓姝ワ級
+4. 鍙�氳繃瀹氭椂浠诲姟鎴栨墜鍔ㄨЕ鍙戦噸璇�
+
+## 浣跨敤绀轰緥
+
+### 鎵嬪姩瑙﹀彂鍚屾
+
+```java
+@Autowired
+private IAdditionalFeeSyncService additionalFeeSyncService;
+
+// 鍚屾鍗曟潯闄勫姞璐圭敤鍒版棫绯荤粺
+boolean success = additionalFeeSyncService.syncAdditionalFeeToLegacy(feeId);
+
+// 浠庢棫绯荤粺鍚屾闄勫姞璐圭敤
+boolean success = additionalFeeSyncService.syncAdditionalFeeFromLegacy(paidMoneyAddId);
+
+// 鎵归噺鍚屾
+int count = additionalFeeSyncService.batchSyncAdditionalFeeToLegacy();
+int count = additionalFeeSyncService.batchSyncAdditionalFeeFromLegacy(24); // 鍚屾24灏忔椂鍐呯殑璁板綍
+```
+
+### 閰嶇疆瀹氭椂浠诲姟
+
+#### 鏂扮郴缁� 鈫� 鏃х郴缁熷悓姝�
+```
+浠诲姟鍚嶇О: 闄勫姞璐圭敤鍚屾
+浠诲姟缁勫悕: DEFAULT
+璋冪敤鐩爣: legacySystemSyncTask.syncAdditionalFeeToLegacy()
+cron琛ㄨ揪寮�: 0 0/10 * * * ? (姣�10鍒嗛挓鎵ц涓�娆�)
+```
+
+#### 鏃х郴缁� 鈫� 鏂扮郴缁熷悓姝�
+```
+浠诲姟鍚嶇О: 闄勫姞璐圭敤鍙嶅悜鍚屾
+浠诲姟缁勫悕: DEFAULT
+璋冪敤鐩爣: legacySystemSyncTask.syncAdditionalFeeFromLegacy()
+cron琛ㄨ揪寮�: 0 0/15 * * * ? (姣�15鍒嗛挓鎵ц涓�娆�)
+```
+
+## 鏁版嵁搴撴洿鏂�
+
+鎵ц SQL 鑴氭湰锛�
+```sql
+source sql/additional_fee_sync_update.sql
+```
+
+## 娉ㄦ剰浜嬮」
+
+1. **鍓嶇疆鏉′欢**: 浠诲姟蹇呴』宸茬粡鍚屾鍒版棫绯荤粺锛堟湁 ServiceOrdID 鍜� DispatchOrdID锛�
+2. **璐圭敤绫诲瀷**: 浣跨敤缁熶竴鐨勫瓧鍏稿�硷紙1-绛夊緟璐�, 2-鎷呮灦, 3-灞呭ICU, 4-鍖荤枟璁惧锛�
+3. **鍚屾闂撮殧**: 鏂扮郴缁熲啋鏃х郴缁熺珛鍗冲悓姝ワ紝鏃х郴缁熲啋鏂扮郴缁熷畾鏃跺悓姝�
+4. **閿欒澶勭悊**: 鍚屾澶辫触涓嶅奖鍝嶄富涓氬姟锛屽彲浠ラ噸璇�
+5. **鎬ц兘浼樺寲**: 鎵归噺鍚屾闄愬埗姣忔100鏉¤褰曪紝姣忔潯璁板綍闂撮殧1绉�
+
+## 楠岃瘉娴嬭瘯
+
+### 娴嬭瘯姝ラ
+
+1. **鏂板闄勫姞璐圭敤锛堟柊绯荤粺 鈫� 鏃х郴缁燂級**
+   - 鍦ˋPP涓负杞繍浠诲姟娣诲姞闄勫姞璐圭敤
+   - 妫�鏌ユ柊绯荤粺 `sys_task_additional_fee` 琛ㄧ殑 `sync_status` 瀛楁
+   - 妫�鏌ユ棫绯荤粺 `PaidMoney_Add` 琛ㄦ槸鍚︽湁瀵瑰簲璁板綍
+
+2. **鏃х郴缁熸柊澧為檮鍔犺垂鐢紙鏃х郴缁� 鈫� 鏂扮郴缁燂級**
+   - 鍦ㄦ棫绯荤粺涓坊鍔犻檮鍔犺垂鐢ㄨ褰�
+   - 杩愯瀹氭椂浠诲姟鎴栨墜鍔ㄨ皟鐢ㄥ悓姝ユ柟娉�
+   - 妫�鏌ユ柊绯荤粺 `sys_task_additional_fee` 琛ㄦ槸鍚︽湁瀵瑰簲璁板綍
+
+### 鏌ヨ楠岃瘉SQL
+
+```sql
+-- 鏌ョ湅鏂扮郴缁熼檮鍔犺垂鐢ㄥ強鍚屾鐘舵��
+SELECT id, task_id, fee_type, fee_name, total_amount, sync_status, pid
+FROM sys_task_additional_fee
+WHERE task_id = ?;
+
+-- 鏌ョ湅鏃х郴缁熼檮鍔犺垂鐢紙鍦⊿QL Server涓墽琛岋級
+SELECT id, ToServiceOrdID, ToDispatchOrdID, AddMoneyType, AddMoney, AddMoneyExplain
+FROM PaidMoney_Add
+WHERE ToServiceOrdID = ? AND ToDispatchOrdID = ?;
+
+-- 鏌ョ湅鏈悓姝ョ殑闄勫姞璐圭敤
+SELECT *
+FROM sys_task_additional_fee
+WHERE (sync_status = 0 OR sync_status = 3 OR sync_status IS NULL);
+```
+
+## 鎶�鏈鐐�
+
+1. **鍙屽悜鍚屾**: 鏀寔鏂版棫绯荤粺涔嬮棿鐨勫弻鍚戞暟鎹悓姝�
+2. **骞傜瓑鎬�**: 閫氳繃 pid 瀛楁閬垮厤閲嶅鍚屾
+3. **浜嬪姟鎬�**: 浣跨敤 @Transactional 纭繚鏁版嵁涓�鑷存��
+4. **寮傛澶勭悊**: 鍚屾涓嶉樆濉炰富涓氬姟娴佺▼
+5. **閿欒閲嶈瘯**: 鏀寔澶辫触璁板綍鐨勯噸鏂板悓姝�
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 624a352..a77a0d9 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -63,6 +63,14 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>ruoyi-generator</artifactId>
         </dependency>
+        
+        <!-- 鏀粯妯″潡 -->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>dryad-payment</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
index cd4693f..e17fb3b 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -3,6 +3,7 @@
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
 
 /**
  * 鍚姩绋嬪簭
@@ -10,6 +11,7 @@
  * @author ruoyi
  */
 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+@ComponentScan(basePackages = {"com.ruoyi", "com.ruoyi.payment"})
 public class RuoYiApplication
 {
     public static void main(String[] args)
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/PaymentCallbackController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/PaymentCallbackController.java
new file mode 100644
index 0000000..abb8ba6
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/PaymentCallbackController.java
@@ -0,0 +1,75 @@
+package com.ruoyi.web.controller.common;
+
+import java.util.Map;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.system.service.ISysTaskPaymentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 鏀粯鍥炶皟Controller
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@RestController
+@RequestMapping("/payment/callback")
+public class PaymentCallbackController extends BaseController {
+    
+    private static final Logger log = LoggerFactory.getLogger(PaymentCallbackController.class);
+    
+    @Autowired
+    private ISysTaskPaymentService taskPaymentService;
+    
+    /**
+     * 寰俊鏀粯鍥炶皟
+     */
+    @Anonymous
+    @PostMapping("/wechat")
+    public AjaxResult wechatCallback(@RequestBody Map<String, Object> params) {
+        log.info("鏀跺埌寰俊鏀粯鍥炶皟锛歿}", params);
+        
+        // TODO: 瀹為檯椤圭洰涓渶瑕侀獙璇佺鍚�
+        String outTradeNo = (String) params.get("outTradeNo");
+        if (StringUtils.isEmpty(outTradeNo)) {
+            outTradeNo = (String) params.get("bizOrderId");
+        }
+        String tradeNo = (String) params.get("tradeNo");
+        if (StringUtils.isEmpty(tradeNo)) {
+            tradeNo = (String) params.get("channelTradeNo");
+        }
+        
+        boolean success = taskPaymentService.handlePaymentCallback(outTradeNo, tradeNo, "WECHAT");
+        
+        return success ? success() : error("澶勭悊澶辫触");
+    }
+    
+    /**
+     * 鏀粯瀹濇敮浠樺洖璋�
+     */
+    @Anonymous
+    @PostMapping("/alipay")
+    public AjaxResult alipayCallback(@RequestBody Map<String, Object> params) {
+        log.info("鏀跺埌鏀粯瀹濇敮浠樺洖璋冿細{}", params);
+        
+        // TODO: 瀹為檯椤圭洰涓渶瑕侀獙璇佺鍚�
+        String outTradeNo = (String) params.get("outTradeNo");
+        if (StringUtils.isEmpty(outTradeNo)) {
+            outTradeNo = (String) params.get("bizOrderId");
+        }
+        String tradeNo = (String) params.get("tradeNo");
+        if (StringUtils.isEmpty(tradeNo)) {
+            tradeNo = (String) params.get("channelTradeNo");
+        }
+        
+        boolean success = taskPaymentService.handlePaymentCallback(outTradeNo, tradeNo, "ALIPAY");
+        
+        return success ? success() : error("澶勭悊澶辫触");
+    }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskPaymentController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskPaymentController.java
new file mode 100644
index 0000000..24baba1
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskPaymentController.java
@@ -0,0 +1,107 @@
+package com.ruoyi.web.controller.task;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.vo.TaskPaymentInfoVO;
+import com.ruoyi.system.domain.vo.TaskPaymentCreateVO;
+import com.ruoyi.system.domain.vo.TaskPaymentResultVO;
+import com.ruoyi.system.service.ISysTaskPaymentService;
+
+/**
+ * 浠诲姟鏀粯Controller
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@RestController
+@RequestMapping("/task/payment")
+public class SysTaskPaymentController extends BaseController {
+    
+    @Autowired
+    private ISysTaskPaymentService taskPaymentService;
+    
+    /**
+     * 鑾峰彇浠诲姟鏀粯淇℃伅
+     */
+    @GetMapping("/info")
+    public AjaxResult getPaymentInfo(@RequestParam Long taskId) {
+        TaskPaymentInfoVO paymentInfo = taskPaymentService.getPaymentInfo(taskId);
+        return success(paymentInfo);
+    }
+    
+    /**
+     * 鏂板闄勫姞璐圭敤
+     */
+    @Log(title = "鏂板闄勫姞璐圭敤", businessType = BusinessType.INSERT)
+    @PostMapping("/additional-fee/add")
+    public AjaxResult addAdditionalFee(@RequestBody Map<String, Object> params) {
+        Long taskId = Long.valueOf(params.get("taskId").toString());
+        String feeType = (String) params.get("feeType");
+        String feeName = (String) params.get("feeName");
+        BigDecimal unitAmount = new BigDecimal(params.get("unitAmount").toString());
+        Integer quantity = Integer.valueOf(params.get("quantity").toString());
+        String remark = params.get("remark") != null ? params.get("remark").toString() : null;
+        
+        BigDecimal additionalAmount = taskPaymentService.addAdditionalFee(
+            taskId, feeType, feeName, unitAmount, quantity, remark
+        );
+        
+        // 閲嶆柊鑾峰彇鏀粯淇℃伅
+        TaskPaymentInfoVO paymentInfo = taskPaymentService.getPaymentInfo(taskId);
+        
+        Map<String, Object> result = new HashMap<>();
+        result.put("additionalAmount", additionalAmount);
+        result.put("totalAmount", paymentInfo.getTotalAmount());
+        
+        return success(result);
+    }
+    
+    /**
+     * 鍒犻櫎闄勫姞璐圭敤
+     */
+    @Log(title = "鍒犻櫎闄勫姞璐圭敤", businessType = BusinessType.DELETE)
+    @PostMapping("/additional-fee/remove")
+    public AjaxResult removeAdditionalFee(@RequestBody Map<String, Object> params) {
+        Long taskId = Long.valueOf(params.get("taskId").toString());
+        Long feeId = Long.valueOf(params.get("feeId").toString());
+        
+        BigDecimal additionalAmount = taskPaymentService.removeAdditionalFee(taskId, feeId);
+        
+        // 閲嶆柊鑾峰彇鏀粯淇℃伅
+        TaskPaymentInfoVO paymentInfo = taskPaymentService.getPaymentInfo(taskId);
+        
+        Map<String, Object> result = new HashMap<>();
+        result.put("additionalAmount", additionalAmount);
+        result.put("totalAmount", paymentInfo.getTotalAmount());
+        
+        return success(result);
+    }
+    
+    /**
+     * 鍒涘缓鏀粯
+     */
+    @Log(title = "鍒涘缓鏀粯", businessType = BusinessType.INSERT)
+    @PostMapping("/create")
+    public AjaxResult createPayment(@RequestBody TaskPaymentCreateVO createVO) {
+        TaskPaymentResultVO result = taskPaymentService.createPayment(createVO);
+        return success(result);
+    }
+    
+    /**
+     * 鏌ヨ鏀粯鐘舵��
+     */
+    @GetMapping("/status")
+    public AjaxResult getPaymentStatus(@RequestParam Long taskId, 
+                                      @RequestParam(required = false) Long paymentId) {
+        TaskPaymentResultVO result = taskPaymentService.getPaymentStatus(taskId, paymentId);
+        return success(result);
+    }
+}
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 73d26f3..e4c6e54 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -6,7 +6,7 @@
         druid:
             # 涓诲簱鏁版嵁婧�
             master:
-                url: jdbc:mysql://120.25.98.119:3307/ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                url: jdbc:mysql://127.0.0.1:3306/966120?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
                 password: abcd1234
             # 浠庡簱鏁版嵁婧�
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 9db576a..ce30935 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -170,3 +170,58 @@
 tianditu:
   map:
     tk: 4d1d0b3a4a03b9c5099c0e25ab1b23f3  # 璇锋浛鎹负鎮ㄧ殑澶╁湴鍥続PI Key
+
+# 鍦板浘鏈嶅姟閰嶇疆
+# provider: 鍦板浘鏈嶅姟鎻愪緵鍟嗭紝鍙�夊�硷細baidu锛堢櫨搴﹀湴鍥撅級銆乼ianditu锛堝ぉ鍦板浘锛�
+map:
+  service:
+    provider: baidu  # 榛樿浣跨敤鐧惧害鍦板浘
+
+# 鏀粯閰嶇疆
+payment:
+  # 鏄惁鍚敤鏀粯妯″潡锛堜綔涓虹粍浠堕泦鎴愭椂鍙�氳繃姝ゅ紑鍏虫帶鍒讹級
+  enabled: true
+  
+  # 寰俊鏀粯閰嶇疆
+  wechat:
+    appId: wx70f6a7346ee842c0
+    mchId: 1573728151
+    appName: 姘戣埅鍖荤枟蹇嚎
+    mchKey: Xz0ClPK3f5sCeT6SGTaha1vpVmyUFcbp
+    notifyUrl: https://dsp.966120.com/api/pay/notify/wechat
+    signType: MD5
+    checkSign: false
+  
+  # 鏀粯瀹濋厤缃�
+  alipay:
+    appId: 2018060160299486
+    privateKey: MIIEpgIBAAKCAQEArt273bWTEPXPjCsUYwFx7CNjhcQlm1NtbNjfeIsZ2g9sbFCQP9qpyufp6zkBv6eq+6WEztkC1KwSsuDjP5LvgY/1pmGFlr8r7cjeZI4bTeIe9jG5UaHolnzbdXUlSoInzgWRvbYXxuQZciwVpokwviW27YK9wPIzz9OTiRquL8b3YWPZLO7xK0gBMa2KfFfUXxCB8gHJtidQ+FjjYXb2WpnScKLJdKfWcGWFnyGiZOknyFR9kI8cm0cYPNHtecQId0bQ1ee7YDLD8dBPd2Pd/JBC4Wn6HuOvZOLqZvIpIj+8q0zGXjUUns6MsjNL3MUKuhKy6hQGwP5sGrPcVcwqiwIDAQABAoIBAQCTeW9iSSsRx61VUlOsN+DDPQlHHCh3OcH0ZWb6e52+2Pkg1EUDhT9jX3lZJsfBwf8iofJCnKSVhdVzRNSCnkIdq7KJsn9+phW/QYPFnE+MvKJOEZtwLDNDD2PqSHS9xM0bJHlIXNTqqR6IuoM740HXa2k+H+A2ZE2r/YzUuUqkASwAYPKYzWa1wivg4CZrvoPZ5bXvYOHoV0jZEtyUQB9dHuCz+bghbR+28vGkYwEGInLsOCe6Gl5D61F0l2qAXRQky3P0jXxIPXPFmhBYutAAUufLpryruQgL3MDDm5dhBJpwp89qwFDjc8fWVS/FFYJ0KDQOpAxAI800YHgaJ4VBAoGBAOdCcoYS49Q9Iula7gFGVXeto7QSUsP0CnQZM/tsAU6TiX3XG5pxBYoVmYSIQPylgagRTBZHD5t/LGa+I+KYMHSVAH/kndPdgTO7EiwfUCzi1DmGZVWs7XJ2zRfTmYRVdsElPy3Z8Pm802jd7mhffw/5p6y9pzNJqOjmGOUbYGrrAoGBAMGS1CGHkK4nD2BsIWJoKW2Lxph3Bq5hN1iaE8ZjOAvFT9drNqfwRa6BVGyfYEXPZTvUT0FUNMdukcTCM6O3FRU8EABJIcVue2QA+BvkfwPEU3JxMA8DrWHO7IcgtG9wjbxretDsf+SZmkQgK0ZUPod5ZZSycFxM3/GiXDQjGhbhAoGBAL/Y/+j6AscvcKbmKEwmbQC7q/LWwJKPAZ0Oy3DoSK1G9+jNarjUyiOjh5fK8R6mrskekGBq0yfMeKlDU8HHP2t3sNJodgYs2+JubsTrtTeHdUfDlo1cyB8NL1d00wZVYA8bNy5yftavLzLv6bfsgRxfoBpNu0dw9A9B06U88N/BAoGBAKCN/nEJFlG8iB570Xzj1GjOJJzVLK96ZwOQWJKWPShWMhEFFkJZIhLJppKp5ppAmUD0qgAPre80oKdIRLin5E7GkKcMAXzWVHXv79qCvW8MagJkK25oqGiVzs2NrNs5yfXcV/PuFW4wkSmsXPhqa6rGYCDjmBqWkLDE8CE2dC9BAoGBAJ2+QfAAvB27mr48+vY4HxZyPRrCBA1YkokraWQ0IlfD0MKsFw0Af4Iu3oy7V6NlE2GwL/AcObyHeGZt7DLbViAQOgmb9BpUrjUZ4bXSBuGPfRe11HCu6j6W67qa76TAoy3A0Dfm0OE/m9r4H99NaLzeBm1KluySKkfYXoqyueQw
+    alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8BjXYaudmGT+sEos0AXEUrKl6+wyw6++hBoJDdY7P+P7poa34GN4YSkkavTA/HplmRM1wTLcY+NqhxhLpNrcgy08AbC/GGcLM2wxQGFa+L+DQLz34uBAShXDK8yN6O49UdbbJ2RRaJSAb+nW4ZVCPMGtMu4S3lXTymQgizM1IYo9L92U5QPRzZRSP8+AmQPzwofRqEgvkO02s66xU2G5AAdkVg5BQm34eM0Io2CmcWF9jSoWQTJdyd7tw3oec9NqD7x3CfcsN3NAJOQLz4+bWWqDWelyviyAr2reeH6AuBVjaWwAvAJx3yuLevKMXTzPC95Ja7w4XYSB9Fg2+aKmwIDAQAB
+    serverUrl: https://openapi.alipay.com/gateway.do
+    notifyUrl: https://dsp.966120.com/api/pay/notify/alipay    
+    signType: RSA2
+    checkSign: false
+    # 鏀粯鏂瑰紡: OFFICIAL(瀹樻柟鏀粯瀹�) 鎴� THIRD_PARTY(绗笁鏂规敮浠樺疂)
+    paymentMethod: THIRD_PARTY
+    # 绗笁鏂规敮浠橀厤缃�
+    thirdParty:
+      enabled: true
+      url: https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php
+      defaultNotifyUrl: https://dsp.966120.com.cn/alipay/pay_notify
+      timeout: 30000
+  
+  # 涓氬姟鍥炶皟閰嶇疆
+  business:
+    callbackSignSecret: your-hmac-secret-key-here
+    callbackRetryMaxCount: 10
+    callbackRetryIntervals: 0,1,5,15,60
+  
+  # 浜岀淮鐮侀厤缃�
+  qrcode:
+    size: 300
+    format: PNG
+  
+  # 瀵硅处閰嶇疆
+  reconciliation:
+    enabled: true
+    cron: "0 0 2 * * ?"
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java
index 02ef3e2..55b9de2 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java
@@ -21,6 +21,9 @@
     /** 璋冨害鍗曞垱寤烘帴鍙h矾寰� */
     private String dispatchCreatePath = "/admin_save_24.gds";
     
+    /** 璋冨害鍗曟洿鏂版帴鍙h矾寰勶紙杞﹁締/浜哄憳鍙樻洿锛� */
+    private String dispatchUpdatePath = "/admin_save_25.asp";
+    
     /** 浠诲姟鐘舵�佹煡璇㈡帴鍙h矾寰勶紙宸插純鐢紝鐩存帴鏌ヨSQL Server鏁版嵁搴擄級 */
     @Deprecated
     private String statusQueryPath = "/task_status_query.asp";
@@ -80,6 +83,14 @@
         this.dispatchCreatePath = dispatchCreatePath;
     }
 
+    public String getDispatchUpdatePath() {
+        return dispatchUpdatePath;
+    }
+
+    public void setDispatchUpdatePath(String dispatchUpdatePath) {
+        this.dispatchUpdatePath = dispatchUpdatePath;
+    }
+
     public int getConnectTimeout() {
         return connectTimeout;
     }
@@ -126,6 +137,13 @@
         return baseUrl + dispatchCreatePath;
     }
     
+    /**
+     * 鑾峰彇瀹屾暣鐨勮皟搴﹀崟鏇存柊URL锛堣溅杈�/浜哄憳鍙樻洿锛�
+     */
+    public String getDispatchUpdateUrl() {
+        return baseUrl + dispatchUpdatePath;
+    }
+    
     public String getStatusQueryPath() {
         return statusQueryPath;
     }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java
new file mode 100644
index 0000000..fa094a8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/MapServiceConfig.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 鍦板浘鏈嶅姟閰嶇疆绫�
+ * 鐢ㄤ簬閰嶇疆浣跨敤鍝釜鍦板浘鏈嶅姟鎻愪緵鍟�
+ */
+@Configuration
+@ConfigurationProperties(prefix = "map.service")
+public class MapServiceConfig {
+    
+    /**
+     * 鍦板浘鏈嶅姟鎻愪緵鍟嗙被鍨�
+     * 鍙�夊��: baidu, tianditu
+     * 榛樿: baidu
+     */
+    private String provider = "baidu";
+
+    public String getProvider() {
+        return provider;
+    }
+
+    public void setProvider(String provider) {
+        this.provider = provider;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
index 272342b..fcb6890 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
@@ -61,6 +61,15 @@
     /** 璋冨害鍗曠紪鐮�(瀵瑰簲鏃х郴缁烵rderClass vType=2) */
     private String dispatchOrderClass;
     
+    /** 榛樿鍑鸿溅鍦板潃 */
+    private String departureAddress;
+    
+    /** 鍑鸿溅鍦板潃缁忓害 */
+    private java.math.BigDecimal departureLongitude;
+    
+    /** 鍑鸿溅鍦板潃绾害 */
+    private java.math.BigDecimal departureLatitude;
+    
     /** 瀛愰儴闂� */
     private List<SysDept> children = new ArrayList<SysDept>();
 
@@ -220,6 +229,36 @@
         this.dispatchOrderClass = dispatchOrderClass;
     }
 
+    public String getDepartureAddress()
+    {
+        return departureAddress;
+    }
+
+    public void setDepartureAddress(String departureAddress)
+    {
+        this.departureAddress = departureAddress;
+    }
+
+    public java.math.BigDecimal getDepartureLongitude()
+    {
+        return departureLongitude;
+    }
+
+    public void setDepartureLongitude(java.math.BigDecimal departureLongitude)
+    {
+        this.departureLongitude = departureLongitude;
+    }
+
+    public java.math.BigDecimal getDepartureLatitude()
+    {
+        return departureLatitude;
+    }
+
+    public void setDepartureLatitude(java.math.BigDecimal departureLatitude)
+    {
+        this.departureLatitude = departureLatitude;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/DepartmentSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/DepartmentSyncTask.java
index b3bdca1..ddd0d64 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/DepartmentSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/DepartmentSyncTask.java
@@ -12,6 +12,7 @@
 import com.ruoyi.system.service.IDepartmentSyncService;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 閮ㄩ棬鍚屾瀹氭椂浠诲姟
@@ -39,13 +40,16 @@
     }
     @Autowired
     private IOrderClassDataService orderClassDataService;
-private List<OrderClassDTO> getServiceOrdCode() {
-    return orderClassDataService.getServiceOrderClass();
-}
-private List<OrderClassDTO> getDispatchOrdCode() {
-    return orderClassDataService.getDispatchOrderClass();
-}
+    private List<OrderClassDTO> getServiceOrdCode() {
+        return orderClassDataService.getServiceOrderClass();
+    }
+    private List<OrderClassDTO> getDispatchOrdCode() {
+        return orderClassDataService.getDispatchOrderClass();
+    }
 
+    private List<Map<String, Object>> getDepartAddress() {
+        return departmentSyncDataService.getAddressList();
+    }
     /**
      * 鍚屾鍒嗗叕鍙稿拰閮ㄩ棬鏁版嵁
      * 
@@ -59,10 +63,12 @@
         try
         {
             log.info("==========寮�濮嬫墽琛岄儴闂ㄥ悓姝ュ畾鏃朵换鍔�==========");
-            
-            AjaxResult result = departmentSyncService.syncBranchDepartments(this.getDepartment(), this.getServiceOrdCode(),this.getDispatchOrdCode());
 
-            departmentSyncService.syncTransportDepartments(this.getTransportDept());
+            List<Map<String, Object>> addressList = this.getDepartAddress();
+            AjaxResult result = departmentSyncService.syncBranchDepartments(this.getDepartment(), this.getServiceOrdCode(),this.getDispatchOrdCode(),addressList);
+
+            departmentSyncService.syncTransportDepartments(this.getTransportDept(),addressList);
+            departmentSyncService.syncDeptAddress(addressList);
             
             if (result.get("code").equals(200))
             {
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
index 6f28280..af6c684 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/LegacySystemSyncTask.java
@@ -1,6 +1,8 @@
 package com.ruoyi.quartz.task;
 
 import com.ruoyi.system.service.ITaskAttachmentSyncService;
+import com.ruoyi.system.service.IPaymentSyncService;
+import com.ruoyi.system.service.IAdditionalFeeSyncService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +24,8 @@
  * 3. TaskStatusSyncService - 浠诲姟鐘舵�佸悓姝ワ紙浠庢棫绯荤粺鍒版柊绯荤粺锛�
  * 4. TaskStatusPushService - 浠诲姟鐘舵�佹帹閫侊紙浠庢柊绯荤粺鍒版棫绯荤粺锛�
  * 5. TaskAttachmentSyncService - 浠诲姟闄勪欢鍚屾锛堜粠鏂扮郴缁熷埌鏃х郴缁燂級
+ * 6. PaymentSyncService - 鏀粯淇℃伅鍚屾锛堝弻鍚戝悓姝ワ級
+ * 7. AdditionalFeeSyncService - 闄勫姞璐圭敤鍚屾锛堝弻鍚戝悓姝ワ級
  */
 @Component("legacySystemSyncTask")
 public class LegacySystemSyncTask {
@@ -39,6 +43,12 @@
     
     @Autowired
     private ITaskAttachmentSyncService taskAttachmentSyncService;
+
+    @Autowired
+    private IPaymentSyncService paymentSyncService;
+    
+    @Autowired
+    private IAdditionalFeeSyncService additionalFeeSyncService;
 
 
     
@@ -166,4 +176,105 @@
             log.error("浠诲姟闄勪欢鍚屾寮傚父", e);
         }
     }
+    
+    /**
+     * 鎵归噺鍚屾鏀粯淇℃伅鍒版棫绯荤粺PaidMoney琛�
+     * 
+     * 浣跨敤绀轰緥:
+     * 鍦ㄧ郴缁熺鐞� -> 瀹氭椂浠诲姟涓坊鍔�:
+     * 浠诲姟鍚嶇О: 鏀粯淇℃伅鍚屾
+     * 浠诲姟缁勫悕: DEFAULT
+     * 璋冪敤鐩爣瀛楃涓�: legacySystemSyncTask.syncPaymentToLegacy()
+     * cron琛ㄨ揪寮�: 0 0/10 * * * ? (姣�10鍒嗛挓鎵ц涓�娆�)
+     */
+    public void syncPaymentToLegacy() {
+        log.info("寮�濮嬫墽琛屾敮浠樹俊鎭悓姝ュ畾鏃朵换鍔★紙鏂扮郴缁� -> 鏃х郴缁燂級");
+        try {
+            int successCount = paymentSyncService.batchSyncPaymentToLegacy();
+            log.info("鏀粯淇℃伅鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+        } catch (Exception e) {
+            log.error("鏀粯淇℃伅鍚屾寮傚父", e);
+        }
+    }
+    
+    /**
+     * 鎵归噺鍚屾鏀粯淇℃伅浠庢棫绯荤粺鍒版柊绯荤粺
+     * 
+     * 浣跨敤绀轰緥:
+     * 鍦ㄧ郴缁熺鐞� -> 瀹氭椂浠诲姟涓坊鍔�:
+     * 浠诲姟鍚嶇О: 鏀粯淇℃伅鍙嶅悜鍚屾
+     * 浠诲姟缁勫悕: DEFAULT
+     * 璋冪敤鐩爣瀛楃涓�: legacySystemSyncTask.syncPaymentFromLegacy()
+     * cron琛ㄨ揪寮�: 0 0/15 * * * ? (姣�15鍒嗛挓鎵ц涓�娆�)
+     */
+    public void syncPaymentFromLegacy() {
+        log.info("寮�濮嬫墽琛屾敮浠樹俊鎭悓姝ュ畾鏃朵换鍔★紙鏃х郴缁� -> 鏂扮郴缁燂級");
+        try {
+            int successCount = paymentSyncService.batchSyncPaymentFromLegacy();
+            log.info("鏀粯淇℃伅鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+        } catch (Exception e) {
+            log.error("鏀粯淇℃伅鍚屾寮傚父", e);
+        }
+    }
+    
+    /**
+     * 鎵归噺鍚屾闄勫姞璐圭敤鍒版棫绯荤粺PaidMoney_Add琛�
+     * 
+     * 浣跨敤绀轰緥:
+     * 鍦ㄧ郴缁熺鐞� -> 瀹氭椂浠诲姟涓坊鍔�:
+     * 浠诲姟鍚嶇О: 闄勫姞璐圭敤鍚屾
+     * 浠诲姟缁勫悕: DEFAULT
+     * 璋冪敤鐩爣瀛楃涓�: legacySystemSyncTask.syncAdditionalFeeToLegacy()
+     * cron琛ㄨ揪寮�: 0 0/10 * * * ? (姣�10鍒嗛挓鎵ц涓�娆�)
+     */
+    public void syncAdditionalFeeToLegacy() {
+        log.info("寮�濮嬫墽琛岄檮鍔犺垂鐢ㄥ悓姝ュ畾鏃朵换鍔★紙鏂扮郴缁� -> 鏃х郴缁燂級");
+        try {
+            int successCount = additionalFeeSyncService.batchSyncAdditionalFeeToLegacy();
+            log.info("闄勫姞璐圭敤鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+        } catch (Exception e) {
+            log.error("闄勫姞璐圭敤鍚屾寮傚父", e);
+        }
+    }
+    
+    /**
+     * 鎵归噺鍚屾闄勫姞璐圭敤浠庢棫绯荤粺鍒版柊绯荤粺
+     * 
+     * 浣跨敤绀轰緥锛�
+     * 鍦ㄧ郴缁熺鐞� -> 瀹氭椂浠诲姟涓坊鍔狅細
+     * 浠诲姟鍚嶇О锛� 闄勫姞璐圭敤鍙嶅悜鍚屾
+     * 浠诲姟缁勫悕锛� DEFAULT
+     * 璋冪敤鐩爣瀛楃涓诧細 legacySystemSyncTask.syncAdditionalFeeFromLegacy()
+     * cron琛ㄨ揪寮忥細 0 0/15 * * * ? (姣�15鍒嗛挓鎵ц涓�娆�)
+     */
+    public void syncAdditionalFeeFromLegacy() {
+        log.info("寮�濮嬫墽琛岄檮鍔犺垂鐢ㄥ悓姝ュ畾鏃朵换鍔★紙鏃х郴缁� -> 鏂扮郴缁燂級");
+        try {
+            // 鍚屾鏈�杩�24灏忔椂鍐呯殑璁板綍
+            int successCount = additionalFeeSyncService.batchSyncAdditionalFeeFromLegacy(24);
+            log.info("闄勫姞璐圭敤鍚屾瀹屾垚锛屾垚鍔熷悓姝�: {} 鏉¤褰�", successCount);
+        } catch (Exception e) {
+            log.error("闄勫姞璐圭敤鍚屾寮傚父", e);
+        }
+    }
+    
+    /**
+     * 鎵归噺閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇寸殑浠诲姟
+     * 
+     * 浣跨敤绀轰緥锛�
+     * 鍦ㄧ郴缁熺鐞� -> 瀹氭椂浠诲姟涓坊鍔狅細
+     * 浠诲姟鍚嶇О锛� 閲嶆柊鍚屾杞﹁締浜哄憳鍙樻洿
+     * 浠诲姟缁勫悕锛� DEFAULT
+     * 璋冪敤鐩爣瀛楃涓诧細 legacySystemSyncTask.resyncVehicleAndPersonnel()
+     * cron琛ㄨ揪寮忥細 0 0/5 * * * ? (姣�5鍒嗛挓鎵ц涓�娆�)
+     */
+    public void resyncVehicleAndPersonnel() {
+        log.info("寮�濮嬫墽琛岄噸鏂板悓姝ヨ溅杈嗗拰浜哄憳鍙樻洿鐨勪换鍔″畾鏃朵换鍔�");
+        try {
+            int successCount = legacySystemSyncService.batchResyncPendingDispatchOrders();
+            log.info("閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇村畬鎴愶紝鎴愬姛鍚屾: {} 涓换鍔�", successCount);
+        } catch (Exception e) {
+            log.error("閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇村紓甯�", e);
+        }
+    }
 }
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java
index 775f837..97d811a 100644
--- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/OaSyncTask.java
@@ -11,6 +11,7 @@
 import com.ruoyi.common.core.domain.AjaxResult;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * OA鏁版嵁鍚屾瀹氭椂浠诲姟锛堢粍鍚堜换鍔★級
@@ -53,6 +54,10 @@
     private List<OrderClassDTO> getDispatchOrdCode() {
         return orderClassDataService.getDispatchOrderClass();
     }
+
+    private List<Map<String,Object>> getAddressList() {
+        return departmentSyncDataService.getAddressList();
+    }
     /**
      * 鍚屾OA鏁版嵁锛堥儴闂�+鐢ㄦ埛锛�
      * 鎸夐『搴忔墽琛岋細1. 閮ㄩ棬鍚屾  2. 鐢ㄦ埛鍚屾
@@ -70,7 +75,7 @@
             
             // 绗竴姝ワ細鍚屾閮ㄩ棬
             log.info("銆愭楠�1/2銆戝紑濮嬪悓姝ラ儴闂ㄦ暟鎹�...");
-            AjaxResult deptResult = departmentSyncService.syncBranchDepartments(this.getDept(),this.getServiceOrdCode(),this.getDispatchOrdCode());
+            AjaxResult deptResult = departmentSyncService.syncBranchDepartments(this.getDept(),this.getServiceOrdCode(),this.getDispatchOrdCode(),this.getAddressList());
             
             if (deptResult.get("code").equals(200))
             {
@@ -125,7 +130,7 @@
         try
         {
             log.info("==========寮�濮嬫墽琛岄儴闂ㄥ悓姝ヤ换鍔�==========");
-            AjaxResult result = departmentSyncService.syncBranchDepartments(this.getDept(),this.getServiceOrdCode(),this.getDispatchOrdCode());
+            AjaxResult result = departmentSyncService.syncBranchDepartments(this.getDept(),this.getServiceOrdCode(),this.getDispatchOrdCode(),this.getAddressList());
             
             if (result.get("code").equals(200))
             {
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
index 3fa5ad3..844fc1e 100644
--- a/ruoyi-system/pom.xml
+++ b/ruoyi-system/pom.xml
@@ -23,6 +23,11 @@
             <artifactId>ruoyi-common</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>dryad-payment</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
             <version>3.5.1</version>
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java b/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java
new file mode 100644
index 0000000..66c619a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/config/MapServiceConfiguration.java
@@ -0,0 +1,54 @@
+package com.ruoyi.system.config;
+
+import com.ruoyi.common.config.MapServiceConfig;
+import com.ruoyi.system.service.IMapService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+/**
+ * 鍦板浘鏈嶅姟閰嶇疆绫�
+ * 鏍规嵁閰嶇疆鍔ㄦ�侀�夋嫨浣跨敤鐧惧害鍦板浘杩樻槸澶╁湴鍥�
+ * 
+ * @author ruoyi
+ */
+@Configuration
+public class MapServiceConfiguration {
+    
+    private static final Logger logger = LoggerFactory.getLogger(MapServiceConfiguration.class);
+    
+    @Autowired
+    private MapServiceConfig mapServiceConfig;
+    
+    @Autowired
+    @Qualifier("baiduMapService")
+    private IMapService baiduMapService;
+    
+    @Autowired
+    @Qualifier("tiandituMapService")
+    private IMapService tiandituMapService;
+    
+    /**
+     * 鏍规嵁閰嶇疆鎻愪緵涓昏鐨勫湴鍥炬湇鍔″疄鐜�
+     * 
+     * @return 鍦板浘鏈嶅姟瀹炰緥
+     */
+    @Bean
+    @Primary
+    public IMapService mapService() {
+        String provider = mapServiceConfig.getProvider();
+        
+        if ("tianditu".equalsIgnoreCase(provider)) {
+            logger.info("浣跨敤澶╁湴鍥炬湇鍔¤繘琛屽湴鐞嗙紪鐮�");
+            return tiandituMapService;
+        } else {
+            // 榛樿浣跨敤鐧惧害鍦板浘
+            logger.info("浣跨敤鐧惧害鍦板浘鏈嶅姟杩涜鍦扮悊缂栫爜");
+            return baiduMapService;
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/DepartmentSyncDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/DepartmentSyncDTO.java
index a3ca439..ed1be91 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/DepartmentSyncDTO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/DepartmentSyncDTO.java
@@ -20,6 +20,7 @@
     /** 鐖堕儴闂ㄥ悕绉� */
     private String parentName;
 
+
     public Integer getDepartmentId()
     {
         return departmentId;
@@ -60,6 +61,7 @@
         this.parentName = parentName;
     }
 
+
     @Override
     public String toString()
     {
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoney.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoney.java
new file mode 100644
index 0000000..7b0bc8b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoney.java
@@ -0,0 +1,191 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 鏃х郴缁熸敮浠樿褰曞璞� PaidMoney
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class PaidMoney {
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭ID */
+    private Long id;
+
+    /** 鏀粯绫诲埆锛岄粯璁I */
+    private String paidMoneyClass;
+
+    /** 鏈嶅姟璁㈠崟ID */
+    private Long serviceOrdIDDt;
+
+    /** 璋冨害璁㈠崟ID */
+    private Long dispatchOrdIDDt;
+
+    /** 鏀粯閲戦 */
+    private BigDecimal paidMoney;
+
+    /** 鏀粯绫诲瀷 */
+    private Integer paidMoneyType;
+
+    /** 鏀粯鍗曞彿锛屾牸寮忥細浜ゆ槗娴佹按[鏀粯涓撶敤] */
+    private String paidMoneyMono;
+
+    /** 鏀粯鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date paidMoneyTime;
+
+    /** 鏀粯浜篛AID */
+    private Integer paidMoneyOaID;
+
+    /** 鍗曚綅ID锛岄粯璁や负0 */
+    private Integer paidMoneyUnitID;
+
+    /** 纭ID */
+    private Integer paidMoneyAPID;
+
+    /** 纭鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date paidMoneyAPTime;
+
+    /** 纭鐘舵�� 1琛ㄧず宸茬‘璁わ紝0琛ㄧず鏈‘璁� */
+    private Integer paidMoneyAPCheck;
+
+    /** 纭鏃堕棿鎴� */
+    private String paidMoneyTimestamp;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getPaidMoneyClass() {
+        return paidMoneyClass;
+    }
+
+    public void setPaidMoneyClass(String paidMoneyClass) {
+        this.paidMoneyClass = paidMoneyClass;
+    }
+
+    public Long getServiceOrdIDDt() {
+        return serviceOrdIDDt;
+    }
+
+    public void setServiceOrdIDDt(Long serviceOrdIDDt) {
+        this.serviceOrdIDDt = serviceOrdIDDt;
+    }
+
+    public Long getDispatchOrdIDDt() {
+        return dispatchOrdIDDt;
+    }
+
+    public void setDispatchOrdIDDt(Long dispatchOrdIDDt) {
+        this.dispatchOrdIDDt = dispatchOrdIDDt;
+    }
+
+    public BigDecimal getPaidMoney() {
+        return paidMoney;
+    }
+
+    public void setPaidMoney(BigDecimal paidMoney) {
+        this.paidMoney = paidMoney;
+    }
+
+    public Integer getPaidMoneyType() {
+        return paidMoneyType;
+    }
+
+    public void setPaidMoneyType(Integer paidMoneyType) {
+        this.paidMoneyType = paidMoneyType;
+    }
+
+    public String getPaidMoneyMono() {
+        return paidMoneyMono;
+    }
+
+    public void setPaidMoneyMono(String paidMoneyMono) {
+        this.paidMoneyMono = paidMoneyMono;
+    }
+
+    public Date getPaidMoneyTime() {
+        return paidMoneyTime;
+    }
+
+    public void setPaidMoneyTime(Date paidMoneyTime) {
+        this.paidMoneyTime = paidMoneyTime;
+    }
+
+    public Integer getPaidMoneyOaID() {
+        return paidMoneyOaID;
+    }
+
+    public void setPaidMoneyOaID(Integer paidMoneyOaID) {
+        this.paidMoneyOaID = paidMoneyOaID;
+    }
+
+    public Integer getPaidMoneyUnitID() {
+        return paidMoneyUnitID;
+    }
+
+    public void setPaidMoneyUnitID(Integer paidMoneyUnitID) {
+        this.paidMoneyUnitID = paidMoneyUnitID;
+    }
+
+    public Integer getPaidMoneyAPID() {
+        return paidMoneyAPID;
+    }
+
+    public void setPaidMoneyAPID(Integer paidMoneyAPID) {
+        this.paidMoneyAPID = paidMoneyAPID;
+    }
+
+    public Date getPaidMoneyAPTime() {
+        return paidMoneyAPTime;
+    }
+
+    public void setPaidMoneyAPTime(Date paidMoneyAPTime) {
+        this.paidMoneyAPTime = paidMoneyAPTime;
+    }
+
+    public Integer getPaidMoneyAPCheck() {
+        return paidMoneyAPCheck;
+    }
+
+    public void setPaidMoneyAPCheck(Integer paidMoneyAPCheck) {
+        this.paidMoneyAPCheck = paidMoneyAPCheck;
+    }
+
+    public String getPaidMoneyTimestamp() {
+        return paidMoneyTimestamp;
+    }
+
+    public void setPaidMoneyTimestamp(String paidMoneyTimestamp) {
+        this.paidMoneyTimestamp = paidMoneyTimestamp;
+    }
+
+    @Override
+    public String toString() {
+        return "PaidMoney{" +
+                "id=" + id +
+                ", paidMoneyClass='" + paidMoneyClass + '\'' +
+                ", serviceOrdIDDt=" + serviceOrdIDDt +
+                ", dispatchOrdIDDt=" + dispatchOrdIDDt +
+                ", paidMoney=" + paidMoney +
+                ", paidMoneyType=" + paidMoneyType +
+                ", paidMoneyMono='" + paidMoneyMono + '\'' +
+                ", paidMoneyTime=" + paidMoneyTime +
+                ", paidMoneyOaID=" + paidMoneyOaID +
+                ", paidMoneyUnitID=" + paidMoneyUnitID +
+                ", paidMoneyAPID=" + paidMoneyAPID +
+                ", paidMoneyAPTime=" + paidMoneyAPTime +
+                ", paidMoneyAPCheck=" + paidMoneyAPCheck +
+                ", paidMoneyTimestamp='" + paidMoneyTimestamp + '\'' +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoneyAdd.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoneyAdd.java
new file mode 100644
index 0000000..713b191
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/PaidMoneyAdd.java
@@ -0,0 +1,118 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曞璞� PaidMoney_Add
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class PaidMoneyAdd {
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭ID */
+    private Long id;
+
+    /** 鏈嶅姟鍗旾D */
+    private Long toServiceOrdID;
+
+    /** 璋冨害鍗旾D */
+    private Long toDispatchOrdID;
+
+    /** 闄勫姞璐圭敤绫诲瀷 */
+    private Integer addMoneyType;
+
+    /** 闄勫姞璐圭敤 */
+    private BigDecimal addMoney;
+
+    /** 闄勫姞璐圭敤璇存槑 */
+    private String addMoneyExplain;
+
+    /** 闄勫姞璐圭敤鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date addMoneyTime;
+
+    /** 娣诲姞鐢ㄦ埛鐨凮AID */
+    private Integer addMoneyOAID;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getToServiceOrdID() {
+        return toServiceOrdID;
+    }
+
+    public void setToServiceOrdID(Long toServiceOrdID) {
+        this.toServiceOrdID = toServiceOrdID;
+    }
+
+    public Long getToDispatchOrdID() {
+        return toDispatchOrdID;
+    }
+
+    public void setToDispatchOrdID(Long toDispatchOrdID) {
+        this.toDispatchOrdID = toDispatchOrdID;
+    }
+
+    public Integer getAddMoneyType() {
+        return addMoneyType;
+    }
+
+    public void setAddMoneyType(Integer addMoneyType) {
+        this.addMoneyType = addMoneyType;
+    }
+
+    public BigDecimal getAddMoney() {
+        return addMoney;
+    }
+
+    public void setAddMoney(BigDecimal addMoney) {
+        this.addMoney = addMoney;
+    }
+
+    public String getAddMoneyExplain() {
+        return addMoneyExplain;
+    }
+
+    public void setAddMoneyExplain(String addMoneyExplain) {
+        this.addMoneyExplain = addMoneyExplain;
+    }
+
+    public Date getAddMoneyTime() {
+        return addMoneyTime;
+    }
+
+    public void setAddMoneyTime(Date addMoneyTime) {
+        this.addMoneyTime = addMoneyTime;
+    }
+
+    public Integer getAddMoneyOAID() {
+        return addMoneyOAID;
+    }
+
+    public void setAddMoneyOAID(Integer addMoneyOAID) {
+        this.addMoneyOAID = addMoneyOAID;
+    }
+
+    @Override
+    public String toString() {
+        return "PaidMoneyAdd{" +
+                "id=" + id +
+                ", toServiceOrdID=" + toServiceOrdID +
+                ", toDispatchOrdID=" + toDispatchOrdID +
+                ", addMoneyType=" + addMoneyType +
+                ", addMoney=" + addMoney +
+                ", addMoneyExplain='" + addMoneyExplain + '\'' +
+                ", addMoneyTime=" + addMoneyTime +
+                ", addMoneyOAID=" + addMoneyOAID +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
index bf7fe22..377d933 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
@@ -123,6 +123,9 @@
     /** 鎿嶄綔鏃ュ織鍒楄〃 */
     private List<SysTaskLog> operationLogs;
 
+    /** 鎵ц浜哄憳鍒楄〃 */
+    private List<SysTaskAssignee> assignees;
+
     /** 鎬ユ晳杞繍鎵╁睍淇℃伅 */
     private SysTaskEmergency emergencyInfo;
 
@@ -361,6 +364,14 @@
         return welfareInfo;
     }
 
+    public void setAssignees(List<SysTaskAssignee> assignees) {
+        this.assignees = assignees;
+    }
+
+    public List<SysTaskAssignee> getAssignees() {
+        return assignees;
+    }
+
     /**
      * 鍒ゆ柇鏄惁鍙互鍙樻洿鐘舵��
      */
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAdditionalFee.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAdditionalFee.java
new file mode 100644
index 0000000..0dac7dc
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAdditionalFee.java
@@ -0,0 +1,168 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 浠诲姟闄勫姞璐圭敤瀵硅薄 sys_task_additional_fee
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class SysTaskAdditionalFee extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭ID */
+    private Long id;
+
+    /** 浠诲姟ID */
+    private Long taskId;
+
+    /** 璐圭敤绫诲瀷(瀛楀吀task_additional_fee_type) */
+    private String feeType;
+
+    /** 璐圭敤鍚嶇О */
+    private String feeName;
+
+    /** 鍗曚环 */
+    private BigDecimal unitAmount;
+
+    /** 鏁伴噺 */
+    private Integer quantity;
+
+    /** 鎬婚噾棰� */
+    private BigDecimal totalAmount;
+
+    /** 鍒涘缓鑰� */
+    private String createdBy;
+
+    /** 鍒涘缓鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createdTime;
+
+    /** 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰旾D(PaidMoney_Add.id) */
+    private Long pid;
+
+    /** 鍚屾鐘舵�侊細0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触 */
+    private Integer syncStatus;
+
+    /** 鍚屾鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date syncTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(Long taskId) {
+        this.taskId = taskId;
+    }
+
+    public String getFeeType() {
+        return feeType;
+    }
+
+    public void setFeeType(String feeType) {
+        this.feeType = feeType;
+    }
+
+    public String getFeeName() {
+        return feeName;
+    }
+
+    public void setFeeName(String feeName) {
+        this.feeName = feeName;
+    }
+
+    public BigDecimal getUnitAmount() {
+        return unitAmount;
+    }
+
+    public void setUnitAmount(BigDecimal unitAmount) {
+        this.unitAmount = unitAmount;
+    }
+
+    public Integer getQuantity() {
+        return quantity;
+    }
+
+    public void setQuantity(Integer quantity) {
+        this.quantity = quantity;
+    }
+
+    public BigDecimal getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(BigDecimal totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    public void setCreatedBy(String createdBy) {
+        this.createdBy = createdBy;
+    }
+
+    public Date getCreatedTime() {
+        return createdTime;
+    }
+
+    public void setCreatedTime(Date createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    public Long getPid() {
+        return pid;
+    }
+
+    public void setPid(Long pid) {
+        this.pid = pid;
+    }
+
+    public Integer getSyncStatus() {
+        return syncStatus;
+    }
+
+    public void setSyncStatus(Integer syncStatus) {
+        this.syncStatus = syncStatus;
+    }
+
+    public Date getSyncTime() {
+        return syncTime;
+    }
+
+    public void setSyncTime(Date syncTime) {
+        this.syncTime = syncTime;
+    }
+
+    @Override
+    public String toString() {
+        return "SysTaskAdditionalFee{" +
+                "id=" + id +
+                ", taskId=" + taskId +
+                ", feeType='" + feeType + '\'' +
+                ", feeName='" + feeName + '\'' +
+                ", unitAmount=" + unitAmount +
+                ", quantity=" + quantity +
+                ", totalAmount=" + totalAmount +
+                ", createdBy='" + createdBy + '\'' +
+                ", createdTime=" + createdTime +
+                ", pid=" + pid +
+                ", syncStatus=" + syncStatus +
+                ", syncTime=" + syncTime +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
index 325700d..d4522e8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskEmergency.java
@@ -129,6 +129,9 @@
     /** 璋冨害鍗曞悓姝ラ敊璇俊鎭� */
     private String dispatchSyncErrorMsg;
 
+    /** 鏄惁闇�瑕侀噸鏂板悓姝ワ細0-涓嶉渶瑕侊紝1-闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鎴栦汉鍛樺彉鏇达級 */
+    private Integer needResync;
+
 
 
     public Long getId() {
@@ -443,6 +446,14 @@
         this.dispatchSyncErrorMsg = dispatchSyncErrorMsg;
     }
 
+    public Integer getNeedResync() {
+        return needResync;
+    }
+
+    public void setNeedResync(Integer needResync) {
+        this.needResync = needResync;
+    }
+
     @Override
     public String toString() {
         return "SysTaskEmergency{" +
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskPayment.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskPayment.java
new file mode 100644
index 0000000..fa0debe
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskPayment.java
@@ -0,0 +1,267 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 浠诲姟鏀粯璁板綍瀵硅薄 sys_task_payment
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class SysTaskPayment extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭ID */
+    private Long id;
+
+    /** 浠诲姟ID */
+    private Long taskId;
+
+    /** 鎬婚噾棰�(鎴愪氦浠�+闄勫姞璐�) */
+    private BigDecimal totalAmount;
+
+    /** 缁撶畻閲戦 */
+    private BigDecimal settlementAmount;
+
+    /** 鏀粯鏂瑰紡:CASH鐜伴噾,ON_ACCOUNT鎸傚笎,WECHAT寰俊,ALIPAY鏀粯瀹� */
+    private String paymentMethod;
+
+    /** 鏀粯鐘舵��:UNPAID鏈敮浠�,PENDING寰呮敮浠�,PAID宸叉敮浠�,FAILED澶辫触,REFUNDED宸查��娆� */
+    private String payStatus;
+
+    /** 鏀粯鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+
+    /** 鍟嗘埛璁㈠崟鍙� */
+    private String outTradeNo;
+
+    /** 涓夋柟浜ゆ槗鍙� */
+    private String tradeNo;
+
+    /** 浜岀淮鐮侀摼鎺� */
+    private String codeUrl;
+
+    /** 浜岀淮鐮佽繃鏈熸椂闂� */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date qrExpireTime;
+
+    /** 鏀粯鎻愪緵鍟�:WECHAT,ALIPAY */
+    private String provider;
+
+    /** 鏀粯妯″潡杩斿洖鐨勫敮涓�鏍囪瘑 */
+    private String paymentRefId;
+
+    /** 鍥炶皟鍦板潃 */
+    private String callbackUrl;
+
+    /** 鍒涘缓鑰� */
+    private String createdBy;
+
+    /** 鍒涘缓鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createdTime;
+
+    /** 鏇存柊鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    /** 鏃х郴缁熸敮浠樿褰旾D锛圥aidMoney.id锛� */
+    private Long pid;
+
+    /** 鍚屾鐘舵�侊細0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触 */
+    private Integer syncStatus;
+
+    /** 鍚屾鏃堕棿 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date syncTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(Long taskId) {
+        this.taskId = taskId;
+    }
+
+    public BigDecimal getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(BigDecimal totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+
+    public BigDecimal getSettlementAmount() {
+        return settlementAmount;
+    }
+
+    public void setSettlementAmount(BigDecimal settlementAmount) {
+        this.settlementAmount = settlementAmount;
+    }
+
+    public String getPaymentMethod() {
+        return paymentMethod;
+    }
+
+    public void setPaymentMethod(String paymentMethod) {
+        this.paymentMethod = paymentMethod;
+    }
+
+    public String getPayStatus() {
+        return payStatus;
+    }
+
+    public void setPayStatus(String payStatus) {
+        this.payStatus = payStatus;
+    }
+
+    public Date getPayTime() {
+        return payTime;
+    }
+
+    public void setPayTime(Date payTime) {
+        this.payTime = payTime;
+    }
+
+    public String getOutTradeNo() {
+        return outTradeNo;
+    }
+
+    public void setOutTradeNo(String outTradeNo) {
+        this.outTradeNo = outTradeNo;
+    }
+
+    public String getTradeNo() {
+        return tradeNo;
+    }
+
+    public void setTradeNo(String tradeNo) {
+        this.tradeNo = tradeNo;
+    }
+
+    public String getCodeUrl() {
+        return codeUrl;
+    }
+
+    public void setCodeUrl(String codeUrl) {
+        this.codeUrl = codeUrl;
+    }
+
+    public Date getQrExpireTime() {
+        return qrExpireTime;
+    }
+
+    public void setQrExpireTime(Date qrExpireTime) {
+        this.qrExpireTime = qrExpireTime;
+    }
+
+    public String getProvider() {
+        return provider;
+    }
+
+    public void setProvider(String provider) {
+        this.provider = provider;
+    }
+
+    public String getPaymentRefId() {
+        return paymentRefId;
+    }
+
+    public void setPaymentRefId(String paymentRefId) {
+        this.paymentRefId = paymentRefId;
+    }
+
+    public String getCallbackUrl() {
+        return callbackUrl;
+    }
+
+    public void setCallbackUrl(String callbackUrl) {
+        this.callbackUrl = callbackUrl;
+    }
+
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    public void setCreatedBy(String createdBy) {
+        this.createdBy = createdBy;
+    }
+
+    public Date getCreatedTime() {
+        return createdTime;
+    }
+
+    public void setCreatedTime(Date createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Long getPid() {
+        return pid;
+    }
+
+    public void setPid(Long pid) {
+        this.pid = pid;
+    }
+
+    public Integer getSyncStatus() {
+        return syncStatus;
+    }
+
+    public void setSyncStatus(Integer syncStatus) {
+        this.syncStatus = syncStatus;
+    }
+
+    public Date getSyncTime() {
+        return syncTime;
+    }
+
+    public void setSyncTime(Date syncTime) {
+        this.syncTime = syncTime;
+    }
+
+    @Override
+    public String toString() {
+        return "SysTaskPayment{" +
+                "id=" + id +
+                ", taskId=" + taskId +
+                ", totalAmount=" + totalAmount +
+                ", settlementAmount=" + settlementAmount +
+                ", paymentMethod='" + paymentMethod + '\'' +
+                ", payStatus='" + payStatus + '\'' +
+                ", payTime=" + payTime +
+                ", outTradeNo='" + outTradeNo + '\'' +
+                ", tradeNo='" + tradeNo + '\'' +
+                ", codeUrl='" + codeUrl + '\'' +
+                ", qrExpireTime=" + qrExpireTime +
+                ", provider='" + provider + '\'' +
+                ", paymentRefId='" + paymentRefId + '\'' +
+                ", callbackUrl='" + callbackUrl + '\'' +
+                ", createdBy='" + createdBy + '\'' +
+                ", createdTime=" + createdTime +
+                ", updateTime=" + updateTime +
+                ", pid=" + pid +
+                ", syncStatus=" + syncStatus +
+                ", syncTime=" + syncTime +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentCreateVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentCreateVO.java
new file mode 100644
index 0000000..e13501d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentCreateVO.java
@@ -0,0 +1,56 @@
+package com.ruoyi.system.domain.vo;
+
+import java.math.BigDecimal;
+
+/**
+ * 鍒涘缓鏀粯VO
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class TaskPaymentCreateVO {
+    
+    /** 浠诲姟ID */
+    private Long taskId;
+    
+    /** 鏀粯鏂瑰紡 */
+    private String paymentMethod;
+    
+    /** 缁撶畻閲戦 */
+    private BigDecimal settlementAmount;
+    
+    /** 澶囨敞 */
+    private String remark;
+
+    public Long getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(Long taskId) {
+        this.taskId = taskId;
+    }
+
+    public String getPaymentMethod() {
+        return paymentMethod;
+    }
+
+    public void setPaymentMethod(String paymentMethod) {
+        this.paymentMethod = paymentMethod;
+    }
+
+    public BigDecimal getSettlementAmount() {
+        return settlementAmount;
+    }
+
+    public void setSettlementAmount(BigDecimal settlementAmount) {
+        this.settlementAmount = settlementAmount;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentInfoVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentInfoVO.java
new file mode 100644
index 0000000..3cb192d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentInfoVO.java
@@ -0,0 +1,158 @@
+package com.ruoyi.system.domain.vo;
+
+import java.math.BigDecimal;
+import java.util.List;
+import com.ruoyi.system.domain.SysTaskAdditionalFee;
+import com.ruoyi.system.domain.SysTaskPayment;
+
+/**
+ * 浠诲姟鏀粯淇℃伅VO
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class TaskPaymentInfoVO {
+    
+    /** 浠诲姟缂栧彿 */
+    private String taskCode;
+    
+    /** 浠诲姟绫诲瀷 */
+    private String taskType;
+    
+    /** 杞﹁締淇℃伅 */
+    private String vehicleInfo;
+    
+    /** 鍑哄彂鍦� */
+    private String departureAddress;
+    
+    /** 鐩殑鍦� */
+    private String destinationAddress;
+    
+    /** 鎴愪氦浠� */
+    private BigDecimal transferPrice;
+    
+    /** 闄勫姞璐圭敤鍒楄〃 */
+    private List<SysTaskAdditionalFee> additionalFees;
+    
+    /** 闄勫姞璐圭敤姹囨�� */
+    private BigDecimal additionalAmount;
+    
+    /** 鎬婚噾棰� */
+    private BigDecimal totalAmount;
+    
+    /** 宸叉敮浠橀噾棰� */
+    private BigDecimal paidAmount;
+    
+    /** 宸叉敮浠樿褰曞垪琛� */
+    private List<SysTaskPayment> paidPayments;
+    
+    /** 鏈�杩戜竴娆℃敮浠樿褰� */
+    private SysTaskPayment latestPayment;
+    
+    /** 鏀粯鏂瑰紡鍒楄〃 */
+    private List<String> paymentMethods;
+
+    public String getTaskCode() {
+        return taskCode;
+    }
+
+    public void setTaskCode(String taskCode) {
+        this.taskCode = taskCode;
+    }
+
+    public String getTaskType() {
+        return taskType;
+    }
+
+    public void setTaskType(String taskType) {
+        this.taskType = taskType;
+    }
+
+    public String getVehicleInfo() {
+        return vehicleInfo;
+    }
+
+    public void setVehicleInfo(String vehicleInfo) {
+        this.vehicleInfo = vehicleInfo;
+    }
+
+    public String getDepartureAddress() {
+        return departureAddress;
+    }
+
+    public void setDepartureAddress(String departureAddress) {
+        this.departureAddress = departureAddress;
+    }
+
+    public String getDestinationAddress() {
+        return destinationAddress;
+    }
+
+    public void setDestinationAddress(String destinationAddress) {
+        this.destinationAddress = destinationAddress;
+    }
+
+    public BigDecimal getTransferPrice() {
+        return transferPrice;
+    }
+
+    public void setTransferPrice(BigDecimal transferPrice) {
+        this.transferPrice = transferPrice;
+    }
+
+    public List<SysTaskAdditionalFee> getAdditionalFees() {
+        return additionalFees;
+    }
+
+    public void setAdditionalFees(List<SysTaskAdditionalFee> additionalFees) {
+        this.additionalFees = additionalFees;
+    }
+
+    public BigDecimal getAdditionalAmount() {
+        return additionalAmount;
+    }
+
+    public void setAdditionalAmount(BigDecimal additionalAmount) {
+        this.additionalAmount = additionalAmount;
+    }
+
+    public BigDecimal getTotalAmount() {
+        return totalAmount;
+    }
+
+    public void setTotalAmount(BigDecimal totalAmount) {
+        this.totalAmount = totalAmount;
+    }
+
+    public BigDecimal getPaidAmount() {
+        return paidAmount;
+    }
+
+    public void setPaidAmount(BigDecimal paidAmount) {
+        this.paidAmount = paidAmount;
+    }
+
+    public List<SysTaskPayment> getPaidPayments() {
+        return paidPayments;
+    }
+
+    public void setPaidPayments(List<SysTaskPayment> paidPayments) {
+        this.paidPayments = paidPayments;
+    }
+
+    public SysTaskPayment getLatestPayment() {
+        return latestPayment;
+    }
+
+    public void setLatestPayment(SysTaskPayment latestPayment) {
+        this.latestPayment = latestPayment;
+    }
+
+    public List<String> getPaymentMethods() {
+        return paymentMethods;
+    }
+
+    public void setPaymentMethods(List<String> paymentMethods) {
+        this.paymentMethods = paymentMethods;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentResultVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentResultVO.java
new file mode 100644
index 0000000..a09add2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskPaymentResultVO.java
@@ -0,0 +1,81 @@
+package com.ruoyi.system.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 鏀粯缁撴灉VO
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public class TaskPaymentResultVO {
+    
+    /** 鏀粯ID */
+    private Long paymentId;
+    
+    /** 鏀粯鐘舵�� */
+    private String payStatus;
+    
+    /** 浜岀淮鐮侀摼鎺�(浠呭井淇�/鏀粯瀹�) */
+    private String codeUrl;
+    
+    /** 浜岀淮鐮佽繃鏈熸椂闂� */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date qrExpireTime;
+    
+    /** 浜ゆ槗鍙�(鏀粯鎴愬姛鍚�) */
+    private String tradeNo;
+    
+    /** 鏀粯鏃堕棿(鏀粯鎴愬姛鍚�) */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date payTime;
+
+    public Long getPaymentId() {
+        return paymentId;
+    }
+
+    public void setPaymentId(Long paymentId) {
+        this.paymentId = paymentId;
+    }
+
+    public String getPayStatus() {
+        return payStatus;
+    }
+
+    public void setPayStatus(String payStatus) {
+        this.payStatus = payStatus;
+    }
+
+    public String getCodeUrl() {
+        return codeUrl;
+    }
+
+    public void setCodeUrl(String codeUrl) {
+        this.codeUrl = codeUrl;
+    }
+
+    public Date getQrExpireTime() {
+        return qrExpireTime;
+    }
+
+    public void setQrExpireTime(Date qrExpireTime) {
+        this.qrExpireTime = qrExpireTime;
+    }
+
+    public String getTradeNo() {
+        return tradeNo;
+    }
+
+    public void setTradeNo(String tradeNo) {
+        this.tradeNo = tradeNo;
+    }
+
+    public Date getPayTime() {
+        return payTime;
+    }
+
+    public void setPayTime(Date payTime) {
+        this.payTime = payTime;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
index 9197068..5bad9f2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
@@ -63,6 +63,9 @@
     /** 鐥呮儏ID鍒楄〃锛堢敤浜庡悓姝ヨ皟搴﹀崟鐨凮rdICD_ID鍙傛暟锛� */
     private List<Long> diseaseIds;
 
+    /** 鎵ц浜哄憳鍒楄〃锛堝寘鍚鑹茬被鍨嬶級 */
+    private List<AssigneeInfo> assignees;
+
     /** 鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅 */
     private EmergencyInfoVO emergencyInfo;
 
@@ -200,6 +203,14 @@
 
     public void setEmergencyInfo(EmergencyInfoVO emergencyInfo) {
         this.emergencyInfo = emergencyInfo;
+    }
+
+    public List<AssigneeInfo> getAssignees() {
+        return assignees;
+    }
+
+    public void setAssignees(List<AssigneeInfo> assignees) {
+        this.assignees = assignees;
     }
 
     /**
@@ -471,4 +482,42 @@
             this.transferPrice = transferPrice;
         }
     }
+
+    /**
+     * 鎵ц浜哄憳淇℃伅鍐呴儴绫�
+     */
+    public static class AssigneeInfo {
+        /** 鐢ㄦ埛ID */
+        private Long userId;
+        
+        /** 鐢ㄦ埛濮撳悕 */
+        private String userName;
+        
+        /** 鐢ㄦ埛绫诲瀷锛堣鑹诧級锛歞river-鍙告満, doctor-鍖荤敓, nurse-鎶ゅ+ */
+        private String userType;
+
+        public Long getUserId() {
+            return userId;
+        }
+
+        public void setUserId(Long userId) {
+            this.userId = userId;
+        }
+
+        public String getUserName() {
+            return userName;
+        }
+
+        public void setUserName(String userName) {
+            this.userName = userName;
+        }
+
+        public String getUserType() {
+            return userType;
+        }
+
+        public void setUserType(String userType) {
+            this.userType = userType;
+        }
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/event/PaymentSuccessEventListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/event/PaymentSuccessEventListener.java
new file mode 100644
index 0000000..9b5b34f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/event/PaymentSuccessEventListener.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.event;
+
+import com.ruoyi.payment.domain.event.PaymentSuccessEvent;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.domain.model.PaymentTransaction;
+import com.ruoyi.system.service.ISysTaskPaymentService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鏀粯鎴愬姛浜嬩欢鐩戝惉鍣�
+ * 灏嗘敮浠樻ā鍧楃殑浜嬩欢鍥炶皟杞崲涓轰笟鍔¤〃鏇存柊
+ */
+@Component
+public class PaymentSuccessEventListener {
+
+    private static final Logger log = LoggerFactory.getLogger(PaymentSuccessEventListener.class);
+
+    @Autowired
+    private ISysTaskPaymentService taskPaymentService;
+
+    /**
+     * 鐩戝惉 dryad-payment 鐨勬敮浠樻垚鍔熶簨浠�
+     */
+    @EventListener
+    public void handlePaymentSuccess(PaymentSuccessEvent event) {
+        PaymentOrder order = event.getOrder();
+        PaymentTransaction transaction = event.getTransaction();
+
+        String outTradeNo = order.getBizOrderId();
+        String tradeNo = order.getChannelTradeNo();
+        String channel = order.getChannel();
+        String provider = "WECHAT";
+        if ("ALIPAY".equalsIgnoreCase(channel)) {
+            provider = "ALIPAY";
+        }
+
+        try {
+            boolean success = taskPaymentService.handlePaymentCallback(outTradeNo, tradeNo, provider);
+            if (success) {
+                log.info("[浜嬩欢鐩戝惉] 涓氬姟鏀粯鏇存柊鎴愬姛: bizOrderId={}, tradeNo={}, provider={}", outTradeNo, tradeNo, provider);
+            } else {
+                log.warn("[浜嬩欢鐩戝惉] 涓氬姟鏀粯鏇存柊澶辫触: bizOrderId={}, tradeNo={}, provider={}", outTradeNo, tradeNo, provider);
+            }
+        } catch (Exception e) {
+            log.error("[浜嬩欢鐩戝惉] 澶勭悊鏀粯鎴愬姛浜嬩欢寮傚父", e);
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DepartmentSyncMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DepartmentSyncMapper.java
index e8b3e01..e2a78c2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DepartmentSyncMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/DepartmentSyncMapper.java
@@ -6,6 +6,7 @@
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 閮ㄩ棬鍚屾Mapper鎺ュ彛
@@ -29,4 +30,11 @@
      * @return 杞繍閮ㄥ瓙閮ㄩ棬鍒楄〃
      */
     List<DepartmentSyncDTO> selectTransportDepartments();
+    
+    /**
+     * 鏌ヨ閮ㄩ棬鍦板潃淇℃伅
+     * 
+     * @return 閮ㄩ棬鍦板潃淇℃伅鍒楄〃
+     */
+    List<Map<String, Object>> selectDepartAddress();
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyAddMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyAddMapper.java
new file mode 100644
index 0000000..6be2886
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyAddMapper.java
@@ -0,0 +1,68 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.system.domain.PaidMoneyAdd;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰昅apper鎺ュ彛
+ * 璁块棶SQL Server鏃х郴缁熸暟鎹簱
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@DataSource(DataSourceType.SQLSERVER)
+public interface PaidMoneyAddMapper {
+    
+    /**
+     * 鏍规嵁ID鏌ヨ闄勫姞璐圭敤璁板綍
+     * 
+     * @param id 涓婚敭
+     * @return 闄勫姞璐圭敤璁板綍
+     */
+    PaidMoneyAdd selectById(Long id);
+    
+    /**
+     * 鏍规嵁ServiceOrdID鍜孌ispatchOrdID鏌ヨ闄勫姞璐圭敤璁板綍鍒楄〃
+     * 
+     * @param toServiceOrdID 鏈嶅姟璁㈠崟ID
+     * @param toDispatchOrdID 璋冨害璁㈠崟ID
+     * @return 闄勫姞璐圭敤璁板綍鍒楄〃
+     */
+    List<PaidMoneyAdd> selectByOrderIds(@Param("toServiceOrdID") Long toServiceOrdID, 
+                                         @Param("toDispatchOrdID") Long toDispatchOrdID);
+    
+    /**
+     * 鏂板闄勫姞璐圭敤璁板綍
+     * 
+     * @param paidMoneyAdd 闄勫姞璐圭敤璁板綍
+     * @return 缁撴灉
+     */
+    int insert(PaidMoneyAdd paidMoneyAdd);
+    
+    /**
+     * 鏇存柊闄勫姞璐圭敤璁板綍
+     * 
+     * @param paidMoneyAdd 闄勫姞璐圭敤璁板綍
+     * @return 缁撴灉
+     */
+    int update(PaidMoneyAdd paidMoneyAdd);
+    
+    /**
+     * 鍒犻櫎闄勫姞璐圭敤璁板綍
+     * 
+     * @param id 涓婚敭
+     * @return 缁撴灉
+     */
+    int deleteById(Long id);
+    
+    /**
+     * 鏌ヨ鏈�杩戝悓姝ョ殑闄勫姞璐圭敤璁板綍锛堢敤浜庡畾鏃朵换鍔℃壒閲忓悓姝ワ級
+     * 
+     * @param hours 鏈�杩慛灏忔椂鍐呯殑璁板綍
+     * @return 闄勫姞璐圭敤璁板綍鍒楄〃
+     */
+    List<PaidMoneyAdd> selectRecentRecords(@Param("hours") Integer hours);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyMapper.java
new file mode 100644
index 0000000..fcebcac
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/PaidMoneyMapper.java
@@ -0,0 +1,67 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.system.domain.PaidMoney;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 鏃х郴缁熸敮浠樿褰昅apper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@DataSource(DataSourceType.SQLSERVER)
+public interface PaidMoneyMapper {
+    
+    /**
+     * 鏍规嵁ID鏌ヨ鏀粯璁板綍
+     * 
+     * @param id 涓婚敭
+     * @return 鏀粯璁板綍
+     */
+    PaidMoney selectById(Long id);
+    
+    /**
+     * 鏍规嵁ServiceOrdIDDt鍜孌ispatchOrdIDDt鏌ヨ鏀粯璁板綍鍒楄〃
+     * 
+     * @param serviceOrdIDDt 鏈嶅姟璁㈠崟ID
+     * @param dispatchOrdIDDt 璋冨害璁㈠崟ID
+     * @return 鏀粯璁板綍鍒楄〃
+     */
+    List<PaidMoney> selectByOrderIds(@Param("serviceOrdIDDt") Long serviceOrdIDDt, 
+                                      @Param("dispatchOrdIDDt") Long dispatchOrdIDDt);
+    
+    /**
+     * 鏂板鏀粯璁板綍
+     * 
+     * @param paidMoney 鏀粯璁板綍
+     * @return 缁撴灉
+     */
+    int insert(PaidMoney paidMoney);
+    
+    /**
+     * 鏇存柊鏀粯璁板綍
+     * 
+     * @param paidMoney 鏀粯璁板綍
+     * @return 缁撴灉
+     */
+    int update(PaidMoney paidMoney);
+    
+    /**
+     * 鍒犻櫎鏀粯璁板綍
+     * 
+     * @param id 涓婚敭
+     * @return 缁撴灉
+     */
+    int deleteById(Long id);
+    
+    /**
+     * 鏌ヨ鏈�杩慛澶╃殑鏀粯璁板綍锛堢敤浜庢壒閲忓悓姝ワ級
+     * 
+     * @param days 鏈�杩慛澶�
+     * @return 鏀粯璁板綍鍒楄〃
+     */
+    List<PaidMoney> selectRecentRecords(@Param("days") Integer days);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
index 7b7365a..27e47e0 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -36,6 +36,7 @@
      */
     public SysDept selectDeptById(Long deptId);
 
+    public List<SysDept> selectDeptListByParentId(Long parentId);
     /**
      * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬
      * 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAdditionalFeeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAdditionalFeeMapper.java
new file mode 100644
index 0000000..bb4249e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskAdditionalFeeMapper.java
@@ -0,0 +1,75 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.system.domain.SysTaskAdditionalFee;
+
+/**
+ * 浠诲姟闄勫姞璐圭敤Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public interface SysTaskAdditionalFeeMapper {
+    
+    /**
+     * 鏌ヨ浠诲姟闄勫姞璐圭敤鍒楄〃
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 闄勫姞璐圭敤鍒楄〃
+     */
+    List<SysTaskAdditionalFee> selectByTaskId(Long taskId);
+    
+    /**
+     * 鏂板浠诲姟闄勫姞璐圭敤
+     * 
+     * @param fee 闄勫姞璐圭敤
+     * @return 缁撴灉
+     */
+    int insert(SysTaskAdditionalFee fee);
+    
+    /**
+     * 鍒犻櫎浠诲姟闄勫姞璐圭敤
+     * 
+     * @param id 涓婚敭
+     * @return 缁撴灉
+     */
+    int deleteById(Long id);
+    
+    /**
+     * 鏍规嵁浠诲姟ID鍒犻櫎闄勫姞璐圭敤
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 缁撴灉
+     */
+    int deleteByTaskId(Long taskId);
+    
+    /**
+     * 鏍规嵁pid鏌ヨ闄勫姞璐圭敤
+     * 
+     * @param pid 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰旾D
+     * @return 闄勫姞璐圭敤
+     */
+    SysTaskAdditionalFee selectByPid(Long pid);
+    
+    /**
+     * 鏇存柊鍚屾淇℃伅
+     * 
+     * @param id 闄勫姞璐圭敤ID
+     * @param pid 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰旾D
+     * @param syncStatus 鍚屾鐘舵��
+     * @param syncTime 鍚屾鏃堕棿
+     * @return 缁撴灉
+     */
+    int updateSyncInfo(@Param("id") Long id, 
+                       @Param("pid") Long pid, 
+                       @Param("syncStatus") Integer syncStatus, 
+                       @Param("syncTime") java.util.Date syncTime);
+    
+    /**
+     * 鏌ヨ鏈悓姝ョ殑闄勫姞璐圭敤鍒楄〃
+     * 
+     * @return 闄勫姞璐圭敤鍒楄〃
+     */
+    List<SysTaskAdditionalFee> selectUnsyncedFees();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskEmergencyMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskEmergencyMapper.java
index 8a852ec..8684a38 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskEmergencyMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskEmergencyMapper.java
@@ -105,4 +105,14 @@
      * @return 鎬ユ晳杞繍浠诲姟鎵╁睍淇℃伅
      */
     public SysTaskEmergency selectByLegacyDispatchOrdId(@Param("legacyDispatchOrdId") Long legacyDispatchOrdId);
+    
+    /**
+     * 鏌ヨ闇�瑕侀噸鏂板悓姝ョ殑浠诲姟鍒楄〃锛堣溅杈嗘垨浜哄憳鍙樻洿锛�
+     * 鏀寔鍒嗛〉鏌ヨ锛岃繃婊ゅ凡瀹屾垚/宸插彇娑堢殑浠诲姟
+     * 
+     * @param offset 鍋忕Щ閲忥紙浠庣鍑犳潯寮�濮嬶級
+     * @param limit 姣忛〉鏁伴噺
+     * @return 鎬ユ晳杞繍浠诲姟鍒楄〃
+     */
+    public List<SysTaskEmergency> selectNeedResyncTasks(@Param("offset") Integer offset, @Param("limit") Integer limit);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskPaymentMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskPaymentMapper.java
new file mode 100644
index 0000000..8ac9c66
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskPaymentMapper.java
@@ -0,0 +1,108 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysTaskPayment;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 浠诲姟鏀粯Mapper鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public interface SysTaskPaymentMapper {
+    
+    /**
+     * 鏍规嵁浠诲姟ID鏌ヨ鏈�杩戜竴娆″凡鏀粯鐨勮褰�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鏀粯璁板綍
+     */
+    SysTaskPayment selectLatestPaidByTaskId(Long taskId);
+    
+    /**
+     * 鏍规嵁浠诲姟ID鏌ヨ鎵�鏈夊凡鏀粯璁板綍
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 宸叉敮浠樿褰曞垪琛�
+     */
+    List<SysTaskPayment> selectAllPaidByTaskId(Long taskId);
+    
+    /**
+     * 鏍规嵁浠诲姟ID鏌ヨ鎵�鏈夋敮浠樿褰�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鏀粯璁板綍鍒楄〃
+     */
+    List<SysTaskPayment> selectByTaskId(Long taskId);
+    
+    /**
+     * 鏍规嵁ID鏌ヨ鏀粯璁板綍
+     * 
+     * @param id 涓婚敭
+     * @return 鏀粯璁板綍
+     */
+    SysTaskPayment selectById(Long id);
+    
+    /**
+     * 鏍规嵁鍟嗘埛璁㈠崟鍙锋煡璇㈡敮浠樿褰�
+     * 
+     * @param outTradeNo 鍟嗘埛璁㈠崟鍙�
+     * @return 鏀粯璁板綍
+     */
+    SysTaskPayment selectByOutTradeNo(String outTradeNo);
+    
+    /**
+     * 鏂板鏀粯璁板綍
+     * 
+     * @param payment 鏀粯璁板綍
+     * @return 缁撴灉
+     */
+    int insert(SysTaskPayment payment);
+    
+    /**
+     * 鏇存柊鏀粯璁板綍
+     * 
+     * @param payment 鏀粯璁板綍
+     * @return 缁撴灉
+     */
+    int update(SysTaskPayment payment);
+    
+    /**
+     * 鏇存柊鏀粯鐘舵��
+     * 
+     * @param id 涓婚敭
+     * @param payStatus 鏀粯鐘舵��
+     * @param tradeNo 浜ゆ槗鍙�
+     * @return 缁撴灉
+     */
+    int updatePayStatus(@Param("id") Long id, @Param("payStatus") String payStatus, 
+                        @Param("tradeNo") String tradeNo);
+    
+    /**
+     * 鏍规嵁鏃х郴缁熸敮浠業D鏌ヨ鏂扮郴缁熸敮浠樿褰�
+     * 
+     * @param pid 鏃х郴缁烶aidMoney.id
+     * @return 鏀粯璁板綍
+     */
+    SysTaskPayment selectByPid(Long pid);
+
+    /**
+     * 鏇存柊鍚屾淇℃伅锛坧id銆乻yncStatus銆乻yncTime锛�
+     * 
+     * @param id 涓婚敭
+     * @param pid 鏃х郴缁熸敮浠業D
+     * @param syncStatus 鍚屾鐘舵��
+     * @param syncTime 鍚屾鏃堕棿
+     * @return 缁撴灉
+     */
+    int updateSyncInfo(@Param("id") Long id, @Param("pid") Long pid,
+                       @Param("syncStatus") Integer syncStatus, @Param("syncTime") java.util.Date syncTime);
+    
+    /**
+     * 鏌ヨ鏈悓姝ョ殑鏀粯鎴愬姛璁板綍锛堢敤浜庢壒閲忓悓姝ワ級
+     * 
+     * @return 鏀粯璁板綍鍒楄〃
+     */
+    List<SysTaskPayment> selectUnsyncedPaidPayments();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IAdditionalFeeSyncService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IAdditionalFeeSyncService.java
new file mode 100644
index 0000000..561f550
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IAdditionalFeeSyncService.java
@@ -0,0 +1,42 @@
+package com.ruoyi.system.service;
+
+/**
+ * 闄勫姞璐圭敤鍚屾Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public interface IAdditionalFeeSyncService {
+    
+    /**
+     * 灏嗘柊绯荤粺闄勫姞璐圭敤鍚屾鍒版棫绯荤粺PaidMoney_Add琛�
+     * 
+     * @param feeId 闄勫姞璐圭敤ID
+     * @return 鏄惁鍚屾鎴愬姛
+     */
+    boolean syncAdditionalFeeToLegacy(Long feeId);
+    
+    /**
+     * 灏嗘棫绯荤粺PaidMoney_Add璁板綍鍚屾鍒版柊绯荤粺
+     * 
+     * @param paidMoneyAddId 鏃х郴缁熼檮鍔犺垂鐢ㄨ褰旾D
+     * @return 鏄惁鍚屾鎴愬姛
+     */
+    boolean syncAdditionalFeeFromLegacy(Long paidMoneyAddId);
+    
+    /**
+     * 鎵归噺鍚屾鏂扮郴缁熸湭鍚屾鐨勯檮鍔犺垂鐢ㄥ埌鏃х郴缁�
+     * 
+     * @return 鎴愬姛鍚屾鐨勬暟閲�
+     */
+    int batchSyncAdditionalFeeToLegacy();
+    
+    /**
+     * 鎵归噺鍚屾鏃х郴缁熸柊澧炵殑闄勫姞璐圭敤鍒版柊绯荤粺
+     * 鐢ㄤ簬瀹氭椂浠诲姟锛屽悓姝ユ渶杩戜竴娈垫椂闂村唴鐨勯檮鍔犺垂鐢ㄨ褰�
+     * 
+     * @param hours 鍚屾鏈�杩慛灏忔椂鍐呯殑璁板綍
+     * @return 鎴愬姛鍚屾鐨勬暟閲�
+     */
+    int batchSyncAdditionalFeeFromLegacy(Integer hours);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java
index c131d29..1939fb7 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncDataService.java
@@ -2,6 +2,7 @@
 
 import com.ruoyi.system.domain.DepartmentSyncDTO;
 import java.util.List;
+import java.util.Map;
 
 /**
  * SQL Server 閮ㄩ棬鏁版嵁鏌ヨ鏈嶅姟鎺ュ彛
@@ -14,6 +15,7 @@
  */
 public interface IDepartmentSyncDataService
 {
+    List<Map<String, Object>> getAddressList();
     /**
      * 浠� SQL Server 鏌ヨ鍚堜綔鍗曚綅涓嬬殑鎵�鏈夊垎鍏徃鏁版嵁
      * 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java
index b7fdcdd..b0cc57d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IDepartmentSyncService.java
@@ -5,6 +5,7 @@
 import com.ruoyi.system.domain.OrderClassDTO;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 閮ㄩ棬鍚屾Service鎺ュ彛
@@ -28,8 +29,10 @@
      * @param branchDepts 澶栭儴浼犲叆鐨勫垎鍏徃鏁版嵁鍒楄〃
      * @return 鍚屾缁撴灉
      */
-    AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts, List<OrderClassDTO> orderClassDTOs,List<OrderClassDTO> dispatchClassDTOs);
-    
+    AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts, List<OrderClassDTO> orderClassDTOs,List<OrderClassDTO> dispatchClassDTOs,List<Map<String,Object>> addressList );
+
+
+    public void syncDeptAddress(List<Map<String,Object>> addressList);
     /**
      * 鍚屾杞繍閮ㄥ拰瀛愰儴闂ㄦ暟鎹紙浣跨敤澶栭儴浼犲叆鐨勬暟鎹簮锛�
      * 
@@ -40,5 +43,5 @@
      * @param transportDepts 澶栭儴浼犲叆鐨勮浆杩愰儴瀛愰儴闂ㄦ暟鎹垪琛�
      * @return 鍚屾缁撴灉
      */
-    AjaxResult syncTransportDepartments(List<DepartmentSyncDTO> transportDepts);
+    AjaxResult syncTransportDepartments(List<DepartmentSyncDTO> transportDepts,List<Map<String,Object>> addressList);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ILegacySystemSyncService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ILegacySystemSyncService.java
index b73955e..4f292d9 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ILegacySystemSyncService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ILegacySystemSyncService.java
@@ -47,4 +47,21 @@
      * @return 鎴愬姛鍚屾鐨勪换鍔℃暟閲�
      */
     int batchSyncPendingDispatchOrders();
+    
+    /**
+     * 閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇寸殑浠诲姟鍒版棫绯荤粺
+     * 褰撲换鍔$殑杞﹁締淇℃伅鎴栦汉鍛樹俊鎭彂鐢熷彉鏇存椂锛岄渶瑕佽皟鐢ㄦ棫绯荤粺鎺ュ彛閲嶆柊鍚屾
+     * 璋冪敤 admin_save_25.asp 鎺ュ彛
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鏄惁鎴愬姛
+     */
+    boolean resyncDispatchOrderToLegacy(Long taskId);
+    
+    /**
+     * 鎵归噺閲嶆柊鍚屾闇�瑕佹洿鏂扮殑璋冨害鍗�
+     * 
+     * @return 鎴愬姛鍚屾鐨勪换鍔℃暟閲�
+     */
+    int batchResyncPendingDispatchOrders();
 }
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java
new file mode 100644
index 0000000..8866f86
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IMapService.java
@@ -0,0 +1,21 @@
+package com.ruoyi.system.service;
+
+import java.util.Map;
+
+/**
+ * 鍦板浘鏈嶅姟鎺ュ彛
+ * 鏀寔澶氱鍦板浘鏈嶅姟鎻愪緵鍟嗭紙鐧惧害鍦板浘銆佸ぉ鍦板浘绛夛級
+ * 
+ * @author ruoyi
+ */
+public interface IMapService {
+    
+    /**
+     * 鍦板潃杞珿PS鍧愭爣锛堝湴鐞嗙紪鐮侊級
+     * 
+     * @param address 鍦板潃
+     * @param city 鍩庡競锛堝彲閫夛紝鐢ㄤ簬鎻愰珮瑙f瀽鍑嗙‘鎬э級
+     * @return GPS鍧愭爣锛屽寘鍚玪ng鍜宭at锛屽鏋滆幏鍙栧け璐ヨ繑鍥瀗ull
+     */
+    Map<String, Double> geocoding(String address, String city);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentModuleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentModuleService.java
new file mode 100644
index 0000000..e13ef79
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentModuleService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.service;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * 鏀粯妯″潡璋冪敤Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public interface IPaymentModuleService {
+    
+    /**
+     * 鍒涘缓鏀粯浜岀淮鐮�
+     * 
+     * @param outTradeNo 鍟嗘埛璁㈠崟鍙�
+     * @param amount 鏀粯閲戦
+     * @param provider 鏀粯鎻愪緵鍟�(WECHAT/ALIPAY)
+     * @param subject 璁㈠崟鏍囬
+     * @param attach 闄勫姞鏁版嵁
+     * @param callbackUrl 鍥炶皟鍦板潃
+     * @return 鏀粯妯″潡杩斿洖缁撴灉 {paymentRefId, codeUrl, expireTime}
+     */
+    Map<String, Object> createQrCode(String outTradeNo, BigDecimal amount, String provider, 
+                                     String subject, String attach, String callbackUrl);
+    
+    /**
+     * 鏌ヨ鏀粯鐘舵��
+     * 
+     * @param paymentRefId 鏀粯妯″潡杩斿洖鐨勫敮涓�鏍囪瘑
+     * @param outTradeNo 鍟嗘埛璁㈠崟鍙�
+     * @return 鏀粯鐘舵�佺粨鏋� {status, tradeNo, payTime}
+     */
+    Map<String, Object> queryPaymentStatus(String paymentRefId, String outTradeNo);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentSyncService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentSyncService.java
new file mode 100644
index 0000000..692b53b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/IPaymentSyncService.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.system.domain.PaidMoney;
+import com.ruoyi.system.domain.SysTaskPayment;
+
+/**
+ * 鏀粯淇℃伅鍚屾Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public interface IPaymentSyncService {
+    
+    /**
+     * 灏嗘柊绯荤粺鏀粯璁板綍鍚屾鍒版棫绯荤粺PaidMoney琛�
+     * 
+     * @param payment 鏀粯璁板綍
+     * @return 鏄惁鍚屾鎴愬姛
+     */
+    boolean syncPaymentToLegacy(SysTaskPayment payment);
+    
+    /**
+     * 灏嗘棫绯荤粺PaidMoney璁板綍鍚屾鍒版柊绯荤粺
+     * 
+     * @param paidMoney 鏃х郴缁熸敮浠樿褰�
+     * @return 鏄惁鍚屾鎴愬姛
+     */
+    boolean syncPaymentFromLegacy(PaidMoney paidMoney);
+    
+    /**
+     * 鎵归噺鍚屾鏂扮郴缁熸湭鍚屾鐨勬敮浠樿褰曞埌鏃х郴缁�
+     * 
+     * @return 鎴愬姛鍚屾鐨勬暟閲�
+     */
+    int batchSyncPaymentToLegacy();
+    
+    /**
+     * 鎵归噺鍚屾鏃х郴缁熸柊澧炵殑鏀粯璁板綍鍒版柊绯荤粺
+     * 鐢ㄤ簬瀹氭椂浠诲姟锛屽悓姝ユ渶杩戜竴娈垫椂闂村唴鐨勬敮浠樿褰�
+     * 
+     * @return 鎴愬姛鍚屾鐨勬暟閲�
+     */
+    int batchSyncPaymentFromLegacy();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskEmergencyService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskEmergencyService.java
index 2bf9ce1..c456593 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskEmergencyService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskEmergencyService.java
@@ -88,4 +88,13 @@
      * @return 鎬ユ晳杞繍浠诲姟鍒楄〃
      */
     public List<SysTaskEmergency> selectSyncedTasksForStatusUpdate(Integer offset, Integer limit);
+    
+    /**
+     * 鏍囪浠诲姟闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鎴栦汉鍛樺彉鏇存椂璋冪敤锛�
+     * 褰撲换鍔$殑杞﹁締淇℃伅鎴栨墽琛屼汉鍛樹俊鎭彂鐢熷彉鏇存椂锛岄渶瑕佽皟鐢ㄦ鏂规硶鏍囪闇�瑕侀噸鏂板悓姝�
+     * 鍙湁宸茬粡鍚屾杩囪皟搴﹀崟鐨勪换鍔℃墠浼氳鏍囪
+     * 
+     * @param taskId 浠诲姟ID
+     */
+    public void markNeedResync(Long taskId);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskPaymentService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskPaymentService.java
new file mode 100644
index 0000000..f94cb0c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskPaymentService.java
@@ -0,0 +1,92 @@
+package com.ruoyi.system.service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import com.ruoyi.system.domain.SysTaskAdditionalFee;
+import com.ruoyi.system.domain.SysTaskPayment;
+import com.ruoyi.system.domain.vo.TaskPaymentInfoVO;
+import com.ruoyi.system.domain.vo.TaskPaymentCreateVO;
+import com.ruoyi.system.domain.vo.TaskPaymentResultVO;
+
+/**
+ * 浠诲姟鏀粯Service鎺ュ彛
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+public interface ISysTaskPaymentService {
+    
+    /**
+     * 鑾峰彇浠诲姟鏀粯淇℃伅
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鏀粯淇℃伅
+     */
+    TaskPaymentInfoVO getPaymentInfo(Long taskId);
+    
+    /**
+     * 鏂板闄勫姞璐圭敤
+     * 
+     * @param taskId 浠诲姟ID
+     * @param feeType 璐圭敤绫诲瀷
+     * @param feeName 璐圭敤鍚嶇О
+     * @param unitAmount 鍗曚环
+     * @param quantity 鏁伴噺
+     * @param remark 澶囨敞
+     * @return 闄勫姞璐圭敤姹囨��
+     */
+    BigDecimal addAdditionalFee(Long taskId, String feeType, String feeName, 
+                                BigDecimal unitAmount, Integer quantity, String remark);
+    
+    /**
+     * 鍒犻櫎闄勫姞璐圭敤
+     * 
+     * @param taskId 浠诲姟ID
+     * @param feeId 璐圭敤ID
+     * @return 闄勫姞璐圭敤姹囨��
+     */
+    BigDecimal removeAdditionalFee(Long taskId, Long feeId);
+    
+    /**
+     * 鍒涘缓鏀粯
+     * 
+     * @param createVO 鍒涘缓鏀粯VO
+     * @return 鏀粯缁撴灉
+     */
+    TaskPaymentResultVO createPayment(TaskPaymentCreateVO createVO);
+    
+    /**
+     * 鏌ヨ鏀粯鐘舵��
+     * 
+     * @param taskId 浠诲姟ID
+     * @param paymentId 鏀粯ID(鍙��)
+     * @return 鏀粯缁撴灉
+     */
+    TaskPaymentResultVO getPaymentStatus(Long taskId, Long paymentId);
+    
+    /**
+     * 鏀粯鍥炶皟澶勭悊
+     * 
+     * @param outTradeNo 鍟嗘埛璁㈠崟鍙�
+     * @param tradeNo 涓夋柟浜ゆ槗鍙�
+     * @param provider 鏀粯鎻愪緵鍟�
+     * @return 鏄惁澶勭悊鎴愬姛
+     */
+    boolean handlePaymentCallback(String outTradeNo, String tradeNo, String provider);
+    
+    /**
+     * 鏌ヨ浠诲姟鐨勯檮鍔犺垂鐢ㄥ垪琛�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 闄勫姞璐圭敤鍒楄〃
+     */
+    List<SysTaskAdditionalFee> getAdditionalFees(Long taskId);
+    
+    /**
+     * 鏌ヨ浠诲姟鐨勬渶鏂版敮浠樿褰�
+     * 
+     * @param taskId 浠诲姟ID
+     * @return 鏀粯璁板綍
+     */
+    SysTaskPayment getLatestPayment(Long taskId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java
new file mode 100644
index 0000000..2aaeef3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AdditionalFeeSyncServiceImpl.java
@@ -0,0 +1,315 @@
+package com.ruoyi.system.service.impl;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.system.domain.PaidMoneyAdd;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskAdditionalFee;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.mapper.PaidMoneyAddMapper;
+import com.ruoyi.system.mapper.SysTaskAdditionalFeeMapper;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.service.IAdditionalFeeSyncService;
+
+/**
+ * 闄勫姞璐圭敤鍚屾Service瀹炵幇
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@Service
+public class AdditionalFeeSyncServiceImpl implements IAdditionalFeeSyncService {
+    
+    private static final Logger log = LoggerFactory.getLogger(AdditionalFeeSyncServiceImpl.class);
+    
+    @Autowired
+    private SysTaskAdditionalFeeMapper additionalFeeMapper;
+    
+    @Autowired
+    private PaidMoneyAddMapper paidMoneyAddMapper;
+    
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+    
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+    
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    
+    /**
+     * 闄勫姞璐圭敤绫诲瀷鏄犲皠锛堟柊绯荤粺 -> 鏃х郴缁燂級
+     * 鏂扮郴缁熷瓧鍏稿�硷細1-绛夊緟璐�, 2-鎷呮灦, 3-灞呭ICU, 4-鍖荤枟璁惧
+     * 鏃х郴缁烝ddMoneyType锛氱洿鎺ヤ娇鐢ㄥ瓧鍏稿��
+     */
+    private Integer convertFeeTypeToLegacy(String feeType) {
+        if (feeType == null || feeType.trim().isEmpty()) {
+            return 1; // 榛樿绛夊緟璐�
+        }
+        try {
+            return Integer.parseInt(feeType);
+        } catch (NumberFormatException e) {
+            log.warn("鏃犳晥鐨勮垂鐢ㄧ被鍨�: {}", feeType);
+            return 1; // 榛樿绛夊緟璐�
+        }
+    }
+    
+    /**
+     * 闄勫姞璐圭敤绫诲瀷鏄犲皠锛堟棫绯荤粺 -> 鏂扮郴缁燂級
+     */
+    private String convertFeeTypeFromLegacy(Integer addMoneyType) {
+        if (addMoneyType == null) {
+            return "1"; // 榛樿绛夊緟璐�
+        }
+        return String.valueOf(addMoneyType);
+    }
+    
+    /**
+     * 鑾峰彇璐圭敤绫诲瀷鍚嶇О
+     */
+    private String getFeeTypeName(String feeType) {
+        switch (feeType) {
+            case "1": return "绛夊緟璐�";
+            case "2": return "鎷呮灦";
+            case "3": return "灞呭ICU";
+            case "4": return "鍖荤枟璁惧";
+            default: return "鍏朵粬璐圭敤";
+        }
+    }
+    
+    @Override
+    @Transactional
+    @DataSource(DataSourceType.SQLSERVER)
+    public boolean syncAdditionalFeeToLegacy(Long feeId) {
+        try {
+            // 1. 鏌ヨ鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰�
+            SysTaskAdditionalFee fee = additionalFeeMapper.selectByTaskId(null).stream()
+                .filter(f -> f.getId().equals(feeId))
+                .findFirst()
+                .orElse(null);
+            
+            if (fee == null) {
+                log.error("鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曚笉瀛樺湪锛宖eeId: {}", feeId);
+                return false;
+            }
+            
+            // 2. 濡傛灉宸插悓姝ヨ繃锛岃烦杩�
+            if (fee.getPid() != null && fee.getPid() > 0) {
+                log.info("闄勫姞璐圭敤宸插悓姝ワ紝feeId: {}, pid: {}", feeId, fee.getPid());
+                return true;
+            }
+            
+            // 3. 鏌ヨ浠诲姟淇℃伅鑾峰彇ServiceOrdID鍜孌ispatchOrdID
+            SysTask task = sysTaskMapper.selectSysTaskByTaskId(fee.getTaskId());
+            if (task == null) {
+                log.error("浠诲姟涓嶅瓨鍦紝taskId: {}", fee.getTaskId());
+                return false;
+            }
+            
+            SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(fee.getTaskId());
+            if (emergency == null || emergency.getLegacyServiceOrdId() == null || emergency.getLegacyDispatchOrdId() == null) {
+                log.error("浠诲姟鏈悓姝ュ埌鏃х郴缁熸垨缂哄皯ServiceOrdID/DispatchOrdID锛宼askId: {}", fee.getTaskId());
+                return false;
+            }
+            
+            // 4. 鑾峰彇鍒涘缓浜篛A鐢ㄦ埛ID
+            Integer oaUserId = null;
+            try {
+                String createdBy = fee.getCreatedBy();
+                if (createdBy != null) {
+                    SysUser user = sysUserMapper.selectUserByUserName(createdBy);
+                    if (user != null) {
+                        oaUserId = user.getOaUserId();
+                    }
+                }
+            } catch (Exception e) {
+                log.warn("鑾峰彇鍒涘缓浜篛A鐢ㄦ埛ID澶辫触锛屼娇鐢ㄩ粯璁ゅ��", e);
+            }
+            
+            // 5. 鏋勫缓PaidMoneyAdd瀵硅薄
+            PaidMoneyAdd paidMoneyAdd = new PaidMoneyAdd();
+            paidMoneyAdd.setToServiceOrdID(emergency.getLegacyServiceOrdId());
+            paidMoneyAdd.setToDispatchOrdID(emergency.getLegacyDispatchOrdId());
+            paidMoneyAdd.setAddMoneyType(convertFeeTypeToLegacy(fee.getFeeType()));
+            paidMoneyAdd.setAddMoney(fee.getTotalAmount());
+            paidMoneyAdd.setAddMoneyExplain(fee.getFeeName() + 
+                (fee.getRemark() != null && !fee.getRemark().isEmpty() ? "(" + fee.getRemark() + ")" : ""));
+            paidMoneyAdd.setAddMoneyTime(fee.getCreatedTime() != null ? fee.getCreatedTime() : new Date());
+            paidMoneyAdd.setAddMoneyOAID(oaUserId);
+            
+            // 6. 鎻掑叆鏃х郴缁烶aidMoney_Add琛�
+            int result = paidMoneyAddMapper.insert(paidMoneyAdd);
+            if (result > 0) {
+                // 7. 鏇存柊鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曠殑鍚屾淇℃伅
+                additionalFeeMapper.updateSyncInfo(feeId, paidMoneyAdd.getId(), 2, new Date());
+                log.info("闄勫姞璐圭敤鍚屾鍒版棫绯荤粺鎴愬姛锛宖eeId: {}, pid: {}", feeId, paidMoneyAdd.getId());
+                return true;
+            } else {
+                log.error("鎻掑叆鏃х郴缁烶aidMoney_Add琛ㄥけ璐ワ紝feeId: {}", feeId);
+                return false;
+            }
+            
+        } catch (Exception e) {
+            log.error("鍚屾闄勫姞璐圭敤鍒版棫绯荤粺寮傚父锛宖eeId: {}", feeId, e);
+            // 鏇存柊鍚屾鐘舵�佷负澶辫触
+            try {
+                additionalFeeMapper.updateSyncInfo(feeId, null, 3, new Date());
+            } catch (Exception ex) {
+                log.error("鏇存柊鍚屾鐘舵�佸け璐�", ex);
+            }
+            return false;
+        }
+    }
+    
+    @Override
+    @Transactional
+    public boolean syncAdditionalFeeFromLegacy(Long paidMoneyAddId) {
+        try {
+            // 1. 鏌ヨ鏃х郴缁烶aidMoney_Add璁板綍
+            PaidMoneyAdd paidMoneyAdd = paidMoneyAddMapper.selectById(paidMoneyAddId);
+            if (paidMoneyAdd == null) {
+                log.error("鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曚笉瀛樺湪锛宲aidMoneyAddId: {}", paidMoneyAddId);
+                return false;
+            }
+            
+            // 2. 妫�鏌ユ槸鍚﹀凡鍚屾杩�
+            SysTaskAdditionalFee existFee = additionalFeeMapper.selectByPid(paidMoneyAddId);
+            if (existFee != null) {
+                log.info("鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曞凡鍚屾锛宲aidMoneyAddId: {}, feeId: {}", paidMoneyAddId, existFee.getId());
+                return true;
+            }
+            
+            // 3. 鏍规嵁ServiceOrdID鏌ヨ鏂扮郴缁熶换鍔�
+            if (paidMoneyAdd.getToServiceOrdID() == null) {
+                log.warn("鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曠己灏慡erviceOrdID锛宲aidMoneyAddId: {}锛岃烦杩囧悓姝�", paidMoneyAddId);
+                return false;
+            }
+            
+            SysTaskEmergency emergency = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(paidMoneyAdd.getToServiceOrdID());
+            if (emergency == null) {
+                log.warn("鏈壘鍒板搴旂殑杞繍浠诲姟锛孲erviceOrdID: {}锛岃烦杩囧悓姝�", paidMoneyAdd.getToServiceOrdID());
+                return false;
+            }
+            
+            // 4. 楠岃瘉DispatchOrdID鏄惁鍖归厤
+            if (paidMoneyAdd.getToDispatchOrdID() == null) {
+                log.warn("鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曠己灏慏ispatchOrdID锛宲aidMoneyAddId: {}锛岃烦杩囧悓姝�", paidMoneyAddId);
+                return false;
+            }
+            
+            if (!paidMoneyAdd.getToDispatchOrdID().equals(emergency.getLegacyDispatchOrdId())) {
+                log.warn("杞繍浠诲姟DispatchOrdID涓嶅尮閰嶏紝ServiceOrdID: {}, 闄勫姞璐圭敤DispatchOrdID: {} vs 浠诲姟DispatchOrdID: {}锛岃烦杩囧悓姝�",
+                    paidMoneyAdd.getToServiceOrdID(), paidMoneyAdd.getToDispatchOrdID(), emergency.getLegacyDispatchOrdId());
+                return false;
+            }
+            
+            // 5. 鏋勫缓SysTaskAdditionalFee瀵硅薄
+            SysTaskAdditionalFee fee = new SysTaskAdditionalFee();
+            fee.setTaskId(emergency.getTaskId());
+            fee.setFeeType(convertFeeTypeFromLegacy(paidMoneyAdd.getAddMoneyType()));
+            fee.setFeeName(getFeeTypeName(fee.getFeeType()));
+            fee.setUnitAmount(paidMoneyAdd.getAddMoney());
+            fee.setQuantity(1);
+            fee.setTotalAmount(paidMoneyAdd.getAddMoney());
+            fee.setRemark(paidMoneyAdd.getAddMoneyExplain());
+            fee.setCreatedBy("system");
+            fee.setCreatedTime(paidMoneyAdd.getAddMoneyTime() != null ? paidMoneyAdd.getAddMoneyTime() : new Date());
+            fee.setPid(paidMoneyAddId);
+            fee.setSyncStatus(2); // 鍚屾鎴愬姛
+            fee.setSyncTime(new Date());
+            
+            // 6. 鎻掑叆鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰�
+            int result = additionalFeeMapper.insert(fee);
+            if (result > 0) {
+                log.info("鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曞悓姝ュ埌鏂扮郴缁熸垚鍔燂紝paidMoneyAddId: {}, feeId: {}", paidMoneyAddId, fee.getId());
+                return true;
+            } else {
+                log.error("鎻掑叆鏂扮郴缁熼檮鍔犺垂鐢ㄨ褰曞け璐ワ紝paidMoneyAddId: {}", paidMoneyAddId);
+                return false;
+            }
+            
+        } catch (Exception e) {
+            log.error("鍚屾鏃х郴缁熼檮鍔犺垂鐢ㄨ褰曞埌鏂扮郴缁熷紓甯革紝paidMoneyAddId: {}", paidMoneyAddId, e);
+            return false;
+        }
+    }
+    
+    @Override
+    public int batchSyncAdditionalFeeToLegacy() {
+        int successCount = 0;
+        try {
+            // 鏌ヨ鏈悓姝ョ殑闄勫姞璐圭敤璁板綍
+            List<SysTaskAdditionalFee> unsyncedFees = additionalFeeMapper.selectUnsyncedFees();
+            
+            log.info("寮�濮嬫壒閲忓悓姝ラ檮鍔犺垂鐢ㄥ埌鏃х郴缁燂紝寰呭悓姝ヨ褰曟暟: {}", unsyncedFees.size());
+            
+            for (SysTaskAdditionalFee fee : unsyncedFees) {
+                try {
+                    if (syncAdditionalFeeToLegacy(fee.getId())) {
+                        successCount++;
+                    }
+                    // 姣忔潯璁板綍闂撮殧1绉掞紝閬垮厤杩囦簬棰戠箒
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    log.error("鍚屾闄勫姞璐圭敤澶辫触锛宖eeId: {}", fee.getId(), e);
+                }
+            }
+            
+            log.info("鎵归噺鍚屾闄勫姞璐圭敤鍒版棫绯荤粺瀹屾垚锛屾垚鍔�: {}, 鎬绘暟: {}", successCount, unsyncedFees.size());
+            
+        } catch (Exception e) {
+            log.error("鎵归噺鍚屾闄勫姞璐圭敤鍒版棫绯荤粺寮傚父", e);
+        }
+        
+        return successCount;
+    }
+    
+    @Override
+    @DataSource(DataSourceType.SQLSERVER)
+    public int batchSyncAdditionalFeeFromLegacy(Integer hours) {
+        int successCount = 0;
+        try {
+            if (hours == null || hours <= 0) {
+                hours = 24; // 榛樿24灏忔椂
+            }
+            
+            // 鏌ヨ鏈�杩慛灏忔椂鐨勯檮鍔犺垂鐢ㄨ褰�
+            List<PaidMoneyAdd> recentRecords = paidMoneyAddMapper.selectRecentRecords(hours);
+            
+            log.info("寮�濮嬫壒閲忓悓姝ユ棫绯荤粺闄勫姞璐圭敤鍒版柊绯荤粺锛屾渶杩憑}灏忔椂璁板綍鏁�: {}", hours, recentRecords.size());
+            
+            for (PaidMoneyAdd paidMoneyAdd : recentRecords) {
+                try {
+                    if (syncAdditionalFeeFromLegacy(paidMoneyAdd.getId())) {
+                        successCount++;
+                    }
+                    // 姣忔潯璁板綍闂撮殧1绉掞紝閬垮厤杩囦簬棰戠箒
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    log.error("鍚屾鏃х郴缁熼檮鍔犺垂鐢ㄥけ璐ワ紝paidMoneyAddId: {}", paidMoneyAdd.getId(), e);
+                }
+            }
+            
+            log.info("鎵归噺鍚屾鏃х郴缁熼檮鍔犺垂鐢ㄥ埌鏂扮郴缁熷畬鎴愶紝鎴愬姛: {}, 鎬绘暟: {}", successCount, recentRecords.size());
+            
+        } catch (Exception e) {
+            log.error("鎵归噺鍚屾鏃х郴缁熼檮鍔犺垂鐢ㄥ埌鏂扮郴缁熷紓甯�", e);
+        }
+        
+        return successCount;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java
new file mode 100644
index 0000000..f44748a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BaiduMapServiceImpl.java
@@ -0,0 +1,85 @@
+package com.ruoyi.system.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.http.HttpUtils;
+import com.ruoyi.common.config.BaiduMapConfig;
+import com.ruoyi.system.service.IMapService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鐧惧害鍦板浘鏈嶅姟瀹炵幇
+ * 
+ * @author ruoyi
+ */
+@Service("baiduMapService")
+public class BaiduMapServiceImpl implements IMapService {
+    
+    private static final Logger logger = LoggerFactory.getLogger(BaiduMapServiceImpl.class);
+    
+    @Autowired
+    private BaiduMapConfig baiduMapConfig;
+    
+    /**
+     * 鍦板潃杞珿PS鍧愭爣锛堝湴鐞嗙紪鐮侊級
+     * 
+     * @param address 鍦板潃
+     * @param city 鍩庡競锛堝彲閫夛紝鐢ㄤ簬鎻愰珮瑙f瀽鍑嗙‘鎬э級
+     * @return GPS鍧愭爣锛屽寘鍚玪ng鍜宭at锛屽鏋滆幏鍙栧け璐ヨ繑鍥瀗ull
+     */
+    @Override
+    public Map<String, Double> geocoding(String address, String city) {
+        // 濡傛灉鍦板潃涓虹┖锛岀洿鎺ヨ繑鍥瀗ull
+        if (address == null || address.trim().isEmpty()) {
+            return null;
+        }
+        
+        try {
+            // 鏋勫缓鐧惧害鍦板浘鍦扮悊缂栫爜API URL
+            String url = "https://api.map.baidu.com/geocoding/v3/";
+            String params = "address=" + URLEncoder.encode(address, StandardCharsets.UTF_8.toString()) +
+                           (city != null && !city.trim().isEmpty() ? 
+                            "&city=" + URLEncoder.encode(city, StandardCharsets.UTF_8.toString()) : "") +
+                           "&output=json" +
+                           "&ak=" + baiduMapConfig.getAk();
+            
+            logger.info("鐧惧害鍦板浘鍦扮悊缂栫爜璇锋眰: address={}, city={}", address, city);
+            
+            // 鍙戦�丠TTP璇锋眰
+            String response = HttpUtils.sendGet(url, params);
+            
+            // 瑙f瀽鍝嶅簲
+            JSONObject jsonObject = JSONObject.parseObject(response);
+            if (jsonObject.getInteger("status") != 0) {
+                logger.warn("鐧惧害鍦板浘鍦扮悊缂栫爜澶辫触: address={}, status={}, message={}", 
+                           address, jsonObject.getInteger("status"), jsonObject.getString("message"));
+                return null;
+            }
+            
+            // 鎻愬彇鍧愭爣
+            JSONObject result = jsonObject.getJSONObject("result");
+            JSONObject location = result.getJSONObject("location");
+            double lng = location.getDouble("lng");
+            double lat = location.getDouble("lat");
+            
+            logger.info("鐧惧害鍦板浘鍦扮悊缂栫爜鎴愬姛: address={}, lng={}, lat={}", address, lng, lat);
+            
+            Map<String, Double> coordinates = new HashMap<>();
+            coordinates.put("lng", lng);
+            coordinates.put("lat", lat);
+            
+            return coordinates;
+        } catch (Exception e) {
+            // 鎹曡幏鎵�鏈夊紓甯革紝閬垮厤褰卞搷涓绘祦绋�
+            logger.error("鐧惧害鍦板浘鍦扮悊缂栫爜寮傚父: address=" + address, e);
+            return null;
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java
index 79ab877..45f2b7f 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncDataServiceImpl.java
@@ -11,6 +11,7 @@
 import com.ruoyi.system.service.IDepartmentSyncDataService;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * SQL Server 閮ㄩ棬鏁版嵁鏌ヨ鏈嶅姟瀹炵幇
@@ -31,6 +32,11 @@
     @Autowired
     private DepartmentSyncMapper departmentSyncMapper;
 
+
+    public List<Map<String, Object>> getAddressList(){
+        return departmentSyncMapper.selectDepartAddress();
+    }
+
     /**
      * 浠� SQL Server 鏌ヨ鍚堜綔鍗曚綅涓嬬殑鎵�鏈夊垎鍏徃鏁版嵁
      * 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
index 3af352b..2fbce75 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DepartmentSyncServiceImpl.java
@@ -1,5 +1,6 @@
 package com.ruoyi.system.service.impl;
 
+import java.math.BigDecimal;
 import java.util.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,7 +53,7 @@
      */
     @Override
     @Transactional
-    public AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts,List<OrderClassDTO> serviceOrderList,List<OrderClassDTO> dispatchOrderList)
+    public AjaxResult syncBranchDepartments(List<DepartmentSyncDTO> branchDepts,List<OrderClassDTO> serviceOrderList,List<OrderClassDTO> dispatchOrderList,List<Map<String, Object>> addressList)
     {
         try
         {
@@ -106,7 +107,7 @@
                         branchMap.put(branchName, branchDeptId);
                         
                         // 妫�鏌ュ苟鏇存柊缂栫爜
-                        syncOrderClassCodes(existingBranch, parts[0].trim(), serviceOrderList, dispatchOrderList);
+                        syncOrderClassCodes(existingBranch, parts[0].trim(), serviceOrderList, dispatchOrderList,addressList);
 //                        existingBranch.setDepartmentId(dto.getDepartmentId());
                         sysDeptMapper.updateDept(existingBranch);
                         log.info("鏇存柊鍒嗗叕鍙哥紪鐮�: {}, 鏈嶅姟鍗曠紪鐮�: {}, 璋冨害鍗曠紪鐮�: {}", 
@@ -125,7 +126,7 @@
 //                        newBranch.setDepartmentId(dto.getDepartmentId());
 
                         // 鑷姩鍖归厤骞惰缃湇鍔″崟鍜岃皟搴﹀崟缂栫爜
-                        syncOrderClassCodes(newBranch, parts[0].trim(), serviceOrderList, dispatchOrderList);
+                        syncOrderClassCodes(newBranch, parts[0].trim(), serviceOrderList, dispatchOrderList,addressList);
 
                         sysDeptMapper.insertDept(newBranch);
                         branchDeptId = newBranch.getDeptId();
@@ -204,6 +205,24 @@
             return AjaxResult.error("鍚屾澶辫触: " + e.getMessage());
         }
     }
+
+    /**
+     * 鍚屾鍒嗗叕鍙哥殑鍦板潃鏁版嵁
+     * @param departAddress
+     */
+    public void syncDeptAddress(List<Map<String,Object>> departAddress){
+        List<SysDept> depts =sysDeptMapper.selectDeptListByParentId(100L);
+        for(SysDept dept:depts){
+            Map<String,Object> addressInfo = getDeptAddressInfo(departAddress,dept.getServiceOrderClass());
+            if(addressInfo != null){
+                dept.setDepartureAddress(getAddress(addressInfo));
+                dept.setDepartureLongitude(getLongitude(addressInfo));
+                dept.setDepartureLatitude(getLatitude(addressInfo));
+            }
+            sysDeptMapper.updateDept(dept);
+        }
+
+    }
     
     /**
      * 鍚屾杞繍閮ㄥ拰瀛愰儴闂ㄦ暟鎹紙浣跨敤澶栭儴浼犲叆鐨勬暟鎹簮锛�
@@ -218,7 +237,7 @@
      */
     @Override
     @Transactional
-    public AjaxResult syncTransportDepartments(List<DepartmentSyncDTO> transportDepts)
+    public AjaxResult syncTransportDepartments(List<DepartmentSyncDTO> transportDepts, List<Map<String, Object>> addressList)
     {
         try
         {
@@ -347,6 +366,34 @@
         }
     }
 
+    private Map<String,Object> getDeptAddressInfo(List<Map<String,Object>> departAddress,String ServiceBranch){
+        return departAddress.stream()
+            .filter(map -> map.get("ServiceBranch").equals(ServiceBranch))
+            .findFirst()
+            .orElse(null);
+    }
+
+    private String getAddress(Map<String, Object> addressInfo){
+        if(addressInfo == null){
+            return null;
+        }
+        return addressInfo.get("ServiceAddress").toString();
+    }
+
+    private BigDecimal getLongitude(Map<String, Object> addressInfo){
+        if(addressInfo == null){
+            return null;
+        }
+        return new BigDecimal(addressInfo.get("ServiceAddress_lng").toString());
+    }
+
+    private BigDecimal getLatitude(Map<String, Object> addressInfo){
+        if(addressInfo == null){
+            return null;
+        }
+        return new BigDecimal(addressInfo.get("ServiceAddress_lat").toString());
+    }
+
     /**
      * 鍚屾璁㈠崟缂栫爜锛堟湇鍔″崟鍜岃皟搴﹀崟缂栫爜锛�
      * 
@@ -359,7 +406,7 @@
      */
     private void syncOrderClassCodes(SysDept dept, String cityName, 
                                     List<OrderClassDTO> serviceOrderList,
-                                    List<OrderClassDTO> dispatchOrderList)
+                                    List<OrderClassDTO> dispatchOrderList, List<Map<String, Object>> addressList)
     {
         if (serviceOrderList == null || dispatchOrderList == null)
         {
@@ -373,6 +420,19 @@
             String serviceOrderClass = matchCityNameToCode(cityName, serviceOrderList);
             if (serviceOrderClass != null)
             {
+                Map<String, Object> addressInfo = this.getDeptAddressInfo(addressList, serviceOrderClass);
+                String address=this.getAddress(addressInfo);
+                if(address!=null){
+                    dept.setDepartureAddress(address);
+                }
+                BigDecimal lon = this.getLongitude(addressInfo);
+                if(lon!=null){
+                    dept.setDepartureLongitude(lon);
+                }
+                BigDecimal lat = this.getLatitude(addressInfo);
+                if(lat!=null){
+                    dept.setDepartureLatitude(lat);
+                }
                 dept.setServiceOrderClass(serviceOrderClass);
                 log.info("鍖归厤鍒版湇鍔″崟缂栫爜 - 鍩庡競: {}, 缂栫爜: {}", cityName, serviceOrderClass);
             }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
index a58c2c8..10b6db7 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/LegacySystemSyncServiceImpl.java
@@ -58,6 +58,9 @@
     private SysTaskMapper sysTaskMapper;
     
     @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+    
+    @Autowired
     private SysUserMapper sysUserMapper;
     
     @Autowired
@@ -252,8 +255,7 @@
     /**
      * 閲嶆柊鍚屾澶辫触鐨勪换鍔�
      */
-    @Override
-    @Transactional
+    @Override    
     public boolean retrySyncTask(Long taskId) {
         try {
             // 閲嶇疆鍚屾鐘舵��
@@ -353,6 +355,7 @@
             // 鏋勫缓璇锋眰鍙傛暟
             Map<String, String> params = buildDispatchOrderParams(task, emergency);
             
+           
             // 鍙戦�丠TTP璇锋眰
             String response = sendHttpPost(legacyConfig.getDispatchCreateUrl(), params);
             
@@ -521,6 +524,7 @@
         params.put("DispatchOrdCoPhone", StringUtils.nvl(emergency.getPatientPhone(), ""));
         params.put("ServiceOrdCoName", StringUtils.nvl(emergency.getPatientContact(), ""));
         params.put("ServiceOrdCoPhone", StringUtils.nvl(emergency.getPatientPhone(), ""));
+        params.put("ServiceOrdPtName", StringUtils.nvl(emergency.getPatientName(), ""));
         
         // 鍦板潃淇℃伅
         params.put("DispatchOrdTraStreet", StringUtils.nvl(task.getDepartureAddress(), StringUtils.nvl(emergency.getHospitalOutAddress(), "")));
@@ -619,7 +623,9 @@
      */
     private void syncTaskAssignees(SysTask task, Map<String, String> params) {
         try {
-            // 鑾峰彇浠诲姟鐨勬墽琛屼汉鍛樹俊鎭垪琛紙鍖呭惈瑙掕壊绫诲瀷锛�
+            // 鑾峰彇浠诲姟鐨勬墽琛屼汉鍛樹俊鎭垪琛紙鍖呭惈瑙掕壊绫诲瀷锛� //TODO 濡傛灉鏈変袱涓徃鏈哄氨瑕� 璁剧疆銆�Entourage_1鍜孍ntourage_2
+            //涓や釜鎶ゅ+灏辫璁剧疆 Entourage_4鍜孍ntourage_6
+            //涓や釜鍖荤敓瑕佽缃� Entourage_3鍜孍ntourage_5
             List<TaskCreateVO.AssigneeInfo> assignees = getTaskAssignees(task.getTaskId());
             
             if (assignees == null || assignees.isEmpty()) {
@@ -627,8 +633,12 @@
                 // 璁剧疆榛樿绌哄��
                 params.put("EntourageLeadID", "");
                 params.put("Entourage_1", ""); // 鍙告満
+                params.put("Entourage_2", ""); //鍙告満
                 params.put("Entourage_3", ""); // 鍖荤敓
+                params.put("Entourage_5", ""); //鍖荤敓
                 params.put("Entourage_4", ""); // 鎶ゅ+
+                params.put("Entourage_6", ""); // 鎶ゅ+
+
                 return;
             }
             
@@ -660,6 +670,11 @@
                 if ("driver".equals(userType)) {
                     if (driverOaId.isEmpty()) {
                         driverOaId = oaUserId;
+                        if(params.get("Entourage_1")==null) {
+                            params.put("Entourage_1", oaUserId);
+                        }else{
+                            params.put("Entourage_2", oaUserId);
+                        }
                         // 濡傛灉鏄涓�涓墽琛屼汉鍛橈紝璁剧疆涓洪闃�
                         if (i == 0 && leadEntourageId.isEmpty()) {
                             leadEntourageId = "1"; // 鍙告満瀵瑰簲Entourage_1
@@ -668,6 +683,11 @@
                 } else if ("doctor".equals(userType)) {
                     if (doctorOaId.isEmpty()) {
                         doctorOaId = oaUserId;
+                        if(params.get("Entourage_3")==null) {
+                            params.put("Entourage_3", oaUserId);
+                        }else{
+                            params.put("Entourage_5", oaUserId);
+                        }
                         // 濡傛灉鏄涓�涓墽琛屼汉鍛橈紝璁剧疆涓洪闃�
                         if (i == 0 && leadEntourageId.isEmpty()) {
                             leadEntourageId = "3"; // 鍖荤敓瀵瑰簲Entourage_3
@@ -676,6 +696,11 @@
                 } else if ("nurse".equals(userType)) {
                     if (nurseOaId.isEmpty()) {
                         nurseOaId = oaUserId;
+                        if(params.get("Entourage_4")==null) {
+                            params.put("Entourage_4", oaUserId);
+                        }else{
+                            params.put("Entourage_6", oaUserId);
+                        }
                         // 濡傛灉鏄涓�涓墽琛屼汉鍛橈紝璁剧疆涓洪闃�
                         if (i == 0 && leadEntourageId.isEmpty()) {
                             leadEntourageId = "4"; // 鎶ゅ+瀵瑰簲Entourage_4
@@ -686,9 +711,9 @@
             
             // 璁剧疆鍙傛暟
             params.put("EntourageLeadID", leadEntourageId);
-            params.put("Entourage_1", driverOaId);  // 鍙告満
-            params.put("Entourage_3", doctorOaId);  // 鍖荤敓
-            params.put("Entourage_4", nurseOaId);   // 鎶ゅ+
+//            params.put("Entourage_1", driverOaId);  // 鍙告満
+//            params.put("Entourage_3", doctorOaId);  // 鍖荤敓
+//            params.put("Entourage_4", nurseOaId);   // 鎶ゅ+
             
             log.info("浠诲姟鎵ц浜哄憳鍚屾鎴愬姛锛屼换鍔D: {}, 棰嗛槦ID: {}, 鍙告満: {}, 鍖荤敓: {}, 鎶ゅ+: {}", 
                 task.getTaskId(), leadEntourageId, driverOaId, doctorOaId, nurseOaId);
@@ -937,7 +962,7 @@
         // 鍦板潃淇℃伅
         params.put("province", ""); // 鍑哄彂鍦扮渷浠�
         params.put("city", ""); // 鍑哄彂鍦板煄甯�
-        params.put("ServiceOrdTraStreet", StringUtils.nvl(task.getDepartureAddress(), StringUtils.nvl(emergency.getHospitalOutAddress(), "")));
+        params.put("ServiceOrdTraStreet",task.getDepartureAddress()); //娲捐溅鍦板潃
         params.put("ServiceOrdTraStreetCoo", ""); // 鍑哄彂鍦板潗鏍�
         params.put("ServiceOrdTraEnd", StringUtils.nvl(task.getDestinationAddress(), StringUtils.nvl(emergency.getHospitalInAddress(), "")));
         params.put("ServiceOrdTraEndCoo", ""); // 鐩殑鍦板潗鏍�
@@ -1109,4 +1134,167 @@
             return null;
         }
     }
+    
+    /**
+     * 閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇寸殑浠诲姟鍒版棫绯荤粺
+     * 褰撲换鍔$殑杞﹁締淇℃伅鎴栦汉鍛樹俊鎭彂鐢熷彉鏇存椂锛岄渶瑕佽皟鐢ㄦ棫绯荤粺鎺ュ彛閲嶆柊鍚屾
+     * 浣跨敤 admin_save_25.asp 鎺ュ彛锛岃�屼笉鏄� admin_save_24.gds
+     */
+    @Override
+    @Transactional
+    public boolean resyncDispatchOrderToLegacy(Long taskId) {
+        if (!legacyConfig.isEnabled()) {
+            log.info("鏃х郴缁熷悓姝ュ凡绂佺敤锛岃烦杩囪皟搴﹀崟閲嶆柊鍚屾锛屼换鍔D: {}", taskId);
+            return false;
+        }
+        
+        try {
+            // 鏌ヨ浠诲姟淇℃伅
+            SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+            if (task == null) {
+                log.error("浠诲姟涓嶅瓨鍦紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            // 鍙悓姝ユ�ユ晳杞繍浠诲姟
+            if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+                log.info("闈炴�ユ晳杞繍浠诲姟锛岃烦杩囪皟搴﹀崟閲嶆柊鍚屾锛屼换鍔D: {}", taskId);
+                return false;
+            }
+            
+            // 鏌ヨ鎬ユ晳杞繍鎵╁睍淇℃伅
+            SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
+            if (emergency == null) {
+                log.error("鎬ユ晳杞繍鎵╁睍淇℃伅涓嶅瓨鍦紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            // 蹇呴』宸茬粡鍚屾杩囪皟搴﹀崟
+            if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) {
+                log.warn("璋冨害鍗曟湭鍚屾锛屾棤娉曢噸鏂板悓姝ワ紝浠诲姟ID: {}", taskId);
+                return false;
+            }
+            
+            Long serviceOrdId = emergency.getLegacyServiceOrdId();
+            if (serviceOrdId == null || serviceOrdId <= 0) {
+                log.warn("鏈嶅姟鍗曟湭鍚屾锛屾棤娉曢噸鏂板悓姝ヨ皟搴﹀崟锛屼换鍔D: {}", taskId);
+                return false;
+            }
+            
+            log.info("寮�濮嬮噸鏂板悓姝ヨ皟搴﹀崟锛屼换鍔D: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
+            
+            // 鏋勫缓璇锋眰鍙傛暟锛堜娇鐢ㄧ浉鍚岀殑鍙傛暟鏋勫缓鏂规硶锛�
+            Map<String, String> params = buildDispatchOrderParams(task, emergency);
+            params.put("DispatchOrdID", emergency.getLegacyDispatchOrdId().toString());
+            params.put("ServiceOrdID", emergency.getLegacyServiceOrdId().toString());
+            params.put("DispatchOrdState", "3");
+            // 鍙戦�丠TTP璇锋眰鍒版棫绯荤粺锛堜娇鐢╝dmin_save_25.asp鎺ュ彛锛�
+            String response = sendHttpPost(legacyConfig.getDispatchUpdateUrl(), params);
+            
+            // 瑙f瀽鍝嶅簲
+            Long dispatchOrdId = parseResponse(response);
+            
+            if (dispatchOrdId != null && dispatchOrdId > 0) {
+                // 閲嶆柊鍚屾鎴愬姛锛屾竻闄ら噸鏂板悓姝ユ爣璁�
+                emergency.setNeedResync(0);
+                emergency.setDispatchSyncTime(new Date());
+                emergency.setDispatchSyncErrorMsg(null);
+                sysTaskEmergencyService.updateSysTaskEmergency(emergency);
+                
+                log.info("璋冨害鍗曢噸鏂板悓姝ユ垚鍔燂紝浠诲姟ID: {}, DispatchOrdID: {}", taskId, dispatchOrdId);
+                return true;
+            } else {
+                // 閲嶆柊鍚屾澶辫触
+                emergency.setDispatchSyncErrorMsg("閲嶆柊鍚屾澶辫触锛�" + response);
+                sysTaskEmergencyService.updateSysTaskEmergency(emergency);
+                
+                log.error("璋冨害鍗曢噸鏂板悓姝ュけ璐ワ紝浠诲姟ID: {}, 鍝嶅簲: {}", taskId, response);
+                return false;
+            }
+            
+        } catch (Exception e) {
+            log.error("閲嶆柊鍚屾璋冨害鍗曞埌鏃х郴缁熷紓甯革紝浠诲姟ID: {}", taskId, e);
+            
+            // 鏇存柊鍚屾鐘舵�佷负澶辫触
+            try {
+                SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
+                if (emergency != null) {
+                    emergency.setDispatchSyncErrorMsg("閲嶆柊鍚屾寮傚父: " + e.getMessage());
+                    sysTaskEmergencyService.updateSysTaskEmergency(emergency);
+                }
+            } catch (Exception ex) {
+                log.error("鏇存柊璋冨害鍗曞悓姝ョ姸鎬佸け璐�", ex);
+            }
+            
+            return false;
+        }
+    }
+    
+    /**
+     * 鎵归噺閲嶆柊鍚屾闇�瑕佹洿鏂扮殑璋冨害鍗�
+     */
+    @Override
+    public int batchResyncPendingDispatchOrders() {
+        if (!legacyConfig.isEnabled()) {
+            log.info("鏃х郴缁熷悓姝ュ凡绂佺敤");
+            return 0;
+        }
+        
+        try {
+            int totalSuccessCount = 0;
+            int pageSize = 100; // 姣忛〉100鏉�
+            int offset = 0;
+            
+            while (true) {
+                // 鍒嗛〉鏌ヨ闇�瑕侀噸鏂板悓姝ョ殑浠诲姟
+                List<SysTaskEmergency> needResyncTasks = sysTaskEmergencyMapper.selectNeedResyncTasks(offset, pageSize);
+                
+                log.info("鏌ヨ鍒伴渶瑕侀噸鏂板悓姝ョ殑浠诲姟鏁伴噺: {}", needResyncTasks.size());
+                if (needResyncTasks == null || needResyncTasks.isEmpty()) {
+                    log.info("娌℃湁鏇村闇�瑕侀噸鏂板悓姝ョ殑浠诲姟锛宱ffset: {}", offset);
+                    break; // 娌℃湁鏇村鏁版嵁锛岄��鍑哄惊鐜�
+                }
+                
+                log.info("寮�濮嬮噸鏂板悓姝ヨ皟搴﹀崟绗� {} 椤碉紝浠诲姟鏁伴噺: {}", (offset / pageSize) + 1, needResyncTasks.size());
+                
+                int pageSuccessCount = 0;
+                for (SysTaskEmergency emergency : needResyncTasks) {
+                    log.info("寮�濮嬮噸鏂板悓姝ヨ皟搴﹀崟锛屼换鍔D: {}", emergency.getTaskId());
+                    boolean success = resyncDispatchOrderToLegacy(emergency.getTaskId());
+                    
+                    if (success) {
+                        pageSuccessCount++;
+                    }
+                    
+                    // 閬垮厤杩囦簬棰戠箒鐨勮姹�
+                    try {
+                        Thread.sleep(1000); // 姣忎釜璇锋眰闂撮殧1绉�
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        log.warn("閲嶆柊鍚屾璋冨害鍗曡涓柇");
+                        return totalSuccessCount + pageSuccessCount;
+                    }
+                }
+                
+                totalSuccessCount += pageSuccessCount;
+                log.info("璋冨害鍗曢噸鏂板悓姝ョ {} 椤靛畬鎴愶紝鎬绘暟: {}, 鎴愬姛: {}", 
+                    (offset / pageSize) + 1, needResyncTasks.size(), pageSuccessCount);
+                
+                // 濡傛灉鏈〉鏁版嵁灏戜簬姣忛〉澶у皬锛岃鏄庡凡缁忔槸鏈�鍚庝竴椤�
+                if (needResyncTasks.size() < pageSize) {
+                    log.info("宸插埌杈炬渶鍚庝竴椤碉紝璋冨害鍗曢噸鏂板悓姝ョ粨鏉�");
+                    break;
+                }
+                
+                offset += pageSize; // 涓嬩竴椤�
+            }
+            
+            log.info("鎵归噺閲嶆柊鍚屾璋冨害鍗曞畬鎴愶紝鎬绘垚鍔熸暟: {}", totalSuccessCount);
+            return totalSuccessCount;
+            
+        } catch (Exception e) {
+            log.error("鎵归噺閲嶆柊鍚屾璋冨害鍗曞紓甯�", e);
+            return 0;
+        }
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentModuleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentModuleServiceImpl.java
new file mode 100644
index 0000000..e57ca71
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentModuleServiceImpl.java
@@ -0,0 +1,118 @@
+package com.ruoyi.system.service.impl;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import org.springframework.stereotype.Service;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.system.service.IPaymentModuleService;
+import com.ruoyi.payment.application.service.PaymentService;
+import com.ruoyi.payment.interfaces.dto.PaymentRequest;
+import com.ruoyi.payment.interfaces.dto.PaymentResponse;
+import com.ruoyi.payment.domain.model.PaymentOrder;
+import com.ruoyi.payment.infrastructure.config.AlipayConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 鏀粯妯″潡璋冪敤Service瀹炵幇
+ * TODO: 瀹為檯椤圭洰涓渶瑕佹浛鎹负鐪熷疄鐨勬敮浠樻ā鍧桯TTP璋冪敤
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@Service
+public class PaymentModuleServiceImpl implements IPaymentModuleService {
+    
+    private static final Logger log = LoggerFactory.getLogger(PaymentModuleServiceImpl.class);
+        @Autowired
+        private PaymentService paymentService;
+        
+    @Autowired
+    private AlipayConfig alipayConfig;
+    
+    @Value("${payment.module.url:http://localhost:8081/pay}")
+    private String paymentModuleUrl;
+    
+    @Override
+    public Map<String, Object> createQrCode(String outTradeNo, BigDecimal amount, String provider, 
+                                           String subject, String attach, String callbackUrl) {
+        log.info("璋冪敤鏀粯妯″潡鍒涘缓浜岀淮鐮�: outTradeNo={}, amount={}, provider={}, subject={}, callbackUrl={}", 
+                 outTradeNo, amount, provider, subject, callbackUrl);
+        
+        try {
+            PaymentRequest request = new PaymentRequest();
+            request.setBizOrderId(outTradeNo);
+            request.setAmount(amount.multiply(new BigDecimal(100)).intValue());
+            request.setSubject(subject);
+            request.setDescription(attach);
+            request.setCallbackUrl(callbackUrl);
+            PaymentResponse response;
+            if (provider != null && "WECHAT".equalsIgnoreCase(provider)) {
+                response = paymentService.createWechatNativePayment(request);
+            } else {
+                // 鏍规嵁閰嶇疆鍐冲畾浣跨敤鍝鏀粯瀹濇敮浠樻柟寮�
+                String paymentMethod = alipayConfig.getPaymentMethod();
+                if ("THIRD_PARTY".equalsIgnoreCase(paymentMethod) || "THIRD-PARTY".equalsIgnoreCase(paymentMethod)) {
+                    response = paymentService.createAlipayThirdPartyPrecreate(request);
+                } else {
+                    response = paymentService.createAlipayPrecreate(request);
+                }
+            }
+            Map<String, Object> result = new HashMap<>();
+            result.put("paymentRefId", response.getOrderId() != null ? response.getOrderId().toString() : null);
+            result.put("codeUrl", response.getQrBase64());
+            java.time.LocalDateTime expireAt = response.getExpireAt();
+            result.put("expireTime", expireAt != null ? java.util.Date.from(expireAt.atZone(java.time.ZoneId.systemDefault()).toInstant()) : new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000));
+            return result;
+        } catch (Exception ex) {
+            log.error("璋冪敤鏀粯妯″潡鍒涘缓浜岀淮鐮佸紓甯�", ex);
+            throw ex;
+        }
+    }
+    
+    @Override
+    public Map<String, Object> queryPaymentStatus(String paymentRefId, String outTradeNo) {
+        log.info("璋冪敤鏀粯妯″潡鏌ヨ鏀粯鐘舵��: paymentRefId={}, outTradeNo={}", paymentRefId, outTradeNo);
+        
+        try {
+            Long orderId = null;
+            try {
+                orderId = paymentRefId != null ? Long.parseLong(paymentRefId) : null;
+            } catch (NumberFormatException e) {
+                log.warn("paymentRefId闈炴暟瀛楋紝鏃犳硶鏌ヨ璁㈠崟: {}", paymentRefId);
+            }
+            Map<String, Object> result = new HashMap<>();
+            if (orderId == null) {
+                result.put("status", "PENDING");
+                result.put("tradeNo", null);
+                result.put("payTime", null);
+                return result;
+            }
+            PaymentOrder order = paymentService.getOrder(orderId);
+            if (order == null) {
+                result.put("status", "PENDING");
+                result.put("tradeNo", null);
+                result.put("payTime", null);
+                return result;
+            }
+            String status = order.getStatus();
+            if ("SUCCEEDED".equalsIgnoreCase(status)) {
+                result.put("status", "PAID");
+            } else if ("FAILED".equalsIgnoreCase(status) || "CANCELED".equalsIgnoreCase(status) || "EXPIRED".equalsIgnoreCase(status)) {
+                result.put("status", "FAILED");
+            } else {
+                result.put("status", "PENDING");
+            }
+            result.put("tradeNo", order.getChannelTradeNo());
+            java.time.LocalDateTime paidAt = order.getPaidAt();
+            result.put("payTime", paidAt != null ? java.util.Date.from(paidAt.atZone(java.time.ZoneId.systemDefault()).toInstant()) : null);
+            return result;
+        } catch (Exception ex) {
+            log.error("璋冪敤鏀粯妯″潡鏌ヨ鏀粯鐘舵�佸紓甯�", ex);
+            throw ex;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java
new file mode 100644
index 0000000..2a8e338
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PaymentSyncServiceImpl.java
@@ -0,0 +1,298 @@
+package com.ruoyi.system.service.impl;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.system.domain.PaidMoney;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.domain.SysTaskPayment;
+import com.ruoyi.system.mapper.PaidMoneyMapper;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysTaskPaymentMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.service.IPaymentSyncService;
+
+/**
+ * 鏀粯淇℃伅鍚屾Service瀹炵幇
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@Service
+public class PaymentSyncServiceImpl implements IPaymentSyncService {
+    
+    private static final Logger log = LoggerFactory.getLogger(PaymentSyncServiceImpl.class);
+    
+    @Autowired
+    private SysTaskPaymentMapper sysTaskPaymentMapper;
+    
+    @Autowired
+    private PaidMoneyMapper paidMoneyMapper;
+    
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+    
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+    
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    
+    /**
+     * 鏀粯鏂瑰紡鏄犲皠锛堟柊绯荤粺 -> 鏃х郴缁燂級
+     * 鏂扮郴缁燂細CASH鐜伴噾, ON_ACCOUNT鎸傝处, WECHAT寰俊, ALIPAY鏀粯瀹�
+     * 鏃х郴缁燂細1-鐜伴噾, 2-閾惰杞处, 3-寰俊鏀粯, 4-鏀粯瀹�, 5-POS鏀舵, 6-鎸傝处, 7-鏄撳尰閫氭寕璐�
+     */
+    private Integer convertPaymentMethodToLegacy(String paymentMethod) {
+        return Integer.valueOf(paymentMethod); // 鐩存帴杞崲锛屽亣璁緋aymentMethod宸茬粡鏄纭殑 legacy 鍊�
+    }
+    
+    /**
+     * 鏀粯鏂瑰紡鏄犲皠锛堟棫绯荤粺 -> 鏂扮郴缁燂級
+     */
+    private String convertPaymentMethodFromLegacy(Integer paidMoneyType) {
+       return paidMoneyType.toString(); // 鐩存帴杞崲锛屽亣璁緋aidMoneyType宸茬粡鏄纭殑 paymentMethod 鍊�
+    }
+    
+    /**
+     * 灏嗘柊绯荤粺鏀粯璁板綍鍚屾鍒版棫绯荤粺PaidMoney琛�
+     */
+    @Override
+    @Transactional    
+    public boolean syncPaymentToLegacy(SysTaskPayment payment) {
+        Long paymentId = payment.getId();
+        try {
+
+
+            // 2. 濡傛灉宸插悓姝ヨ繃锛岃烦杩�
+            if (payment.getPid() != null && payment.getPid() > 0) {
+                log.info("鏀粯璁板綍宸插悓姝ワ紝paymentId: {}, pid: {}", payment.getId(), payment.getPid());
+                return true;
+            }
+            
+            // 3. 鏌ヨ浠诲姟淇℃伅鑾峰彇ServiceOrdIDDt鍜孌ispatchOrdIDDt
+            SysTask task = sysTaskMapper.selectSysTaskByTaskId(payment.getTaskId());
+            if (task == null) {
+                log.error("浠诲姟涓嶅瓨鍦紝taskId: {}", payment.getTaskId());
+                return false;
+            }
+            
+            SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(payment.getTaskId());
+            if (emergency == null || emergency.getLegacyServiceOrdId() == null || emergency.getLegacyDispatchOrdId() == null) {
+                log.error("浠诲姟鏈悓姝ュ埌鏃х郴缁熸垨缂哄皯ServiceOrdID/DispatchOrdID锛宼askId: {}", payment.getTaskId());
+                return false;
+            }
+            
+            // 4. 鑾峰彇鏀粯浜篛A鐢ㄦ埛ID
+            Integer oaUserId = null;
+            try {
+                String createdBy = payment.getCreatedBy();
+                if (createdBy != null) {
+                    SysUser user = sysUserMapper.selectUserByUserName(createdBy);
+                    if (user != null) {
+                        oaUserId = user.getOaUserId();
+                    }
+                }
+            } catch (Exception e) {
+                log.warn("鑾峰彇鏀粯浜篛A鐢ㄦ埛ID澶辫触锛屼娇鐢ㄩ粯璁ゅ��", e);
+            }
+            
+            // 5. 鏋勫缓PaidMoney瀵硅薄
+            PaidMoney paidMoney = new PaidMoney();
+            paidMoney.setPaidMoneyClass("FI"); // 榛樿FI
+            paidMoney.setServiceOrdIDDt(emergency.getLegacyServiceOrdId());
+            paidMoney.setDispatchOrdIDDt(emergency.getLegacyDispatchOrdId());
+            paidMoney.setPaidMoney(payment.getSettlementAmount());
+            paidMoney.setPaidMoneyType(convertPaymentMethodToLegacy(payment.getPaymentMethod()));
+            paidMoney.setPaidMoneyMono(payment.getTradeNo() != null ? payment.getTradeNo() : payment.getOutTradeNo());
+            paidMoney.setPaidMoneyTime(payment.getPayTime() != null ? payment.getPayTime() : new Date());
+            paidMoney.setPaidMoneyOaID(oaUserId);
+            paidMoney.setPaidMoneyUnitID(0); // 榛樿涓�0
+            paidMoney.setPaidMoneyAPCheck(1); // 宸茬‘璁�
+            paidMoney.setPaidMoneyAPTime(new Date());
+            paidMoney.setPaidMoneyTimestamp(String.valueOf(System.currentTimeMillis()));
+
+            // 6. 鎻掑叆鏃х郴缁烶aidMoney琛�
+            int result = paidMoneyMapper.insert(paidMoney);
+            if (result > 0) {
+                // 7. 鏇存柊鏂扮郴缁熸敮浠樿褰曠殑鍚屾淇℃伅
+                sysTaskPaymentMapper.updateSyncInfo(paymentId, paidMoney.getId(), 2, new Date());
+                log.info("鏀粯璁板綍鍚屾鍒版棫绯荤粺鎴愬姛锛宲aymentId: {}, pid: {}", paymentId, paidMoney.getId());
+                return true;
+            } else {
+                log.error("鎻掑叆鏃х郴缁烶aidMoney琛ㄥけ璐ワ紝paymentId: {}", paymentId);
+                return false;
+            }
+            
+        } catch (Exception e) {
+            log.error("鍚屾鏀粯璁板綍鍒版棫绯荤粺寮傚父锛宲aymentId: {}", paymentId, e);
+            // 鏇存柊鍚屾鐘舵�佷负澶辫触
+            try {
+                sysTaskPaymentMapper.updateSyncInfo(paymentId, null, 3, new Date());
+            } catch (Exception ex) {
+                log.error("鏇存柊鍚屾鐘舵�佸け璐�", ex);
+            }
+            return false;
+        }
+    }
+    
+    /**
+     * 灏嗘棫绯荤粺PaidMoney璁板綍鍚屾鍒版柊绯荤粺
+     */
+    @Override    
+    public boolean syncPaymentFromLegacy(PaidMoney paidMoney) {
+        Long paidMoneyId = paidMoney.getId();
+        try {
+           
+            
+            // 2. 妫�鏌ユ槸鍚﹀凡鍚屾杩�
+            SysTaskPayment existPayment = sysTaskPaymentMapper.selectByPid(paidMoney.getId());
+            if (existPayment != null) {
+                log.info("鏃х郴缁熸敮浠樿褰曞凡鍚屾锛宲aidMoneyId: {}, paymentId: {}", paidMoney.getId(), existPayment.getId());
+                return true;
+            }
+            
+            // 3. 鏍规嵁ServiceOrdIDDt鏌ヨ鏂扮郴缁熶换鍔�
+            if (paidMoney.getServiceOrdIDDt() == null) {
+                log.warn("鏃х郴缁熸敮浠樿褰曠己灏慡erviceOrdID锛宲aidMoneyId: {}锛岃烦杩囧悓姝�", paidMoneyId);
+                return false;
+            }
+            
+            SysTaskEmergency emergency = sysTaskEmergencyMapper.selectByLegacyServiceOrdId(paidMoney.getServiceOrdIDDt());
+            if (emergency == null) {
+                log.warn("鏈壘鍒板搴旂殑杞繍浠诲姟锛孲erviceOrdID: {}锛岃烦杩囧悓姝�", paidMoney.getServiceOrdIDDt());
+                return false;
+            }
+            
+            // 4. 楠岃瘉DispatchOrdID鏄惁鍖归厤
+            if (paidMoney.getDispatchOrdIDDt() == null) {
+                log.warn("鏃х郴缁熸敮浠樿褰曠己灏慏ispatchOrdID锛宲aidMoneyId: {}锛岃烦杩囧悓姝�", paidMoneyId);
+                return false;
+            }
+            
+            if (!paidMoney.getDispatchOrdIDDt().equals(emergency.getLegacyDispatchOrdId())) {
+                log.warn("杞繍浠诲姟DispatchOrdID涓嶅尮閰嶏紝ServiceOrdID: {}, 鏀粯璁板綍DispatchOrdID: {} vs 浠诲姟DispatchOrdID: {}锛岃烦杩囧悓姝�",
+                    paidMoney.getServiceOrdIDDt(), paidMoney.getDispatchOrdIDDt(), emergency.getLegacyDispatchOrdId());
+                return false;
+            }
+            
+            // 5. 鏌ヨ浠诲姟淇℃伅
+            SysTask task = sysTaskMapper.selectSysTaskByTaskId(emergency.getTaskId());
+            if (task == null) {
+                log.error("浠诲姟涓嶅瓨鍦紝taskId: {}", emergency.getTaskId());
+                return false;
+            }
+            
+            // 6. 鏋勫缓SysTaskPayment瀵硅薄
+            SysTaskPayment payment = new SysTaskPayment();
+            payment.setTaskId(task.getTaskId());
+            payment.setTotalAmount(paidMoney.getPaidMoney());
+            payment.setSettlementAmount(paidMoney.getPaidMoney());
+            payment.setPaymentMethod(convertPaymentMethodFromLegacy(paidMoney.getPaidMoneyType()));
+            payment.setPayStatus("PAID"); // 宸叉敮浠�
+            payment.setPayTime(paidMoney.getPaidMoneyTime() != null ? paidMoney.getPaidMoneyTime() : new Date());
+            payment.setOutTradeNo(task.getTaskCode() + "-" + paidMoneyId);
+            payment.setTradeNo(paidMoney.getPaidMoneyMono());
+            payment.setPid(paidMoneyId);
+            payment.setSyncStatus(2); // 鍚屾鎴愬姛
+            payment.setSyncTime(new Date());
+            payment.setCreatedBy("system");
+            payment.setCreatedTime(paidMoney.getPaidMoneyTime() != null ? paidMoney.getPaidMoneyTime() : new Date());
+            
+            // 7. 鎻掑叆鏂扮郴缁熸敮浠樿褰�
+            int result = sysTaskPaymentMapper.insert(payment);
+            if (result > 0) {
+                log.info("鏃х郴缁熸敮浠樿褰曞悓姝ュ埌鏂扮郴缁熸垚鍔燂紝paidMoneyId: {}, paymentId: {}", paidMoneyId, payment.getId());
+                return true;
+            } else {
+                log.error("鎻掑叆鏂扮郴缁熸敮浠樿褰曞け璐ワ紝paidMoneyId: {}", paidMoneyId);
+                return false;
+            }
+            
+        } catch (Exception e) {
+            log.error("鍚屾鏃х郴缁熸敮浠樿褰曞埌鏂扮郴缁熷紓甯革紝paidMoneyId: {}", paidMoneyId, e);
+            return false;
+        }
+    }
+    
+    /**
+     * 鎵归噺鍚屾鏂扮郴缁熸湭鍚屾鐨勬敮浠樿褰曞埌鏃х郴缁�
+     */
+    @Override
+    public int batchSyncPaymentToLegacy() {
+        int successCount = 0;
+        try {
+            // 鏌ヨ鏈悓姝ョ殑鏀粯鎴愬姛璁板綍
+            List<SysTaskPayment> unsyncedPayments = sysTaskPaymentMapper.selectUnsyncedPaidPayments();
+            
+            log.info("寮�濮嬫壒閲忓悓姝ユ敮浠樿褰曞埌鏃х郴缁燂紝寰呭悓姝ヨ褰曟暟: {}", unsyncedPayments.size());
+            
+            for (SysTaskPayment payment : unsyncedPayments) {
+                try {
+                    if (syncPaymentToLegacy(payment)) {
+                        successCount++;
+                    }
+                    // 姣忔潯璁板綍闂撮殧1绉掞紝閬垮厤杩囦簬棰戠箒
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    log.error("鍚屾鏀粯璁板綍澶辫触锛宲aymentId: {}", payment.getId(), e);
+                }
+            }
+            
+            log.info("鎵归噺鍚屾鏀粯璁板綍鍒版棫绯荤粺瀹屾垚锛屾垚鍔�: {}, 鎬绘暟: {}", successCount, unsyncedPayments.size());
+            
+        } catch (Exception e) {
+            log.error("鎵归噺鍚屾鏀粯璁板綍鍒版棫绯荤粺寮傚父", e);
+        }
+        
+        return successCount;
+    }
+    
+    /**
+     * 鎵归噺鍚屾鏃х郴缁熸柊澧炵殑鏀粯璁板綍鍒版柊绯荤粺
+     */
+    @Override    
+    public int batchSyncPaymentFromLegacy() {
+        int successCount = 0;
+        try {
+            // 鏌ヨ鏃х郴缁熸渶杩�7澶╃殑鏀粯璁板綍
+            List<PaidMoney> recentPayments = paidMoneyMapper.selectRecentRecords(7);
+            
+            log.info("寮�濮嬫壒閲忓悓姝ユ棫绯荤粺鏀粯璁板綍鍒版柊绯荤粺锛屾渶杩�7澶╄褰曟暟: {}", recentPayments.size());
+            
+            for (PaidMoney paidMoney : recentPayments) {
+                try {
+                    if (syncPaymentFromLegacy(paidMoney)) {
+                        successCount++;
+                    }
+                    // 姣忔潯璁板綍闂撮殧1绉掞紝閬垮厤杩囦簬棰戠箒
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    log.error("鍚屾鏃х郴缁熸敮浠樿褰曞け璐ワ紝paidMoneyId: {}", paidMoney.getId(), e);
+                }
+            }
+            
+            log.info("鎵归噺鍚屾鏃х郴缁熸敮浠樿褰曞埌鏂扮郴缁熷畬鎴愶紝鎴愬姛: {}, 鎬绘暟: {}", successCount, recentPayments.size());
+            
+        } catch (Exception e) {
+            log.error("鎵归噺鍚屾鏃х郴缁熸敮浠樿褰曞埌鏂扮郴缁熷紓甯�", e);
+        }
+        
+        return successCount;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskEmergencyServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskEmergencyServiceImpl.java
index a106835..c145c31 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskEmergencyServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskEmergencyServiceImpl.java
@@ -1,5 +1,7 @@
 package com.ruoyi.system.service.impl;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
@@ -121,4 +123,28 @@
     public List<SysTaskEmergency> selectSyncedTasksForStatusUpdate(Integer offset, Integer limit) {
         return sysTaskEmergencyMapper.selectSyncedTasksForStatusUpdate(offset, limit);
     }
+    
+    /**
+     * 鏍囪浠诲姟闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鎴栦汉鍛樺彉鏇存椂璋冪敤锛�
+     */
+    @Override
+    public void markNeedResync(Long taskId) {
+        try {
+            SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+            if (emergency == null) {
+                return;
+            }
+            
+            // 鍙湁宸茬粡鍚屾杩囪皟搴﹀崟鐨勪换鍔℃墠闇�瑕佹爣璁伴噸鏂板悓姝�
+            if (emergency.getDispatchSyncStatus() != null && emergency.getDispatchSyncStatus() == 2 
+                    && emergency.getLegacyDispatchOrdId() != null && emergency.getLegacyDispatchOrdId() > 0) {
+                emergency.setNeedResync(1);
+                sysTaskEmergencyMapper.updateSysTaskEmergency(emergency);
+            }
+        } catch (Exception e) {
+            // 鏍囪澶辫触涓嶅奖鍝嶄富娴佺▼锛屽彧璁板綍鏃ュ織
+            Logger log = LoggerFactory.getLogger(SysTaskEmergencyServiceImpl.class);
+            log.error("鏍囪浠诲姟闇�瑕侀噸鏂板悓姝ュけ璐ワ紝浠诲姟ID: {}", taskId, e);
+        }
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java
new file mode 100644
index 0000000..be42618
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskPaymentServiceImpl.java
@@ -0,0 +1,415 @@
+package com.ruoyi.system.service.impl;
+
+import java.math.BigDecimal;
+import java.util.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysTask;
+import com.ruoyi.system.domain.SysTaskEmergency;
+import com.ruoyi.system.domain.SysTaskAdditionalFee;
+import com.ruoyi.system.domain.SysTaskPayment;
+import com.ruoyi.system.domain.vo.TaskPaymentInfoVO;
+import com.ruoyi.system.domain.vo.TaskPaymentCreateVO;
+import com.ruoyi.system.domain.vo.TaskPaymentResultVO;
+import com.ruoyi.system.mapper.SysTaskMapper;
+import com.ruoyi.system.mapper.SysTaskEmergencyMapper;
+import com.ruoyi.system.mapper.SysTaskAdditionalFeeMapper;
+import com.ruoyi.system.mapper.SysTaskPaymentMapper;
+import com.ruoyi.system.service.ISysTaskPaymentService;
+import com.ruoyi.system.service.IPaymentModuleService;
+import com.ruoyi.system.service.IPaymentSyncService;
+import com.ruoyi.system.service.IAdditionalFeeSyncService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 浠诲姟鏀粯Service瀹炵幇
+ * 
+ * @author ruoyi
+ * @date 2025-01-15
+ */
+@Service
+public class SysTaskPaymentServiceImpl implements ISysTaskPaymentService {
+    
+    private static final Logger log = LoggerFactory.getLogger(SysTaskPaymentServiceImpl.class);
+    
+    @Autowired
+    private SysTaskMapper sysTaskMapper;
+    
+    @Autowired
+    private SysTaskEmergencyMapper sysTaskEmergencyMapper;
+    
+    @Autowired
+    private SysTaskAdditionalFeeMapper additionalFeeMapper;
+    
+    @Autowired
+    private SysTaskPaymentMapper paymentMapper;
+    
+    @Autowired
+    private IPaymentModuleService paymentModuleService;
+
+    @Autowired
+    private IPaymentSyncService paymentSyncService;
+
+    @Autowired
+    private IAdditionalFeeSyncService additionalFeeSyncService;
+
+    /**
+     * 渚涘閮ㄥ簲鐢ㄥ洖璋冪殑鎺ュ彛
+     */
+    @Value("${payment.callback.base-url:http://localhost:8080}")
+    private String callbackBaseUrl;
+    
+    @Override
+    public TaskPaymentInfoVO getPaymentInfo(Long taskId) {
+        // 鏌ヨ浠诲姟
+        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+        if (task == null) {
+            throw new ServiceException("浠诲姟涓嶅瓨鍦�");
+        }
+        
+        // 鍙湁杞繍浠诲姟鎵嶆敮鎸佹敮浠�
+        if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
+            throw new ServiceException("鍙湁杞繍浠诲姟鏀寔鏀粯鍔熻兘");
+        }
+        
+        // 鏌ヨ杞繍浠诲姟鎵╁睍淇℃伅鑾峰彇鎴愪氦浠�
+        SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
+        BigDecimal transferPrice = emergencyInfo != null && emergencyInfo.getTransferPrice() != null 
+                                   ? emergencyInfo.getTransferPrice() : BigDecimal.ZERO;
+        
+        // 鑾峰彇浠诲姟鍩烘湰淇℃伅
+        String taskCode = task.getTaskCode();
+        String taskType = task.getTaskType();
+        
+        // 鑾峰彇杞﹁締淇℃伅
+        String vehicleInfo = "";
+        if (task.getAssignedVehicles() != null && !task.getAssignedVehicles().isEmpty()) {
+            vehicleInfo = task.getAssignedVehicles().get(0).getVehicleNo();
+            if (task.getAssignedVehicles().size() > 1) {
+                vehicleInfo += " 绛�" + task.getAssignedVehicles().size() + "杈�";
+            }
+        }
+        
+        // 鑾峰彇鍑哄彂鍦板拰鐩殑鍦帮紙浠庤浆杩愪换鍔℃墿灞曚俊鎭級
+        String departureAddress = "";
+        String destinationAddress = "";
+        if (emergencyInfo != null) {
+            departureAddress = emergencyInfo.getHospitalOutAddress() != null 
+                ? emergencyInfo.getHospitalOutAddress() : "";
+            destinationAddress = emergencyInfo.getHospitalInAddress() != null 
+                ? emergencyInfo.getHospitalInAddress() : "";
+        }
+        
+        // 鏌ヨ闄勫姞璐圭敤
+        List<SysTaskAdditionalFee> additionalFees = additionalFeeMapper.selectByTaskId(taskId);
+        
+        // 璁$畻闄勫姞璐圭敤姹囨��
+        BigDecimal additionalAmount = additionalFees.stream()
+            .map(SysTaskAdditionalFee::getTotalAmount)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        
+        // 璁$畻鎬婚噾棰�
+        BigDecimal totalAmount = transferPrice.add(additionalAmount);
+        
+        // 鏌ヨ鎵�鏈夊凡鏀粯璁板綍锛岃绠楀凡鏀粯鎬婚
+        List<SysTaskPayment> paidPayments = paymentMapper.selectAllPaidByTaskId(taskId);
+        BigDecimal paidAmount = paidPayments.stream()
+            .map(SysTaskPayment::getSettlementAmount)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        
+        // 鏌ヨ鏈�杩戜竴娆℃敮浠樿褰�
+        SysTaskPayment latestPayment = paymentMapper.selectLatestPaidByTaskId(taskId);
+        
+        // 鏋勯�犺繑鍥炴暟鎹�
+        TaskPaymentInfoVO vo = new TaskPaymentInfoVO();
+        vo.setTaskCode(taskCode);
+        vo.setTaskType(taskType);
+        vo.setVehicleInfo(vehicleInfo);
+        vo.setDepartureAddress(departureAddress);
+        vo.setDestinationAddress(destinationAddress);
+        vo.setTransferPrice(transferPrice);
+        vo.setAdditionalFees(additionalFees);
+        vo.setAdditionalAmount(additionalAmount);
+        vo.setTotalAmount(totalAmount);
+        vo.setPaidAmount(paidAmount);
+        vo.setPaidPayments(paidPayments); // 璁剧疆宸叉敮浠樿褰曞垪琛�
+        vo.setLatestPayment(latestPayment);
+        vo.setPaymentMethods(Arrays.asList("CASH", "ON_ACCOUNT", "WECHAT", "ALIPAY"));
+        
+        return vo;
+    }
+    
+    @Override
+    @Transactional
+    public BigDecimal addAdditionalFee(Long taskId, String feeType, String feeName, 
+                                      BigDecimal unitAmount, Integer quantity, String remark) {
+        // 楠岃瘉鍙傛暟
+        if (unitAmount == null || unitAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("鍗曚环蹇呴』澶т簬0");
+        }
+        if (quantity == null || quantity <= 0) {
+            throw new ServiceException("鏁伴噺蹇呴』澶т簬0");
+        }
+        
+        // 璁$畻鎬婚噾棰�
+        BigDecimal totalAmount = unitAmount.multiply(new BigDecimal(quantity));
+        
+        // 鍒涘缓闄勫姞璐圭敤璁板綍
+        SysTaskAdditionalFee fee = new SysTaskAdditionalFee();
+        fee.setTaskId(taskId);
+        fee.setFeeType(feeType);
+        fee.setFeeName(feeName);
+        fee.setUnitAmount(unitAmount);
+        fee.setQuantity(quantity);
+        fee.setTotalAmount(totalAmount);
+        fee.setRemark(remark);
+        fee.setCreatedBy(SecurityUtils.getUsername());
+        
+        additionalFeeMapper.insert(fee);
+        
+        // 寮傛鍚屾鍒版棫绯荤粺
+        try {
+            additionalFeeSyncService.syncAdditionalFeeToLegacy(fee.getId());
+        } catch (Exception e) {
+            log.error("鍚屾闄勫姞璐圭敤鍒版棫绯荤粺澶辫触", e);
+        }
+        
+        // 杩斿洖褰撳墠闄勫姞璐圭敤姹囨��
+        return calculateAdditionalAmount(taskId);
+    }
+    
+    @Override
+    @Transactional
+    public BigDecimal removeAdditionalFee(Long taskId, Long feeId) {
+        additionalFeeMapper.deleteById(feeId);
+        return calculateAdditionalAmount(taskId);
+    }
+    
+    @Override
+    @Transactional
+    public TaskPaymentResultVO createPayment(TaskPaymentCreateVO createVO) {
+        Long taskId = createVO.getTaskId();
+        String paymentMethod = createVO.getPaymentMethod();
+        BigDecimal settlementAmount = createVO.getSettlementAmount();
+        
+        // 鑾峰彇鏀粯淇℃伅骞舵牎楠�
+        TaskPaymentInfoVO paymentInfo = getPaymentInfo(taskId);
+        BigDecimal paidAmount = paymentInfo.getPaidAmount();
+        BigDecimal remainingAmount = paymentInfo.getTotalAmount().subtract(paidAmount);
+        
+        // 鏍¢獙缁撶畻閲戦蹇呴』澶т簬0涓斾笉瓒呰繃鍓╀綑閲戦
+        if (settlementAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("缁撶畻閲戦蹇呴』澶т簬0");
+        }
+        if (settlementAmount.compareTo(remainingAmount) > 0) {
+            throw new ServiceException("缁撶畻閲戦涓嶈兘瓒呰繃鍓╀綑鏈敮浠橀噾棰濓細" + remainingAmount);
+        }
+        
+        // 鏌ヨ浠诲姟缂栧彿
+        SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
+        String taskCode = task.getTaskCode();
+        
+        // 鐢熸垚鍟嗘埛璁㈠崟鍙�: {taskCode}-{timestampMillis}
+        String outTradeNo = taskCode + "-" + System.currentTimeMillis();
+        
+        // 鍒涘缓鏀粯璁板綍
+        SysTaskPayment payment = new SysTaskPayment();
+        payment.setTaskId(taskId);
+        payment.setTotalAmount(paymentInfo.getTotalAmount());
+        payment.setSettlementAmount(settlementAmount);
+        payment.setPaymentMethod(paymentMethod);
+        payment.setOutTradeNo(outTradeNo);
+        payment.setRemark(createVO.getRemark());
+        payment.setCreatedBy(SecurityUtils.getUsername());
+        payment.setCreatedTime(new Date());
+        
+        TaskPaymentResultVO result = new TaskPaymentResultVO();
+        
+        // 鏀粯鏂瑰紡瀛楀吀鍊硷細1-鐜伴噾, 2-閾惰杞处, 3-寰俊鏀粯, 4-鏀粯瀹�, 5-POS鏀舵, 6-鎸傝处, 7-鏄撳尰閫氭寕璐�
+        // 1-鐜伴噾, 2-閾惰杞处, 5-POS鏀舵, 6-鎸傝处, 7-鏄撳尰閫氭寕璐� 鐩存帴鏍囪涓哄凡鏀粯
+        if ("1".equals(paymentMethod) || "2".equals(paymentMethod) || "5".equals(paymentMethod) 
+                || "6".equals(paymentMethod) || "7".equals(paymentMethod)) {
+            payment.setPayStatus("PAID");
+            payment.setPayTime(new Date());
+            payment.setSyncStatus(0); // 鏈悓姝�
+            paymentMapper.insert(payment);
+            
+            result.setPaymentId(payment.getId());
+            result.setPayStatus("PAID");
+            result.setPayTime(payment.getPayTime());
+            
+            log.info("浠诲姟{}鍒涘缓鏀粯鏂瑰紡{}鏀粯鎴愬姛锛岃鍗曞彿锛歿}", taskId, paymentMethod, outTradeNo);
+            
+            // 寮傛鍚屾鍒版棫绯荤粺
+            try {
+                paymentSyncService.syncPaymentToLegacy(payment);
+            } catch (Exception e) {
+                log.error("鍚屾鏀粯璁板綍鍒版棫绯荤粺澶辫触", e);
+            }
+        }
+        // 3-寰俊鏀粯, 4-鏀粯瀹� 闇�瑕佺敓鎴愪簩缁寸爜
+        else if ("3".equals(paymentMethod) || "4".equals(paymentMethod)) {
+            payment.setPayStatus("PENDING");
+            // 璁剧疆鏀粯鎻愪緵鍟嗭細3-WECHAT, 4-ALIPAY
+            String provider = "3".equals(paymentMethod) ? "WECHAT" : "ALIPAY";
+            payment.setProvider(provider);
+            
+            // 鐢熸垚鍥炶皟鍦板潃
+            String callbackUrl = callbackBaseUrl + "/payment/callback/" + provider.toLowerCase();
+            payment.setCallbackUrl(callbackUrl);
+            
+            try {
+                // 璋冪敤鏀粯妯″潡鍒涘缓浜岀淮鐮�
+                String subject = "鍖荤枟杞繍鏀粯锛�" + taskCode + "锛�";
+                String attach = "taskId:" + taskId;
+                
+                Map<String, Object> qrResult = paymentModuleService.createQrCode(
+                    outTradeNo, settlementAmount, provider, subject, attach, callbackUrl
+                );
+                
+                // 淇濆瓨鏀粯妯″潡杩斿洖鐨勪俊鎭�
+                payment.setPaymentRefId((String) qrResult.get("paymentRefId"));
+                payment.setCodeUrl((String) qrResult.get("codeUrl"));
+                payment.setQrExpireTime((Date) qrResult.get("expireTime"));
+                
+                paymentMapper.insert(payment);
+                
+                result.setPaymentId(payment.getId());
+                result.setPayStatus("PENDING");
+                result.setCodeUrl(payment.getCodeUrl());
+                result.setQrExpireTime(payment.getQrExpireTime());
+                
+                log.info("浠诲姟{}鍒涘缓鏀粯鏂瑰紡{}鏀粯浜岀淮鐮佹垚鍔燂紝璁㈠崟鍙凤細{}锛屼簩缁寸爜锛歿}", 
+                        taskId, paymentMethod, outTradeNo, payment.getCodeUrl());
+            } catch (Exception e) {
+                log.error("璋冪敤鏀粯妯″潡澶辫触", e);
+                throw new ServiceException("鍒涘缓鏀粯浜岀淮鐮佸け璐ワ細" + e.getMessage());
+            }
+        } else {
+            throw new ServiceException("涓嶆敮鎸佺殑鏀粯鏂瑰紡锛�" + paymentMethod);
+        }
+        
+        return result;
+    }
+    
+    @Override
+    public TaskPaymentResultVO getPaymentStatus(Long taskId, Long paymentId) {
+        SysTaskPayment payment;
+        
+        if (paymentId != null) {
+            payment = paymentMapper.selectById(paymentId);
+        } else {
+            // 鏌ヨ鏈�杩戜竴娆℃敮浠樿褰�
+            List<SysTaskPayment> payments = paymentMapper.selectByTaskId(taskId);
+            if (payments.isEmpty()) {
+                throw new ServiceException("鏈壘鍒版敮浠樿褰�");
+            }
+            payment = payments.get(0);
+        }
+        
+        if (payment == null) {
+            throw new ServiceException("鏀粯璁板綍涓嶅瓨鍦�");
+        }
+        
+        // 濡傛灉鏄緟鏀粯鐘舵�侊紝鏌ヨ鏀粯妯″潡鑾峰彇鏈�鏂扮姸鎬�
+        if ("PENDING".equals(payment.getPayStatus())) {
+            try {
+                Map<String, Object> statusResult = paymentModuleService.queryPaymentStatus(
+                    payment.getPaymentRefId(), payment.getOutTradeNo()
+                );
+                
+                String status = (String) statusResult.get("status");
+                
+                // 濡傛灉鏀粯鎴愬姛锛屾洿鏂版湰鍦拌褰�
+                if ("PAID".equals(status)) {
+                    String tradeNo = (String) statusResult.get("tradeNo");
+                    paymentMapper.updatePayStatus(payment.getId(), "PAID", tradeNo);
+                    payment.setPayStatus("PAID");
+                    payment.setTradeNo(tradeNo);
+                    payment.setPayTime(new Date());
+                    
+                    log.info("鏀粯璁板綍{}鐘舵�佹洿鏂颁负宸叉敮浠橈紝浜ゆ槗鍙凤細{}", payment.getId(), tradeNo);
+                    
+                    // 寮傛鍚屾鍒版棫绯荤粺
+                    try {
+                        paymentSyncService.syncPaymentToLegacy(payment);
+                    } catch (Exception ex) {
+                        log.error("鍚屾鏀粯璁板綍鍒版棫绯荤粺澶辫触", ex);
+                    }
+                }
+            } catch (Exception e) {
+                log.error("鏌ヨ鏀粯鐘舵�佸け璐�", e);
+            }
+        }
+        
+        // 鏋勯�犺繑鍥炵粨鏋�
+        TaskPaymentResultVO result = new TaskPaymentResultVO();
+        result.setPaymentId(payment.getId());
+        result.setPayStatus(payment.getPayStatus());
+        result.setCodeUrl(payment.getCodeUrl());
+        result.setQrExpireTime(payment.getQrExpireTime());
+        result.setTradeNo(payment.getTradeNo());
+        result.setPayTime(payment.getPayTime());
+        
+        return result;
+    }
+    
+    @Override
+    @Transactional
+    public boolean handlePaymentCallback(String outTradeNo, String tradeNo, String provider) {
+        log.info("鏀跺埌鏀粯鍥炶皟锛歰utTradeNo={}, tradeNo={}, provider={}", outTradeNo, tradeNo, provider);
+        
+        // 鏌ヨ鏀粯璁板綍
+        SysTaskPayment payment = paymentMapper.selectByOutTradeNo(outTradeNo);
+        if (payment == null) {
+            log.error("鏀粯鍥炶皟澶辫触锛氭湭鎵惧埌璁㈠崟锛宱utTradeNo={}", outTradeNo);
+            return false;
+        }
+        
+        // 濡傛灉宸茬粡鏄凡鏀粯鐘舵�侊紝鐩存帴杩斿洖鎴愬姛
+        if ("PAID".equals(payment.getPayStatus())) {
+            log.info("璁㈠崟{}宸叉敮浠橈紝蹇界暐閲嶅鍥炶皟", outTradeNo);
+            return true;
+        }
+        
+        // 鏇存柊鏀粯鐘舵��
+        paymentMapper.updatePayStatus(payment.getId(), "PAID", tradeNo);
+        
+        log.info("鏀粯鍥炶皟澶勭悊鎴愬姛锛氳鍗晎}宸叉洿鏂颁负宸叉敮浠樼姸鎬�", outTradeNo);
+        
+        // 寮傛鍚屾鍒版棫绯荤粺
+        try {
+            paymentSyncService.syncPaymentToLegacy(payment);
+        } catch (Exception e) {
+            log.error("鍚屾鏀粯璁板綍鍒版棫绯荤粺澶辫触", e);
+        }
+        
+        return true;
+    }
+    
+    @Override
+    public List<SysTaskAdditionalFee> getAdditionalFees(Long taskId) {
+        return additionalFeeMapper.selectByTaskId(taskId);
+    }
+    
+    @Override
+    public SysTaskPayment getLatestPayment(Long taskId) {
+        return paymentMapper.selectLatestPaidByTaskId(taskId);
+    }
+    
+    /**
+     * 璁$畻闄勫姞璐圭敤姹囨��
+     */
+    private BigDecimal calculateAdditionalAmount(Long taskId) {
+        List<SysTaskAdditionalFee> fees = additionalFeeMapper.selectByTaskId(taskId);
+        return fees.stream()
+            .map(SysTaskAdditionalFee::getTotalAmount)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index b939e42..ccff010 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -36,7 +36,9 @@
 import com.ruoyi.system.domain.VehicleInfo;
 import com.ruoyi.system.service.ISysTaskService;
 import com.ruoyi.system.service.ILegacySystemSyncService;
+import com.ruoyi.system.service.ISysTaskEmergencyService;
 import com.ruoyi.system.service.ITaskAttachmentSyncService;
+import com.ruoyi.system.service.IMapService;
 import com.ruoyi.system.event.TaskCreatedEvent;
 import com.ruoyi.system.event.TaskAssignedEvent;
 import com.ruoyi.system.event.TaskStatusChangedEvent;
@@ -84,6 +86,9 @@
     private ILegacySystemSyncService legacySystemSyncService;
     
     @Autowired
+    private ISysTaskEmergencyService sysTaskEmergencyService;
+    
+    @Autowired
     private ApplicationEventPublisher eventPublisher;
     
     @Autowired
@@ -94,6 +99,9 @@
 
     @Autowired
     private SysUserMapper sysUserMapper;
+
+    @Autowired(required = false)
+    private IMapService mapService;
 
     /**
      * 鏌ヨ浠诲姟绠$悊
@@ -202,6 +210,44 @@
         // 璁剧疆绂忕杞﹀叕閲屾暟
         if (createVO.getDistance() != null) {
             task.setEstimatedDistance(createVO.getDistance());
+        }
+        
+        // 鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
+        if (task.getDepartureAddress() != null && 
+            (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) && 
+            mapService != null) {
+            try {
+                Map<String, Double> coords = mapService.geocoding(
+                    task.getDepartureAddress(), 
+                    extractCityFromAddress(task.getDepartureAddress())
+                );
+                if (coords != null) {
+                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
+                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
+                    log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                }
+            } catch (Exception e) {
+                log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
+            }
+        }
+        
+        // 鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
+        if (task.getDestinationAddress() != null && 
+            (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) && 
+            mapService != null) {
+            try {
+                Map<String, Double> coords = mapService.geocoding(
+                    task.getDestinationAddress(), 
+                    extractCityFromAddress(task.getDestinationAddress())
+                );
+                if (coords != null) {
+                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
+                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
+                    log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                }
+            } catch (Exception e) {
+                log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
+            }
         }
         
         int result = sysTaskMapper.insertSysTask(task);
@@ -379,6 +425,44 @@
             task.setEstimatedDistance(createVO.getDistance());
         }
         
+        // 鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
+        if (task.getDepartureAddress() != null && 
+            (task.getDepartureLongitude() == null || task.getDepartureLatitude() == null) && 
+            mapService != null) {
+            try {
+                Map<String, Double> coords = mapService.geocoding(
+                    task.getDepartureAddress(), 
+                    extractCityFromAddress(task.getDepartureAddress())
+                );
+                if (coords != null) {
+                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
+                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
+                    log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                }
+            } catch (Exception e) {
+                log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
+            }
+        }
+        
+        // 鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣锛堝鏋滅己澶憋級
+        if (task.getDestinationAddress() != null && 
+            (task.getDestinationLongitude() == null || task.getDestinationLatitude() == null) && 
+            mapService != null) {
+            try {
+                Map<String, Double> coords = mapService.geocoding(
+                    task.getDestinationAddress(), 
+                    extractCityFromAddress(task.getDestinationAddress())
+                );
+                if (coords != null) {
+                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
+                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
+                    log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                }
+            } catch (Exception e) {
+                log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
+            }
+        }
+        
         int result = sysTaskMapper.insertSysTask(task);
         
         // 淇濆瓨杞﹁締鍏宠仈淇℃伅
@@ -394,7 +478,7 @@
                 taskVehicle.setCreateTime(createTime);
                 taskVehicle.setUpdateBy(userName);
                 taskVehicle.setUpdateTime(updateTime);
-                
+
                 sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
             }
         }
@@ -492,10 +576,51 @@
             task.setDeptId(updateVO.getDeptId());
         }
         
+        // 鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣锛堝鏋滄洿鏂颁簡鍦板潃浣嗙己澶卞潗鏍囷級
+        if (updateVO.getDepartureAddress() != null && 
+            (updateVO.getDepartureLongitude() == null || updateVO.getDepartureLatitude() == null) && 
+            mapService != null) {
+            try {
+                Map<String, Double> coords = mapService.geocoding(
+                    updateVO.getDepartureAddress(), 
+                    extractCityFromAddress(updateVO.getDepartureAddress())
+                );
+                if (coords != null) {
+                    task.setDepartureLongitude(BigDecimal.valueOf(coords.get("lng")));
+                    task.setDepartureLatitude(BigDecimal.valueOf(coords.get("lat")));
+                    log.info("鍑哄彂鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                }
+            } catch (Exception e) {
+                log.error("鑷姩鑾峰彇鍑哄彂鍦癎PS鍧愭爣澶辫触", e);
+            }
+        }
+        
+        // 鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣锛堝鏋滄洿鏂颁簡鍦板潃浣嗙己澶卞潗鏍囷級
+        if (updateVO.getDestinationAddress() != null && 
+            (updateVO.getDestinationLongitude() == null || updateVO.getDestinationLatitude() == null) && 
+            mapService != null) {
+            try {
+                Map<String, Double> coords = mapService.geocoding(
+                    updateVO.getDestinationAddress(), 
+                    extractCityFromAddress(updateVO.getDestinationAddress())
+                );
+                if (coords != null) {
+                    task.setDestinationLongitude(BigDecimal.valueOf(coords.get("lng")));
+                    task.setDestinationLatitude(BigDecimal.valueOf(coords.get("lat")));
+                    log.info("鐩殑鍦癎PS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                }
+            } catch (Exception e) {
+                log.error("鑷姩鑾峰彇鐩殑鍦癎PS鍧愭爣澶辫触", e);
+            }
+        }
+        
         // 閲嶆柊璁$畻棰勮鍏噷鏁�
         calculateEstimatedDistance(task);
         
         int result = sysTaskMapper.updateSysTask(task);
+        
+        // 鐢ㄤ簬璺熻釜鏄惁闇�瑕侀噸鏂板悓姝ワ紙杞﹁締銆佷汉鍛樸�佸湴鍧�銆佹垚浜や环鍙樻洿锛�
+        boolean needResync = false;
         
         // 鏇存柊杞﹁締鍏宠仈
         if (result > 0 && updateVO.getVehicleIds() != null && !updateVO.getVehicleIds().isEmpty()) {
@@ -525,12 +650,98 @@
                     taskVehicle.setCreateTime(now);
                     sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
                 }
+                
+                // 鏍囪闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鍙樻洿锛�
+                needResync = true;
             }
         }
         
-        // 鏇存柊鎬ユ晳杞繍鎵╁睍淇℃伅
+        // 鏇存柊鎵ц浜哄憳锛堟娴嬩汉鍛樺彉鏇达級
+        if (result > 0 && updateVO.getAssignees() != null) {
+            // 鏌ヨ鐜版湁鐨勬墽琛屼汉鍛�
+            List<SysTaskAssignee> existingAssignees = sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(updateVO.getTaskId());
+            List<Long> existingAssigneeIds = existingAssignees.stream()
+                .map(SysTaskAssignee::getUserId)
+                .collect(Collectors.toList());
+            
+            List<Long> newAssigneeIds = updateVO.getAssignees().stream()
+                .map(TaskUpdateVO.AssigneeInfo::getUserId)
+                .collect(Collectors.toList());
+            
+            // 姣旇緝鏂版棫鎵ц浜哄憳ID鍒楄〃锛屽垽鏂槸鍚︽湁鍙樺寲
+            boolean assigneesChanged = !new HashSet<>(existingAssigneeIds).equals(new HashSet<>(newAssigneeIds));
+            
+            // 鍙湁鎵ц浜哄憳鍙戠敓鍙樺寲鏃舵墠鏇存柊
+            if (assigneesChanged) {
+                // 鍒犻櫎鏃х殑鎵ц浜哄憳鍏宠仈
+                sysTaskAssigneeMapper.deleteSysTaskAssigneeByTaskId(updateVO.getTaskId());
+                
+                // 娣诲姞鏂扮殑鎵ц浜哄憳鍏宠仈
+                if (!updateVO.getAssignees().isEmpty()) {
+                    // 灏� TaskUpdateVO.AssigneeInfo 杞崲涓� TaskCreateVO.AssigneeInfo
+                    List<TaskCreateVO.AssigneeInfo> createAssignees = updateVO.getAssignees().stream()
+                        .map(assignee -> {
+                            TaskCreateVO.AssigneeInfo createAssignee = new TaskCreateVO.AssigneeInfo();
+                            createAssignee.setUserId(assignee.getUserId());
+                            createAssignee.setUserName(assignee.getUserName());
+                            createAssignee.setUserType(assignee.getUserType());
+                            return createAssignee;
+                        })
+                        .collect(Collectors.toList());
+                    saveTaskAssignees(updateVO.getTaskId(), createAssignees, SecurityUtils.getUsername());
+                }
+                
+                // 鏍囪闇�瑕侀噸鏂板悓姝ワ紙浜哄憳鍙樻洿锛�
+                needResync = true;
+            }
+        }
+        
+        // 鏇存柊鎬ユ晳杞繍鎵╁睍淇℃伅锛堟娴嬪湴鍧�鍜屾垚浜や环鍙樻洿锛�
         if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) && updateVO.getEmergencyInfo() != null) {
+            // 鑾峰彇鏃х殑鎬ユ晳杞繍淇℃伅
+            SysTaskEmergency oldEmergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(updateVO.getTaskId());
+            
+            // 妫�娴嬭浆鍑哄尰闄㈠湴鍧�鍙樻洿
+            boolean hospitalOutAddressChanged = false;
+            if (updateVO.getEmergencyInfo().getHospitalOutAddress() != null 
+                && oldEmergency != null 
+                && !updateVO.getEmergencyInfo().getHospitalOutAddress().equals(oldEmergency.getHospitalOutAddress())) {
+                hospitalOutAddressChanged = true;
+            }
+            
+            // 妫�娴嬭浆鍏ュ尰闄㈠湴鍧�鍙樻洿
+            boolean hospitalInAddressChanged = false;
+            if (updateVO.getEmergencyInfo().getHospitalInAddress() != null 
+                && oldEmergency != null 
+                && !updateVO.getEmergencyInfo().getHospitalInAddress().equals(oldEmergency.getHospitalInAddress())) {
+                hospitalInAddressChanged = true;
+            }
+            
+            // 妫�娴嬫垚浜や环鍙樻洿
+            boolean transferPriceChanged = false;
+            if (updateVO.getEmergencyInfo().getTransferPrice() != null 
+                && oldEmergency != null 
+                && oldEmergency.getTransferPrice() != null
+                && updateVO.getEmergencyInfo().getTransferPrice().compareTo(oldEmergency.getTransferPrice()) != 0) {
+                transferPriceChanged = true;
+            }
+            
+            // 鏇存柊鎬ユ晳杞繍淇℃伅
             updateEmergencyInfo(updateVO.getTaskId(), updateVO);
+            
+            // 濡傛灉鍦板潃鎴栨垚浜や环鍙戠敓鍙樻洿锛屾爣璁伴渶瑕侀噸鏂板悓姝�
+            if (hospitalOutAddressChanged || hospitalInAddressChanged || transferPriceChanged) {
+                needResync = true;
+            }
+        }
+        
+        // 濡傛灉鏄�ユ晳杞繍浠诲姟涓旀湁鍙樻洿锛屾爣璁伴渶瑕侀噸鏂板悓姝�
+        if (result > 0 && "EMERGENCY_TRANSFER".equals(oldTask.getTaskType()) && needResync) {
+            try {
+                sysTaskEmergencyService.markNeedResync(updateVO.getTaskId());
+            } catch (Exception e) {
+                // 鏍囪澶辫触涓嶅奖鍝嶄富娴佺▼
+            }
         }
         
         // 璁板綍鎿嶄綔鏃ュ織
@@ -741,7 +952,7 @@
                 recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null, 
                              "涓婁紶鏂囦欢锛�" + file.getOriginalFilename() + "(鍒嗙被锛�" + categoryDesc + ")", 
                              SecurityUtils.getUserId(), SecurityUtils.getUsername());
-                
+
 
             }
             
@@ -801,7 +1012,7 @@
                 recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null, 
                              "閫氳繃寰俊涓婁紶鏂囦欢锛�" + fileName + "(鍒嗙被锛�" + categoryDesc + ")", 
                              SecurityUtils.getUserId(), SecurityUtils.getUsername());
-                
+
 
             }
             
@@ -1150,6 +1361,8 @@
             task.setAttachments(attachments);
             // 鏌ヨ鎿嶄綔鏃ュ織
             task.setOperationLogs(sysTaskLogMapper.selectSysTaskLogByTaskId(taskId));
+            // 鏌ヨ鎵ц浜哄憳鍒楄〃
+            task.setAssignees(sysTaskAssigneeMapper.selectSysTaskAssigneeByTaskId(taskId));
             // 鍔犺浇鎬ユ晳杞繍鎵╁睍淇℃伅
             if ("EMERGENCY_TRANSFER".equals(task.getTaskType())) {
                 SysTaskEmergency emergencyInfo = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId);
@@ -1250,6 +1463,30 @@
      */
     private String generateTaskCode() {
         return taskCodeGenerator.generateTaskCode();
+    }
+    
+    /**
+     * 浠庡湴鍧�涓彁鍙栧煄甯傚悕绉帮紙鐢ㄤ簬鍦板浘鍦扮悊缂栫爜锛�
+     * 
+     * @param address 鍦板潃
+     * @return 鍩庡競鍚嶇О
+     */
+    private String extractCityFromAddress(String address) {
+        if (address == null || address.trim().isEmpty()) {
+            return null;
+        }
+        
+        // 甯歌鍩庡競鍚嶅垪琛�
+        String[] cities = {"骞垮窞", "娣卞湷", "涓滆帪", "浣涘北", "鐝犳捣", "鎯犲窞", "涓北", "姹熼棬", "婀涙睙", "鑲囧簡", "娓呰繙", "闊跺叧", "姊呭窞", "娌虫簮", "娼窞", "鎻槼", "姹曞ご", "姹曞熬", "浜戞诞", "闃虫睙","鍖椾含","涓婃捣","澶╂触"};
+        
+        
+        for (String city : cities) {
+            if (address.contains(city)) {
+                return city;
+            }
+        }
+        
+        return null;
     }
 
     /**
@@ -1434,8 +1671,27 @@
             emergencyInfo.setHospitalOutDepartmentId(createVO.getHospitalOut().getDepartmentId());
             emergencyInfo.setHospitalOutBedNumber(createVO.getHospitalOut().getBedNumber());
             emergencyInfo.setHospitalOutAddress(createVO.getHospitalOut().getAddress());
-            emergencyInfo.setHospitalOutLongitude(createVO.getHospitalOut().getLongitude());
-            emergencyInfo.setHospitalOutLatitude(createVO.getHospitalOut().getLatitude());
+            
+            // GPS鍧愭爣锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ョ殑锛屽惁鍒欏悗绔嚜鍔ㄨ幏鍙�
+            if (createVO.getHospitalOut().getLongitude() != null && createVO.getHospitalOut().getLatitude() != null) {
+                emergencyInfo.setHospitalOutLongitude(createVO.getHospitalOut().getLongitude());
+                emergencyInfo.setHospitalOutLatitude(createVO.getHospitalOut().getLatitude());
+            } else if (mapService != null && createVO.getHospitalOut().getAddress() != null) {
+                // 鍚庣鑷姩鑾峰彇GPS鍧愭爣
+                try {
+                    Map<String, Double> coords = mapService.geocoding(
+                        createVO.getHospitalOut().getAddress(), 
+                        extractCityFromAddress(createVO.getHospitalOut().getAddress())
+                    );
+                    if (coords != null) {
+                        emergencyInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
+                        emergencyInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
+                        log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                    }
+                } catch (Exception e) {
+                    log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
+                }
+            }
         }
         
         // 璁剧疆杞叆鍖婚櫌淇℃伅
@@ -1446,8 +1702,27 @@
             emergencyInfo.setHospitalInDepartmentId(createVO.getHospitalIn().getDepartmentId());
             emergencyInfo.setHospitalInBedNumber(createVO.getHospitalIn().getBedNumber());
             emergencyInfo.setHospitalInAddress(createVO.getHospitalIn().getAddress());
-            emergencyInfo.setHospitalInLongitude(createVO.getHospitalIn().getLongitude());
-            emergencyInfo.setHospitalInLatitude(createVO.getHospitalIn().getLatitude());
+            
+            // GPS鍧愭爣锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ョ殑锛屽惁鍒欏悗绔嚜鍔ㄨ幏鍙�
+            if (createVO.getHospitalIn().getLongitude() != null && createVO.getHospitalIn().getLatitude() != null) {
+                emergencyInfo.setHospitalInLongitude(createVO.getHospitalIn().getLongitude());
+                emergencyInfo.setHospitalInLatitude(createVO.getHospitalIn().getLatitude());
+            } else if (mapService != null && createVO.getHospitalIn().getAddress() != null) {
+                // 鍚庣鑷姩鑾峰彇GPS鍧愭爣
+                try {
+                    Map<String, Double> coords = mapService.geocoding(
+                        createVO.getHospitalIn().getAddress(), 
+                        extractCityFromAddress(createVO.getHospitalIn().getAddress())
+                    );
+                    if (coords != null) {
+                        emergencyInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
+                        emergencyInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
+                        log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                    }
+                } catch (Exception e) {
+                    log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
+                    }
+                }
         }
         
         // 璁剧疆璐圭敤淇℃伅
@@ -1479,8 +1754,6 @@
             emergencyInfo.setDispatchSyncStatus(2);
             emergencyInfo.setDispatchSyncTime(new Date());
             emergencyInfo.setDispatchSyncErrorMsg("鏃х郴缁熷悓姝ヨ繃鏉�");
-
-        // 绯荤粺瀛楁
         }
         // 绯荤粺瀛楁
         emergencyInfo.setCreateTime(DateUtils.getNowDate());
@@ -1548,6 +1821,23 @@
         }
         if (emergencyInfo.getHospitalOutAddress() != null) {
             existingInfo.setHospitalOutAddress(emergencyInfo.getHospitalOutAddress());
+            
+            // 濡傛灉鏇存柊浜嗗湴鍧�浣嗘病鏈塆PS鍧愭爣锛屽悗绔嚜鍔ㄨ幏鍙�
+            if (emergencyInfo.getHospitalOutLongitude() == null && emergencyInfo.getHospitalOutLatitude() == null && mapService != null) {
+                try {
+                    Map<String, Double> coords = mapService.geocoding(
+                        emergencyInfo.getHospitalOutAddress(), 
+                        extractCityFromAddress(emergencyInfo.getHospitalOutAddress())
+                    );
+                    if (coords != null) {
+                        existingInfo.setHospitalOutLongitude(BigDecimal.valueOf(coords.get("lng")));
+                        existingInfo.setHospitalOutLatitude(BigDecimal.valueOf(coords.get("lat")));
+                        log.info("杞嚭鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                    }
+                } catch (Exception e) {
+                    log.error("鑷姩鑾峰彇杞嚭鍖婚櫌GPS鍧愭爣澶辫触", e);
+                }
+            }
         }
         if (emergencyInfo.getHospitalOutLongitude() != null) {
             existingInfo.setHospitalOutLongitude(emergencyInfo.getHospitalOutLongitude());
@@ -1574,6 +1864,23 @@
         }
         if (emergencyInfo.getHospitalInAddress() != null) {
             existingInfo.setHospitalInAddress(emergencyInfo.getHospitalInAddress());
+            
+            // 濡傛灉鏇存柊浜嗗湴鍧�浣嗘病鏈塆PS鍧愭爣锛屽悗绔嚜鍔ㄨ幏鍙�
+            if (emergencyInfo.getHospitalInLongitude() == null && emergencyInfo.getHospitalInLatitude() == null && mapService != null) {
+                try {
+                    Map<String, Double> coords = mapService.geocoding(
+                        emergencyInfo.getHospitalInAddress(), 
+                        extractCityFromAddress(emergencyInfo.getHospitalInAddress())
+                    );
+                    if (coords != null) {
+                        existingInfo.setHospitalInLongitude(BigDecimal.valueOf(coords.get("lng")));
+                        existingInfo.setHospitalInLatitude(BigDecimal.valueOf(coords.get("lat")));
+                        log.info("杞叆鍖婚櫌GPS鍧愭爣鑷姩鑾峰彇鎴愬姛: {}, {}", coords.get("lng"), coords.get("lat"));
+                    }
+                } catch (Exception e) {
+                    log.error("鑷姩鑾峰彇杞叆鍖婚櫌GPS鍧愭爣澶辫触", e);
+                }
+            }
         }
         if (emergencyInfo.getHospitalInLongitude() != null) {
             existingInfo.setHospitalInLongitude(emergencyInfo.getHospitalInLongitude());
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
new file mode 100644
index 0000000..996bf70
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TiandituMapServiceImpl.java
@@ -0,0 +1,94 @@
+package com.ruoyi.system.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.http.HttpUtils;
+import com.ruoyi.common.config.TiandituMapConfig;
+import com.ruoyi.system.service.IMapService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 澶╁湴鍥炬湇鍔″疄鐜�
+ * 
+ * @author ruoyi
+ */
+@Service("tiandituMapService")
+public class TiandituMapServiceImpl implements IMapService {
+    
+    private static final Logger logger = LoggerFactory.getLogger(TiandituMapServiceImpl.class);
+    
+    @Autowired
+    private TiandituMapConfig tiandituMapConfig;
+    
+    /**
+     * 鍦板潃杞珿PS鍧愭爣锛堝湴鐞嗙紪鐮侊級
+     * 
+     * @param address 鍦板潃
+     * @param city 鍩庡競锛堝彲閫夛紝鐢ㄤ簬鎻愰珮瑙f瀽鍑嗙‘鎬э級
+     * @return GPS鍧愭爣锛屽寘鍚玪ng鍜宭at锛屽鏋滆幏鍙栧け璐ヨ繑鍥瀗ull
+     */
+    @Override
+    public Map<String, Double> geocoding(String address, String city) {
+        // 濡傛灉鍦板潃涓虹┖锛岀洿鎺ヨ繑鍥瀗ull
+        if (address == null || address.trim().isEmpty()) {
+            return null;
+        }
+        
+        try {
+            // 鏋勫缓澶╁湴鍥惧湴鐞嗙紪鐮丄PI URL
+            String url = "http://api.tianditu.gov.cn/geocoder";
+            String params = "ds=" + URLEncoder.encode("{\"keyWord\":\"" + address + "\"}", StandardCharsets.UTF_8.toString()) +
+                           "&tk=" + tiandituMapConfig.getTk();
+            
+            logger.info("澶╁湴鍥惧湴鐞嗙紪鐮佽姹�: address={}, city={}", address, city);
+            
+            // 鍙戦�丠TTP璇锋眰
+            String response = HttpUtils.sendGet(url, params);
+            
+            // 瑙f瀽鍝嶅簲
+            JSONObject jsonObject = JSONObject.parseObject(response);
+            
+            // 妫�鏌ョ姸鎬�
+            if (jsonObject.getInteger("status") == null || jsonObject.getInteger("status") != 0) {
+                logger.warn("澶╁湴鍥惧湴鐞嗙紪鐮佸け璐�: address={}, status={}, msg={}", 
+                           address, jsonObject.getInteger("status"), jsonObject.getString("msg"));
+                return null;
+            }
+            
+            // 鎻愬彇鍧愭爣
+            JSONObject result = jsonObject.getJSONObject("result");
+            if (result == null) {
+                logger.warn("澶╁湴鍥惧湴鐞嗙紪鐮佸搷搴旀棤result: address={}", address);
+                return null;
+            }
+            
+            JSONObject location = result.getJSONObject("location");
+            if (location == null) {
+                logger.warn("澶╁湴鍥惧湴鐞嗙紪鐮佸搷搴旀棤location: address={}", address);
+                return null;
+            }
+            
+            double lng = location.getDouble("lon");
+            double lat = location.getDouble("lat");
+            
+            logger.info("澶╁湴鍥惧湴鐞嗙紪鐮佹垚鍔�: address={}, lng={}, lat={}", address, lng, lat);
+            
+            Map<String, Double> coordinates = new HashMap<>();
+            coordinates.put("lng", lng);
+            coordinates.put("lat", lat);
+            
+            return coordinates;
+        } catch (Exception e) {
+            // 鎹曡幏鎵�鏈夊紓甯革紝閬垮厤褰卞搷涓绘祦绋�
+            logger.error("澶╁湴鍥惧湴鐞嗙紪鐮佸紓甯�: address=" + address, e);
+            return null;
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/DepartmentSyncMapper.xml b/ruoyi-system/src/main/resources/mapper/system/DepartmentSyncMapper.xml
index 65e76ae..d62ff57 100644
--- a/ruoyi-system/src/main/resources/mapper/system/DepartmentSyncMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/DepartmentSyncMapper.xml
@@ -9,8 +9,26 @@
         <result property="departmentName" column="departmentName" />
         <result property="parentId" column="parentID" />
         <result property="parentName" column="parentName" />
+        
     </resultMap>
 
+    <select id="selectDepartAddress" resultType="java.util.HashMap">
+        <![CDATA[
+            select 
+                ServiceBranch,
+                ServiceAddress,
+                ServiceAddress_lat,
+                ServiceAddress_lng,
+                UnitName,
+                UnitShort,
+                ServiceMinPrice,
+                ServiceUnitPrice,
+                ServiceLong
+            from IntroducerUnitData 
+            where UnitState>0 and ServiceAddress_lat is not null and ServiceAddress_lng is not null and ServiceBranch<>''
+        ]]>
+    </select>
+
     <!-- 鏌ヨ鍚堜綔鍗曚綅涓嬬殑鎵�鏈夊垎鍏徃 -->
     <select id="selectBranchDepartments" resultMap="DepartmentSyncResult">
         <![CDATA[
diff --git a/ruoyi-system/src/main/resources/mapper/system/PaidMoneyAddMapper.xml b/ruoyi-system/src/main/resources/mapper/system/PaidMoneyAddMapper.xml
new file mode 100644
index 0000000..a9ebe04
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/PaidMoneyAddMapper.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.PaidMoneyAddMapper">
+
+    <resultMap id="PaidMoneyAddResult" type="com.ruoyi.system.domain.PaidMoneyAdd">
+        <result property="id" column="id" />
+        <result property="toServiceOrdID" column="ToServiceOrdID" />
+        <result property="toDispatchOrdID" column="ToDispatchOrdID" />
+        <result property="addMoneyType" column="AddMoneyType" />
+        <result property="addMoney" column="AddMoney" />
+        <result property="addMoneyExplain" column="AddMoneyExplain" />
+        <result property="addMoneyTime" column="AddMoneyTime" />
+        <result property="addMoneyOAID" column="AddMoneyOAID" />
+    </resultMap>
+
+    <sql id="selectPaidMoneyAddVo">
+        SELECT id, ToServiceOrdID, ToDispatchOrdID, AddMoneyType, AddMoney, 
+               AddMoneyExplain, AddMoneyTime, AddMoneyOAID
+        FROM PaidMoney_Add
+    </sql>
+
+    <select id="selectById" parameterType="Long" resultMap="PaidMoneyAddResult">
+        <include refid="selectPaidMoneyAddVo"/>
+        WHERE id = #{id}
+    </select>
+
+    <select id="selectByOrderIds" resultMap="PaidMoneyAddResult">
+        <include refid="selectPaidMoneyAddVo"/>
+        WHERE ToServiceOrdID = #{toServiceOrdID}
+          AND ToDispatchOrdID = #{toDispatchOrdID}
+        ORDER BY id DESC
+    </select>
+
+    <select id="selectRecentRecords" resultMap="PaidMoneyAddResult">
+        <include refid="selectPaidMoneyAddVo"/>
+        WHERE AddMoneyTime >= DATEADD(HOUR, -#{hours}, GETDATE())
+        ORDER BY id DESC
+    </select>
+
+    <insert id="insert" parameterType="com.ruoyi.system.domain.PaidMoneyAdd" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO PaidMoney_Add
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="toServiceOrdID != null">ToServiceOrdID,</if>
+            <if test="toDispatchOrdID != null">ToDispatchOrdID,</if>
+            <if test="addMoneyType != null">AddMoneyType,</if>
+            <if test="addMoney != null">AddMoney,</if>
+            <if test="addMoneyExplain != null and addMoneyExplain != ''">AddMoneyExplain,</if>
+            <if test="addMoneyTime != null">AddMoneyTime,</if>
+            <if test="addMoneyOAID != null">AddMoneyOAID,</if>
+        </trim>
+        <trim prefix="VALUES (" suffix=")" suffixOverrides=",">
+            <if test="toServiceOrdID != null">#{toServiceOrdID},</if>
+            <if test="toDispatchOrdID != null">#{toDispatchOrdID},</if>
+            <if test="addMoneyType != null">#{addMoneyType},</if>
+            <if test="addMoney != null">#{addMoney},</if>
+            <if test="addMoneyExplain != null and addMoneyExplain != ''">#{addMoneyExplain},</if>
+            <if test="addMoneyTime != null">#{addMoneyTime},</if>
+            <if test="addMoneyOAID != null">#{addMoneyOAID},</if>
+        </trim>
+    </insert>
+
+    <update id="update" parameterType="com.ruoyi.system.domain.PaidMoneyAdd">
+        UPDATE PaidMoney_Add
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="toServiceOrdID != null">ToServiceOrdID = #{toServiceOrdID},</if>
+            <if test="toDispatchOrdID != null">ToDispatchOrdID = #{toDispatchOrdID},</if>
+            <if test="addMoneyType != null">AddMoneyType = #{addMoneyType},</if>
+            <if test="addMoney != null">AddMoney = #{addMoney},</if>
+            <if test="addMoneyExplain != null">AddMoneyExplain = #{addMoneyExplain},</if>
+            <if test="addMoneyTime != null">AddMoneyTime = #{addMoneyTime},</if>
+            <if test="addMoneyOAID != null">AddMoneyOAID = #{addMoneyOAID},</if>
+        </trim>
+        WHERE id = #{id}
+    </update>
+
+    <delete id="deleteById" parameterType="Long">
+        DELETE FROM PaidMoney_Add WHERE id = #{id}
+    </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/PaidMoneyMapper.xml b/ruoyi-system/src/main/resources/mapper/system/PaidMoneyMapper.xml
new file mode 100644
index 0000000..f847997
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/PaidMoneyMapper.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.PaidMoneyMapper">
+    
+    <resultMap type="com.ruoyi.system.domain.PaidMoney" id="PaidMoneyResult">
+        <result property="id" column="id" />
+        <result property="paidMoneyClass" column="PaidMoneyClass" />
+        <result property="serviceOrdIDDt" column="ServiceOrdIDDt" />
+        <result property="dispatchOrdIDDt" column="DispatchOrdIDDt" />
+        <result property="paidMoney" column="PaidMoney" />
+        <result property="paidMoneyType" column="PaidMoneyType" />
+        <result property="paidMoneyMono" column="PaidMoneyMono" />
+        <result property="paidMoneyTime" column="PaidMoneyTime" />
+        <result property="paidMoneyOaID" column="PaidMoneyOaID" />
+        <result property="paidMoneyUnitID" column="PaidMoneyUnitID" />
+        <result property="paidMoneyAPID" column="PaidMoney_AP_ID" />
+        <result property="paidMoneyAPTime" column="PaidMoney_AP_Time" />
+        <result property="paidMoneyAPCheck" column="PaidMoney_AP_Check" />
+        <result property="paidMoneyTimestamp" column="PaidMoneyTimestamp" />
+    </resultMap>
+
+    <sql id="selectPaidMoneyVo">
+        select id, PaidMoneyClass, ServiceOrdIDDt, DispatchOrdIDDt, PaidMoney, PaidMoneyType,
+               PaidMoneyMono, PaidMoneyTime, PaidMoneyOaID, PaidMoneyUnitID, PaidMoney_AP_ID,
+               PaidMoney_AP_Time, PaidMoney_AP_Check, PaidMoneyTimestamp
+        from PaidMoney
+    </sql>
+
+    <select id="selectById" parameterType="Long" resultMap="PaidMoneyResult">
+        <include refid="selectPaidMoneyVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectByOrderIds" resultMap="PaidMoneyResult">
+        <include refid="selectPaidMoneyVo"/>
+        where ServiceOrdIDDt = #{serviceOrdIDDt}
+        <if test="dispatchOrdIDDt != null">
+            and DispatchOrdIDDt = #{dispatchOrdIDDt}
+        </if>
+        order by PaidMoneyTime desc
+    </select>
+
+    <insert id="insert" parameterType="com.ruoyi.system.domain.PaidMoney" useGeneratedKeys="true" keyProperty="id">
+        insert into PaidMoney
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="paidMoneyClass != null and paidMoneyClass != ''">PaidMoneyClass,</if>
+            <if test="serviceOrdIDDt != null">ServiceOrdIDDt,</if>
+            <if test="dispatchOrdIDDt != null">DispatchOrdIDDt,</if>
+            <if test="paidMoney != null">PaidMoney,</if>
+            <if test="paidMoneyType != null">PaidMoneyType,</if>
+            <if test="paidMoneyMono != null and paidMoneyMono != ''">PaidMoneyMono,</if>
+            <if test="paidMoneyTime != null">PaidMoneyTime,</if>
+            <if test="paidMoneyOaID != null">PaidMoneyOaID,</if>
+            <if test="paidMoneyUnitID != null">PaidMoneyUnitID,</if>
+            <if test="paidMoneyAPID != null">PaidMoney_AP_ID,</if>
+            <if test="paidMoneyAPTime != null">PaidMoney_AP_Time,</if>
+            <if test="paidMoneyAPCheck != null">PaidMoney_AP_Check,</if>
+            <if test="paidMoneyTimestamp != null and paidMoneyTimestamp != ''">PaidMoneyTimestamp,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="paidMoneyClass != null and paidMoneyClass != ''">#{paidMoneyClass},</if>
+            <if test="serviceOrdIDDt != null">#{serviceOrdIDDt},</if>
+            <if test="dispatchOrdIDDt != null">#{dispatchOrdIDDt},</if>
+            <if test="paidMoney != null">#{paidMoney},</if>
+            <if test="paidMoneyType != null">#{paidMoneyType},</if>
+            <if test="paidMoneyMono != null and paidMoneyMono != ''">#{paidMoneyMono},</if>
+            <if test="paidMoneyTime != null">#{paidMoneyTime},</if>
+            <if test="paidMoneyOaID != null">#{paidMoneyOaID},</if>
+            <if test="paidMoneyUnitID != null">#{paidMoneyUnitID},</if>
+            <if test="paidMoneyAPID != null">#{paidMoneyAPID},</if>
+            <if test="paidMoneyAPTime != null">#{paidMoneyAPTime},</if>
+            <if test="paidMoneyAPCheck != null">#{paidMoneyAPCheck},</if>
+            <if test="paidMoneyTimestamp != null and paidMoneyTimestamp != ''">#{paidMoneyTimestamp},</if>
+        </trim>
+    </insert>
+
+    <update id="update" parameterType="com.ruoyi.system.domain.PaidMoney">
+        update PaidMoney
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="paidMoneyClass != null and paidMoneyClass != ''">PaidMoneyClass = #{paidMoneyClass},</if>
+            <if test="serviceOrdIDDt != null">ServiceOrdIDDt = #{serviceOrdIDDt},</if>
+            <if test="dispatchOrdIDDt != null">DispatchOrdIDDt = #{dispatchOrdIDDt},</if>
+            <if test="paidMoney != null">PaidMoney = #{paidMoney},</if>
+            <if test="paidMoneyType != null">PaidMoneyType = #{paidMoneyType},</if>
+            <if test="paidMoneyMono != null and paidMoneyMono != ''">PaidMoneyMono = #{paidMoneyMono},</if>
+            <if test="paidMoneyTime != null">PaidMoneyTime = #{paidMoneyTime},</if>
+            <if test="paidMoneyOaID != null">PaidMoneyOaID = #{paidMoneyOaID},</if>
+            <if test="paidMoneyUnitID != null">PaidMoneyUnitID = #{paidMoneyUnitID},</if>
+            <if test="paidMoneyAPID != null">PaidMoney_AP_ID = #{paidMoneyAPID},</if>
+            <if test="paidMoneyAPTime != null">PaidMoney_AP_Time = #{paidMoneyAPTime},</if>
+            <if test="paidMoneyAPCheck != null">PaidMoney_AP_Check = #{paidMoneyAPCheck},</if>
+            <if test="paidMoneyTimestamp != null and paidMoneyTimestamp != ''">PaidMoneyTimestamp = #{paidMoneyTimestamp},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteById" parameterType="Long">
+        delete from PaidMoney where id = #{id}
+    </delete>
+
+    <select id="selectRecentRecords" resultMap="PaidMoneyResult">
+        <include refid="selectPaidMoneyVo"/>
+        where PaidMoneyTime >= DATEADD(DAY, -#{days}, GETDATE())
+        order by PaidMoneyTime desc
+    </select>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
index 9b9bce3..67c9fae 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -19,6 +19,9 @@
 		<result property="departmentId" column="department_id" />
 		<result property="serviceOrderClass" column="service_order_class" />
 		<result property="dispatchOrderClass" column="dispatch_order_class" />
+		<result property="departureAddress" column="departure_address" />
+		<result property="departureLongitude" column="departure_longitude" />
+		<result property="departureLatitude" column="departure_latitude" />
 		<result property="createBy"   column="create_by"   />
 		<result property="createTime" column="create_time" />
 		<result property="updateBy"   column="update_by"   />
@@ -26,7 +29,7 @@
 	</resultMap>
 	
 	<sql id="selectDeptVo">
-        select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.department_id, d.service_order_class, d.dispatch_order_class, d.create_by, d.create_time 
+        select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.department_id, d.service_order_class, d.dispatch_order_class, d.departure_address, d.departure_longitude, d.departure_latitude, d.create_by, d.create_time 
         from sys_dept d
     </sql>
     
@@ -54,6 +57,14 @@
 
 		order by d.parent_id, d.order_num
     </select>
+
+    <select id="selectDeptListByParentId" parameterType="Long" resultMap="SysDeptResult">
+            <include refid="selectDeptVo"/>
+            where d.del_flag = '0'
+
+			AND parent_id = #{parentId}
+
+    </select>
     
     <select id="selectDeptListByRoleId" resultType="Long">
 		select d.dept_id
@@ -67,7 +78,7 @@
 	</select>
     
     <select id="selectDeptById" parameterType="Long" resultMap="SysDeptResult">
-		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.department_id, d.service_order_class, d.dispatch_order_class,
+		select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.department_id, d.service_order_class, d.dispatch_order_class, d.departure_address, d.departure_longitude, d.departure_latitude,
 			(select dept_name from sys_dept where dept_id = d.parent_id) parent_name
 		from sys_dept d
 		where d.dept_id = #{deptId}
@@ -109,6 +120,9 @@
  			<if test="departmentId != null">department_id,</if>
  			<if test="serviceOrderClass != null and serviceOrderClass != ''">service_order_class,</if>
  			<if test="dispatchOrderClass != null and dispatchOrderClass != ''">dispatch_order_class,</if>
+ 			<if test="departureAddress != null and departureAddress != ''">departure_address,</if>
+ 			<if test="departureLongitude != null">departure_longitude,</if>
+ 			<if test="departureLatitude != null">departure_latitude,</if>
  			<if test="createBy != null and createBy != ''">create_by,</if>
  			create_time
  		)values(
@@ -124,6 +138,9 @@
  			<if test="departmentId != null">#{departmentId},</if>
  			<if test="serviceOrderClass != null and serviceOrderClass != ''">#{serviceOrderClass},</if>
  			<if test="dispatchOrderClass != null and dispatchOrderClass != ''">#{dispatchOrderClass},</if>
+ 			<if test="departureAddress != null and departureAddress != ''">#{departureAddress},</if>
+ 			<if test="departureLongitude != null">#{departureLongitude},</if>
+ 			<if test="departureLatitude != null">#{departureLatitude},</if>
  			<if test="createBy != null and createBy != ''">#{createBy},</if>
  			sysdate()
  		)
@@ -143,6 +160,9 @@
  			<if test="departmentId != null">department_id = #{departmentId},</if>
  			<if test="serviceOrderClass != null">service_order_class = #{serviceOrderClass},</if>
  			<if test="dispatchOrderClass != null">dispatch_order_class = #{dispatchOrderClass},</if>
+ 			<if test="departureAddress != null">departure_address = #{departureAddress},</if>
+ 			<if test="departureLongitude != null">departure_longitude = #{departureLongitude},</if>
+ 			<if test="departureLatitude != null">departure_latitude = #{departureLatitude},</if>
  			<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
  			update_time = sysdate()
  		</set>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskAdditionalFeeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskAdditionalFeeMapper.xml
new file mode 100644
index 0000000..8afa1e2
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskAdditionalFeeMapper.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysTaskAdditionalFeeMapper">
+    
+    <resultMap type="SysTaskAdditionalFee" id="SysTaskAdditionalFeeResult">
+        <result property="id" column="id" />
+        <result property="taskId" column="task_id" />
+        <result property="feeType" column="fee_type" />
+        <result property="feeName" column="fee_name" />
+        <result property="unitAmount" column="unit_amount" />
+        <result property="quantity" column="quantity" />
+        <result property="totalAmount" column="total_amount" />
+        <result property="remark" column="remark" />
+        <result property="createdBy" column="created_by" />
+        <result property="createdTime" column="created_time" />
+        <result property="pid" column="pid" />
+        <result property="syncStatus" column="sync_status" />
+        <result property="syncTime" column="sync_time" />
+    </resultMap>
+
+    <sql id="selectSysTaskAdditionalFeeVo">
+        select id, task_id, fee_type, fee_name, unit_amount, quantity, total_amount, remark, created_by, created_time, pid, sync_status, sync_time
+        from sys_task_additional_fee
+    </sql>
+
+    <select id="selectByTaskId" parameterType="Long" resultMap="SysTaskAdditionalFeeResult">
+        <include refid="selectSysTaskAdditionalFeeVo"/>
+        where task_id = #{taskId}
+        order by created_time desc
+    </select>
+
+    <insert id="insert" parameterType="SysTaskAdditionalFee" useGeneratedKeys="true" keyProperty="id">
+        insert into sys_task_additional_fee
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="taskId != null">task_id,</if>
+            <if test="feeType != null and feeType != ''">fee_type,</if>
+            <if test="feeName != null and feeName != ''">fee_name,</if>
+            <if test="unitAmount != null">unit_amount,</if>
+            <if test="quantity != null">quantity,</if>
+            <if test="totalAmount != null">total_amount,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createdBy != null and createdBy != ''">created_by,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="taskId != null">#{taskId},</if>
+            <if test="feeType != null and feeType != ''">#{feeType},</if>
+            <if test="feeName != null and feeName != ''">#{feeName},</if>
+            <if test="unitAmount != null">#{unitAmount},</if>
+            <if test="quantity != null">#{quantity},</if>
+            <if test="totalAmount != null">#{totalAmount},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createdBy != null and createdBy != ''">#{createdBy},</if>
+        </trim>
+    </insert>
+
+    <delete id="deleteById" parameterType="Long">
+        delete from sys_task_additional_fee where id = #{id}
+    </delete>
+
+    <delete id="deleteByTaskId" parameterType="Long">
+        delete from sys_task_additional_fee where task_id = #{taskId}
+    </delete>
+
+    <select id="selectByPid" parameterType="Long" resultMap="SysTaskAdditionalFeeResult">
+        <include refid="selectSysTaskAdditionalFeeVo"/>
+        where pid = #{pid}
+    </select>
+
+    <update id="updateSyncInfo">
+        update sys_task_additional_fee
+        set pid = #{pid},
+            sync_status = #{syncStatus},
+            sync_time = #{syncTime}
+        where id = #{id}
+    </update>
+
+    <select id="selectUnsyncedFees" resultMap="SysTaskAdditionalFeeResult">
+        <include refid="selectSysTaskAdditionalFeeVo"/>
+        where (sync_status = 0 or sync_status = 3 or sync_status is null)
+        order by id desc
+        limit 100
+    </select>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
index 3318e20..05675ce 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskEmergencyMapper.xml
@@ -44,6 +44,7 @@
         <result property="dispatchSyncStatus"      column="dispatch_sync_status"    />
         <result property="dispatchSyncTime"        column="dispatch_sync_time"      />
         <result property="dispatchSyncErrorMsg"    column="dispatch_sync_error_msg" />
+        <result property="needResync"              column="need_resync"             />
         <result property="createTime"              column="create_time"             />
         <result property="updateTime"              column="update_time"             />
         <result property="createBy"                column="create_by"               />
@@ -58,7 +59,7 @@
                hospital_in_department_id, hospital_in_bed_number, hospital_in_address, hospital_in_longitude, 
                hospital_in_latitude, transfer_distance, transfer_price, passenger_contact, 
                passenger_phone, disease_ids, document_type_id, task_type_id, legacy_service_ord_id, legacy_dispatch_ord_id, 
-               sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg,
+               sync_status, sync_time, sync_error_msg, dispatch_sync_status, dispatch_sync_time, dispatch_sync_error_msg, need_resync,
                create_time, update_time, create_by, update_by
         from sys_task_emergency
     </sql>
@@ -114,6 +115,7 @@
             <if test="dispatchSyncStatus != null">dispatch_sync_status,</if>
             <if test="dispatchSyncTime != null">dispatch_sync_time,</if>
             <if test="dispatchSyncErrorMsg != null">dispatch_sync_error_msg,</if>
+            <if test="needResync != null">need_resync,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateTime != null">update_time,</if>
             <if test="createBy != null">create_by,</if>
@@ -158,6 +160,7 @@
             <if test="dispatchSyncStatus != null">#{dispatchSyncStatus},</if>
             <if test="dispatchSyncTime != null">#{dispatchSyncTime},</if>
             <if test="dispatchSyncErrorMsg != null">#{dispatchSyncErrorMsg},</if>
+            <if test="needResync != null">#{needResync},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateTime != null">#{updateTime},</if>
             <if test="createBy != null">#{createBy},</if>
@@ -205,6 +208,7 @@
             <if test="dispatchSyncStatus != null">dispatch_sync_status = #{dispatchSyncStatus},</if>
             <if test="dispatchSyncTime != null">dispatch_sync_time = #{dispatchSyncTime},</if>
             <if test="dispatchSyncErrorMsg != null">dispatch_sync_error_msg = #{dispatchSyncErrorMsg},</if>
+            <if test="needResync != null">need_resync = #{needResync},</if>
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
         </trim>
@@ -297,5 +301,29 @@
         <include refid="selectSysTaskEmergencyVo"/>
         where legacy_dispatch_ord_id = #{legacyDispatchOrdId}
     </select>
+    
+    <!-- 鏌ヨ闇�瑕侀噸鏂板悓姝ョ殑浠诲姟锛堣溅杈嗘垨浜哄憳鍙樻洿锛� -->
+    <select id="selectNeedResyncTasks" resultMap="SysTaskEmergencyResult">
+        <include refid="selectSysTaskEmergencyVo"/>
+        where need_resync = 1
+          and dispatch_sync_status = 2 
+          and legacy_dispatch_ord_id is not null
+          and task_id in (
+              select task_id from sys_task 
+              where task_type = 'EMERGENCY_TRANSFER'
+                and task_status not in ('COMPLETED', 'CANCELLED')
+                and del_flag = '0'
+          )
+        order by id asc
+        <if test="offset != null and limit != null">
+            limit #{offset}, #{limit}
+        </if>
+        <if test="offset == null and limit != null">
+            limit #{limit}
+        </if>
+        <if test="offset == null and limit == null">
+            limit 100
+        </if>
+    </select>
 
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskPaymentMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskPaymentMapper.xml
new file mode 100644
index 0000000..f58b3ec
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskPaymentMapper.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysTaskPaymentMapper">
+    
+    <resultMap type="SysTaskPayment" id="SysTaskPaymentResult">
+        <result property="id" column="id" />
+        <result property="taskId" column="task_id" />
+        <result property="totalAmount" column="total_amount" />
+        <result property="settlementAmount" column="settlement_amount" />
+        <result property="paymentMethod" column="payment_method" />
+        <result property="payStatus" column="pay_status" />
+        <result property="payTime" column="pay_time" />
+        <result property="outTradeNo" column="out_trade_no" />
+        <result property="tradeNo" column="trade_no" />
+        <result property="codeUrl" column="code_url" />
+        <result property="qrExpireTime" column="qr_expire_time" />
+        <result property="provider" column="provider" />
+        <result property="paymentRefId" column="payment_ref_id" />
+        <result property="callbackUrl" column="callback_url" />
+        <result property="remark" column="remark" />
+        <result property="createdBy" column="created_by" />
+        <result property="createdTime" column="created_time" />
+        <result property="updateTime" column="update_time" />
+        <result property="pid" column="pid" />
+        <result property="syncStatus" column="sync_status" />
+        <result property="syncTime" column="sync_time" />
+    </resultMap>
+
+    <sql id="selectSysTaskPaymentVo">
+        select id, task_id, total_amount, settlement_amount, payment_method, pay_status, pay_time, 
+               out_trade_no, trade_no, code_url, qr_expire_time, provider, payment_ref_id, callback_url,
+               remark, created_by, created_time, update_time, pid, sync_status, sync_time
+        from sys_task_payment
+    </sql>
+
+    <select id="selectLatestPaidByTaskId" parameterType="Long" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where task_id = #{taskId} and pay_status = 'PAID'
+        order by pay_time desc
+        limit 1
+    </select>
+
+    <select id="selectAllPaidByTaskId" parameterType="Long" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where task_id = #{taskId} and pay_status = 'PAID'
+        order by pay_time desc
+    </select>
+
+    <select id="selectByTaskId" parameterType="Long" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where task_id = #{taskId}
+        order by created_time desc
+    </select>
+
+    <select id="selectById" parameterType="Long" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectByOutTradeNo" parameterType="String" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where out_trade_no = #{outTradeNo}
+    </select>
+
+    <insert id="insert" parameterType="SysTaskPayment" useGeneratedKeys="true" keyProperty="id">
+        insert into sys_task_payment
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="taskId != null">task_id,</if>
+            <if test="totalAmount != null">total_amount,</if>
+            <if test="settlementAmount != null">settlement_amount,</if>
+            <if test="paymentMethod != null and paymentMethod != ''">payment_method,</if>
+            <if test="payStatus != null and payStatus != ''">pay_status,</if>
+            <if test="payTime != null">pay_time,</if>
+            <if test="outTradeNo != null and outTradeNo != ''">out_trade_no,</if>
+            <if test="tradeNo != null and tradeNo != ''">trade_no,</if>
+            <if test="codeUrl != null and codeUrl != ''">code_url,</if>
+            <if test="qrExpireTime != null">qr_expire_time,</if>
+            <if test="provider != null and provider != ''">provider,</if>
+            <if test="paymentRefId != null and paymentRefId != ''">payment_ref_id,</if>
+            <if test="callbackUrl != null and callbackUrl != ''">callback_url,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createdBy != null and createdBy != ''">created_by,</if>
+            <if test="createdTime != null">created_time,</if>
+            <if test="pid != null">pid,</if>
+            <if test="syncStatus != null">sync_status,</if>
+            <if test="syncTime != null">sync_time,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="taskId != null">#{taskId},</if>
+            <if test="totalAmount != null">#{totalAmount},</if>
+            <if test="settlementAmount != null">#{settlementAmount},</if>
+            <if test="paymentMethod != null and paymentMethod != ''">#{paymentMethod},</if>
+            <if test="payStatus != null and payStatus != ''">#{payStatus},</if>
+            <if test="payTime != null">#{payTime},</if>
+            <if test="outTradeNo != null and outTradeNo != ''">#{outTradeNo},</if>
+            <if test="tradeNo != null and tradeNo != ''">#{tradeNo},</if>
+            <if test="codeUrl != null and codeUrl != ''">#{codeUrl},</if>
+            <if test="qrExpireTime != null">#{qrExpireTime},</if>
+            <if test="provider != null and provider != ''">#{provider},</if>
+            <if test="paymentRefId != null and paymentRefId != ''">#{paymentRefId},</if>
+            <if test="callbackUrl != null and callbackUrl != ''">#{callbackUrl},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createdBy != null and createdBy != ''">#{createdBy},</if>
+            <if test="createdTime != null">#{createdTime},</if>
+            <if test="pid != null">#{pid},</if>
+            <if test="syncStatus != null">#{syncStatus},</if>
+            <if test="syncTime != null">#{syncTime},</if>
+        </trim>
+    </insert>
+
+    <update id="update" parameterType="SysTaskPayment">
+        update sys_task_payment
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="payStatus != null and payStatus != ''">pay_status = #{payStatus},</if>
+            <if test="payTime != null">pay_time = #{payTime},</if>
+            <if test="tradeNo != null and tradeNo != ''">trade_no = #{tradeNo},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            update_time = now(),
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="updatePayStatus">
+        update sys_task_payment
+        set pay_status = #{payStatus},
+            <if test="tradeNo != null and tradeNo != ''">trade_no = #{tradeNo},</if>
+            pay_time = now(),
+            update_time = now()
+        where id = #{id}
+    </update>
+
+    <select id="selectByPid" parameterType="Long" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where pid = #{pid}
+    </select>
+
+    <update id="updateSyncInfo">
+        update sys_task_payment
+        set pid = #{pid},
+            sync_status = #{syncStatus},
+            sync_time = #{syncTime},
+            update_time = now()
+        where id = #{id}
+    </update>
+
+    <select id="selectUnsyncedPaidPayments" resultMap="SysTaskPaymentResult">
+        <include refid="selectSysTaskPaymentVo"/>
+        where pay_status = 'PAID'
+          and (sync_status = 0 or sync_status = 3 or sync_status is null)
+        order by id desc
+        limit 100
+    </select>
+
+</mapper>
diff --git a/ruoyi-ui/src/api/task.js b/ruoyi-ui/src/api/task.js
index f269b23..ce09668 100644
--- a/ruoyi-ui/src/api/task.js
+++ b/ruoyi-ui/src/api/task.js
@@ -1,5 +1,7 @@
 import request from '@/utils/request'
 
+// ========== 浠诲姟绠$悊鐩稿叧API ==========
+
 // 鏌ヨ浠诲姟绠$悊鍒楄〃 (鍚庡彴绠$悊绔�)
 export function listTask(query) {
   return request({
@@ -244,4 +246,33 @@
     method: 'put',
     params: { status }
   })
+}
+
+// ========== 浠诲姟鏀粯鐩稿叧API ==========
+
+// 鑾峰彇浠诲姟鏀粯淇℃伅
+export function getPaymentInfo(taskId) {
+  return request({
+    url: '/task/payment/info',
+    method: 'get',
+    params: { taskId }
+  })
+}
+
+// 鏌ヨ浠诲姟鐨勯檮鍔犺垂鐢ㄥ垪琛�
+export function getAdditionalFees(taskId) {
+  return request({
+    url: '/task/payment/info',
+    method: 'get',
+    params: { taskId }
+  })
+}
+
+// 鏌ヨ浠诲姟鐨勬渶鏂版敮浠樿褰�
+export function getLatestPayment(taskId) {
+  return request({
+    url: '/task/payment/info',
+    method: 'get',
+    params: { taskId }
+  })
 }
\ No newline at end of file
diff --git a/ruoyi-ui/src/views/task/detail/index.vue b/ruoyi-ui/src/views/task/detail/index.vue
index 90d608e..801568c 100644
--- a/ruoyi-ui/src/views/task/detail/index.vue
+++ b/ruoyi-ui/src/views/task/detail/index.vue
@@ -28,12 +28,62 @@
 
     <!-- GPS閲岀▼缁熻缁勪欢 -->
     <task-mileage-detail v-if="taskInfo.taskId" :task-id="taskInfo.taskId" />
+    
+    <!-- 鏀粯淇℃伅鍗$墖 -->
+    <el-card v-if="showPaymentInfo && paymentInfo" class="box-card" style="margin-top: 20px;" shadow="hover">
+      <div slot="header" class="clearfix">
+        <span><i class="el-icon-wallet"></i> 鏀粯淇℃伅</span>
+      </div>
+      
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="鎴愪氦浠�">楼{{ paymentInfo.transferPrice || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="闄勫姞璐圭敤">楼{{ paymentInfo.additionalAmount || 0 }}</el-descriptions-item>
+        <el-descriptions-item label="鎬婚噾棰�">
+          <span style="color: #e54d42; font-weight: bold; font-size: 16px;">楼{{ paymentInfo.totalAmount || 0 }}</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="鏀粯鐘舵��" v-if="paymentInfo.latestPayment">
+          <el-tag :type="getPaymentStatusType(paymentInfo.latestPayment.payStatus)">
+            {{ getPaymentStatusText(paymentInfo.latestPayment.payStatus) }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="鏀粯鐘舵��" v-else>
+          <el-tag type="info">鏈敮浠�</el-tag>
+        </el-descriptions-item>
+        <template v-if="paymentInfo.latestPayment">
+          <el-descriptions-item label="鏀粯鏂瑰紡">{{ getPaymentMethodText(paymentInfo.latestPayment.paymentMethod) }}</el-descriptions-item>
+          <el-descriptions-item label="缁撶畻閲戦">楼{{ paymentInfo.latestPayment.settlementAmount }}</el-descriptions-item>
+          <el-descriptions-item label="浜ゆ槗鍙�" v-if="paymentInfo.latestPayment.tradeNo">{{ paymentInfo.latestPayment.tradeNo }}</el-descriptions-item>
+          <el-descriptions-item label="鏀粯鏃堕棿" v-if="paymentInfo.latestPayment.payTime">{{ paymentInfo.latestPayment.payTime }}</el-descriptions-item>
+        </template>
+      </el-descriptions>
+      
+      <!-- 闄勫姞璐圭敤鏄庣粏 -->
+      <div v-if="paymentInfo.additionalFees && paymentInfo.additionalFees.length > 0" style="margin-top: 20px;">
+        <el-divider content-position="left">闄勫姞璐圭敤鏄庣粏</el-divider>
+        <el-table :data="paymentInfo.additionalFees" border style="width: 100%">
+          <el-table-column prop="feeName" label="璐圭敤鍚嶇О" width="150" />
+          <el-table-column prop="unitAmount" label="鍗曚环" width="100">
+            <template slot-scope="scope">
+              楼{{ scope.row.unitAmount }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="quantity" label="鏁伴噺" width="80" />
+          <el-table-column prop="totalAmount" label="灏忚" width="100">
+            <template slot-scope="scope">
+              楼{{ scope.row.totalAmount }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="remark" label="澶囨敞" show-overflow-tooltip />
+        </el-table>
+      </div>
+    </el-card>
   </div>
 </template>
 
 <script>
 import TaskMileageDetail from '@/components/TaskMileageDetail'
 import { getTask } from '@/api/task'
+import { getPaymentInfo } from '@/api/task'
 
 export default {
   name: 'TaskDetail',
@@ -46,6 +96,7 @@
         taskId: null,
         taskCode: '',
         taskStatus: '',
+        taskType: '',
         vehicleNo: '',
         assigneeName: '',
         plannedStartTime: '',
@@ -54,13 +105,16 @@
         actualEndTime: '',
         departureAddress: '',
         destinationAddress: ''
-      }
+      },
+      paymentInfo: null,
+      showPaymentInfo: false
     }
   },
   created() {
     const taskId = this.$route.params && this.$route.params.taskId
     if (taskId) {
       this.loadTaskInfo(taskId)
+      this.loadPaymentInfo(taskId)
     }
   },
   methods: {
@@ -68,6 +122,19 @@
     loadTaskInfo(taskId) {
       getTask(taskId).then(response => {
         this.taskInfo = response.data
+        // 鍙湁杞繍浠诲姟鎵嶆樉绀烘敮浠樹俊鎭�
+        this.showPaymentInfo = this.taskInfo.taskType === 'EMERGENCY_TRANSFER'
+      })
+    },
+    
+    /** 鍔犺浇鏀粯淇℃伅 */
+    loadPaymentInfo(taskId) {
+      getPaymentInfo(taskId).then(response => {
+        if (response.code === 200) {
+          this.paymentInfo = response.data
+        }
+      }).catch(error => {
+        console.error('鍔犺浇鏀粯淇℃伅澶辫触:', error)
       })
     },
     
@@ -100,6 +167,41 @@
         'CANCELLED': '宸插彇娑�'
       }
       return statusMap[status] || status
+    },
+    
+    /** 鑾峰彇鏀粯鐘舵�佺被鍨� */
+    getPaymentStatusType(status) {
+      const typeMap = {
+        'UNPAID': 'info',
+        'PENDING': 'warning',
+        'PAID': 'success',
+        'FAILED': 'danger',
+        'REFUNDED': 'info'
+      }
+      return typeMap[status] || 'info'
+    },
+    
+    /** 鑾峰彇鏀粯鐘舵�佹枃鏈� */
+    getPaymentStatusText(status) {
+      const textMap = {
+        'UNPAID': '鏈敮浠�',
+        'PENDING': '鏀粯涓�',
+        'PAID': '宸叉敮浠�',
+        'FAILED': '鏀粯澶辫触',
+        'REFUNDED': '宸查��娆�'
+      }
+      return textMap[status] || status
+    },
+    
+    /** 鑾峰彇鏀粯鏂瑰紡鏂囨湰 */
+    getPaymentMethodText(method) {
+      const methodMap = {
+        'CASH': '鐜伴噾鏀粯',
+        'ON_ACCOUNT': '鎸傝处鏀粯',
+        'WECHAT': '寰俊鏀粯',
+        'ALIPAY': '鏀粯瀹濇敮浠�'
+      }
+      return methodMap[method] || method
     }
   }
 }
diff --git a/sql/PaidMoney.sql b/sql/PaidMoney.sql
new file mode 100644
index 0000000..d42bb8c
--- /dev/null
+++ b/sql/PaidMoney.sql
@@ -0,0 +1,16 @@
+create table PaidMoney(
+id	int	no	4	10   	0    	no	(n/a)	(n/a)	NULL
+PaidMoneyClass	comment "榛樿FI",
+ServiceOrdIDDt	bigint	comment "ServiceOrderID",
+DispatchOrdIDDt	bigint	comment "DispatchOrderID",
+PaidMoney	money	comment "閲戦",
+PaidMoneyType	int	comment "鏀粯绫诲瀷",
+PaidMoneyMono	nvarchar	comment "鐢ㄦ潵瀛樻斁鏀粯鍗曞彿,鏍煎紡锛氫氦鏄撴祦姘碵鏀粯涓撶敤]",
+PaidMoneyTime	datetime	comment "鏀粯鏃堕棿",
+PaidMoneyOaID	int	comment "鏀粯浜篛AID",
+PaidMoneyUnitID	int	comment "榛樿涓�0"
+PaidMoney_AP_ID	int	comment "纭ID",
+PaidMoney_AP_Time	datetime	comment "纭鏃堕棿"
+PaidMoney_AP_Check	int	comment "纭鐘舵�� 1琛ㄧず宸茬‘璁わ紝0琛ㄧず鏈‘璁�",
+PaidMoneyTimestamp	nvarchar comment "纭鏃堕棿鎴�",
+)
\ No newline at end of file
diff --git a/sql/PaidMoney_Add.sql b/sql/PaidMoney_Add.sql
new file mode 100644
index 0000000..529e77c
--- /dev/null
+++ b/sql/PaidMoney_Add.sql
@@ -0,0 +1,12 @@
+create table PaidMoney_Add
+(
+id	int	no	4	10   	0    	no	(n/a)	(n/a)	NULL
+ToServiceOrdID	bigint	comment '鏈嶅姟鍗旾D',
+ToDispatchOrdID	bigint	comment '璋冨害鍗旾D',
+AddMoneyType	int	comment '闄勫姞璐圭敤绫诲瀷',
+AddMoney	money	comment '闄勫姞璐圭敤',
+AddMoneyExplain	nvarchar	comment '闄勫姞璐圭敤璇存槑',
+AddMoneyTime	datetime	comment '闄勫姞璐圭敤鏃堕棿',
+AddMoneyOAID	int	comment '娣诲姞鐢ㄦ埛鐨凮AID',
+
+)
\ No newline at end of file
diff --git a/sql/add_emergency_resync_flag.sql b/sql/add_emergency_resync_flag.sql
new file mode 100644
index 0000000..cab9f3f
--- /dev/null
+++ b/sql/add_emergency_resync_flag.sql
@@ -0,0 +1,9 @@
+-- 涓簊ys_task_emergency琛ㄦ坊鍔爊eed_resync瀛楁
+-- 鐢ㄤ簬鏍囪杞﹁締鎴栦汉鍛樹慨鏀瑰悗闇�瑕侀噸鏂板悓姝ュ埌鏃х郴缁�
+
+ALTER TABLE sys_task_emergency 
+ADD COLUMN need_resync TINYINT(1) DEFAULT 0 COMMENT '鏄惁闇�瑕侀噸鏂板悓姝ワ細0-涓嶉渶瑕侊紝1-闇�瑕侀噸鏂板悓姝ワ紙杞﹁締鎴栦汉鍛樺彉鏇达級';
+
+-- 娣诲姞绱㈠紩浠ヤ紭鍖栨煡璇㈤渶瑕侀噸鏂板悓姝ョ殑浠诲姟
+ALTER TABLE sys_task_emergency 
+ADD INDEX idx_need_resync (need_resync, dispatch_sync_status);
diff --git a/sql/additional_fee_sync_update.sql b/sql/additional_fee_sync_update.sql
new file mode 100644
index 0000000..300c18c
--- /dev/null
+++ b/sql/additional_fee_sync_update.sql
@@ -0,0 +1,34 @@
+-- 闄勫姞璐圭敤鍚屾鍔熻兘 - 鏁版嵁琛ㄥ彉鏇�
+-- 浣滆��: ruoyi
+-- 鏃ユ湡: 2025-01-15
+
+-- =============================================
+-- 1. 淇敼鏂扮郴缁� sys_task_additional_fee 琛紝娣诲姞鍚屾鐩稿叧瀛楁
+-- =============================================
+ALTER TABLE sys_task_additional_fee ADD COLUMN pid BIGINT COMMENT '鏃х郴缁熼檮鍔犺垂鐢ㄨ褰旾D(PaidMoney_Add.id)' AFTER created_time;
+ALTER TABLE sys_task_additional_fee ADD COLUMN sync_status INT DEFAULT 0 COMMENT '鍚屾鐘舵�侊細0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触' AFTER pid;
+ALTER TABLE sys_task_additional_fee ADD COLUMN sync_time DATETIME COMMENT '鍚屾鏃堕棿' AFTER sync_status;
+
+-- 涓簆id瀛楁娣诲姞绱㈠紩锛屾彁楂樻煡璇㈡晥鐜�
+CREATE INDEX idx_pid ON sys_task_additional_fee(pid);
+
+-- 涓簊ync_status瀛楁娣诲姞绱㈠紩锛岀敤浜庢壒閲忓悓姝ユ煡璇�
+CREATE INDEX idx_sync_status ON sys_task_additional_fee(sync_status);
+
+-- =============================================
+-- 璇存槑锛�
+-- =============================================
+-- 1. pid: 瀛樺偍鏃х郴缁烶aidMoney_Add琛ㄧ殑涓婚敭ID锛岀敤浜庡弻鍚戝叧鑱�
+-- 2. sync_status: 鍚屾鐘舵�佹爣璇�
+--    - 0: 鏈悓姝� - 鏂板垱寤虹殑闄勫姞璐圭敤璁板綍锛屽皻鏈悓姝ュ埌鏃х郴缁�
+--    - 1: 鍚屾涓� - 姝e湪鎵ц鍚屾鎿嶄綔
+--    - 2: 鍚屾鎴愬姛 - 宸叉垚鍔熷悓姝ュ埌鏃х郴缁�
+--    - 3: 鍚屾澶辫触 - 鍚屾杩囩▼涓彂鐢熼敊璇�
+-- 3. sync_time: 璁板綍鏈�鍚庝竴娆″悓姝ユ搷浣滅殑鏃堕棿
+--
+-- 鍚屾閫昏緫锛�
+-- - 鏂扮郴缁� -> 鏃х郴缁燂細鏂扮郴缁熸坊鍔犻檮鍔犺垂鐢ㄥ悗锛岃嚜鍔ㄥ悓姝ュ埌鏃х郴缁烶aidMoney_Add琛�
+-- - 鏃х郴缁� -> 鏂扮郴缁燂細瀹氭椂浠诲姟浠庢棫绯荤粺PaidMoney_Add琛ㄥ悓姝ユ渶鏂伴檮鍔犺垂鐢ㄨ褰曞埌鏂扮郴缁�
+-- - 閫氳繃ToServiceOrdID鍜孴oDispatchOrdID瀛楁鍏宠仈浠诲姟
+-- - 璐圭敤绫诲瀷鏄犲皠锛�
+--   鏂扮郴缁熷瓧鍏稿��(1-绛夊緟璐�, 2-鎷呮灦, 3-灞呭ICU, 4-鍖荤枟璁惧) <-> 鏃х郴缁烝ddMoneyType(1,2,3,4)
diff --git a/sql/dryad_payment_tables.sql b/sql/dryad_payment_tables.sql
new file mode 100644
index 0000000..a879875
--- /dev/null
+++ b/sql/dryad_payment_tables.sql
@@ -0,0 +1,126 @@
+-- dryad-payment 鏀粯妯″潡鏁版嵁琛�
+-- 鍦ㄤ富鏁版嵁搴� 966120 涓垱寤烘敮浠樻ā鍧楁墍闇�鐨勮〃
+
+USE `966120`;
+
+-- 鏀粯璁㈠崟琛�
+CREATE TABLE IF NOT EXISTS `pay_order` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '璁㈠崟ID',
+  `biz_order_id` VARCHAR(64) NOT NULL COMMENT '涓氬姟璁㈠崟鍙�',
+  `amount` INT NOT NULL COMMENT '閲戦锛堝垎锛�',
+  `currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '甯佺',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `status` VARCHAR(16) NOT NULL COMMENT '璁㈠崟鐘舵��',
+  `subject` VARCHAR(128) NOT NULL COMMENT '璁㈠崟鏍囬',
+  `description` VARCHAR(512) COMMENT '璁㈠崟鎻忚堪',
+  `callback_url` VARCHAR(512) NOT NULL COMMENT '涓氬姟鍥炶皟鍦板潃',
+  `expire_at` DATETIME NOT NULL COMMENT '杩囨湡鏃堕棿',
+  `latest_transaction_id` BIGINT COMMENT '鏈�鏂颁氦鏄揑D',
+  `channel_trade_no` VARCHAR(64) COMMENT '娓犻亾浜ゆ槗鍙�',
+  `paid_at` DATETIME COMMENT '鏀粯鎴愬姛鏃堕棿',
+  `version` INT NOT NULL DEFAULT 0 COMMENT '涔愯閿佺増鏈彿',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  `updated_at` DATETIME NOT NULL COMMENT '鏇存柊鏃堕棿',
+  INDEX `idx_biz_order_id` (`biz_order_id`),
+  INDEX `idx_channel_trade_no` (`channel_trade_no`),
+  INDEX `idx_status` (`status`),
+  INDEX `idx_expire_at` (`expire_at`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鏀粯璁㈠崟琛�';
+
+-- 鏀粯浜ゆ槗娴佹按琛�
+CREATE TABLE IF NOT EXISTS `pay_transaction` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '浜ゆ槗ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `client_type` VARCHAR(32) NOT NULL COMMENT '瀹㈡埛绔被鍨�',
+  `status` VARCHAR(16) NOT NULL COMMENT '浜ゆ槗鐘舵��',
+  `code_or_qr` VARCHAR(512) COMMENT '浜岀淮鐮佸唴瀹�',
+  `qr_base64` TEXT COMMENT 'Base64浜岀淮鐮佸浘鐗�',
+  `request_params` TEXT COMMENT '璇锋眰鍙傛暟蹇収',
+  `response_snapshot` TEXT COMMENT '鍝嶅簲蹇収',
+  `channel_trade_no` VARCHAR(64) COMMENT '娓犻亾浜ゆ槗鍙�',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  `paid_at` DATETIME COMMENT '鏀粯瀹屾垚鏃堕棿',
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_channel_trade_no` (`channel_trade_no`),
+  INDEX `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鏀粯浜ゆ槗娴佹按琛�';
+
+-- 娓犻亾鍥炶皟鏃ュ織琛�
+CREATE TABLE IF NOT EXISTS `pay_notify_log` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏃ュ織ID',
+  `channel` VARCHAR(16) NOT NULL COMMENT '鏀粯娓犻亾',
+  `notify_id_or_serial` VARCHAR(64) NOT NULL COMMENT '娓犻亾閫氱煡鍞竴鏍囪瘑',
+  `order_id` BIGINT COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `payload` TEXT NOT NULL COMMENT '鍥炶皟鍘熷鎶ユ枃',
+  `verified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '绛惧悕楠岃瘉鏄惁閫氳繃',
+  `processed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁宸插鐞�',
+  `result` VARCHAR(128) COMMENT '澶勭悊缁撴灉',
+  `created_at` DATETIME NOT NULL COMMENT '鎺ユ敹鏃堕棿',
+  UNIQUE KEY `uk_channel_notify` (`channel`, `notify_id_or_serial`),
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_transaction_id` (`transaction_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='娓犻亾鍥炶皟鏃ュ織琛�';
+
+-- 涓氬姟鍥炶皟鏃ュ織琛�
+CREATE TABLE IF NOT EXISTS `pay_biz_callback_log` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏃ュ織ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT NOT NULL COMMENT '浜ゆ槗ID',
+  `callback_url` VARCHAR(512) NOT NULL COMMENT '鍥炶皟鍦板潃',
+  `payload` TEXT NOT NULL COMMENT '鍥炶皟璇锋眰浣�',
+  `http_status` INT COMMENT 'HTTP鐘舵�佺爜',
+  `response` TEXT COMMENT '鍝嶅簲鍐呭',
+  `success` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁鎴愬姛',
+  `retry_count` INT NOT NULL DEFAULT 0 COMMENT '閲嶈瘯娆℃暟',
+  `last_retry_at` DATETIME COMMENT '鏈�鍚庨噸璇曟椂闂�',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  INDEX `idx_order_id` (`order_id`),
+  INDEX `idx_success` (`success`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='涓氬姟鍥炶皟鏃ュ織琛�';
+
+-- 鎿嶄綔瀹¤琛�
+CREATE TABLE IF NOT EXISTS `pay_operation_audit` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '瀹¤ID',
+  `operator` VARCHAR(64) NOT NULL COMMENT '鎿嶄綔浜�',
+  `operation_type` VARCHAR(32) NOT NULL COMMENT '鎿嶄綔绫诲瀷',
+  `order_id` BIGINT COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `params` TEXT COMMENT '鎿嶄綔鍙傛暟',
+  `approved` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '鏄惁閫氳繃',
+  `created_at` DATETIME NOT NULL COMMENT '鎿嶄綔鏃堕棿',
+  INDEX `idx_operator` (`operator`),
+  INDEX `idx_operation_type` (`operation_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鎿嶄綔瀹¤琛�';
+
+-- 瀵硅处浠诲姟琛�
+CREATE TABLE IF NOT EXISTS `pay_reconciliation_task` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '浠诲姟ID',
+  `task_date` DATE NOT NULL COMMENT '瀵硅处鏃ユ湡',
+  `status` VARCHAR(16) NOT NULL COMMENT '浠诲姟鐘舵��',
+  `total_count` INT NOT NULL DEFAULT 0 COMMENT '鎬昏鍗曟暟',
+  `success_count` INT NOT NULL DEFAULT 0 COMMENT '鎴愬姛鏁�',
+  `failed_count` INT NOT NULL DEFAULT 0 COMMENT '澶辫触鏁�',
+  `diff_count` INT NOT NULL DEFAULT 0 COMMENT '宸紓鏁�',
+  `fixed_count` INT NOT NULL DEFAULT 0 COMMENT '鑷姩淇鏁�',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  `finished_at` DATETIME COMMENT '瀹屾垚鏃堕棿',
+  UNIQUE KEY `uk_task_date` (`task_date`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀵硅处浠诲姟琛�';
+
+-- 瀵硅处宸紓鏄庣粏琛�
+CREATE TABLE IF NOT EXISTS `pay_reconciliation_result` (
+  `id` BIGINT NOT NULL PRIMARY KEY COMMENT '鏄庣粏ID',
+  `task_id` BIGINT NOT NULL COMMENT '浠诲姟ID',
+  `order_id` BIGINT NOT NULL COMMENT '璁㈠崟ID',
+  `transaction_id` BIGINT COMMENT '浜ゆ槗ID',
+  `local_status` VARCHAR(16) COMMENT '鏈湴鐘舵��',
+  `channel_status` VARCHAR(16) COMMENT '娓犻亾鐘舵��',
+  `diff_type` VARCHAR(32) NOT NULL COMMENT '宸紓绫诲瀷',
+  `fixed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '鏄惁宸蹭慨澶�',
+  `note` VARCHAR(512) COMMENT '澶囨敞',
+  `created_at` DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+  INDEX `idx_task_id` (`task_id`),
+  INDEX `idx_order_id` (`order_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='瀵硅处宸紓鏄庣粏琛�';
diff --git a/sql/payment_sync_job.sql b/sql/payment_sync_job.sql
new file mode 100644
index 0000000..cca2113
--- /dev/null
+++ b/sql/payment_sync_job.sql
@@ -0,0 +1,113 @@
+-- 鏀粯淇℃伅鍜岄檮鍔犺垂鐢ㄥ悓姝ュ畾鏃朵换鍔¢厤缃甋QL
+-- 鍦╯ys_job琛ㄤ腑娣诲姞瀹氭椂浠诲姟
+
+-- 1. 鏀粯淇℃伅鍚屾锛堟柊绯荤粺 -> 鏃х郴缁燂級
+INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark)
+VALUES 
+('鏀粯淇℃伅鍚屾鍒版棫绯荤粺', 'DEFAULT', 'legacySystemSyncTask.syncPaymentToLegacy', '0 0/10 * * * ?', '3', '1', '0', 'admin', sysdate(), 
+'姣�10鍒嗛挓鑷姩鍚屾鏂扮郴缁熸湭鍚屾鐨勬敮浠樻垚鍔熻褰曞埌鏃х郴缁烶aidMoney琛ㄣ�傚悓姝ユ潯浠讹細pay_status=PAID涓攕ync_status=0鎴�3銆�');
+
+-- 2. 鏀粯淇℃伅鍙嶅悜鍚屾锛堟棫绯荤粺 -> 鏂扮郴缁燂級
+INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark)
+VALUES 
+('鏀粯淇℃伅浠庢棫绯荤粺鍚屾', 'DEFAULT', 'legacySystemSyncTask.syncPaymentFromLegacy', '0 0/15 * * * ?', '3', '1', '0', 'admin', sysdate(), 
+'姣�15鍒嗛挓鑷姩鍚屾鏃х郴缁烶aidMoney琛ㄦ渶杩�7澶╃殑鏀粯璁板綍鍒版柊绯荤粺銆傚彧鍚屾鍦ㄦ柊绯荤粺涓瓨鍦ㄥ搴旇浆杩愪换鍔★紙ServiceOrdID鍜孌ispatchOrdID鍖归厤锛夌殑璁板綍銆�');
+
+-- 3. 闄勫姞璐圭敤鍚屾锛堟柊绯荤粺 -> 鏃х郴缁燂級
+INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark)
+VALUES 
+('闄勫姞璐圭敤鍚屾鍒版棫绯荤粺', 'DEFAULT', 'legacySystemSyncTask.syncAdditionalFeeToLegacy', '0 0/10 * * * ?', '3', '1', '0', 'admin', sysdate(), 
+'姣�10鍒嗛挓鑷姩鍚屾鏂扮郴缁熸湭鍚屾鐨勯檮鍔犺垂鐢ㄨ褰曞埌鏃х郴缁烶aidMoney_Add琛ㄣ�傚悓姝ユ潯浠讹細sync_status=0鎴�3銆�');
+
+-- 4. 闄勫姞璐圭敤鍙嶅悜鍚屾锛堟棫绯荤粺 -> 鏂扮郴缁燂級
+INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark)
+VALUES 
+('闄勫姞璐圭敤浠庢棫绯荤粺鍚屾', 'DEFAULT', 'legacySystemSyncTask.syncAdditionalFeeFromLegacy', '0 0/15 * * * ?', '3', '1', '0', 'admin', sysdate(), 
+'姣�15鍒嗛挓鑷姩鍚屾鏃х郴缁烶aidMoney_Add琛ㄦ渶杩�24灏忔椂鐨勯檮鍔犺垂鐢ㄨ褰曞埌鏂扮郴缁熴�傚彧鍚屾鍦ㄦ柊绯荤粺涓瓨鍦ㄥ搴旇浆杩愪换鍔★紙ServiceOrdID鍜孌ispatchOrdID鍖归厤锛夌殑璁板綍銆�');
+
+-- 璇存槑锛�
+-- job_name: 浠诲姟鍚嶇О
+-- job_group: 浠诲姟缁勫悕锛圖EFAULT涓洪粯璁ょ粍锛�
+-- invoke_target: 璋冪敤鐩爣瀛楃涓诧紙Bean鍚嶇О.鏂规硶鍚嶏級
+--   鏀粯鍚屾鏂规硶锛�
+--   - legacySystemSyncTask.syncPaymentToLegacy() 鏂扮郴缁� -> 鏃х郴缁�
+--   - legacySystemSyncTask.syncPaymentFromLegacy() 鏃х郴缁� -> 鏂扮郴缁�
+--   闄勫姞璐圭敤鍚屾鏂规硶锛�
+--   - legacySystemSyncTask.syncAdditionalFeeToLegacy() 鏂扮郴缁� -> 鏃х郴缁�
+--   - legacySystemSyncTask.syncAdditionalFeeFromLegacy() 鏃х郴缁� -> 鏂扮郴缁�
+-- 
+-- cron_expression: cron琛ㄨ揪寮�
+--   - '0 0/10 * * * ?' = 姣�10鍒嗛挓鎵ц涓�娆★紙鎺ㄨ崘鐢ㄤ簬鏂扮郴缁熷埌鏃х郴缁熺殑鍚屾锛�
+--   - '0 0/15 * * * ?' = 姣�15鍒嗛挓鎵ц涓�娆★紙鎺ㄨ崘鐢ㄤ簬鏃х郴缁熷埌鏂扮郴缁熺殑鍚屾锛�
+--   - '0 0/5 * * * ?' = 姣�5鍒嗛挓鎵ц涓�娆★紙浠呭湪鍚屾瑕佹眰楂樻椂浣跨敤锛�
+--   - '0 0/30 * * * ?' = 姣�30鍒嗛挓鎵ц涓�娆�
+-- 
+-- misfire_policy: 閿欒繃鎵ц绛栫暐
+--   - 1=绔嬪嵆鎵ц
+--   - 2=鎵ц涓�娆�
+--   - 3=鏀惧純鎵ц锛堟帹鑽愶級
+-- 
+-- concurrent: 鏄惁骞跺彂
+--   - 0=鍏佽骞跺彂
+--   - 1=绂佹骞跺彂锛堟帹鑽愶紝閬垮厤閲嶅鍚屾鍜屾暟鎹啿绐侊級
+-- 
+-- status: 鐘舵��
+--   - 0=姝e父锛堝惎鐢級
+--   - 1=鏆傚仠锛堝仠鐢級
+
+-- 浣跨敤寤鸿锛�
+-- 1. 鏂扮郴缁熷埌鏃х郴缁熷悓姝ワ紙10鍒嗛挓锛夛細
+--    - 鐢ㄦ埛鎿嶄綔鍚庨渶蹇�熷悓姝ュ埌鏃х郴缁熶緵鍏朵粬涓氬姟浣跨敤
+--    - 鏈悓姝ヨ褰曚細鑷姩閲嶈瘯
+-- 
+-- 2. 鏃х郴缁熷埌鏂扮郴缁熷悓姝ワ紙15鍒嗛挓锛夛細
+--    - 浠呭悓姝ュ瓨鍦ㄥ搴旇浆杩愪换鍔$殑璁板綍锛堥獙璇丼erviceOrdID鍜孌ispatchOrdID锛�
+--    - 鏀粯璁板綍鏌ヨ鏈�杩�7澶�
+--    - 闄勫姞璐圭敤鏌ヨ鏈�杩�24灏忔椂
+--    - 閬垮厤鍚屾鏃犳晥鐨勫绔嬫暟鎹�
+-- 
+-- 3. 鎬ц兘浼樺寲锛�
+--    - 姣忔壒娆¢檺鍒�100鏉¤褰�
+--    - 姣忔潯璁板綍闂撮殧1绉�
+--    - 绂佹骞跺彂鎵ц
+-- 
+-- 4. 鐩戞帶寤鸿锛�
+--    - 瀹氭湡妫�鏌ync_status=3鐨勫け璐ヨ褰�
+--    - 鏌ョ湅瀹氭椂浠诲姟鎵ц鏃ュ織
+--    - 鐩戞帶鍚屾鑰楁椂鍜屾垚鍔熺巼
+
+-- 鐩戞帶鏌ヨ绀轰緥锛�
+
+-- 鏌ョ湅鏀粯璁板綍鍚屾鐘舵�侊細
+-- SELECT 
+--     sync_status,
+--     CASE sync_status
+--         WHEN 0 THEN '鏈悓姝�'
+--         WHEN 1 THEN '鍚屾涓�'
+--         WHEN 2 THEN '鍚屾鎴愬姛'
+--         WHEN 3 THEN '鍚屾澶辫触'
+--     END AS status_name,
+--     COUNT(*) AS count
+-- FROM sys_task_payment
+-- WHERE pay_status = 'PAID'
+-- GROUP BY sync_status;
+
+-- 鏌ョ湅闄勫姞璐圭敤鍚屾鐘舵�侊細
+-- SELECT 
+--     sync_status,
+--     CASE sync_status
+--         WHEN 0 THEN '鏈悓姝�'
+--         WHEN 1 THEN '鍚屾涓�'
+--         WHEN 2 THEN '鍚屾鎴愬姛'
+--         WHEN 3 THEN '鍚屾澶辫触'
+--     END AS status_name,
+--     COUNT(*) AS count
+-- FROM sys_task_additional_fee
+-- GROUP BY sync_status;
+
+-- 鏌ョ湅浠婃棩鍚屾澶辫触鐨勮褰曪細
+-- SELECT * FROM sys_task_payment 
+-- WHERE sync_status = 3 AND DATE(sync_time) = CURDATE();
+
+-- SELECT * FROM sys_task_additional_fee 
+-- WHERE sync_status = 3 AND DATE(sync_time) = CURDATE();
diff --git a/sql/payment_sync_update.sql b/sql/payment_sync_update.sql
new file mode 100644
index 0000000..5b0a2cc
--- /dev/null
+++ b/sql/payment_sync_update.sql
@@ -0,0 +1,34 @@
+-- 鏀粯淇℃伅鍙屽悜鍚屾鍔熻兘 - 鏁版嵁琛ㄥ彉鏇�
+-- 浣滆��: ruoyi
+-- 鏃ユ湡: 2025-01-15
+
+-- =============================================
+-- 1. 淇敼鏂扮郴缁� sys_task_payment 琛紝娣诲姞鍚屾鐩稿叧瀛楁
+-- =============================================
+ALTER TABLE sys_task_payment ADD COLUMN pid BIGINT COMMENT '鏃х郴缁熸敮浠樿褰旾D(PaidMoney.id)' AFTER update_time;
+ALTER TABLE sys_task_payment ADD COLUMN sync_status INT DEFAULT 0 COMMENT '鍚屾鐘舵�侊細0鏈悓姝ワ紝1鍚屾涓紝2鍚屾鎴愬姛锛�3鍚屾澶辫触' AFTER pid;
+ALTER TABLE sys_task_payment ADD COLUMN sync_time DATETIME COMMENT '鍚屾鏃堕棿' AFTER sync_status;
+
+-- 涓簆id瀛楁娣诲姞绱㈠紩锛屾彁楂樻煡璇㈡晥鐜�
+CREATE INDEX idx_pid ON sys_task_payment(pid);
+
+-- 涓簊ync_status瀛楁娣诲姞绱㈠紩锛岀敤浜庢壒閲忓悓姝ユ煡璇�
+CREATE INDEX idx_sync_status ON sys_task_payment(sync_status);
+
+-- =============================================
+-- 璇存槑锛�
+-- =============================================
+-- 1. pid: 瀛樺偍鏃х郴缁烶aidMoney琛ㄧ殑涓婚敭ID锛岀敤浜庡弻鍚戝叧鑱�
+-- 2. sync_status: 鍚屾鐘舵�佹爣璇�
+--    - 0: 鏈悓姝� - 鏂板垱寤虹殑鏀粯璁板綍锛屽皻鏈悓姝ュ埌鏃х郴缁�
+--    - 1: 鍚屾涓� - 姝e湪鎵ц鍚屾鎿嶄綔
+--    - 2: 鍚屾鎴愬姛 - 宸叉垚鍔熷悓姝ュ埌鏃х郴缁�
+--    - 3: 鍚屾澶辫触 - 鍚屾杩囩▼涓彂鐢熼敊璇�
+-- 3. sync_time: 璁板綍鏈�鍚庝竴娆″悓姝ユ搷浣滅殑鏃堕棿
+--
+-- 鍚屾閫昏緫锛�
+-- - 鏂扮郴缁� -> 鏃х郴缁燂細鏂扮郴缁熸敮浠樻垚鍔熷悗锛岃嚜鍔ㄥ悓姝ュ埌鏃х郴缁烶aidMoney琛�
+-- - 鏃х郴缁� -> 鏂扮郴缁燂細瀹氭椂浠诲姟浠庢棫绯荤粺PaidMoney琛ㄥ悓姝ユ渶鏂版敮浠樿褰曞埌鏂扮郴缁�
+-- - 閫氳繃ServiceOrdIDDt鍜孌ispatchOrdIDDt瀛楁鍏宠仈浠诲姟
+-- - 鏀粯鏂瑰紡鏄犲皠锛�
+--   鏂扮郴缁�(CASH/ON_ACCOUNT/WECHAT/ALIPAY) <-> 鏃х郴缁�(1鐜伴噾/6鎸傝处/3寰俊/4鏀粯瀹�)
diff --git a/sql/resync_vehicle_personnel_job.sql b/sql/resync_vehicle_personnel_job.sql
new file mode 100644
index 0000000..128b77b
--- /dev/null
+++ b/sql/resync_vehicle_personnel_job.sql
@@ -0,0 +1,96 @@
+-- 杞﹁締鍜屼汉鍛樺彉鏇撮噸鏂板悓姝ュ畾鏃朵换鍔¢厤缃甋QL
+-- 鍦╯ys_job琛ㄤ腑娣诲姞瀹氭椂浠诲姟
+-- 璋冪敤鏃х郴缁� admin_save_25.asp 鎺ュ彛鏇存柊璋冨害鍗�
+-- 
+-- 闇�瑕侀噸鏂板悓姝ョ殑鍙樻洿绫诲瀷锛�
+--   1. 杞﹁締鍙樻洿锛氫慨鏀逛簡鍒嗛厤鐨勮溅杈�
+--   2. 鎵ц浜哄憳鍙樻洿锛氫慨鏀逛簡鎵ц浜哄憳锛堝徃鏈恒�佸尰鐢熴�佹姢澹級
+--   3. 鍦板潃鍙樻洿锛氫慨鏀逛簡杞嚭鍖婚櫌鍦板潃鎴栬浆鍏ュ尰闄㈠湴鍧�
+--   4. 鎴愪氦浠峰彉鏇达細淇敼浜嗚浆杩愯垂鐢紙transfer_price锛�
+
+-- 閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇寸殑浠诲姟鍒版棫绯荤粺
+INSERT INTO sys_job (job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark)
+VALUES 
+('閲嶆柊鍚屾杞﹁締浜哄憳鍙樻洿', 'DEFAULT', 'legacySystemSyncTask.resyncVehicleAndPersonnel', '0 0/5 * * * ?', '3', '1', '0', 'admin', sysdate(), 
+'姣�5鍒嗛挓鑷姩閲嶆柊鍚屾杞﹁締銆佷汉鍛樸�佸湴鍧�銆佹垚浜や环鍙戠敓鍙樻洿鐨勪换鍔″埌鏃х郴缁熴�傚綋浠诲姟鐨勮溅杈嗐�佷汉鍛樸�佸湴鍧�鎴栬垂鐢ㄨ淇敼鍚庯紝浼氭爣璁皀eed_resync=1锛屽畾鏃朵换鍔′細灏嗚繖浜涘彉鏇村悓姝ュ埌鏃х郴缁熻皟搴﹀崟琛ㄣ��');
+
+-- 璇存槑锛�
+-- job_name: 浠诲姟鍚嶇О
+-- job_group: 浠诲姟缁勫悕锛圖EFAULT涓洪粯璁ょ粍锛�
+-- invoke_target: 璋冪敤鐩爣瀛楃涓诧紙Bean鍚嶇О.鏂规硶鍚嶏級
+--   - legacySystemSyncTask.resyncVehicleAndPersonnel() 閲嶆柊鍚屾杞﹁締鍜屼汉鍛樺彉鏇�
+--
+-- cron_expression: cron琛ㄨ揪寮�
+--   - '0 0/5 * * * ?' = 姣�5鍒嗛挓鎵ц涓�娆★紙鎺ㄨ崘锛�
+--   - '0 0/10 * * * ?' = 姣�10鍒嗛挓鎵ц涓�娆�
+--   - '0 0/3 * * * ?' = 姣�3鍒嗛挓鎵ц涓�娆★紙浠呭湪鍙樻洿棰戠箒鏃朵娇鐢級
+--
+-- misfire_policy: 閿欒繃鎵ц绛栫暐
+--   - 1=绔嬪嵆鎵ц
+--   - 2=鎵ц涓�娆�
+--   - 3=鏀惧純鎵ц锛堟帹鑽愶級
+--
+-- concurrent: 鏄惁骞跺彂
+--   - 0=鍏佽骞跺彂
+--   - 1=绂佹骞跺彂锛堟帹鑽愶紝閬垮厤閲嶅鍚屾锛�
+--
+-- status: 鐘舵��
+--   - 0=姝e父锛堝惎鐢級
+--   - 1=鏆傚仠锛堝仠鐢級
+
+-- 浣跨敤鍦烘櫙锛�
+-- 1. 杞﹁締淇℃伅鍙樻洿锛�
+--    - 浠诲姟鍒嗛厤鐨勮溅杈嗚鏇存崲
+--    - 杞﹁締淇℃伅锛堣溅鐗屽彿绛夛級琚慨鏀�
+--
+-- 2. 浜哄憳淇℃伅鍙樻洿锛�
+--    - 鎵ц浜哄憳锛堝徃鏈恒�佸尰鐢熴�佹姢澹瓑锛夎閲嶆柊鍒嗛厤
+--    - 浜哄憳淇℃伅琚慨鏀�
+--
+-- 3. 鍦板潃淇℃伅鍙樻洿锛�
+--    - 杞嚭鍖婚櫌鍦板潃琚慨鏀�
+--    - 杞叆鍖婚櫌鍦板潃琚慨鏀�
+--
+-- 4. 鎴愪氦浠峰彉鏇达細
+--    - 杞繍璐圭敤锛坱ransfer_price锛夎淇敼
+--
+-- 3. 鍚屾娴佺▼锛�
+--    - 鍦ㄤ慨鏀硅溅杈嗐�佷汉鍛樸�佸湴鍧�鎴栨垚浜や环鏃讹紝璁剧疆 need_resync = 1
+--    - 瀹氭椂浠诲姟鏌ヨ need_resync = 1 涓� dispatch_sync_status = 2 鐨勪换鍔�
+--    - 璋冪敤鏃х郴缁� admin_save_25.asp 鎺ュ彛閲嶆柊鍚屾璋冨害鍗曚俊鎭紙鑰岄潪 admin_save_24.gds锛�
+--    - 鍚屾鎴愬姛鍚庤缃� need_resync = 0
+--
+-- 4. 鎬ц兘浼樺寲锛�
+--    - 姣忔壒娆¢檺鍒�100鏉¤褰�
+--    - 姣忔潯璁板綍闂撮殧1绉�
+--    - 绂佹骞跺彂鎵ц
+--    - 鍙悓姝ユ湭瀹屾垚鍜屾湭鍙栨秷鐨勪换鍔�
+
+-- 鐩戞帶鏌ヨ绀轰緥锛�
+
+-- 鏌ョ湅闇�瑕侀噸鏂板悓姝ョ殑浠诲姟鏁伴噺锛�
+-- SELECT COUNT(*) FROM sys_task_emergency
+-- WHERE need_resync = 1
+--   AND dispatch_sync_status = 2
+--   AND legacy_dispatch_ord_id IS NOT NULL;
+
+-- 鏌ョ湅閲嶆柊鍚屾鐘舵�佺粺璁★細
+-- SELECT 
+--     need_resync,
+--     CASE need_resync
+--         WHEN 0 THEN '鏃犻渶閲嶆柊鍚屾'
+--         WHEN 1 THEN '闇�瑕侀噸鏂板悓姝�'
+--     END AS resync_status,
+--     COUNT(*) AS count
+-- FROM sys_task_emergency
+-- WHERE dispatch_sync_status = 2
+-- GROUP BY need_resync;
+
+-- 鏌ョ湅浠婃棩閲嶆柊鍚屾澶辫触鐨勮褰曪細
+-- SELECT te.*, t.task_code, t.task_status
+-- FROM sys_task_emergency te
+-- JOIN sys_task t ON te.task_id = t.task_id
+-- WHERE te.need_resync = 1
+--   AND te.dispatch_sync_status = 2
+--   AND DATE(te.dispatch_sync_time) = CURDATE()
+--   AND te.dispatch_sync_error_msg IS NOT NULL;
diff --git a/sql/sys_dept_add_departure_fields.sql b/sql/sys_dept_add_departure_fields.sql
new file mode 100644
index 0000000..c1bbf33
--- /dev/null
+++ b/sql/sys_dept_add_departure_fields.sql
@@ -0,0 +1,14 @@
+-- 涓� sys_dept 琛ㄥ鍔犲嚭鍙戝湴鐩稿叧瀛楁
+-- 鐢ㄤ簬閰嶇疆鍚勫垎鍏徃鐨勯粯璁ゅ嚭杞﹀湴鍧�
+
+-- 澧炲姞鍑鸿溅鍦板潃瀛楁
+ALTER TABLE sys_dept ADD COLUMN departure_address VARCHAR(500) COMMENT '榛樿鍑鸿溅鍦板潃';
+
+-- 澧炲姞鍑鸿溅鍦板潃缁忓害
+ALTER TABLE sys_dept ADD COLUMN departure_longitude DECIMAL(10, 6) COMMENT '鍑鸿溅鍦板潃缁忓害';
+
+-- 澧炲姞鍑鸿溅鍦板潃绾害
+ALTER TABLE sys_dept ADD COLUMN departure_latitude DECIMAL(10, 6) COMMENT '鍑鸿溅鍦板潃绾害';
+
+-- 鏇存柊澶囨敞
+ALTER TABLE sys_dept MODIFY COLUMN remark VARCHAR(500) COMMENT '澶囨敞(鍙厤缃粯璁ゅ嚭杞﹀湴鍧�绛変俊鎭�)';
diff --git a/sql/task_payment_method_dict.sql b/sql/task_payment_method_dict.sql
new file mode 100644
index 0000000..15680d9
--- /dev/null
+++ b/sql/task_payment_method_dict.sql
@@ -0,0 +1,15 @@
+-- 浠诲姟鏀粯鏂瑰紡瀛楀吀绫诲瀷
+INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) 
+VALUES ('浠诲姟鏀粯鏂瑰紡', 'task_payment_method', '0', 'admin', NOW(), '浠诲姟缁撶畻鏀粯鏂瑰紡瀛楀吀');
+
+-- 浠诲姟鏀粯鏂瑰紡瀛楀吀鏁版嵁
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES
+(1, '鐜伴噾', '1', 'task_payment_method', '', 'primary', 'N', '0', 'admin', NOW(), '鐜伴噾鏀粯'),
+(2, '閾惰杞处', '2', 'task_payment_method', '', 'info', 'N', '0', 'admin', NOW(), '閾惰杞处鏀粯'),
+(3, '寰俊鏀粯', '3', 'task_payment_method', '', 'success', 'N', '0', 'admin', NOW(), '寰俊鎵爜鏀粯'),
+(4, '鏀粯瀹�', '4', 'task_payment_method', '', 'primary', 'N', '0', 'admin', NOW(), '鏀粯瀹濇壂鐮佹敮浠�'),
+(5, 'POS鏀舵', '5', 'task_payment_method', '', 'warning', 'N', '0', 'admin', NOW(), 'POS鏈哄埛鍗℃敹娆�'),
+(6, '鎸傝处', '6', 'task_payment_method', '', 'danger', 'N', '0', 'admin', NOW(), '鎸傝处鏀粯'),
+(7, '鏄撳尰閫氭寕璐�', '7', 'task_payment_method', '', 'danger', 'N', '0', 'admin', NOW(), '鏄撳尰閫氭寕璐︽敮浠�'),
+(8, '閫�娆�', '8', 'task_payment_method', '', 'default', 'N', '0', 'admin', NOW(), '閫�娆炬搷浣�(鍓嶇涓嶆樉绀�)'),
+(9, '绉垎', '9', 'task_payment_method', '', 'default', 'N', '0', 'admin', NOW(), '绉垎鏀粯(鍓嶇涓嶆樉绀�)');
diff --git a/sql/task_payment_tables.sql b/sql/task_payment_tables.sql
new file mode 100644
index 0000000..d051761
--- /dev/null
+++ b/sql/task_payment_tables.sql
@@ -0,0 +1,53 @@
+-- 闄勫姞璐圭敤鏄庣粏琛�
+CREATE TABLE sys_task_additional_fee (
+    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    task_id BIGINT NOT NULL COMMENT '浠诲姟ID',
+    fee_type VARCHAR(50) NOT NULL COMMENT '璐圭敤绫诲瀷(瀛楀吀task_additional_fee_type)',
+    fee_name VARCHAR(100) NOT NULL COMMENT '璐圭敤鍚嶇О',
+    unit_amount DECIMAL(10,2) NOT NULL COMMENT '鍗曚环',
+    quantity INT NOT NULL DEFAULT 1 COMMENT '鏁伴噺',
+    total_amount DECIMAL(10,2) NOT NULL COMMENT '鎬婚噾棰�',
+    remark VARCHAR(500) COMMENT '澶囨敞',
+    created_by VARCHAR(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+    created_time DATETIME DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+    PRIMARY KEY (id),
+    KEY idx_task_id (task_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='浠诲姟闄勫姞璐圭敤鏄庣粏琛�';
+
+-- 浠诲姟鏀粯璁板綍琛�
+CREATE TABLE sys_task_payment (
+    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    task_id BIGINT NOT NULL COMMENT '浠诲姟ID',
+    total_amount DECIMAL(10,2) NOT NULL COMMENT '鎬婚噾棰�(鎴愪氦浠�+闄勫姞璐�)',
+    settlement_amount DECIMAL(10,2) NOT NULL COMMENT '缁撶畻閲戦',
+    payment_method VARCHAR(20) NOT NULL COMMENT '鏀粯鏂瑰紡:CASH鐜伴噾,ON_ACCOUNT鎸傚笎,WECHAT寰俊,ALIPAY鏀粯瀹�',
+    pay_status VARCHAR(20) NOT NULL DEFAULT 'UNPAID' COMMENT '鏀粯鐘舵��:UNPAID鏈敮浠�,PENDING寰呮敮浠�,PAID宸叉敮浠�,FAILED澶辫触,REFUNDED宸查��娆�',
+    pay_time DATETIME COMMENT '鏀粯鏃堕棿',
+    out_trade_no VARCHAR(64) COMMENT '鍟嗘埛璁㈠崟鍙�',
+    trade_no VARCHAR(64) COMMENT '涓夋柟浜ゆ槗鍙�',
+    code_url TEXT COMMENT '浜岀淮鐮侀摼鎺�',
+    qr_expire_time DATETIME COMMENT '浜岀淮鐮佽繃鏈熸椂闂�',
+    provider VARCHAR(20) COMMENT '鏀粯鎻愪緵鍟�:WECHAT,ALIPAY',
+    payment_ref_id VARCHAR(100) COMMENT '鏀粯妯″潡杩斿洖鐨勫敮涓�鏍囪瘑',
+    callback_url VARCHAR(500) COMMENT '鍥炶皟鍦板潃',
+    remark VARCHAR(500) COMMENT '澶囨敞',
+    created_by VARCHAR(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+    created_time DATETIME DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+    update_time DATETIME DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+    PRIMARY KEY (id),
+    UNIQUE KEY uk_out_trade_no (out_trade_no),
+    KEY idx_task_id (task_id),
+    KEY idx_pay_status (pay_status),
+    KEY idx_payment_ref_id (payment_ref_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='浠诲姟鏀粯璁板綍琛�';
+
+-- 闄勫姞璐圭敤绫诲瀷瀛楀吀
+INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark) 
+VALUES ('浠诲姟闄勫姞璐圭敤绫诲瀷', 'task_additional_fee_type', '0', 'admin', NOW(), '杞繍浠诲姟闄勫姞璐圭敤绫诲瀷瀛楀吀');
+
+-- 闄勫姞璐圭敤绫诲瀷瀛楀吀鏁版嵁
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES
+(1, '绛夊緟璐�', '1', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '绛夊緟璐�'),
+(2, '鎷呮灦', '2', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '鎷呮灦'),
+(3, '灞呭ICU', '3', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '灞呭ICU'),
+(4, '鍖荤枟璁惧', '4', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '鍖荤枟璁惧');
diff --git a/sql/update_additional_fee_type_dict.sql b/sql/update_additional_fee_type_dict.sql
new file mode 100644
index 0000000..1785df9
--- /dev/null
+++ b/sql/update_additional_fee_type_dict.sql
@@ -0,0 +1,10 @@
+-- 鏇存柊闄勫姞璐圭敤绫诲瀷瀛楀吀鏁版嵁
+-- 鍒犻櫎鏃х殑瀛楀吀鏁版嵁
+DELETE FROM sys_dict_data WHERE dict_type = 'task_additional_fee_type';
+
+-- 鎻掑叆鏂扮殑瀛楀吀鏁版嵁
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES
+(1, '绛夊緟璐�', '1', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '绛夊緟璐�'),
+(2, '鎷呮灦', '2', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '鎷呮灦'),
+(3, '灞呭ICU', '3', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '灞呭ICU'),
+(4, '鍖荤枟璁惧', '4', 'task_additional_fee_type', '', 'default', 'N', '0', 'admin', NOW(), '鍖荤枟璁惧');
diff --git a/sql/update_task_payment_20250123.sql b/sql/update_task_payment_20250123.sql
new file mode 100644
index 0000000..ea08740
--- /dev/null
+++ b/sql/update_task_payment_20250123.sql
@@ -0,0 +1,8 @@
+-- 淇敼sys_task_payment琛紝璋冩暣浜岀淮鐮佺浉鍏冲瓧娈�
+-- 1. 淇敼code_url瀛楁涓篢EXT绫诲瀷锛岀敤浜庡瓨鍌˙ase64浜岀淮鐮佸浘鐗�
+ALTER TABLE sys_task_payment MODIFY COLUMN code_url TEXT COMMENT 'Base64缂栫爜鐨勪簩缁寸爜鍥剧墖';
+
+-- 濡傛灉浠ュ悗闇�瑕佸尯鍒哢RL鍜孊ase64锛屽彲浠ヨ�冭檻鎷嗗垎涓轰袱涓瓧娈碉細
+-- ALTER TABLE sys_task_payment 
+--   MODIFY COLUMN code_url VARCHAR(500) COMMENT '浜岀淮鐮佸師濮嬮摼鎺RL',
+--   ADD COLUMN qr_base64 LONGTEXT COMMENT 'Base64缂栫爜鐨勪簩缁寸爜鍥剧墖' AFTER code_url;

--
Gitblit v1.9.1