import type { CSSProperties } from 'react' import { Alert, Card, Collapse, Descriptions, Space, Table, Tabs, Tag, Typography } from 'antd' import EndpointDoc, { CommonResponseDoc } from '../openapi/EndpointDoc' import { commonResponseFields, endpoints, errorCodes, orderStatusTable, paymentStatusTable, } from '../openapi/endpoints' const { Title, Paragraph, Text } = Typography const baseUrl = typeof window !== 'undefined' ? window.location.origin.replace(':5173', ':8080') : 'http://localhost:8080' const preStyle: CSSProperties = { margin: 0, padding: 12, background: '#f6f8fa', borderRadius: 6, fontSize: 12.5, lineHeight: 1.6, overflow: 'auto', whiteSpace: 'pre-wrap', wordBreak: 'break-all', } const deliveryModes = [ { mode: 'Web 发货页', scene: '商户想要“只返回一个链接”,让用户直接打开平台页面填写 UID', interfaces: '/api/client/v1/orders/{order_no}/delivery-link', }, { mode: '自建发货页', scene: '商户自己有前端页面,想在自己的系统里完成发货流程', interfaces: '/api/client/v1/orders/{order_no}/delivery\n/api/client/v1/orders/{order_no}/delivery/bind\n/api/client/v1/orders/{order_no}/delivery/submit', }, ] export default function OpenApiDocs() { return (
开放接口 面向商户系统调用的开放 API。凭证在「商户中心 / API 客户端」创建, 采用 X-App-Key + HMAC-SHA256 签名鉴权。 发货链路同时支持「返回签名链接」和「返回结构化数据」两种模式。 /api/open/v1 仍是上游回调链路,和本页的商户 API 分开。 , }, { key: 'auth', label: '鉴权与签名', children: , }, { key: 'endpoints', label: '接口列表', children: , }, { key: 'delivery', label: '发货模式', children: , }, { key: 'status', label: '状态说明', children: , }, ]} />
) } function OverviewTab() { return (
  • 在「商户中心 / API 客户端」创建凭证,获得 AppKey 与 AppSecret。
  • 每次请求携带 X-App-Key / X-Timestamp / X-Nonce / X-Sign 四个鉴权头。
  • 调用「商品列表」拿到可售 sku,调用「下单」创建订单并扣款。
  • 拿到 order_no 后,可选择返回发货链接,或者用结构化发货接口完成自建页面流程。
  • } /> (
    {v}
    ), }, ]} /> {baseUrl} X-App-Key、X-Timestamp、X-Nonce、X-Sign 允许 ±300 秒 POST 请求使用 application/json ) } function DeliveryModeTab() { return ( 用 delivery-link,后端直接返回签名后的 Web 发货页地址,前端只负责跳转或复制。 用 delivery 获取订单数据,再按需调用 bind 和 submit。 取消作废属于商户后台操作,恢复后会重新签发新有效期和新签名。 ) } function AuthTab() { return (
    {v} }, { title: '必填', dataIndex: 'required', width: 80, render: (v) => v ? 是 : 否 }, { title: '说明', dataIndex: 'desc' }, ]} /> app_key、body_sha256、method、nonce、path、timestamp 参数按 ASCII 字典序,用 & 拼成 k1=v1&k2=v2&... app_key, body_sha256, method, nonce, path, timestamp 大写,如 GET / POST 仅 URL.Path,不含域名和 query SHA256(原始 body 字节) 的十六进制小写;GET 用空 body 的摘要 原样拼接,不做 URL encode hex( HMAC-SHA256( app_secret, 签名串 ) ),小写十六进制
    {`app_key=ak_xxx&body_sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&method=GET&nonce=a1b2c3d4e5f67890&path=/api/client/v1/products×tamp=1721450000`}
    {`# body = {"client_order_no":"shop-10001","sku":"suit_pink_sheep"}
    app_key=ak_xxx&body_sha256=<实际请求 body 字节的 SHA256 十六进制>&method=POST&nonce=a1b2c3d4e5f67890&path=/api/client/v1/orders×tamp=1721450000`}
  • POST 签名用的 body 必须与实际发送的 body 字节级一致,不要签名后再改空格或字段顺序。
  • value 不要 URL encode,原样参与拼接。
  • 签名失败常见原因:secret 错、path 多了 query、body 与签名不一致、时间戳过期、nonce 重复、参数未按字典序拼接。
  • 下单接口还需携带 Idempotency-Key,且必须与 client_order_no 一致。
  • } /> ) } function EndpointsTab() { return ( ({ key: spec.key, label: ( {spec.method} {spec.path} {spec.summary} ), children: , }))} /> ) } function StatusTab() { return (
    {v} }, { title: 'can_fulfill', dataIndex: 'example', width: 160, render: (v: string) => v === 'can_fulfill=true' ? true : false, }, { title: '说明', dataIndex: 'desc' }, ]} />
    {v} }, { title: '说明', dataIndex: 'desc' }, ]} /> {`拿到 sku(商品列表) ↓ POST /orders 下单(幂等,Idempotency-Key = client_order_no) ↓ 拿响应里的 order_no 进入发货平台链接 ↓ 发货平台查询订单并执行发货 ↓ 发货平台通过上游回调更新 fulfillment_status ↓ GET /orders/{order_no} 轮询,或接收 order.fulfillment.updated 回调`} } /> ) }