# 带看相关：开放平台路由（客户集成摘要）
# 基路径：/api/v2/op/
openapi: 3.0.3
info:
  title: 开放平台 - 带看接口（客户集成摘要）
  description: |
    **本文档保留与「TIM 带看客户义务」及客户可调用的会议室查询相关的调用入口**：获取 token、触发派单、拉取经纪人列表、查询展示用用户信息、QueryRoom（会议室详情）。

    - **客户须实现的业务回调（101、104～107）与客户查询类（4、108）**：契约与字段表以 [TIM 带看 · 服务端接入（客户义务说明）](../guided-tour-tim/server-integration.md) 为准。
    - **会议室查询（POST `rooms/query/` 与 GET `rooms/{room_id}/`）**：见该文档第三节；返回结构以带看 `TakelookRoomSerializer` 为准。
    - 路径前缀：`/api/v2/op/`。除「获取带看 token」外，业务接口需在 Header 携带 `Authorization: <takelook_token>`（与开放平台 `Token.get_token_from_request` 一致）。
    - 开放平台转发 POST 至带看时，会在 JSON body 中注入 `c_id`、`o_id`、`app_id`（调用方可不传）。
    - 带看统一 JSON 响应：`{ "code", "msg", "data" }`（`code === 1` 为成功）。

    **未列入本文的路径**（如 `start`、`usersig`、`tim_event`、`rooms/allocate` 等）仍以 nest_open_platform / nest_takelook 代码为准；需要全量 OpenAPI 时请使用内部完整规格或向众趣索取。
  version: "1.0.0"

servers:
  - url: https://{host}
    variables:
      host:
        default: example.com
        description: 开放平台网关

tags:
  - name: Token
  - name: Takelook-Tencent

paths:
  /api/v2/op/token/takelook/:
    post:
      tags: [Token]
      summary: 获取带看 token（takelook）
      description: |
        仅支持 v2。签名校验：`MD5(app_id + app_secret + timestamp + request_id)`（不区分大小写）。
        时间戳与服务器相差不超过 300 秒；`request_id` 不可重复。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TokenIssueRequest"
      responses:
        "200":
          description: OpenResponse 包装
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/OpenResponseEnvelope"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/TakelookTokenData"

  /api/v2/op/openapi/takelook/tencent/agents/:
    post:
      tags: [Takelook-Tencent]
      summary: 获取经纪人列表（触发客户 service_id=4）
      security:
        - TakelookBearer: []
      description: |
        转发至带看后由带看经开放平台调用客户在 **service_id=4** 上配置的地址。客户侧接口契约见文档「众趣获取带看经纪人列表」。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AgentsRequest"
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/OpenResponseEnvelope"
                  - type: object
                    properties:
                      data:
                        type: array
                        description: 客户返回的经纪人列表，常见元素含 agentId / agentName / agentPhone 等
                        items:
                          type: object
                          additionalProperties: true

  /api/v2/op/openapi/takelook/tencent/dispatch/:
    post:
      tags: [Takelook-Tencent]
      summary: 新方案派单（异步推送客户 service_id=101）
      security:
        - TakelookBearer: []
      description: |
        开放平台受理成功后，异步向客户推送 **101**；`request_data` 为驼峰字段（见客户义务文档）。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DispatchRequest"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OpenResponseEnvelope"
              examples:
                success:
                  value:
                    code: 1
                    msg: success
                    data: null

  /api/v2/op/openapi/takelook/tencent/rooms/query/:
    post:
      tags: [Takelook-Tencent]
      summary: 查询会议室详情（QueryRoom，POST body roomId）
      security:
        - TakelookBearer: []
      description: |
        转发至带看服务；与 `GET .../rooms/{room_id}/` 返回的 `data` 结构相同。详见
        [服务端接入 · 第三节 会议室查询](../guided-tour-tim/server-integration.md)。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/QueryRoomRequest"
            examples:
              byRoomId:
                value:
                  roomId: 1234567890123456789
              bySnake:
                value:
                  room_id: 1234567890123456789
      responses:
        "200":
          description: OpenResponse，`data` 为会议室详情
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/OpenResponseEnvelope"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/TakelookRoomDetail"

  /api/v2/op/openapi/takelook/tencent/rooms/{room_id}/:
    get:
      tags: [Takelook-Tencent]
      summary: 查询会议室详情（路径参数 room_id，与 QueryRoom 等价）
      security:
        - TakelookBearer: []
      description: |
        与 `POST .../rooms/query/` 返回结构一致；`room_id` 为会议室业务 ID（整数）。
      parameters:
        - name: room_id
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/OpenResponseEnvelope"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/TakelookRoomDetail"

  /api/v2/op/openapi/takelook/tencent/user_info/:
    get:
      tags: [Takelook-Tencent]
      summary: 查询展示用用户信息（转发客户 service_id=108）
      security:
        - TakelookBearer: []
      description: |
        用于头像、姓名、角色等展示；业务上可用于 **指定经纪人** 等场景。开放平台将 GET 转发至客户在 **service_id=108** 上配置的地址。
      parameters:
        - name: user_id
          in: query
          required: true
          schema:
            type: string
        - name: c_id
          in: query
          schema: { type: string }
        - name: o_id
          in: query
          schema: { type: string }
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/OpenResponseEnvelope"
                  - type: object
                    properties:
                      data:
                        $ref: "#/components/schemas/UserInfoData"

