补齐 v3 合同管理完整接口通知
这个提交包含在:
父节点
1a03185395
当前提交
01b39a30df
@ -0,0 +1,608 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "5368"
|
||||
title: "v3 合同管理完整接口与订单号搜索"
|
||||
consumer: "admin"
|
||||
change_type: "修改接口"
|
||||
author: "yaosutu(GIT)"
|
||||
backend_status: "pending"
|
||||
gateway_status: "pending"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "PR #5501 已合并 dev-v3;本文按合并代码静态核对 8 个 admin Controller 共 56 端点,尚未对本 PR 执行测试服网关 HTTP 验证。"
|
||||
updated_at: "2026-08-04"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# 🔧【修改接口·管理后台】v3 合同管理完整接口与订单号搜索 (#5368)
|
||||
|
||||
> **PR**: [#5501](https://git.1814.love:8443/wx/HL/pulls/5501) | **服务**: `hl-order-service-v3` | **更新日期**: 2026-08-04
|
||||
> **范围**: 仅 8 个 admin Controller 的 56 个 `/v3/admin/*` 端点;不含 internal、mp、callback、job。
|
||||
|
||||
## 1. 接口背景与历史文档关系
|
||||
|
||||
管理后台合同页需要统一使用 v3 读写链路,并在合同列表按订单号定位数据。本文同时给出该页面依赖的全部 admin 契约,便于前端一次性移除 v1/v3 混用。
|
||||
|
||||
与已发布的 `2026-07/31_5368_非订单页面统一补齐真实团号与团号搜索` 的关系:
|
||||
|
||||
- 2026-07 文档对应 PR #5386 / commit `c9d1b12618`,已约定 `teamNo: string|null`、列表 `teamNo` 搜索、详情返回 `teamNo` 和 v3 完整写侧。
|
||||
- 本文对应 PR #5501;不重复声称上述能力是本次新增,而是补齐全量 admin 契约并说明本次仅有的两项可见变化。
|
||||
|
||||
## 2. 本次真实变更
|
||||
|
||||
| # | 接口 | 原来 | 现在 |
|
||||
|---|---|---|---|
|
||||
| 1 | `GET /v3/admin/contract/list` | 无独立 `orderNo` 查询参数 | 新增可选 `orderNo`,对人类可读订单号做包含匹配 |
|
||||
| 2 | 同上 | `teamNo` / `contactName` 文本边界未完整固化 | `orderNo` / `teamNo` / `contactName` 统一 trim;全空白忽略;`%`、`_`、`\` 都按字面字符匹配;多条件按 AND 组合 |
|
||||
|
||||
N+1 消除是内部性能修复,不属于前端契约变更。
|
||||
|
||||
## 3. 通用协议
|
||||
|
||||
- 认证:所有端点都需要管理后台 JWT;旅行社敏感写操作按接口标注需 ADMIN 或 SUPER_ADMIN。
|
||||
- 成功包装:`{"code":200,"data":...,"message":"操作成功","success":true}`,字段名是 `message`,不是 `msg`。
|
||||
- 分页包装:`data.records` / `data.total` / `data.page` / `data.pageSize`。
|
||||
- 失败包装:`{"code":业务错误码,"data":null,"message":"可读提示","success":false}`。
|
||||
- 幂等:GET 幂等;PUT 为目标状态更新时可重试;POST 创建/上传不得盲目重试;DELETE 不保证重复调用仍成功。
|
||||
- 金额按 JSON string 消费;雪花 ID 按 string 消费,不得转 JavaScript `Number`。
|
||||
|
||||
## 4. 完整接口清单(56)
|
||||
|
||||
| Controller | 数量 | 路径域 |
|
||||
|---|---:|---|
|
||||
| AdminContractController | 15 | `/v3/admin/contract` |
|
||||
| AdminContractSchemeController | 7 | `/v3/admin/contract/scheme` |
|
||||
| AdminContractSchemeAttachmentController | 4 | `/v3/admin/contract/scheme/{schemeId}/attachments` |
|
||||
| AdminContractSchemeTourGuideController | 4 | `/v3/admin/contract/scheme/{schemeId}/tour-guides` |
|
||||
| AdminClauseTemplateController | 6 | `/v3/admin/contract/clause-template` |
|
||||
| AdminTravelAgencyController | 11 | `/v3/admin/travel-agency` |
|
||||
| AdminTravelAgencyQualificationController | 4 | `/v3/admin/travel-agency/{agencyId}/qualification` |
|
||||
| AdminTravelAgencyPaymentController | 5 | `/v3/admin/travel-agency/{agencyId}/payment` |
|
||||
|
||||
## 5. 接口详情
|
||||
|
||||
### 5.1 AdminContractController(15)
|
||||
|
||||
#### 5.1.1 创建合同(标准模式)
|
||||
|
||||
- **场景/协议**:手工填写全量签约数据;`POST /v3/admin/contract/create`;管理员 JWT;非幂等。
|
||||
- **请求体(全部字段)**:`orderId:long?`、`contractType:string?(TOUR/INSURANCE)`、`platform:string?(12301/LOCAL/TENCENT_ESIGN)`、`vendorCode:string?`、`templateCode:string!`、`agencyCode:string?`、`mchId:string?`、`transactorName:string?`、`transactorPhone:string?`、`destination:string!`、`routeName:string!`、`days:int?`、`nights:int?`、`departureDate:date!`、`returnDate:date!`、`departureCity:string?`、`groupId:string?`、`signatoryMode:int?(1..3)`、`signatoryName:string!`、`signatoryPhone:string!`、`signatoryIdType:int?`、`signatoryIdNumber:string!`、`signingPlace:string?`、`adultCost:decimal!`、`childCost:decimal?`、`totalAmount:decimal!`、`paymentMethod:int?(1..3)`、`disputeResolution:int?(1..2)`、`tribunalName:string?`、`litigationCourt:string?`、`contactName:string!`、`contactPhone:string!`、`supplementaryClause:string?`、`travelers:array!`、`accordingContract:boolean?`、`accordingContractPhase:object?`、`contractNum:string?`、`holdNum:string?`、`paymentDescription:string?`、`paymentOther:string?`、`agreeToBuyInsurance:boolean?`、`insuranceCompany:string?`、`insuranceCoverage:string?`、`insurancePremium:string?`、`insuranceProductName:string?`、`insurancePurchaseMethod:int?(1..3)`、`guideServiceCost:decimal?`、`paymentTime:string?`、`startHour:int?(0..23)`、`endHour:int?(0..23)`、`touristCondition:string?`、`schemeId:string?`。`travelers[]`:`name:string!`、`gender:string?(0/1/2)`、`age:int?`、`idCardType:int?(1/2)`、`idCardNo:string!`、`phone:string?`、`isSigner:boolean?`、`isChild:boolean?`、`nationality:string?`、`race:string?`、`roomGroupNo:int?`。
|
||||
- **响应(完整)**:`ContractDetailVO`:`contractId:string, orderId:string, schemeId:string|null, orderNo:string|null, teamNo:string|null, templateCode, templateName, contractNumber, platform, contractType, contractTypeLabel, mode, modeLabel, status, statusLabel, signUrl, qrCodeUrl, fileUrl, agencyCode, travelAgencyName, destination, departureDate, returnDate, totalAmount:string, touristCount:int, contactName, contactPhone, createTime, supplementaryClause, travelers[], statusLogs[]`;`travelers[]={travelerId:string,name,idCardType,idCardTypeLabel,idCardNo,phone,isSigner}`;`statusLogs[]={logId:string,contractId:string,oldStatus,oldStatusLabel,newStatus,newStatusLabel,source,sourceLabel,rawPayload,createTime}`。
|
||||
- **边界/错误**:行程未确认 `510220`;已有有效合同 `510214`;模板不存在 `510215`;签署人手机缺失 `510213`;必填/长度/手机格式错误返回参数校验失败。
|
||||
- **典型示例**:请求 `{"orderId":"2079000000000000001","templateCode":"TOURAGE_STANDARD","destination":"呼伦贝尔","routeName":"草原5日","departureDate":"2026-08-10","returnDate":"2026-08-14","signatoryName":"张某","signatoryPhone":"138****8000","signatoryIdNumber":"110101********1234","adultCost":"3000.00","totalAmount":"6000.00","contactName":"张某","contactPhone":"138****8000","travelers":[{"name":"张某","idCardNo":"110101********1234","isSigner":true}]}`;响应 `{"code":200,"data":{"contractId":"2080000000000000001","orderId":"2079000000000000001","status":"GENERATED","totalAmount":"6000.00","travelers":[],"statusLogs":[]},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.2 按方案创建合同
|
||||
|
||||
- **场景/协议**:后台从订单与方案自动组装合同;`POST /v3/admin/contract/create-by-scheme`; JWT;非幂等。
|
||||
- **入参**:请求体 `orderId:string!`、`schemeId:string!`。
|
||||
- **响应(完整)**:与 5.1.1 的 `ContractDetailVO` 字段完全一致:`contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount,touristCount,contactName,contactPhone,createTime,supplementaryClause,travelers[],statusLogs[]`。
|
||||
- **边界/错误**:方案不存在/已停用 `510205`;方案未配模板 `510206`;订单信息失败 `510207`;行程未确认 `510220`;已有合同 `510214`。
|
||||
- **示例**:请求 `{"orderId":"2079000000000000001","schemeId":"2020001"}`;响应 `{"code":200,"data":{"contractId":"2080000000000000001","orderId":"2079000000000000001","schemeId":"2020001","status":"GENERATED","travelers":[],"statusLogs":[]},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.3 作废合同
|
||||
|
||||
- **场景/协议**:不可恢复地作废有效合同;`POST /v3/admin/contract/{id}/invalidate`; JWT;重复调用不保证成功。
|
||||
- **入参**:路径 `id:string!` 合同 ID;无请求体。
|
||||
- **响应(完整)**:`ContractVO={contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount:string,touristCount,contactName,contactPhone,createTime}`。
|
||||
- **边界/错误**:合同不存在 `510001`;缺合同编号 `510003`;上游作废失败 `510104`。
|
||||
- **示例**:请求 `POST /v3/admin/contract/2080000000000000001/invalidate` 无 body;响应 `{"code":200,"data":{"contractId":"2080000000000000001","status":"VOIDED","statusLabel":"已作废"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.4 合同列表(本 PR 修改)
|
||||
|
||||
- **场景/协议**:合同管理分页列表;`GET /v3/admin/contract/list`; JWT;幂等。
|
||||
- **Query(全部)**:`page:int?=1`、`pageSize:int?=10`、`orderId:string?`、`status:string?`、`platform:string?`、`orderNo:string?`、`teamNo:string?`、`contactName:string?`。三个文本条件都 trim;全空白忽略;`%` / `_` / `\` 字面匹配;条件间 AND。
|
||||
- **响应(完整)**:`PageResult.records[]` 每项为 `ContractVO={contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount:string,touristCount,contactName,contactPhone,createTime}`;顶层 `total:long,page:int,pageSize:int`。
|
||||
- **边界**:`orderNo=%` 只匹配订单号中真实的 `%`,不会全表命中;`orderNo= ` 等价于未传;无结果返回空 `records`。
|
||||
- **示例**:请求 `GET /v3/admin/contract/list?page=1&pageSize=10&orderNo=HL2026&teamNo=26-08`;响应 `{"code":200,"data":{"records":[{"contractId":"2080000000000000001","orderId":"2079000000000000001","orderNo":"HL202608040001","teamNo":"26-0804","status":"SIGNED","totalAmount":"6000.00"}],"total":1,"page":1,"pageSize":10},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.5 合同详情
|
||||
|
||||
- **场景/协议**:查看合同、出行人和状态日志;`GET /v3/admin/contract/{id}`; JWT;幂等。
|
||||
- **入参**:路径 `id:string!`。
|
||||
- **响应(完整)**:`ContractDetailVO`全字段:`contractId,orderId,schemeId,orderNo,teamNo,templateCode,templateName,contractNumber,platform,contractType,contractTypeLabel,mode,modeLabel,status,statusLabel,signUrl,qrCodeUrl,fileUrl,agencyCode,travelAgencyName,destination,departureDate,returnDate,totalAmount,touristCount,contactName,contactPhone,createTime,supplementaryClause,travelers[{travelerId,name,idCardType,idCardTypeLabel,idCardNo,phone,isSigner}],statusLogs[{logId,contractId,oldStatus,oldStatusLabel,newStatus,newStatusLabel,source,sourceLabel,rawPayload,createTime}]`。
|
||||
- **错误/示例**:不存在 `510001`。请求 `GET /v3/admin/contract/2080000000000000001`;响应 `{"code":200,"data":{"contractId":"2080000000000000001","orderId":"2079000000000000001","teamNo":"26-0804","totalAmount":"6000.00","travelers":[{"travelerId":"2081000000000000001","name":"张某"}],"statusLogs":[]},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.6 下载合同文件
|
||||
|
||||
- **场景/协议**:取得已签署/已上报合同下载 URL;`GET /v3/admin/contract/{id}/download`; JWT;幂等。
|
||||
- **入参/响应**:路径 `id:string!`;`data:string` 为下载 URL,无其他 data 字段。
|
||||
- **错误/边界**:`510001` 不存在;`510101` 未签署完成;`510102` 文件 URL 缺失。
|
||||
- **示例**:请求 `GET /v3/admin/contract/2080000000000000001/download`;响应 `{"code":200,"data":"https://example.invalid/signed/contract.pdf?token=masked","message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.7 重发签署短信
|
||||
|
||||
- **场景/协议**:为未完成签署的合同重发短信;`POST /v3/admin/contract/{id}/resend-sms`; JWT;有 1 分钟频控,不可并发重试。
|
||||
- **入参/响应**:路径 `id:string!`;`data:boolean`。
|
||||
- **错误/边界**:`510001`、`510005` 已签署、`510006` 过于频繁、`510007` 合同编号缺失、`510008` 联系人手机缺失。
|
||||
- **示例**:请求 `POST /v3/admin/contract/2080000000000000001/resend-sms` 无 body;响应 `{"code":200,"data":true,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.8 合同模板列表
|
||||
|
||||
- **场景/协议**:创建合同时选择平台模板;`GET /v3/admin/contract/templates`; JWT;幂等。
|
||||
- **Query**:`platform:string?` (`12301` 等)。
|
||||
- **响应(完整)**:`data[]` 每项 `templateId:string,templateCode:string,templateName:string,platform:string,mode:string,status:string,description:string|null,createTime:datetime`。
|
||||
- **示例**:请求 `GET /v3/admin/contract/templates?platform=12301`;响应 `{"code":200,"data":[{"templateId":"101","templateCode":"TOURAGE_STANDARD","templateName":"标准旅游合同","platform":"12301","mode":"STANDARD","status":"ACTIVE","description":null,"createTime":"2026-08-01T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.9 刷新合同状态
|
||||
|
||||
- **场景/协议**:主动从合同平台同步最新状态;`GET /v3/admin/contract/{id}/status`; JWT;查询可重试,但可产生状态更新。
|
||||
- **入参/响应**:路径 `id:string!`;`ContractVO`完整字段同 5.1.3。
|
||||
- **错误/示例**:`510001`;`510103` 缺合同编号。请求 `GET /v3/admin/contract/2080000000000000001/status`;响应 `{"code":200,"data":{"contractId":"2080000000000000001","status":"SIGNED","statusLabel":"已签署"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.10 按订单查询全部合同
|
||||
|
||||
- **场景/协议**:查询订单下包含已作废数据的全部合同;`GET /v3/admin/contract/by-order/{orderId}`; JWT;幂等。
|
||||
- **入参/响应**:`orderId:string!`;`data[]` 每项为 5.1.3 的完整 `ContractVO`。无记录返回 `[]`。
|
||||
- **示例**:请求 `GET /v3/admin/contract/by-order/2079000000000000001`;响应 `{"code":200,"data":[{"contractId":"2080000000000000001","orderId":"2079000000000000001","status":"SIGNED","totalAmount":"6000.00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.11 获取订单有效合同
|
||||
|
||||
- **场景/协议**:取指定订单最新非作废合同;`GET /v3/admin/contract/active-by-order/{orderId}`; JWT;幂等。
|
||||
- **入参/响应**:`orderId:string!`;`data` 为 5.1.3 的完整 `ContractVO`,没有有效合同时可为 `null`。
|
||||
- **示例**:请求 `GET /v3/admin/contract/active-by-order/2079000000000000001`;响应 `{"code":200,"data":{"contractId":"2080000000000000001","status":"SIGNED","totalAmount":"6000.00"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.12 可用合同平台列表
|
||||
|
||||
- **场景/协议**:展示已注册平台及可用性;`GET /v3/admin/contract/platforms`; JWT;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项 `platformName:string,displayName:string,available:boolean`。
|
||||
- **示例**:请求 `GET /v3/admin/contract/platforms`;响应 `{"code":200,"data":[{"platformName":"12301","displayName":"12301团队报送","available":true}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.13 已配置旅行社列表
|
||||
|
||||
- **场景/协议**:按平台筛选可用旅行社;`GET /v3/admin/contract/agencies`; JWT;幂等。
|
||||
- **Query**:`platform:string?`。
|
||||
- **响应(完整)**:`data[]` 每项 `code,agencyName,licenseNumber,businessLicenseNumber,agencyAddress,agencyCountry,agencyState,agencyCity,agencyDistrict,transactorName,transactorPhone,regionId,businessScope,zjParentId,appId,signKey,teamReportAppId,teamReportSignKey,mchId,complaintPhone,email,supportedPlatforms[],bankCard,complaintProvince,complaintCity,complaintAreaCode,complaintAddress,tribunalName,litigationCourt`。注意其中存在高敏配置,仅在授权后台使用,不得写日志/埋点。
|
||||
- **示例**:请求 `GET /v3/admin/contract/agencies?platform=12301`;响应 `{"code":200,"data":[{"code":"hulai","agencyName":"呼籁旅行社","licenseNumber":"L-XX-100001","supportedPlatforms":["12301"],"appId":"***","signKey":"***"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.14 报备合同(线下签约)
|
||||
|
||||
- **场景/协议**:线下签完后上报监管平台;`POST /v3/admin/contract/report`; JWT;非幂等。
|
||||
- **请求体**:字段、必填性与校验完全同 5.1.1 `CreateContractRequest`。
|
||||
- **响应(完整)**:与 5.1.1 `ContractDetailVO` 完全一致。
|
||||
- **错误/边界**:参数校验;未知旅行社 `510201`;上报失败 `510203`;腾讯电子签不支持 SYNC `510403`。
|
||||
- **示例**:请求同 5.1.1,`platform=12301`;响应 `{"code":200,"data":{"contractId":"2080000000000000002","mode":"SYNC","status":"REPORTED","travelers":[],"statusLogs":[]},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.1.15 上传已签署合同 PDF
|
||||
|
||||
- **场景/协议**:仅 SYNC 合同上传签署后 PDF;`POST /v3/admin/contract/{id}/upload-pdf`; JWT;非幂等。
|
||||
- **入参**:路径 `id:string!`;`multipart/form-data` 中 `file:file!`。
|
||||
- **响应(完整)**:5.1.3 的完整 `ContractVO`。
|
||||
- **错误/边界**:`510001`、`510105` 缺合同编号、`510106` 当前状态不允许、`510107` 上传失败;ONLINE/STANDARD 合同不适用。
|
||||
- **示例**:请求 `POST /v3/admin/contract/2080000000000000002/upload-pdf` + `file=@signed-contract.pdf`;响应 `{"code":200,"data":{"contractId":"2080000000000000002","mode":"SYNC","status":"UPLOADED","fileUrl":"https://example.invalid/signed.pdf"},"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.2 AdminContractSchemeController(7)
|
||||
|
||||
`ContractSchemeVO` 完整字段:`schemeId:string,name,description,contractPlatform,vendorCode,channel,contractTemplateCode,templateCode,contractTemplateName,contractMode,signatoryMode,agencyCode,agencyName,supplementaryClause,transactorName,transactorPhone,sortOrder,status,createTime`。`ContractSchemeRequest` 完整字段:`name:string!(max100),description:string?(max500),contractPlatform:string?(max50),vendorCode:string?(max32),channel:string?(max32),contractTemplateCode:string?(max50;兼容 templateCode/template_code),contractMode:string?(max50),signatoryMode:int?(1..3),agencyCode:string?(max50),supplementaryClause:string?(max2000),transactorName:string?(max50),transactorPhone:string?(11位手机),sortOrder:int?`。
|
||||
|
||||
#### 5.2.1 启用方案列表
|
||||
|
||||
- `GET /v3/admin/contract/scheme/list`;产品/合同方案下拉;JWT;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项包含上述 `ContractSchemeVO` 全部 19 字段,仅返回 `status=ACTIVE`。
|
||||
- **示例**:`GET .../list` → `{"code":200,"data":[{"schemeId":"2020001","name":"标准方案","contractPlatform":"12301","contractMode":"STANDARD","status":"ACTIVE"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.2.2 全部方案列表
|
||||
|
||||
- `GET /v3/admin/contract/scheme/list-all`;方案管理页;JWT;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项包含 `ContractSchemeVO` 全部 19 字段,包含 ACTIVE/INACTIVE。
|
||||
- **示例**:`GET .../list-all` → `{"code":200,"data":[{"schemeId":"2020001","name":"标准方案","status":"ACTIVE"},{"schemeId":"2020002","name":"旧方案","status":"INACTIVE"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.2.3 方案详情
|
||||
|
||||
- `GET /v3/admin/contract/scheme/{schemeId}`;编辑回显;JWT;幂等;路径 `schemeId:string!`。
|
||||
- **响应(完整)**:`ContractSchemeVO` 全部 19 字段。不存在返回 `510209`。
|
||||
- **示例**:`GET .../2020001` → `{"code":200,"data":{"schemeId":"2020001","name":"标准方案","contractPlatform":"12301","contractTemplateCode":"A00001","templateCode":"A00001","status":"ACTIVE"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.2.4 创建方案
|
||||
|
||||
- `POST /v3/admin/contract/scheme`;新增平台/模板/签约模式配置;JWT;非幂等。
|
||||
- **请求体**:上述 `ContractSchemeRequest` 全部 13 字段。**响应**:上述 `ContractSchemeVO` 全部 19 字段。
|
||||
- **边界/错误**:`name` 必填;手机/长度/签署模式校验;未知旅行社 `510201`。
|
||||
- **示例**:请求 `{"name":"标准方案","contractPlatform":"12301","contractTemplateCode":"A00001","contractMode":"STANDARD","signatoryMode":1,"agencyCode":"hulai","sortOrder":10}`;响应 `{"code":200,"data":{"schemeId":"2020001","name":"标准方案","status":"ACTIVE"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.2.5 更新方案
|
||||
|
||||
- `PUT /v3/admin/contract/scheme/{schemeId}`;编辑方案;JWT;目标更新可重试。
|
||||
- **入参**:路径 `schemeId:string!` + `ContractSchemeRequest` 全部字段。**响应**:`ContractSchemeVO` 全部字段。
|
||||
- **边界/错误**:已用方案创建的合同不受后续修改影响;不存在 `510209`。
|
||||
- **示例**:请求 `PUT .../2020001` + `{"name":"标准方案V2","contractPlatform":"12301","contractMode":"STANDARD"}`;响应 `{"code":200,"data":{"schemeId":"2020001","name":"标准方案V2","status":"ACTIVE"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.2.6 切换启停状态
|
||||
|
||||
- `PUT /v3/admin/contract/scheme/{schemeId}/toggle-status`;启用/停用方案;JWT;每次翻转,非幂等。
|
||||
- **入参**:`schemeId:string!`;无 body。**响应**:`ContractSchemeVO` 全部字段。不存在 `510209`。
|
||||
- **示例**:`PUT .../2020001/toggle-status` → `{"code":200,"data":{"schemeId":"2020001","status":"INACTIVE"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.2.7 删除方案
|
||||
|
||||
- `DELETE /v3/admin/contract/scheme/{schemeId}`;软删除;JWT;不保证重复调用成功。
|
||||
- **入参/响应**:`schemeId:string!`;成功 `data:null`,无其他响应字段。
|
||||
- **错误/边界**:不存在 `510209`;被产品引用 `510218`;引用校验不可用 `510219`。
|
||||
- **示例**:`DELETE .../2020001` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.3 AdminContractSchemeAttachmentController(4)
|
||||
|
||||
`AttachmentResp` 完整字段:`attachmentId:string,schemeId:string,fileName:string,ossUrl:string,ossKey:string,fileSize:long,fileType:string,sortOrder:int,createTime:datetime`。
|
||||
|
||||
#### 5.3.1 附件列表
|
||||
|
||||
- `GET /v3/admin/contract/scheme/{schemeId}/attachments`;按 `sortOrder` 升序回显;JWT;幂等;`schemeId:string!`。
|
||||
- **响应(完整)**:`data[]` 每项含 `AttachmentResp` 全部 9 字段;无配置返回 `[]`。
|
||||
- **示例**:`GET .../2020001/attachments` → `{"code":200,"data":[{"attachmentId":"1010001","schemeId":"2020001","fileName":"service.pdf","ossUrl":"https://example.invalid/a.pdf","ossKey":"contract/a.pdf","fileSize":1024,"fileType":"PDF","sortOrder":10,"createTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.3.2 上传附件
|
||||
|
||||
- `POST /v3/admin/contract/scheme/{schemeId}/attachments`;上传合同方案附件;JWT;非幂等。
|
||||
- **入参**:`schemeId:string!`;multipart `file:file!`、`fileType:string?(PDF/IMAGE/OTHER)`、`sortOrder:int?`。**响应**:`AttachmentResp` 全部 9 字段。
|
||||
- **错误/边界**:空文件、超限、OSS 不可用或上传失败都返回 `510508`。
|
||||
- **示例**:`POST .../2020001/attachments` + `file=@service.pdf&fileType=PDF&sortOrder=10` → `{"code":200,"data":{"attachmentId":"1010001","schemeId":"2020001","fileType":"PDF","sortOrder":10},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.3.3 删除附件
|
||||
|
||||
- `DELETE /v3/admin/contract/scheme/{schemeId}/attachments/{attachmentId}`;软删;JWT;路径 `schemeId:string!`,`attachmentId:string!`;无 body。
|
||||
- **响应/错误**:成功 `data:null`;附件不存在或不属于该方案 `510506`。已生成合同的旧 URL 不受影响。
|
||||
- **示例**:`DELETE .../2020001/attachments/1010001` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.3.4 更新附件排序
|
||||
|
||||
- `PUT /v3/admin/contract/scheme/{schemeId}/attachments/{attachmentId}/sort`;JWT;目标更新可重试。
|
||||
- **入参**:路径 `schemeId:string!`,`attachmentId:string!`;body `sortOrder:int!(>=0)`。**响应**:`data:null`。
|
||||
- **错误/示例**:不存在 `510506`;负数为参数校验失败。请求 `{"sortOrder":20}` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.4 AdminContractSchemeTourGuideController(4)
|
||||
|
||||
`GuideResp={guideId:string,schemeId:string,name:string,phone:string|null,licenseNumber:string|null,sortOrder:int,createTime:datetime}`;`GuideSave={name:string!(max50),phone:string?(11位手机,max20),licenseNumber:string?(max64),sortOrder:int?(>=0)}`。
|
||||
|
||||
#### 5.4.1 导游列表
|
||||
|
||||
- `GET /v3/admin/contract/scheme/{schemeId}/tour-guides`;JWT;幂等;`schemeId:string!`;未配导游返回 `[]`,不兜底。
|
||||
- **响应(完整)**:`data[]` 每项含 `GuideResp` 全部 7 字段。
|
||||
- **示例**:`GET .../2020001/tour-guides` → `{"code":200,"data":[{"guideId":"3030001","schemeId":"2020001","name":"张某","phone":"138****8000","licenseNumber":"L-XX-100001","sortOrder":0,"createTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.4.2 新增导游
|
||||
|
||||
- `POST /v3/admin/contract/scheme/{schemeId}/tour-guides`;JWT;创建加锁,非幂等。
|
||||
- **入参**:`schemeId:string!` + `GuideSave` 全部 4 字段。**响应**:`GuideResp` 全部 7 字段。
|
||||
- **边界/示例**:姓名必填;手机格式错误拒绝。请求 `{"name":"张某","phone":"13800138000","licenseNumber":"L-XX-100001","sortOrder":0}` → `{"code":200,"data":{"guideId":"3030001","schemeId":"2020001","name":"张某","phone":"13800138000","licenseNumber":"L-XX-100001","sortOrder":0,"createTime":"2026-08-04T10:00:00"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.4.3 修改导游
|
||||
|
||||
- `PUT /v3/admin/contract/scheme/{schemeId}/tour-guides/{guideId}`;JWT;目标更新可重试。
|
||||
- **入参**:`schemeId:string!`,`guideId:string!` + `GuideSave` 全部字段。**响应**:`GuideResp` 全部字段。
|
||||
- **错误/示例**:不存在/归属不符 `510507`。请求 `{"name":"李某","sortOrder":1}` → `{"code":200,"data":{"guideId":"3030001","schemeId":"2020001","name":"李某","sortOrder":1},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.4.4 删除导游
|
||||
|
||||
- `DELETE /v3/admin/contract/scheme/{schemeId}/tour-guides/{guideId}`;JWT;不保证重复调用成功。
|
||||
- **入参/响应**:`schemeId:string!`,`guideId:string!`;成功 `data:null`。不存在/归属不符 `510507`。
|
||||
- **示例**:`DELETE .../2020001/tour-guides/3030001` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.5 AdminClauseTemplateController(6)
|
||||
|
||||
`ClauseTemplateVO={templateId:string,name:string,content:string,sortOrder:int,status:string,createTime:datetime}`;`ClauseTemplateRequest={name:string!,content:string!,sortOrder:int?}`。
|
||||
|
||||
#### 5.5.1 启用模板列表
|
||||
|
||||
- `GET /v3/admin/contract/clause-template/list`;创建合同时选择;JWT;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项含 `ClauseTemplateVO` 全部 6 字段,仅 ACTIVE。
|
||||
- **示例**:`GET .../list` → `{"code":200,"data":[{"templateId":"401","name":"夏季小团","content":"脱敏示例条款","sortOrder":1,"status":"ACTIVE","createTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.5.2 全部模板列表
|
||||
|
||||
- `GET /v3/admin/contract/clause-template/list-all`;模板管理页;JWT;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项含 `ClauseTemplateVO` 全部 6 字段,包含 ACTIVE/INACTIVE。
|
||||
- **示例**:`GET .../list-all` → `{"code":200,"data":[{"templateId":"401","name":"夏季小团","content":"条款","sortOrder":1,"status":"INACTIVE","createTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.5.3 创建补充约定模板
|
||||
|
||||
- `POST /v3/admin/contract/clause-template`;JWT;非幂等。
|
||||
- **请求/响应**:body `ClauseTemplateRequest` 全部 3 字段;返回 `ClauseTemplateVO` 全部 6 字段。名称和内容必填。
|
||||
- **示例**:请求 `{"name":"夏季小团","content":"脱敏示例条款","sortOrder":1}` → `{"code":200,"data":{"templateId":"401","name":"夏季小团","content":"脱敏示例条款","sortOrder":1,"status":"ACTIVE","createTime":"2026-08-04T10:00:00"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.5.4 更新补充约定模板
|
||||
|
||||
- `PUT /v3/admin/contract/clause-template/{id}`;JWT;可重试。
|
||||
- **入参/响应**:`id:string!` + `ClauseTemplateRequest` 全部字段;返回 `ClauseTemplateVO` 全部字段。旧合同快照不受影响。
|
||||
- **错误/示例**:不存在 `510211`。请求 `{"name":"夏季小团V2","content":"新条款","sortOrder":2}` → `{"code":200,"data":{"templateId":"401","name":"夏季小团V2","content":"新条款","sortOrder":2,"status":"ACTIVE"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.5.5 切换模板启停
|
||||
|
||||
- `PUT /v3/admin/contract/clause-template/{id}/toggle-status`;JWT;每次翻转,非幂等。
|
||||
- **入参/响应**:`id:string!`;无 body;返回 `ClauseTemplateVO` 全部 6 字段。不存在 `510211`。
|
||||
- **示例**:`PUT .../401/toggle-status` → `{"code":200,"data":{"templateId":"401","name":"夏季小团","content":"条款","sortOrder":1,"status":"INACTIVE","createTime":"2026-08-04T10:00:00"},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.5.6 删除补充约定模板
|
||||
|
||||
- `DELETE /v3/admin/contract/clause-template/{id}`;JWT;软删;重复调用不保证成功。
|
||||
- **入参/响应**:`id:string!`;成功 `data:null`。已创建合同保留快照。不存在 `510211`。
|
||||
- **示例**:`DELETE .../401` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.6 AdminTravelAgencyController(11)
|
||||
|
||||
`AgencySimpleResp={agencyId:string,code,agencyName,isPrimary:int,sortOrder:int,createTime,updateTime}`。
|
||||
|
||||
`AgencyResp` 完整字段:`agencyId:string,code,agencyName,licenseNumber,businessLicenseNumber,agencyCountry,agencyState,agencyCity,agencyDistrict,agencyAddress,transactorName,transactorPhone,email,bankCard,complaintPhone,complaintProvince,complaintCity,complaintAreaCode,complaintAddress,tribunalName,litigationCourt,regionId,businessScope,zjParentId,appId,signKey,teamReportAppId,teamReportSignKey,supportedPlatforms,supportedPlatformsList[],supportedPlatformsLabels[],isPrimary,status,statusLabel,sortOrder,visible,remark,qualifications[],payments[],createTime,updateTime`。
|
||||
`AgencySave` 完整字段:`code:string!(2..32,小写字母/数字/-),agencyName:string!(max128),licenseNumber:string?(max64),businessLicenseNumber:string!,agencyCountry,agencyState,agencyCity,agencyDistrict,agencyAddress,transactorName,transactorPhone,email,bankCard,complaintPhone,complaintProvince,complaintCity,complaintAreaCode,complaintAddress,tribunalName,litigationCourt,regionId,businessScope,zjParentId:int?,appId,signKey,teamReportAppId,teamReportSignKey,supportedPlatforms:string(JSON array),isPrimary:int?(0/1),status:string?,sortOrder:int?,visible:int?(0/1),remark`。
|
||||
|
||||
#### 5.6.1 旅行社分页
|
||||
|
||||
- `GET /v3/admin/travel-agency/page`;管理列表;ADMIN+;幂等。
|
||||
- **Query(全部)**:`page:int?`,`pageSize:int?`,`status:string?(ENABLED/DISABLED)`,`isPrimary:int?(0/1)`,`agencyName:string?`。
|
||||
- **响应(完整)**:`records[]` 每项含上述 `AgencyResp` 全部字段;顶层 `total,page,pageSize`。
|
||||
- **示例**:`GET .../page?page=1&pageSize=10&status=ENABLED` → `{"code":200,"data":{"records":[{"agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","status":"ENABLED","statusLabel":"启用","qualifications":[],"payments":[]}],"total":1,"page":1,"pageSize":10},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.2 启用旅行社下拉
|
||||
|
||||
- `GET /v3/admin/travel-agency/enabled`;ADMIN+;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项含 `AgencySimpleResp` 全部 7 字段。
|
||||
- **示例**:`GET .../enabled` → `{"code":200,"data":[{"agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","isPrimary":1,"sortOrder":1,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.3 产品页可用旅行社
|
||||
|
||||
- `GET /v3/admin/travel-agency/enabled-for-product`;过滤经营许可证号为空的公司;ADMIN+;幂等;无入参。
|
||||
- **响应(完整)**:`data[]` 每项含 `AgencySimpleResp` 全部 7 字段。
|
||||
- **示例**:`GET .../enabled-for-product` → `{"code":200,"data":[{"agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","isPrimary":1,"sortOrder":1,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.4 按合同平台筛选旅行社
|
||||
|
||||
- `GET /v3/admin/travel-agency/enabled-by-platform`;合同方案下拉;ADMIN+;幂等。
|
||||
- **Query**:`contractPlatform:string!` (`12301`/`TENCENT_ESIGN`)。**响应**:`AgencySimpleResp` 全部 7 字段;主体公司优先、ID 升序。
|
||||
- **边界/示例**:空值返回“合同平台不能为空”。`GET .../enabled-by-platform?contractPlatform=12301` → `{"code":200,"data":[{"agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","isPrimary":1,"sortOrder":1,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-04T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.5 旅行社详情
|
||||
|
||||
- `GET /v3/admin/travel-agency/{id}`;含资质和支付子表;ADMIN+;幂等;`id:string!`。
|
||||
- **响应(完整)**:上述 `AgencyResp` 全部字段;`qualifications[]` 字段见 5.7;`payments[]` 字段见 5.8。不存在 `594001`。
|
||||
- **示例**:`GET .../7001` → `{"code":200,"data":{"agencyId":"7001","code":"hulai","agencyName":"呼籁旅行社","status":"ENABLED","qualifications":[],"payments":[]},"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.6 新建旅行社
|
||||
|
||||
- `POST /v3/admin/travel-agency`;SUPER_ADMIN;非幂等。
|
||||
- **请求体**:上述 `AgencySave` 全部 33 字段。**响应**:`data:string` 新 agencyId,无其他 data 字段。
|
||||
- **边界/错误**:编码重复 `594010`;非 SUPER_ADMIN `594009`;编码格式/必填/长度校验。高敏 key 不得打印。
|
||||
- **示例**:请求 `{"code":"demo-agency","agencyName":"示例旅行社","businessLicenseNumber":"9115********0001","supportedPlatforms":"[\"12301\"]","status":"ENABLED","isPrimary":0,"visible":1}` → `{"code":200,"data":"7002","message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.7 编辑旅行社
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{id}`;ADMIN+;目标更新可重试。
|
||||
- **入参/响应**:`id:string!` + `AgencySave` 全部字段;成功 `data:null`。`code` 编辑时不可改。
|
||||
- **错误/示例**:不存在 `594001`。请求 `{"code":"hulai","agencyName":"呼籁旅行社","businessLicenseNumber":"9115********0001","status":"ENABLED"}` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.8 停用旅行社
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{id}/disable`;ADMIN+;路径 `id:string!`;无 body;目标状态幂等。
|
||||
- **响应/错误**:成功 `data:null`;不存在 `594001`;主体公司不可停用 `594005`。
|
||||
- **示例**:`PUT .../7002/disable` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.9 启用旅行社
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{id}/enable`;ADMIN+;路径 `id:string!`;无 body;目标状态幂等。
|
||||
- **响应/错误**:成功 `data:null`;不存在 `594001`。
|
||||
- **示例**:`PUT .../7002/enable` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.10 删除旅行社
|
||||
|
||||
- `DELETE /v3/admin/travel-agency/{id}`;ADMIN+;强保留语义(状态置 DISABLED);不保证重复调用成功。
|
||||
- **入参/响应**:`id:string!`;成功 `data:null`。
|
||||
- **错误/边界**:`594001`;主体公司 `594005`;本接口不做物理删除。
|
||||
- **示例**:`DELETE .../7002` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.6.11 设为主体公司
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{id}/set-primary`;SUPER_ADMIN;路径 `id:string!`;无 body;目标状态幂等。
|
||||
- **响应/错误**:成功 `data:null`;`594001`;目标停用或主体约束失败 `594005/594006`;非 SUPER_ADMIN `594009`。
|
||||
- **示例**:`PUT .../7001/set-primary` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.7 AdminTravelAgencyQualificationController(4)
|
||||
|
||||
`QualificationResp={qualificationId:string,agencyId:string,name,qualificationType,qualificationTypeLabel,fileUrl,fileType,fileTypeLabel,issueDate,expireDate,sortOrder,remark,createTime,updateTime}`。
|
||||
`QualificationSave={name:string!(max64),qualificationType:string!(max32),fileUrl:string!,fileType:string?(PDF/IMAGE/OTHER),issueDate:date?,expireDate:date|null,sortOrder:int?,remark:string?}`。
|
||||
|
||||
#### 5.7.1 资质列表
|
||||
|
||||
- `GET /v3/admin/travel-agency/{agencyId}/qualification`;ADMIN+;幂等;`agencyId:string!`。
|
||||
- **响应(完整)**:`data[]` 每项含 `QualificationResp` 全部 14 字段;`fileUrl` 为有效期 30 分钟的临时 URL。
|
||||
- **示例**:`GET .../7001/qualification` → `{"code":200,"data":[{"qualificationId":"8001","agencyId":"7001","name":"旅行社业务经营许可证","qualificationType":"TRAVEL_AGENCY_LICENSE","qualificationTypeLabel":"旅行社业务经营许可证","fileUrl":"https://example.invalid/temp?token=masked","fileType":"PDF","fileTypeLabel":"PDF","issueDate":"2024-01-01","expireDate":null,"sortOrder":1,"remark":null,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-01T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.7.2 新增资质
|
||||
|
||||
- `POST /v3/admin/travel-agency/{agencyId}/qualification`;ADMIN+;非幂等。
|
||||
- **入参/响应**:`agencyId:string!` + `QualificationSave` 全部 8 字段;成功 `data:string` 新 qualificationId。
|
||||
- **错误/边界**:文件无效(>10MB、非 PDF/JPG/PNG、上传失败)`594008`;长期有效传 `expireDate:null`。
|
||||
- **示例**:请求 `{"name":"旅行社业务经营许可证","qualificationType":"TRAVEL_AGENCY_LICENSE","fileUrl":"oss://private/masked.pdf","fileType":"PDF","issueDate":"2024-01-01","expireDate":null,"sortOrder":1}` → `{"code":200,"data":"8001","message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.7.3 编辑资质
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{agencyId}/qualification/{qualificationId}`;ADMIN+;目标更新可重试。
|
||||
- **入参/响应**:路径中 `agencyId` 用于 URL 归类,后端操作键为 `qualificationId:string!`;body `QualificationSave` 全部字段;成功 `data:null`。
|
||||
- **错误/示例**:不存在 `594001`;文件无效 `594008`。请求 `{"name":"经营许可证(新)","qualificationType":"TRAVEL_AGENCY_LICENSE","fileUrl":"oss://private/masked.pdf","fileType":"PDF"}` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.7.4 删除资质
|
||||
|
||||
- `DELETE /v3/admin/travel-agency/{agencyId}/qualification/{qualificationId}`;ADMIN+;软删;不保证重复调用成功。
|
||||
- **入参/响应**:`qualificationId:string!`;成功 `data:null`;不存在 `594001`。
|
||||
- **示例**:`DELETE .../7001/qualification/8001` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
### 5.8 AdminTravelAgencyPaymentController(5)
|
||||
|
||||
`PaymentResp={paymentId:string,agencyId:string,name,mchId,appId,apiV3Key,mchSerialNo,publicKeyId,privateKeyPath,publicKeyPath,isDefault:int,status,statusLabel,remark,createTime,updateTime}`。
|
||||
`PaymentSave={name:string!(max64),mchId:string!(max32),appId:string!(max64),apiV3Key:string!,mchSerialNo:string?,publicKeyId:string?,isDefault:int?(0/1),status:string?(ENABLED/DISABLED),remark:string?}`。这些接口包含高敏密钥/证书信息,仅 SUPER_ADMIN 使用,响应不得写入日志、埋点或客户端持久存储。
|
||||
|
||||
#### 5.8.1 支付配置列表
|
||||
|
||||
- `GET /v3/admin/travel-agency/{agencyId}/payment`;SUPER_ADMIN;幂等;`agencyId:string!`。
|
||||
- **响应(完整)**:`data[]` 每项含 `PaymentResp` 全部 16 字段。
|
||||
- **示例(脱敏)**:`GET .../7001/payment` → `{"code":200,"data":[{"paymentId":"9001","agencyId":"7001","name":"微信支付-主商户","mchId":"1106******39","appId":"wx************ff36","apiV3Key":"***","mchSerialNo":"***","publicKeyId":"PUB_***","privateKeyPath":"cert/***/apiclient_key.pem","publicKeyPath":"cert/***/public_key.pem","isDefault":1,"status":"ENABLED","statusLabel":"启用","remark":null,"createTime":"2026-08-01T10:00:00","updateTime":"2026-08-01T10:00:00"}],"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.8.2 新增支付配置
|
||||
|
||||
- `POST /v3/admin/travel-agency/{agencyId}/payment`;SUPER_ADMIN;非幂等。
|
||||
- **入参/响应**:`agencyId:string!` + `PaymentSave` 全部 9 字段;成功 `data:string` 新 paymentId。`privateKeyPath/publicKeyPath` 不接受前端传入。
|
||||
- **错误/边界**:商户号重复 `594011`;非 SUPER_ADMIN `594009`;必填/长度校验。
|
||||
- **示例(虚构)**:请求 `{"name":"微信支付-主商户","mchId":"1900000001","appId":"wxdemo000000000001","apiV3Key":"***REDACTED***","mchSerialNo":"***REDACTED***","publicKeyId":"PUB_DEMO","isDefault":1,"status":"ENABLED"}` → `{"code":200,"data":"9001","message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.8.3 编辑支付配置
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{agencyId}/payment/{paymentId}`;SUPER_ADMIN;目标更新可重试。
|
||||
- **入参/响应**:URL 含 `agencyId`,操作键为 `paymentId:string!`;body `PaymentSave` 全部字段;成功 `data:null`。
|
||||
- **错误/示例**:不存在 `594001`;商户号冲突 `594011`。请求 `{"name":"微信支付-主商户","mchId":"1900000001","appId":"wxdemo000000000001","apiV3Key":"***REDACTED***","status":"ENABLED"}` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.8.4 删除支付配置
|
||||
|
||||
- `DELETE /v3/admin/travel-agency/{agencyId}/payment/{paymentId}`;SUPER_ADMIN;不保证重复调用成功。
|
||||
- **入参/响应**:`paymentId:string!`;成功 `data:null`。
|
||||
- **错误/边界**:不存在 `594001`;默认商户不可删 `594007`,须先将另一条设为默认。
|
||||
- **示例**:`DELETE .../7001/payment/9002` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
#### 5.8.5 设为默认支付商户
|
||||
|
||||
- `PUT /v3/admin/travel-agency/{agencyId}/payment/{paymentId}/set-default`;SUPER_ADMIN;目标状态幂等。
|
||||
- **入参/响应**:`agencyId:string!`,`paymentId:string!`;无 body;成功 `data:null`。
|
||||
- **错误/边界**:支付配置不存在/归属不符 `594001`;同一公司最多一条 `isDefault=1`。
|
||||
- **示例**:`PUT .../7001/payment/9001/set-default` → `{"code":200,"data":null,"message":"操作成功","success":true}`。
|
||||
|
||||
## 6. 枚举/数据字典(按类型分表)
|
||||
|
||||
### 6.1 `contract_status`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `PENDING` | 待生成 | 初始等待 |
|
||||
| `GENERATED` | 已生成 | 合同已生成,待签署 |
|
||||
| `SIGNING` | 签署中 | 平台签署流程中 |
|
||||
| `SIGNED` | 已签署 | 签署完成 |
|
||||
| `REPORTED` | 已上报 | SYNC 报备完成 |
|
||||
| `UPLOADED` | 已上传 | SYNC PDF 已上传 |
|
||||
| `VOIDING` | 作废中 | 等待平台确认 |
|
||||
| `VOIDED` | 已作废 | 终态 |
|
||||
|
||||
### 6.2 `contract_platform`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `12301` | 12301 团队报送 | 监管平台 |
|
||||
| `LOCAL` | 本地/线下 | 本地报备 |
|
||||
| `TENCENT_ESIGN` | 腾讯电子签 | 电子签约 |
|
||||
|
||||
### 6.3 `contract_mode`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `STANDARD` | 电子签约 | 平台生成并签署 |
|
||||
| `SYNC` | 线下报备 | 线下签署后报备/上传 |
|
||||
|
||||
### 6.4 `common_status` / `contract_scheme_status` / `contract_template_status`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `ACTIVE` | 启用 | 可供新业务选择 |
|
||||
| `INACTIVE` | 停用 | 历史引用不受影响 |
|
||||
|
||||
### 6.5 `contract_attachment_type`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `PDF` | PDF | PDF 附件 |
|
||||
| `IMAGE` | 图片 | 图片附件 |
|
||||
| `OTHER` | 其他 | 其他文件 |
|
||||
|
||||
### 6.6 `agency_status`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `ENABLED` | 启用 | 可被产品/合同选择 |
|
||||
| `DISABLED` | 停用 | 不可用于新业务 |
|
||||
|
||||
### 6.7 `agency_contract_platform`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `12301` | 12301 团队报送 | 旅行社已开通 12301 |
|
||||
| `TENCENT_ESIGN` | 腾讯电子签 | 旅行社已开通腾讯电子签 |
|
||||
|
||||
### 6.8 `agency_qualification_type`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `BUSINESS_LICENSE` | 营业执照 | 公司营业执照 |
|
||||
| `TRAVEL_AGENCY_LICENSE` | 旅行社业务经营许可证 | 旅行社经营资质 |
|
||||
| `VALUE_ADDED_TELECOM_LICENSE` | 增值电信业务经营许可证 | 电信业务资质 |
|
||||
|
||||
### 6.9 `agency_qualification_file_type`
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|---|---|---|
|
||||
| `PDF` | PDF | PDF 文件 |
|
||||
| `IMAGE` | 图片 | JPG/PNG 等 |
|
||||
| `OTHER` | 其他 | 其他类型(服务端仍会做安全校验) |
|
||||
|
||||
### 6.10 其他取值
|
||||
|
||||
| 字段 | 值 | 说明 |
|
||||
|---|---|---|
|
||||
| `contractType` | `TOUR` / `INSURANCE` | 旅游合同 / 保险单 |
|
||||
| `signatoryMode` | `1` / `2` / `3` | 短信 / 现场 / 线下 |
|
||||
| `paymentMethod` | `1` / `2` / `3` | 现金 / 转账 / 在线 |
|
||||
| `disputeResolution` | `1` / `2` | 诉讼 / 仲裁 |
|
||||
| `insurancePurchaseMethod` | `1` / `2` / `3` | 委托旅行社 / 自行购买 / 放弃 |
|
||||
| `gender` | `0` / `1` / `2` | 未知 / 男 / 女 |
|
||||
| `idCardType` | `1` / `2` | 身份证 / 护照 |
|
||||
| `channel` | `MP` / `ADMIN` / `CHANNEL` / `null` | 小程序 / 管理端 / 分销 / 兜底 |
|
||||
|
||||
## 7. 错误码摘要
|
||||
|
||||
| code | 含义 | 典型接口 |
|
||||
|---:|---|---|
|
||||
| 510001 | 合同不存在 | 详情/作废/下载/刷新/上传 |
|
||||
| 510005-510008 | 短信重发状态、频控或必要数据缺失 | 重发短信 |
|
||||
| 510101-510107 | 下载/刷新/作废/PDF 上传业务校验 | 合同写操作 |
|
||||
| 510201-510220 | 旅行社、方案、模板、订单、签署人及重复合同校验 | 创建/方案管理 |
|
||||
| 510403 | 腾讯电子签不支持 SYNC | 报备合同 |
|
||||
| 510506-510508 | 附件/导游不存在或上传失败 | 方案附件/导游 |
|
||||
| 594001 | 旅行社或其子资源不存在 | 旅行社/资质/支付 |
|
||||
| 594005-594006 | 主体公司约束 | 停用/删除/设为主体 |
|
||||
| 594007 | 默认支付商户不可删 | 删除支付配置 |
|
||||
| 594008 | 资质文件无效 | 新增/编辑资质 |
|
||||
| 594009 | 仅 SUPER_ADMIN 可执行 | 敏感管理操作 |
|
||||
| 594010 | 旅行社编码重复 | 新建旅行社 |
|
||||
| 594011 | 微信支付商户号冲突 | 新增/编辑支付配置 |
|
||||
|
||||
## 8. 业务边界与 v1/v3 数据隔离
|
||||
|
||||
- 根据 Issue #5368 在 2026-08-04 的决策,管理后台合同整页的列表、详情、创建、作废、刷新、下载、短信和上传统一调用 `/v3/admin/*`。
|
||||
- v1 存量合同不迁移,自然消亡;新合同全部走 v3。
|
||||
- v1 与 v3 合同数据不互通;不得把 v3 响应的 `contractId` 传给 v1 端点,也不得用 v3 详情读 v1 旧 ID。
|
||||
- `teamNo` 未生成时为 `null`;不得用 `orderNo` 伪装团号。
|
||||
- 列表多条件为 AND;文本筛选是数据库分页前的包含匹配,`total` 与翻页结果一致。
|
||||
|
||||
## 9. 修改前后对比
|
||||
|
||||
| 维度 | 修改前 | 修改后 |
|
||||
|---|---|---|
|
||||
| 订单号搜索 | 合同列表不能独立按 `orderNo` 查询 | 可传 `orderNo` 包含匹配 |
|
||||
| 文本空白 | 语义未完整固化 | 三个文本条件 trim,全空白忽略 |
|
||||
| LIKE 特殊字符 | 可能被当作通配符 | `%`、`_`、`\` 按字面字符 |
|
||||
| 数据版本 | 前端可能仍混用 v1/v3 | 合同整页读写统一 v3,v1 存量不迁移 |
|
||||
|
||||
## 10. 影响评估/回滚
|
||||
|
||||
- **向后兼容**:是。`orderNo` 为新增可选 query;原有参数和响应字段不删除。
|
||||
- **前端是否必须同步上线**:不必与后端强绑同时上线;但合同页应尽快切到本文的 v3 端点,否则无法正确消费 v3 数据。
|
||||
- **回滚后前端行为**:停止传递 `orderNo`;保留原 `teamNo/contactName` 及其他查询。不得回滚为 v1/v3 混用。
|
||||
|
||||
## 11. 注意事项
|
||||
|
||||
- 前端可清理“拉全量合同后在浏览器按订单号过滤”的 workaround,直接传 `orderNo`。
|
||||
- 请求参数中用户输入的 `%`、`_`、`\` 不需前端自行转义;正常 URL 编码即可。
|
||||
- 支付配置、证书、身份证、手机号和签约密钥都不得写入前端日志/埋点;本文示例全部为虚构脱敏值。
|
||||
|
||||
## 12. 关联/联系人
|
||||
|
||||
- **Issue**: [#5368](https://git.1814.love:8443/wx/HL/issues/5368)
|
||||
- **PR**: [#5501](https://git.1814.love:8443/wx/HL/pulls/5501)
|
||||
- **Merge commit**: [45117d3d5896515909e303dcbfa9d3616f881803](https://git.1814.love:8443/wx/HL/commit/45117d3d5896515909e303dcbfa9d3616f881803)
|
||||
- **Head commit**: [f66d236f2aea2d0a63db8cb58d59f2ae74e2b6fb](https://git.1814.love:8443/wx/HL/commit/f66d236f2aea2d0a63db8cb58d59f2ae74e2b6fb)
|
||||
- **前置契约**: PR #5386 / commit `c9d1b12618` 的 `teamNo` 与 v3 写侧说明
|
||||
- **后端负责人**: 腰苏图
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户