{
  "openapi": "3.0.3",
  "info": {
    "title": "三全消费机支付宝内部接口",
    "version": "1.0.0",
    "description": "store 调用 ai_api 的支付宝付款码支付、查单和退款接口。支付接口内部包含支付结果不明确时的自动查单与支付宝撤销流程；当前没有独立对外撤销路由。三个接口均为服务间内部接口，顶层 status=200 仅表示接口正常处理；支付、查单和退款的业务结果必须继续检查 data.status。生产环境必须携带内部令牌。"
  },
  "servers": [
    {
      "url": "http://127.0.0.1/aizhct",
      "description": "本地 Docker 示例，现场替换为实际 ai_api 地址"
    }
  ],
  "tags": [
    {
      "name": "支付宝消费支付",
      "description": "消费机订单的 ai_api 内部支付能力"
    }
  ],
  "paths": {
    "/index.php?s=api/InternalPayment/pay": {
      "post": {
        "summary": "消费订单支付宝付款码支付",
        "description": "# 接口 A：消费订单支付宝付款码支付\n\n## 1. 接口概述\n\nstore 创建待支付消费订单后调用本接口。ai_api 根据 `storeId` 隔离交易数据，读取配置的支付宝支付模板，创建 `order_type=200` 的 `yoshop_payment_trade` 交易记录，并调用支付宝当面付付款码支付。\n\n首次支付时 `trade_id` 传 `0`；已有交易重试时传原 `trade_id`。已支付交易重复调用直接返回原成功结果，不重复扣款；已关闭交易返回 `CLOSED`。\n\n## 2. 接口信息\n\n- **接口地址**：`https://xxx.com/index.php?s=api/InternalPayment/pay`\n- **请求方法**：POST\n- **Content-Type**：`application/x-www-form-urlencoded`\n- **接口版本**：v1.0\n\n## 3. 请求头（Header）\n\n| 参数名 | 类型 | 是否必填 | 描述 | 示例值 |\n| --- | --- | --- | --- | --- |\n| storeId | Integer | 是 | 商城 ID，用于交易数据隔离 | 10001 |\n| Payment-Internal-Token | String | 是 | store 与 ai_api 约定的内部令牌；local 环境可省略 | 不提供固定示例 |\n| Payment-Auth-Code | String | 是 | 用户当前支付宝动态付款码；真实环境可能立即扣款 | 运行时临时输入 |\n\n## 4. 请求参数（Body）\n\n| 参数名 | 类型 | 是否必填 | 描述 | 示例值 |\n| --- | --- | --- | --- | --- |\n| trade_id | Integer | 否 | ai_api 交易主键；首次支付传 0，已有交易重试传原 trade_id | 0 |\n| order_id | Integer | 是 | store 的 `ydy_meal_order.id` | 68001 |\n| order_no | String | 是 | store 消费订单号，同时作为支付宝 `out_trade_no`；同一业务支付保持不变 | 260902100000001 |\n| total_amount | String | 是 | 应付金额，单位元，必须大于 0，保留两位小数 | 0.01 |\n\n请求示例：\n\n```text\ntrade_id=0&order_id=68001&order_no=260902100000001&total_amount=0.01\n```\n\n付款码通过 `Payment-Auth-Code` 请求头传递，不放入普通 Body。local 环境可使用固定码 `2999999999999999` 做无资金验证；非 local 环境会调用真实支付宝。\n\n## 5. 响应格式\n\n**支付成功响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"trade_id\": 530,\n    \"out_trade_no\": \"260902100000001\",\n    \"trade_no\": \"2026090322001000000000000001\",\n    \"status\": \"SUCCESS\",\n    \"trade_state\": 20\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**支付处理中响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"trade_id\": 530,\n    \"out_trade_no\": \"260902100000001\",\n    \"trade_no\": \"\",\n    \"status\": \"PAYING\",\n    \"trade_state\": 10\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**明确支付失败响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"trade_id\": 530,\n    \"out_trade_no\": \"260902100000001\",\n    \"trade_no\": \"\",\n    \"status\": \"FAILED\",\n    \"trade_state\": 40\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**接口处理失败响应示例**\n\n```json\n{\n  \"status\": 500,\n  \"message\": \"缺少参数total_amount\",\n  \"data\": [],\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n注意：顶层 `status=200` 只代表接口正常处理。store 必须检查 `data.status`；只有 `SUCCESS` 才表示支付成功。\n\n## 6. 状态说明\n\n| status / data.status | 描述 | store 处理方式 |\n| --- | --- | --- |\n| 顶层 status=200 | 接口正常处理 | 继续检查 data.status |\n| 顶层 status=500 | 明确业务或系统异常 | 记录 trace_id 和失败原因，不标记支付成功 |\n| SUCCESS | 支付成功 | 将消费订单更新为已支付并保存 trade_id |\n| PAYING | 支付处理中 | 保持待支付，按原 trade_id 调用查单接口 |\n| UNKNOWN | 支付结果未知 | 保持待支付，按原 trade_id 调用查单接口 |\n| FAILED | 明确支付失败 | 不得更新为已支付 |\n| CLOSED | 交易已关闭 | 不得更新为已支付 |\n\n## 7. 响应字段说明\n\n| 字段名 | 类型 | 描述 |\n| --- | --- | --- |\n| status | Integer | 顶层接口结果：200 正常处理、500 明确异常 |\n| message | String | 接口处理消息或失败原因 |\n| data | Object / Array | 正常时为交易对象；失败时可能为空数组 |\n| data.trade_id | Integer | ai_api 交易主键，store 保存到 `ydy_meal_order.trade_id` |\n| data.out_trade_no | String | 支付宝商户订单号，即 store 消费订单号 |\n| data.trade_no | String | 支付宝交易号，尚未生成时为空 |\n| data.status | String | 支付业务状态 |\n| data.trade_state | Integer | 本地交易状态：10未支付、20支付成功、30转入退款、40已关闭 |\n| trace_id | String | 本次请求链路标识 |\n\n## 8. trace_id 说明\n\n本接口通过系统通用返回方法在响应顶层返回 `trace_id`。问题排查时请优先提供 `trace_id`，并补充接口调用时间、`storeId`、`order_id`、`order_no`、`trade_id`、顶层 `status`、`message` 和 `data.status`。不要在普通日志或工单中粘贴完整内部令牌。",
        "x-apifox-folder": "支付宝消费支付",
        "parameters": [
          {"$ref": "#/components/parameters/StoreId"},
          {"$ref": "#/components/parameters/InternalToken"},
          {"$ref": "#/components/parameters/AuthCode"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/PayRequest"},
              "examples": {
                "firstPay": {
                  "summary": "首次支付",
                  "value": {
                    "trade_id": 0,
                    "order_id": 68001,
                    "order_no": "260902100000001",
                    "total_amount": "0.01"
                  }
                },
                "retryExistingTrade": {
                  "summary": "复用已有交易重试",
                  "value": {
                    "trade_id": 530,
                    "order_id": 68001,
                    "order_no": "260902100000001",
                    "total_amount": "0.01"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {"$ref": "#/components/schemas/PayRequest"}
            }
          }
        },
        "responses": {
          "200": {
            "description": "HTTP 固定正常响应；顶层 status=200 后必须继续判断 data.status",
            "content": {
              "application/json": {
                "schema": {"oneOf": [{"$ref": "#/components/schemas/TradeResponse"}, {"$ref": "#/components/schemas/ErrorResponse"}]},
                "examples": {
                  "success": {"summary": "支付成功", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001", "trade_no": "2026090322001000000000000001", "status": "SUCCESS", "trade_state": 20}, "trace_id": "6a671d7d5539d"}},
                  "paying": {"summary": "支付处理中，服务端进入自动查单与撤销流程", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001-530", "trade_no": "", "status": "PAYING", "trade_state": 10}, "trace_id": "6a671d7d5539d"}},
                  "closed": {"summary": "支付宝撤销成功，交易已关闭", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001-530", "trade_no": "", "status": "CLOSED", "trade_state": 40}, "trace_id": "6a671d7d5539d"}},
                  "unknown": {"summary": "查单及撤销重试后结果仍未知", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001-530", "trade_no": "", "status": "UNKNOWN", "trade_state": 10}, "trace_id": "6a671d7d5539d"}},
                  "failed": {"summary": "明确支付失败", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001", "trade_no": "", "status": "FAILED", "trade_state": 40}, "trace_id": "6a671d7d5539d"}},
                  "businessError": {"summary": "参数或配置错误", "value": {"status": 500, "message": "缺少参数total_amount", "data": [], "trace_id": "6a671d7d5539d"}}
                }
              }
            }
          }
        }
      }
    },
    "/index.php?s=api/InternalPayment/query": {
      "post": {
        "summary": "查询消费订单支付宝交易",
        "description": "# 接口 B：查询消费订单支付宝交易\n\n## 1. 接口概述\n\n按 ai_api 的 `yoshop_payment_trade.trade_id` 查询消费订单支付宝交易。本地状态为支付成功、已退款或已关闭时直接返回本地终态；本地尚未支付时调用支付宝 `alipay.trade.query`，并同步支付宝交易号和交易状态。本接口只接受 `order_type=200` 的消费订单交易。\n\n## 2. 接口信息\n\n- **接口地址**：`https://xxx.com/index.php?s=api/InternalPayment/query`\n- **请求方法**：POST\n- **Content-Type**：`application/x-www-form-urlencoded`\n- **接口版本**：v1.0\n\n## 3. 请求头（Header）\n\n| 参数名 | 类型 | 是否必填 | 描述 | 示例值 |\n| --- | --- | --- | --- | --- |\n| storeId | Integer | 是 | 商城 ID，用于交易数据隔离 | 10001 |\n| Payment-Internal-Token | String | 是 | store 与 ai_api 约定的内部令牌；local 环境可省略 | 不提供固定示例 |\n\n## 4. 请求参数（Body）\n\n| 参数名 | 类型 | 是否必填 | 描述 | 示例值 |\n| --- | --- | --- | --- | --- |\n| trade_id | Integer | 是 | 支付接口返回并写入 `ydy_meal_order.trade_id` 的 ai_api 交易主键 | 530 |\n\n请求示例：\n\n```text\ntrade_id=530\n```\n\n## 5. 响应格式\n\n**查询到支付成功响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"trade_id\": 530,\n    \"out_trade_no\": \"260902100000001\",\n    \"trade_no\": \"2026090322001000000000000001\",\n    \"status\": \"SUCCESS\",\n    \"trade_state\": 20\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**仍在支付中响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"trade_id\": 530,\n    \"out_trade_no\": \"260902100000001\",\n    \"trade_no\": \"\",\n    \"status\": \"PAYING\",\n    \"trade_state\": 10\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**交易已退款响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"trade_id\": 530,\n    \"out_trade_no\": \"260902100000001\",\n    \"trade_no\": \"2026090322001000000000000001\",\n    \"status\": \"REFUNDED\",\n    \"trade_state\": 30\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**交易不存在响应示例**\n\n```json\n{\n  \"status\": 500,\n  \"message\": \"第三方支付交易不存在\",\n  \"data\": [],\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n注意：顶层 `status=200` 只代表查单接口正常处理，仍须检查 `data.status`。\n\n## 6. 状态说明\n\n| status / data.status | trade_state | 描述 | store 处理方式 |\n| --- | ---: | --- | --- |\n| 顶层 status=200 | - | 接口正常处理 | 继续检查 data.status |\n| 顶层 status=500 | - | 交易不存在或明确异常 | 记录 trace_id，不更新支付状态 |\n| SUCCESS | 20 | 支付成功 | 将待支付消费订单更新为已支付 |\n| PAYING | 10 | 支付处理中 | 保持待支付，后续继续查单 |\n| UNKNOWN | 10 | 支付结果未知 | 保持待支付，后续继续查单 |\n| FAILED | 40 | 明确支付失败 | 不得标记支付成功 |\n| CLOSED | 40 | 交易已关闭 | 不得标记支付成功 |\n| REFUNDED | 30 | 已转入退款 | 按已退款状态处理 |\n\n## 7. 响应字段说明\n\n| 字段名 | 类型 | 描述 |\n| --- | --- | --- |\n| status | Integer | 顶层接口结果：200 正常处理、500 明确异常 |\n| message | String | 接口处理消息或失败原因 |\n| data | Object / Array | 正常时为交易对象；失败时可能为空数组 |\n| data.trade_id | Integer | ai_api 交易主键 |\n| data.out_trade_no | String | 支付宝商户订单号，即 store 消费订单号 |\n| data.trade_no | String | 支付宝交易号，尚未生成时为空 |\n| data.status | String | 查询得到的支付业务状态 |\n| data.trade_state | Integer | 本地交易状态：10未支付、20支付成功、30转入退款、40已关闭 |\n| trace_id | String | 本次请求链路标识 |\n\n## 8. trace_id 说明\n\n问题排查时请优先提供 `trace_id`，并补充查单时间、`storeId`、`trade_id`、顶层 `status`、`message`、`data.status`、`out_trade_no` 和 `trade_no`。不要提供完整内部令牌。",
        "x-apifox-folder": "支付宝消费支付",
        "parameters": [
          {"$ref": "#/components/parameters/StoreId"},
          {"$ref": "#/components/parameters/InternalToken"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/QueryRequest"},
              "example": {"trade_id": 530}
            },
            "application/x-www-form-urlencoded": {
              "schema": {"$ref": "#/components/schemas/QueryRequest"}
            }
          }
        },
        "responses": {
          "200": {
            "description": "查单结果；顶层 status=200 后继续判断 data.status",
            "content": {
              "application/json": {
                "schema": {"oneOf": [{"$ref": "#/components/schemas/TradeResponse"}, {"$ref": "#/components/schemas/ErrorResponse"}]},
                "examples": {
                  "success": {"summary": "交易支付成功", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001", "trade_no": "2026090322001000000000000001", "status": "SUCCESS", "trade_state": 20}, "trace_id": "6a671d7d5539d"}},
                  "paying": {"summary": "仍在支付中", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001", "trade_no": "", "status": "PAYING", "trade_state": 10}, "trace_id": "6a671d7d5539d"}},
                  "refunded": {"summary": "交易已退款", "value": {"status": 200, "message": "success", "data": {"trade_id": 530, "out_trade_no": "260902100000001", "trade_no": "2026090322001000000000000001", "status": "REFUNDED", "trade_state": 30}, "trace_id": "6a671d7d5539d"}},
                  "notFound": {"summary": "交易不存在", "value": {"status": 500, "message": "第三方支付交易不存在", "data": [], "trace_id": "6a671d7d5539d"}}
                }
              }
            }
          }
        }
      }
    },
    "/index.php?s=api/InternalPayment/refund": {
      "post": {
        "summary": "消费订单支付宝退款",
        "description": "# 接口 C：消费订单支付宝退款\n\n## 1. 接口概述\n\n对已支付的消费订单支付宝交易发起退款。本接口调用支付宝 `alipay.trade.refund`，不调用撤销接口。`trade_id` 必须对应 `order_type=200` 且状态为支付成功或已退款的交易。\n\n`refund_no` 使用 store 稳定且唯一的业务退款单号，并作为支付宝 `out_request_no`。相同 `refund_no、trade_id、refund_amount` 重复请求返回原退款记录；累计成功退款金额不得超过原支付金额。\n\n## 2. 接口信息\n\n- **接口地址**：`https://xxx.com/index.php?s=api/InternalPayment/refund`\n- **请求方法**：POST\n- **Content-Type**：`application/x-www-form-urlencoded`\n- **接口版本**：v1.0\n\n## 3. 请求头（Header）\n\n| 参数名 | 类型 | 是否必填 | 描述 | 示例值 |\n| --- | --- | --- | --- | --- |\n| storeId | Integer | 是 | 商城 ID，用于交易数据隔离 | 10001 |\n| Payment-Internal-Token | String | 是 | store 与 ai_api 约定的内部令牌；local 环境可省略 | 不提供固定示例 |\n\n## 4. 请求参数（Body）\n\n| 参数名 | 类型 | 是否必填 | 描述 | 示例值 |\n| --- | --- | --- | --- | --- |\n| trade_id | Integer | 是 | 支付接口返回并写入 `ydy_meal_order.trade_id` 的 ai_api 交易主键 | 530 |\n| refund_no | String | 是 | store 稳定且唯一的退款业务单号，同时作为支付宝 `out_request_no` | RF260902100000001 |\n| refund_amount | String | 是 | 本次退款金额，单位元，必须大于 0，保留两位小数 | 0.01 |\n\n请求示例：\n\n```text\ntrade_id=530&refund_no=RF260902100000001&refund_amount=0.01\n```\n\n## 5. 响应格式\n\n**退款成功响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"refund_id\": 81,\n    \"trade_id\": 530,\n    \"refund_no\": \"RF260902100000001\",\n    \"refund_amount\": \"0.01\",\n    \"status\": \"SUCCESS\"\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**退款处理中响应示例**\n\n```json\n{\n  \"status\": 200,\n  \"message\": \"success\",\n  \"data\": {\n    \"refund_id\": 81,\n    \"trade_id\": 530,\n    \"refund_no\": \"RF260902100000001\",\n    \"refund_amount\": \"0.01\",\n    \"status\": \"PROCESSING\"\n  },\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**累计退款超额响应示例**\n\n```json\n{\n  \"status\": 500,\n  \"message\": \"累计退款金额不能超过支付金额\",\n  \"data\": [],\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n**交易状态不可退款响应示例**\n\n```json\n{\n  \"status\": 500,\n  \"message\": \"当前交易状态不可退款\",\n  \"data\": [],\n  \"trace_id\": \"6a671d7d5539d\"\n}\n```\n\n注意：顶层 `status=200` 只代表退款接口正常处理。只有 `data.status=SUCCESS` 才表示本次退款成功；`PROCESSING` 表示退款尚未确认完成。\n\n## 6. 状态说明\n\n| status / data.status | 描述 | store 处理方式 |\n| --- | --- | --- |\n| 顶层 status=200 | 接口正常处理 | 继续检查 data.status |\n| 顶层 status=500 | 参数、状态、金额或支付宝调用异常 | 记录 trace_id 和失败原因 |\n| SUCCESS | 本次退款成功 | 更新 store 退款单和消费订单退款状态 |\n| PROCESSING | 退款尚未确认完成 | 不得标记退款成功 |\n\n## 7. 响应字段说明\n\n| 字段名 | 类型 | 描述 |\n| --- | --- | --- |\n| status | Integer | 顶层接口结果：200 正常处理、500 明确异常 |\n| message | String | 接口处理消息或失败原因 |\n| data | Object / Array | 正常时为退款对象；失败时可能为空数组 |\n| data.refund_id | Integer | ai_api 退款记录主键 |\n| data.trade_id | Integer | 原支付交易主键 |\n| data.refund_no | String | store 退款业务单号，也是支付宝 `out_request_no` |\n| data.refund_amount | String | 本次退款金额，单位元 |\n| data.status | String | 退款业务状态：SUCCESS 或 PROCESSING |\n| trace_id | String | 本次请求链路标识 |\n\n## 8. trace_id 说明\n\n问题排查时请优先提供 `trace_id`，并补充退款调用时间、`storeId`、`trade_id`、`refund_no`、`refund_amount`、顶层 `status`、`message` 和 `data.status`。不要提供完整内部令牌。",
        "x-apifox-folder": "支付宝消费支付",
        "parameters": [
          {"$ref": "#/components/parameters/StoreId"},
          {"$ref": "#/components/parameters/InternalToken"}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {"$ref": "#/components/schemas/RefundRequest"},
              "example": {"trade_id": 530, "refund_no": "RF260902100000001", "refund_amount": "0.01"}
            },
            "application/x-www-form-urlencoded": {
              "schema": {"$ref": "#/components/schemas/RefundRequest"}
            }
          }
        },
        "responses": {
          "200": {
            "description": "退款结果；顶层 status=200 后继续判断 data.status",
            "content": {
              "application/json": {
                "schema": {"oneOf": [{"$ref": "#/components/schemas/RefundResponse"}, {"$ref": "#/components/schemas/ErrorResponse"}]},
                "examples": {
                  "success": {"summary": "退款成功", "value": {"status": 200, "message": "success", "data": {"refund_id": 81, "trade_id": 530, "refund_no": "RF260902100000001", "refund_amount": "0.01", "status": "SUCCESS"}, "trace_id": "6a671d7d5539d"}},
                  "processing": {"summary": "退款处理中", "value": {"status": 200, "message": "success", "data": {"refund_id": 81, "trade_id": 530, "refund_no": "RF260902100000001", "refund_amount": "0.01", "status": "PROCESSING"}, "trace_id": "6a671d7d5539d"}},
                  "overRefund": {"summary": "累计退款超额", "value": {"status": 500, "message": "累计退款金额不能超过支付金额", "data": [], "trace_id": "6a671d7d5539d"}},
                  "invalidState": {"summary": "交易状态不可退款", "value": {"status": 500, "message": "当前交易状态不可退款", "data": [], "trace_id": "6a671d7d5539d"}}
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "StoreId": {
        "name": "storeId",
        "in": "header",
        "required": true,
        "description": "商城 ID，用于交易数据隔离；由 store 服务传入",
        "schema": {"type": "integer", "example": 10001}
      },
      "InternalToken": {
        "name": "Payment-Internal-Token",
        "in": "header",
        "required": true,
        "description": "store 与 ai_api 的服务间内部令牌；local 环境代码放行，测试和生产环境必须配置且保持一致",
        "schema": {"type": "string", "format": "password", "example": "{{paymentInternalToken}}"}
      },
      "AuthCode": {
        "name": "Payment-Auth-Code",
        "in": "header",
        "required": true,
        "description": "用户当前支付宝付款码。真实付款码动态变化且可能立即扣款；仅支付接口需要，本接口会将其保存到交易记录，但不会放入普通 Body 和响应",
        "schema": {"type": "string", "format": "password", "example": "{{alipayAuthCode}}"}
      }
    },
    "schemas": {
      "PayRequest": {
        "type": "object",
        "required": ["order_id", "order_no", "total_amount"],
        "properties": {
          "trade_id": {"type": "integer", "minimum": 0, "default": 0, "description": "ai_api 交易主键；首次支付传 0，已有交易重试传原 trade_id"},
          "order_id": {"type": "integer", "minimum": 1, "description": "store 的 ydy_meal_order.id"},
          "order_no": {"type": "string", "maxLength": 30, "description": "store 消费订单号，同时作为支付宝商户订单号 out_trade_no；同一业务支付保持不变"},
          "total_amount": {"type": "string", "pattern": "^\\d+\\.\\d{2}$", "description": "应付金额，单位元，必须大于 0，保留两位小数"}
        }
      },
      "QueryRequest": {
        "type": "object",
        "required": ["trade_id"],
        "properties": {"trade_id": {"type": "integer", "minimum": 1, "description": "支付接口返回的 ai_api 交易主键"}}
      },
      "RefundRequest": {
        "type": "object",
        "required": ["trade_id", "refund_no", "refund_amount"],
        "properties": {
          "trade_id": {"type": "integer", "minimum": 1, "description": "支付接口返回并写入 ydy_meal_order.trade_id 的 ai_api 交易主键"},
          "refund_no": {"type": "string", "maxLength": 50, "description": "稳定且唯一的业务退款单号，同时作为支付宝 out_request_no"},
          "refund_amount": {"type": "string", "pattern": "^\\d+\\.\\d{2}$", "description": "本次退款金额，单位元，两位小数"}
        }
      },
      "TradeData": {
        "type": "object",
        "required": ["trade_id", "out_trade_no", "trade_no", "status", "trade_state"],
        "properties": {
          "trade_id": {"type": "integer"},
          "out_trade_no": {"type": "string"},
          "trade_no": {"type": "string", "description": "支付宝交易流水号；未生成时为空"},
          "status": {"type": "string", "enum": ["SUCCESS", "PAYING", "UNKNOWN", "FAILED", "CLOSED", "REFUNDED"], "description": "业务状态：成功、处理中、未知、失败、关闭、已退款"},
          "trade_state": {"type": "integer", "enum": [10, 20, 30, 40], "description": "10未支付 20支付成功 30转入退款 40已关闭"}
        }
      },
      "RefundData": {
        "type": "object",
        "required": ["refund_id", "trade_id", "refund_no", "refund_amount", "status"],
        "properties": {
          "refund_id": {"type": "integer"},
          "trade_id": {"type": "integer"},
          "refund_no": {"type": "string"},
          "refund_amount": {"type": "string"},
          "status": {"type": "string", "enum": ["SUCCESS", "PROCESSING"]}
        }
      },
      "TradeResponse": {
        "type": "object",
        "required": ["status", "message", "data", "trace_id"],
        "properties": {
          "status": {"type": "integer", "enum": [200, 500], "example": 200, "description": "200=接口正常处理；500=明确业务或系统异常"},
          "message": {"type": "string", "example": "success"},
          "data": {"$ref": "#/components/schemas/TradeData"},
          "trace_id": {"type": "string", "description": "请求链路标识；排查时连同调用时间、接口、storeId、order_no/trade_id 一并提供"}
        }
      },
      "RefundResponse": {
        "type": "object",
        "required": ["status", "message", "data", "trace_id"],
        "properties": {
          "status": {"type": "integer", "enum": [200, 500], "example": 200, "description": "200=接口正常处理；500=明确业务或系统异常"},
          "message": {"type": "string", "example": "success"},
          "data": {"$ref": "#/components/schemas/RefundData"},
          "trace_id": {"type": "string", "description": "请求链路标识；排查时连同调用时间、接口、storeId、trade_id/refund_no 一并提供"}
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["status", "message", "data", "trace_id"],
        "properties": {
          "status": {"type": "integer", "enum": [500], "description": "明确业务或系统异常"},
          "message": {"type": "string", "description": "失败原因"},
          "data": {"type": "array", "items": {}, "maxItems": 0, "description": "失败时为空数组"},
          "trace_id": {"type": "string", "description": "请求链路标识"}
        }
      }
    }
  }
}