components:
  securitySchemes:
    TakelookBearer:
      type: apiKey
      in: header
      name: Authorization
      description: 填入 `POST /api/v2/op/token/takelook/` 返回的 `data.token`（通常不含 Bearer 前缀）

  schemas:
    OpenResponseEnvelope:
      type: object
      required: [code, msg, data]
      properties:
        code:
          type: integer
          description: 1 成功；其它见业务错误码说明
        msg:
          type: string
        data:
          nullable: true
        detail:
          type: string
          description: 仅 DEBUG 下可能出现

    TokenIssueRequest:
      type: object
      required: [app_id, timestamp, request_id, sign]
      properties:
        app_id: { type: string }
        timestamp: { type: string, description: 毫秒时间戳 }
        request_id: { type: string }
        sign: { type: string }

    TakelookTokenData:
      type: object
      properties:
        token: { type: string }
        expire_in: { type: integer, description: 秒，默认 86400（24h） }

    AgentsRequest:
      type: object
      required: [project_id]
      description: 带看校验需 c_id+project_id；经开放平台转发时 c_id/o_id/app_id 由平台注入，客户端一般只需 project_id（及可选 custom_params）
      properties:
        c_id: { type: integer, description: 直连带看必填；走开放平台时由平台注入 }
        o_id: { type: integer, default: 0 }
        project_id: { type: string }
        custom_params: { type: string }
        app_id: { type: string, description: 平台注入 }

    DispatchRequest:
      type: object
      required: [project_id, user_id, room_id]
      description: 带看校验需 c_id；经开放平台转发时由平台注入
      properties:
        c_id: { type: integer, description: 直连带看必填；走开放平台时由平台注入 }
        o_id: { type: integer, default: 0 }
        project_id: { type: string, description: 客户侧 packageId }
        user_id: { type: string }
        room_id:
          description: 会议室 ID（实现上可为字符串形式的雪花 ID）
          oneOf:
            - type: string
            - type: integer
              format: int64
        ext:
          oneOf:
            - type: object
            - type: string
          description: 可选；须为 object 或可解析的 JSON 字符串

    UserInfoData:
      type: object
      description: 与客户在 service_id=108 上约定的展示字段
      properties:
        UserId: { type: string }
        UserName: { type: string }
        Avatar: { type: string }
        RoleId: { type: string }
        RoleName: { type: string }
        PhoneNumber: { type: string }
        ElectronicCard: { type: string }

    QueryRoomRequest:
      type: object
      description: roomId 与 room_id 至少其一；同时存在时以 roomId 为准
      properties:
        roomId:
          description: 会议室 ID（推荐）
          oneOf:
            - type: integer
              format: int64
            - type: string
        room_id:
          description: 与 roomId 等价（蛇形命名）
          oneOf:
            - type: integer
              format: int64
            - type: string
        c_id: { type: integer, description: 走开放平台时由平台注入 }
        o_id: { type: integer, description: 走开放平台时由平台注入 }
        app_id: { type: string, description: 走开放平台时由平台注入 }

    TakelookRoomDetail:
      type: object
      description: 带看会议室详情（与 nest_takelook TakelookRoomSerializer 一致）
      properties:
        roomId:
          description: 会议室业务 ID
          oneOf:
            - type: integer
              format: int64
            - type: string
        createTime:
          type: string
          description: 创建时间，格式 YYYY-MM-DDTHH:MM:SS
        active:
          type: boolean
          description: 会议室是否进行中（status=1）
        roomType:
          type: integer
        meetings:
          type: array
          items:
            $ref: "#/components/schemas/TakelookMeetingDetail"

    TakelookMeetingDetail:
      type: object
      properties:
        meetingId:
          oneOf:
            - type: integer
              format: int64
            - type: string
        startTime:
          type: string
          nullable: true
        endTime:
          type: string
          nullable: true
        status:
          type: integer
          description: 会议状态（实现上 1 进行中、2 已结束等，以带看定义为准）
        participants:
          type: array
          items:
            $ref: "#/components/schemas/TakelookParticipantDetail"

    TakelookParticipantDetail:
      type: object
      properties:
        userId: { type: string }
        joinTime:
          type: string
          nullable: true
        exitTime:
          type: string
          nullable: true
          description: 对应 leave_time，未离场时可能为空
        isFirst: { type: boolean }
