data-cleaning-api.md 88 KB

数据清洗统一接口设计文档

版本:v1.0.0
更新日期:2025-01-01
基础URL:https://server-msq.fmode.cn
接口前缀:/api/clean/


目录


1. 概述

本项目对接三个平台的 API:

平台 模块路径 原始接口前缀 说明
Amazon SP-API modules/fmode-amazon-sp-api /api/amazon/ 订单、商品、目录、销售、卖家、退货等
Sorftime modules/fmode-sorftime-api /api/sorftime/ 产品分析、类目、关键词、监控等
TikHub modules/fmode-tikhub-api /api/tikhub/ TikTok 用户、视频、商品、广告等

各平台返回的数据格式不统一,字段命名风格各异(PascalCase / snake_case / camelCase 混用),前端对接困难。本文档设计一套数据清洗后的统一接口,挂载在 /api/clean/ 下,便于前端直接使用。


2. 设计原则

  1. 统一响应格式:所有接口返回 { code, message, data, timestamp } 结构
  2. 跨平台数据标准化:相同概念的数据(产品、订单、关键词)使用统一字段命名
  3. 分页统一:列表接口统一使用 { items, total, page, pageSize, hasMore } 结构
  4. 前端友好:字段命名统一使用 camelCase,时间统一为 ISO 8601 格式
  5. 数据来源透明:每条数据携带 _source 字段标识来源平台
  6. 向下兼容:清洗层不修改原始 API 逻辑,仅做格式转换和聚合

3. 统一响应格式

/** 统一响应包装 */
interface ApiResponse<T> {
  /** 业务状态码,0 表示成功 */
  code: number;
  /** 状态描述 */
  message: string;
  /** 响应数据 */
  data: T;
  /** 响应时间戳 ISO 8601 */
  timestamp: string;
}

成功响应示例:

{
  "code": 0,
  "message": "success",
  "data": { "..." : "..." },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

错误响应示例:

{
  "code": 40001,
  "message": "缺少必填参数: keyword",
  "data": null,
  "timestamp": "2025-01-01T12:00:00.000Z"
}

4. 统一分页格式

/** 统一分页响应 */
interface PaginatedResponse<T> {
  /** 数据列表 */
  items: T[];
  /** 总记录数 */
  total: number;
  /** 当前页码(从 1 开始) */
  page: number;
  /** 每页条数 */
  pageSize: number;
  /** 是否有更多数据 */
  hasMore: boolean;
}

/** 统一分页请求参数 */
interface PaginationParams {
  /** 页码,默认 1 */
  page?: number;
  /** 每页条数,默认 20 */
  pageSize?: number;
}

5. 错误码定义

错误码 说明 HTTP 状态码
0 成功 200
40001 缺少必填参数 400
40002 参数格式错误 400
40003 参数值超出范围 400
40101 未授权(缺少认证信息) 401
40102 认证过期 401
40301 无权访问该资源 403
40401 资源不存在 404
40901 请求冲突(重复操作) 409
42901 请求频率超限 429
50001 服务器内部错误 500
50002 Amazon SP-API 调用失败 502
50003 Sorftime API 调用失败 502
50004 TikHub API 调用失败 502
50005 数据清洗转换异常 500
50301 上游服务不可用 503
50401 上游服务响应超时 504

6. 接口详细定义

6.1 产品相关(跨平台)

6.1.1 GET /api/clean/products/search — 统一产品搜索

聚合 Amazon Catalog Items 搜索 + Sorftime ProductQuery,返回统一格式的产品列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | CatalogItemsApi.searchCatalogItems | GET /api/amazon/catalog/items | | Sorftime | ProductApi.getProductQuery | POST /api/sorftime/forward -> /api/ProductQuery |

请求参数:

interface ProductSearchParams extends PaginationParams {
  /** 搜索关键词 */
  keyword?: string;
  /** ASIN 列表(逗号分隔) */
  asins?: string;
  /** 品牌名称 */
  brand?: string;
  /** 类目 ID */
  categoryId?: string;
  /** 数据来源:amazon | sorftime | all(默认 all) */
  source?: 'amazon' | 'sorftime' | 'all';
  /** 市场域名,如 amazon.com(Sorftime 需要) */
  domain?: string;
  /** Amazon MarketplaceId */
  marketplaceId?: string;
}

响应数据:

interface CleanProduct {
  /** 统一产品 ID(ASIN) */
  id: string;
  /** 产品标题 */
  title: string;
  /** 品牌 */
  brand: string;
  /** 主图 URL */
  imageUrl: string;
  /** 价格 */
  price: number | null;
  /** 货币代码 */
  currency: string;
  /** 评分(1-5) */
  rating: number | null;
  /** 评论数 */
  reviewCount: number | null;
  /** 类目名称 */
  category: string;
  /** BSR 排名 */
  bsrRank: number | null;
  /** 数据来源平台 */
  _source: 'amazon' | 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanProduct>>

数据映射关系:

清洗后字段 Amazon 原始字段 Sorftime 原始字段
id asin ASIN
title summaries[0].itemName Title
brand summaries[0].brand Brand
imageUrl images[0].images[0].link ImageUrl
price summaries[0].price.amount Price
currency summaries[0].price.currencyCode 根据 domain 推断
rating Rating
reviewCount Reviews
category salesRanks[0].displayGroupRanks[0].title CategoryName
bsrRank salesRanks[0].displayGroupRanks[0].rank BSR
_source 'amazon' 'sorftime'

6.1.2 GET /api/clean/products/:id — 统一产品详情

聚合 Amazon CatalogItem 详情 + Sorftime ProductRequest,返回完整产品信息。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | CatalogItemsApi.getCatalogItem | GET /api/amazon/catalog/items/:asin | | Sorftime | ProductApi.getProductRequest | POST /api/sorftime/forward -> /api/ProductRequest |

请求参数:

// URL 参数: id = ASIN
interface ProductDetailParams {
  source?: 'amazon' | 'sorftime' | 'all';
  domain?: string;
  marketplaceId?: string;
  /** 是否包含趋势数据(Sorftime,默认 false) */
  includeTrend?: boolean;
  trendStartDate?: string;
  trendEndDate?: string;
}

响应数据:

interface CleanProductDetail extends CleanProduct {
  /** 产品描述 */
  description: string;
  /** 商品特征/卖点列表 */
  features: string[];
  /** 尺寸信息 */
  dimensions: {
    length: number | null;
    width: number | null;
    height: number | null;
    weight: number | null;
    unit: string;
    weightUnit: string;
  } | null;
  /** 变体列表 */
  variants: Array<{
    asin: string;
    title: string;
    attributes: Record<string, string>;
  }>;
  /** 上架时间 */
  listedAt: string | null;
  /** 月销量估算(Sorftime) */
  estimatedMonthlySales: number | null;
  /** 月收入估算(Sorftime) */
  estimatedMonthlyRevenue: number | null;
  /** 卖家数量 */
  sellerCount: number | null;
  /** FBA 费用估算 */
  fbaFee: number | null;
  /** 趋势数据(需 includeTrend=true) */
  trend: Array<{
    date: string;
    price: number | null;
    bsrRank: number | null;
    rating: number | null;
    reviewCount: number | null;
    sales: number | null;
  }> | null;
  /** 数据来源详情 */
  _sources: Array<{
    platform: 'amazon' | 'sorftime';
    fetchedAt: string;
  }>;
}

// 响应: ApiResponse<CleanProductDetail>

数据映射关系:

清洗后字段 Amazon 原始字段 Sorftime 原始字段
description summaries[0].itemDescription Description
features summaries[0].bulletPoints Features
dimensions.length dimensions[0].item.length.value
dimensions.width dimensions[0].item.width.value
dimensions.height dimensions[0].item.height.value
dimensions.weight dimensions[0].item.weight.value
variants relationships[0].variationTheme
listedAt DateFirstAvailable
estimatedMonthlySales MonthlySales
estimatedMonthlyRevenue MonthlyRevenue
sellerCount SellerNum
fbaFee FBAFee
trend TrendData[]

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "B0EXAMPLE1",
    "title": "Wireless Bluetooth Headphones",
    "brand": "ExampleBrand",
    "imageUrl": "https://m.media-amazon.com/images/I/example.jpg",
    "price": 29.99,
    "currency": "USD",
    "rating": 4.5,
    "reviewCount": 12580,
    "category": "Electronics",
    "bsrRank": 1523,
    "description": "High quality wireless headphones with noise cancellation...",
    "features": [
      "Active Noise Cancellation",
      "40-hour battery life",
      "Bluetooth 5.3"
    ],
    "dimensions": {
      "length": 18.5,
      "width": 15.2,
      "height": 7.8,
      "weight": 250,
      "unit": "cm",
      "weightUnit": "g"
    },
    "variants": [
      { "asin": "B0EXAMPLE2", "title": "Black", "attributes": { "color": "Black" } },
      { "asin": "B0EXAMPLE3", "title": "White", "attributes": { "color": "White" } }
    ],
    "listedAt": "2024-03-15T00:00:00.000Z",
    "estimatedMonthlySales": 8500,
    "estimatedMonthlyRevenue": 254915,
    "sellerCount": 3,
    "fbaFee": 5.42,
    "trend": null,
    "_source": "sorftime",
    "_sources": [
      { "platform": "amazon", "fetchedAt": "2025-01-01T12:00:00.000Z" },
      { "platform": "sorftime", "fetchedAt": "2025-01-01T12:00:01.000Z" }
    ]
  },
  "timestamp": "2025-01-01T12:00:01.500Z"
}

6.1.3 GET /api/clean/products/:id/sales — 产品销量数据

聚合 Amazon Sales 数据 + Sorftime AsinSalesVolume,返回产品销量统计。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | SalesApi.getOrderMetrics | GET /api/amazon/sales/orderMetrics | | Sorftime | ProductApi.getAsinSalesVolume | POST /api/sorftime/forward -> /api/AsinSalesVolume |

请求参数:

// URL 参数: id = ASIN
interface ProductSalesParams {
  source?: 'amazon' | 'sorftime' | 'all';
  domain?: string;
  marketplaceId?: string;
  /** 时间粒度 */
  granularity?: 'day' | 'week' | 'month';
  /** 开始日期 ISO 8601 */
  startDate: string;
  /** 结束日期 ISO 8601 */
  endDate: string;
}

响应数据:

interface CleanProductSales {
  /** ASIN */
  asin: string;
  /** 统计周期 */
  period: {
    startDate: string;
    endDate: string;
    granularity: 'day' | 'week' | 'month';
  };
  /** 汇总数据 */
  summary: {
    totalUnits: number;
    totalRevenue: number;
    currency: string;
    averageDailyUnits: number;
    averagePrice: number;
  };
  /** 时间序列数据 */
  timeline: Array<{
    date: string;
    units: number;
    revenue: number;
    price: number | null;
    bsrRank: number | null;
  }>;
  _source: 'amazon' | 'sorftime';
}

// 响应: ApiResponse<CleanProductSales>

数据映射关系:

清洗后字段 Amazon 原始字段 Sorftime 原始字段
summary.totalUnits orderMetrics[].unitCount (求和) TotalSales
summary.totalRevenue orderMetrics[].totalSales.amount (求和) TotalRevenue
summary.currency orderMetrics[].totalSales.currencyCode 根据 domain 推断
timeline[].date orderMetrics[].interval (解析) SalesData[].Date
timeline[].units orderMetrics[].unitCount SalesData[].Sales
timeline[].revenue orderMetrics[].totalSales.amount SalesData[].Revenue
timeline[].bsrRank SalesData[].BSR

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "asin": "B0EXAMPLE1",
    "period": {
      "startDate": "2025-01-01",
      "endDate": "2025-01-31",
      "granularity": "day"
    },
    "summary": {
      "totalUnits": 8500,
      "totalRevenue": 254915.00,
      "currency": "USD",
      "averageDailyUnits": 274,
      "averagePrice": 29.99
    },
    "timeline": [
      { "date": "2025-01-01", "units": 280, "revenue": 8397.20, "price": 29.99, "bsrRank": 1520 },
      { "date": "2025-01-02", "units": 265, "revenue": 7947.35, "price": 29.99, "bsrRank": 1535 }
    ],
    "_source": "sorftime"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.1.4 GET /api/clean/products/:id/reviews — 产品评论分析

聚合 Amazon CustomerFeedback + Sorftime ProductReviewsQuery,返回产品评论统计与列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | SellersApi.getCustomerFeedback | GET /api/amazon/sellers/feedback | | Sorftime | ProductApi.getProductReviewsQuery | POST /api/sorftime/forward -> /api/ProductReviewsQuery |

请求参数:

// URL 参数: id = ASIN
interface ProductReviewsParams extends PaginationParams {
  source?: 'amazon' | 'sorftime' | 'all';
  domain?: string;
  marketplaceId?: string;
  /** 评分筛选 1-5 */
  rating?: number;
  /** 排序方式 */
  sortBy?: 'date' | 'rating' | 'helpful';
  /** 排序方向 */
  sortOrder?: 'asc' | 'desc';
}

响应数据:

interface CleanReviewSummary {
  /** ASIN */
  asin: string;
  /** 评分分布 */
  ratingDistribution: {
    '1': number;
    '2': number;
    '3': number;
    '4': number;
    '5': number;
  };
  /** 平均评分 */
  averageRating: number;
  /** 总评论数 */
  totalReviews: number;
}

interface CleanReview {
  /** 评论 ID */
  id: string;
  /** 评论标题 */
  title: string;
  /** 评论内容 */
  content: string;
  /** 评分 1-5 */
  rating: number;
  /** 评论者名称 */
  reviewer: string;
  /** 评论日期 */
  date: string;
  /** 是否已验证购买 */
  verifiedPurchase: boolean;
  /** 有帮助数 */
  helpfulCount: number;
  /** 数据来源 */
  _source: 'amazon' | 'sorftime';
}

// 响应: ApiResponse<{ summary: CleanReviewSummary; reviews: PaginatedResponse<CleanReview> }>

数据映射关系:

清洗后字段 Amazon 原始字段 Sorftime 原始字段
id feedbackId ReviewId
title title Title
content comments Content
rating rating Rating
reviewer buyerName Reviewer
date feedbackDate Date
verifiedPurchase verified VerifiedPurchase
helpfulCount HelpfulVotes

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "summary": {
      "asin": "B0EXAMPLE1",
      "ratingDistribution": { "1": 120, "2": 85, "3": 310, "4": 3200, "5": 8865 },
      "averageRating": 4.5,
      "totalReviews": 12580
    },
    "reviews": {
      "items": [
        {
          "id": "R1EXAMPLE",
          "title": "Great headphones!",
          "content": "Amazing sound quality and comfortable to wear...",
          "rating": 5,
          "reviewer": "John D.",
          "date": "2025-01-10T00:00:00.000Z",
          "verifiedPurchase": true,
          "helpfulCount": 42,
          "_source": "sorftime"
        }
      ],
      "total": 12580,
      "page": 1,
      "pageSize": 20,
      "hasMore": true
    }
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.1.5 GET /api/clean/products/:id/similar — 同类产品

获取 Sorftime 同类产品实时数据。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | ProductApi.getSimilarProductRealtime | POST /api/sorftime/forward -> /api/SimilarProductRealtimeRequest |

请求参数:

// URL 参数: id = ASIN
interface SimilarProductsParams extends PaginationParams {
  domain: string;
  /** 排序字段 */
  sortBy?: 'price' | 'rating' | 'sales' | 'bsr';
  sortOrder?: 'asc' | 'desc';
}

响应数据:

interface CleanSimilarProduct {
  /** ASIN */
  id: string;
  /** 产品标题 */
  title: string;
  /** 品牌 */
  brand: string;
  /** 主图 URL */
  imageUrl: string;
  /** 价格 */
  price: number | null;
  /** 货币代码 */
  currency: string;
  /** 评分 */
  rating: number | null;
  /** 评论数 */
  reviewCount: number | null;
  /** BSR 排名 */
  bsrRank: number | null;
  /** 月销量估算 */
  estimatedMonthlySales: number | null;
  /** 与原产品的相似度评分 */
  similarityScore: number | null;
  _source: 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanSimilarProduct>>

数据映射关系:

清洗后字段 Sorftime 原始字段
id ASIN
title Title
brand Brand
imageUrl ImageUrl
price Price
rating Rating
reviewCount Reviews
bsrRank BSR
estimatedMonthlySales MonthlySales
similarityScore SimilarityScore

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": "B0SIMILAR1",
        "title": "Noise Cancelling Wireless Earbuds",
        "brand": "CompetitorBrand",
        "imageUrl": "https://m.media-amazon.com/images/I/similar1.jpg",
        "price": 34.99,
        "currency": "USD",
        "rating": 4.3,
        "reviewCount": 8920,
        "bsrRank": 2105,
        "estimatedMonthlySales": 6200,
        "similarityScore": 0.92,
        "_source": "sorftime"
      }
    ],
    "total": 25,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.2 订单相关(Amazon)

6.2.1 GET /api/clean/orders — 订单列表

获取 Amazon 订单列表,统一格式输出。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | OrdersApi.getOrders | GET /api/amazon/orders |

请求参数:

interface OrderListParams extends PaginationParams {
  /** 市场 ID */
  marketplaceId: string;
  /** 订单状态筛选 */
  status?: 'pending' | 'unshipped' | 'shipped' | 'canceled' | 'unfulfillable';
  /** 创建时间起始 ISO 8601 */
  createdAfter?: string;
  /** 创建时间截止 ISO 8601 */
  createdBefore?: string;
  /** 配送方式 */
  fulfillmentChannel?: 'AFN' | 'MFN';
  /** 排序方式 */
  sortBy?: 'createdAt' | 'updatedAt' | 'totalAmount';
  sortOrder?: 'asc' | 'desc';
}

响应数据:

interface CleanOrder {
  /** 订单 ID */
  id: string;
  /** 订单状态 */
  status: string;
  /** 订单总金额 */
  totalAmount: number;
  /** 货币代码 */
  currency: string;
  /** 商品数量 */
  itemCount: number;
  /** 配送方式 AFN=FBA, MFN=自发货 */
  fulfillmentChannel: 'AFN' | 'MFN';
  /** 购买日期 */
  createdAt: string;
  /** 最后更新时间 */
  updatedAt: string;
  /** 发货地址(脱敏) */
  shippingAddress: {
    city: string;
    state: string;
    country: string;
    postalCode: string;
  } | null;
  /** 市场 ID */
  marketplaceId: string;
  _source: 'amazon';
}

// 响应: ApiResponse<PaginatedResponse<CleanOrder>>

数据映射关系:

清洗后字段 Amazon 原始字段
id AmazonOrderId
status OrderStatus
totalAmount OrderTotal.Amount
currency OrderTotal.CurrencyCode
itemCount NumberOfItemsShipped + NumberOfItemsUnshipped
fulfillmentChannel FulfillmentChannel
createdAt PurchaseDate
updatedAt LastUpdateDate
shippingAddress.city ShippingAddress.City
shippingAddress.state ShippingAddress.StateOrRegion
shippingAddress.country ShippingAddress.CountryCode
shippingAddress.postalCode ShippingAddress.PostalCode

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": "111-1234567-1234567",
        "status": "shipped",
        "totalAmount": 59.98,
        "currency": "USD",
        "itemCount": 2,
        "fulfillmentChannel": "AFN",
        "createdAt": "2025-01-15T08:30:00.000Z",
        "updatedAt": "2025-01-16T14:20:00.000Z",
        "shippingAddress": {
          "city": "Seattle",
          "state": "WA",
          "country": "US",
          "postalCode": "98101"
        },
        "marketplaceId": "ATVPDKIKX0DER",
        "_source": "amazon"
      }
    ],
    "total": 156,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.2.2 GET /api/clean/orders/:id — 订单详情

获取单个订单的完整信息,包含订单项明细。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | OrdersApi.getOrder | GET /api/amazon/orders/:orderId | | Amazon | OrdersApi.getOrderItems | GET /api/amazon/orders/:orderId/items |

请求参数:

// URL 参数: id = Amazon 订单号
interface OrderDetailParams {
  marketplaceId?: string;
}

响应数据:

interface CleanOrderDetail extends CleanOrder {
  /** 订单项列表 */
  items: Array<{
    /** 订单项 ID */
    id: string;
    /** ASIN */
    asin: string;
    /** SKU */
    sku: string;
    /** 商品标题 */
    title: string;
    /** 数量 */
    quantity: number;
    /** 单价 */
    unitPrice: number;
    /** 小计 */
    subtotal: number;
    /** 货币代码 */
    currency: string;
    /** 商品图片 */
    imageUrl: string | null;
  }>;
  /** 买家信息(脱敏) */
  buyer: {
    name: string | null;
    email: string | null;
  } | null;
  /** 配送信息 */
  shipping: {
    service: string | null;
    trackingNumber: string | null;
    estimatedDelivery: string | null;
    shippedAt: string | null;
    deliveredAt: string | null;
  } | null;
  /** 支付信息 */
  payment: {
    method: string | null;
    subtotal: number;
    shippingFee: number;
    tax: number;
    discount: number;
    total: number;
    currency: string;
  };
}

// 响应: ApiResponse<CleanOrderDetail>

数据映射关系:

清洗后字段 Amazon 原始字段
items[].id OrderItemId
items[].asin ASIN
items[].sku SellerSKU
items[].title Title
items[].quantity QuantityOrdered
items[].unitPrice ItemPrice.Amount / QuantityOrdered
items[].subtotal ItemPrice.Amount
buyer.name BuyerInfo.BuyerName
buyer.email BuyerInfo.BuyerEmail
shipping.service ShipmentServiceLevelCategory
payment.subtotal OrderTotal.Amount - ShippingPrice - Tax
payment.shippingFee ShippingPrice.Amount
payment.tax TaxCollection.Amount
payment.total OrderTotal.Amount

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "111-1234567-1234567",
    "status": "shipped",
    "totalAmount": 59.98,
    "currency": "USD",
    "itemCount": 2,
    "fulfillmentChannel": "AFN",
    "createdAt": "2025-01-15T08:30:00.000Z",
    "updatedAt": "2025-01-16T14:20:00.000Z",
    "shippingAddress": {
      "city": "Seattle",
      "state": "WA",
      "country": "US",
      "postalCode": "98101"
    },
    "marketplaceId": "ATVPDKIKX0DER",
    "items": [
      {
        "id": "ITEM001",
        "asin": "B0EXAMPLE1",
        "sku": "WH-BT-001",
        "title": "Wireless Bluetooth Headphones",
        "quantity": 2,
        "unitPrice": 29.99,
        "subtotal": 59.98,
        "currency": "USD",
        "imageUrl": "https://m.media-amazon.com/images/I/example.jpg"
      }
    ],
    "buyer": {
      "name": "J*** D***",
      "email": null
    },
    "shipping": {
      "service": "Expedited",
      "trackingNumber": "TBA123456789",
      "estimatedDelivery": "2025-01-18T00:00:00.000Z",
      "shippedAt": "2025-01-16T10:00:00.000Z",
      "deliveredAt": null
    },
    "payment": {
      "method": "Other",
      "subtotal": 59.98,
      "shippingFee": 0,
      "tax": 5.40,
      "discount": 0,
      "total": 65.38,
      "currency": "USD"
    },
    "_source": "amazon"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.2.3 GET /api/clean/orders/metrics — 订单统计

获取 Amazon 销售订单指标汇总。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | SalesApi.getOrderMetrics | GET /api/amazon/sales/orderMetrics |

请求参数:

interface OrderMetricsParams {
  marketplaceId: string;
  /** 时间粒度 */
  granularity: 'day' | 'week' | 'month' | 'year';
  /** 开始日期 ISO 8601 */
  startDate: string;
  /** 结束日期 ISO 8601 */
  endDate: string;
  /** 按 ASIN 筛选 */
  asin?: string;
  /** 按 SKU 筛选 */
  sku?: string;
}

响应数据:

interface CleanOrderMetrics {
  /** 统计周期 */
  period: {
    startDate: string;
    endDate: string;
    granularity: string;
  };
  /** 汇总 */
  summary: {
    totalOrders: number;
    totalUnits: number;
    totalRevenue: number;
    averageOrderValue: number;
    currency: string;
  };
  /** 时间序列 */
  timeline: Array<{
    date: string;
    orders: number;
    units: number;
    revenue: number;
    averageOrderValue: number;
  }>;
  _source: 'amazon';
}

// 响应: ApiResponse<CleanOrderMetrics>

数据映射关系:

清洗后字段 Amazon 原始字段
summary.totalOrders orderMetrics[].orderCount (求和)
summary.totalUnits orderMetrics[].unitCount (求和)
summary.totalRevenue orderMetrics[].totalSales.amount (求和)
summary.averageOrderValue totalRevenue / totalOrders
summary.currency orderMetrics[0].totalSales.currencyCode
timeline[].date orderMetrics[].interval (解析)
timeline[].orders orderMetrics[].orderCount
timeline[].units orderMetrics[].unitCount
timeline[].revenue orderMetrics[].totalSales.amount

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "period": {
      "startDate": "2025-01-01",
      "endDate": "2025-01-31",
      "granularity": "week"
    },
    "summary": {
      "totalOrders": 420,
      "totalUnits": 680,
      "totalRevenue": 20386.20,
      "averageOrderValue": 48.54,
      "currency": "USD"
    },
    "timeline": [
      { "date": "2025-01-01", "orders": 95, "units": 150, "revenue": 4497.00, "averageOrderValue": 47.34 },
      { "date": "2025-01-08", "orders": 110, "units": 180, "revenue": 5398.20, "averageOrderValue": 49.07 },
      { "date": "2025-01-15", "orders": 105, "units": 170, "revenue": 5098.30, "averageOrderValue": 48.56 },
      { "date": "2025-01-22", "orders": 110, "units": 180, "revenue": 5392.70, "averageOrderValue": 49.02 }
    ],
    "_source": "amazon"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.3 商品管理(Amazon Listings)

6.3.1 GET /api/clean/listings — Listing 列表

获取卖家的 Amazon Listing 列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | ListingsApi.getListingsItems | GET /api/amazon/listings |

请求参数:

interface ListingListParams extends PaginationParams {
  marketplaceId: string;
  /** 按状态筛选 */
  status?: 'active' | 'inactive' | 'incomplete';
  /** 搜索关键词(标题/SKU/ASIN) */
  keyword?: string;
}

响应数据:

interface CleanListing {
  /** SKU */
  sku: string;
  /** ASIN */
  asin: string;
  /** 商品标题 */
  title: string;
  /** 主图 URL */
  imageUrl: string | null;
  /** 价格 */
  price: number | null;
  /** 货币代码 */
  currency: string;
  /** 状态 */
  status: 'active' | 'inactive' | 'incomplete';
  /** FBA 库存数量 */
  fbaQuantity: number;
  /** 自发货库存数量 */
  fbmQuantity: number;
  /** 创建时间 */
  createdAt: string;
  /** 最后更新时间 */
  updatedAt: string;
  /** 市场 ID */
  marketplaceId: string;
  _source: 'amazon';
}

// 响应: ApiResponse<PaginatedResponse<CleanListing>>

数据映射关系:

清洗后字段 Amazon 原始字段
sku sku
asin summaries[0].asin
title summaries[0].itemName
imageUrl summaries[0].mainImage.link
price attributes.purchasable_offer[0].our_price[0].schedule[0].value_with_tax
status summaries[0].status[0]
fbaQuantity fulfillmentAvailability[0].quantity (AFN)
fbmQuantity fulfillmentAvailability[0].quantity (MFN)
createdAt summaries[0].createdDate
updatedAt summaries[0].lastUpdatedDate

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "sku": "WH-BT-001",
        "asin": "B0EXAMPLE1",
        "title": "Wireless Bluetooth Headphones",
        "imageUrl": "https://m.media-amazon.com/images/I/example.jpg",
        "price": 29.99,
        "currency": "USD",
        "status": "active",
        "fbaQuantity": 580,
        "fbmQuantity": 0,
        "createdAt": "2024-03-15T00:00:00.000Z",
        "updatedAt": "2025-01-10T08:00:00.000Z",
        "marketplaceId": "ATVPDKIKX0DER",
        "_source": "amazon"
      }
    ],
    "total": 45,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.3.2 GET /api/clean/listings/:sku — Listing 详情

获取单个 Listing 的完整信息。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | ListingsApi.getListingsItem | GET /api/amazon/listings/:sku |

请求参数:

// URL 参数: sku = 卖家 SKU
interface ListingDetailParams {
  marketplaceId: string;
}

响应数据:

interface CleanListingDetail extends CleanListing {
  /** 商品描述 */
  description: string | null;
  /** 商品特征 */
  features: string[];
  /** 商品属性 */
  attributes: Record<string, string>;
  /** 变体信息 */
  variants: Array<{
    sku: string;
    asin: string;
    attributes: Record<string, string>;
  }>;
  /** 商品问题/警告 */
  issues: Array<{
    code: string;
    message: string;
    severity: 'error' | 'warning' | 'info';
  }>;
  /** 配送信息 */
  fulfillment: {
    channel: 'AFN' | 'MFN';
    quantity: number;
    inboundShipments: number;
    reservedQuantity: number;
  };
}

// 响应: ApiResponse<CleanListingDetail>

数据映射关系:

清洗后字段 Amazon 原始字段
description attributes.product_description[0].value
features attributes.bullet_point[].value
attributes attributes.* (扁平化)
variants relationships[0].variationTheme
issues[].code issues[].code
issues[].message issues[].message
issues[].severity issues[].severity
fulfillment.channel fulfillmentAvailability[0].fulfillmentChannelCode
fulfillment.quantity fulfillmentAvailability[0].quantity

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "sku": "WH-BT-001",
    "asin": "B0EXAMPLE1",
    "title": "Wireless Bluetooth Headphones",
    "imageUrl": "https://m.media-amazon.com/images/I/example.jpg",
    "price": 29.99,
    "currency": "USD",
    "status": "active",
    "fbaQuantity": 580,
    "fbmQuantity": 0,
    "createdAt": "2024-03-15T00:00:00.000Z",
    "updatedAt": "2025-01-10T08:00:00.000Z",
    "marketplaceId": "ATVPDKIKX0DER",
    "description": "Premium wireless headphones with active noise cancellation...",
    "features": [
      "Active Noise Cancellation",
      "40-hour battery life",
      "Bluetooth 5.3",
      "Comfortable over-ear design"
    ],
    "attributes": {
      "color": "Black",
      "connectivity": "Bluetooth",
      "brand": "ExampleBrand"
    },
    "variants": [
      { "sku": "WH-BT-001-BK", "asin": "B0EXAMPLE1", "attributes": { "color": "Black" } },
      { "sku": "WH-BT-001-WH", "asin": "B0EXAMPLE3", "attributes": { "color": "White" } }
    ],
    "issues": [],
    "fulfillment": {
      "channel": "AFN",
      "quantity": 580,
      "inboundShipments": 200,
      "reservedQuantity": 15
    },
    "_source": "amazon"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.4 类目相关(Sorftime)

6.4.1 GET /api/clean/categories/tree — 类目树

获取 Sorftime 类目树结构。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | CategoryApi.getCategoryTree | POST /api/sorftime/forward -> /api/CategoryTree |

请求参数:

interface CategoryTreeParams {
  /** 市场域名,如 amazon.com */
  domain: string;
  /** 父类目 ID(不传则返回顶级类目) */
  parentId?: string;
  /** 展开层级深度,默认 1 */
  depth?: number;
}

响应数据:

interface CleanCategory {
  /** 类目 ID */
  id: string;
  /** 类目名称 */
  name: string;
  /** 父类目 ID */
  parentId: string | null;
  /** 层级深度 */
  level: number;
  /** 子类目数量 */
  childCount: number;
  /** 该类目下产品数量估算 */
  productCount: number | null;
  /** 子类目列表 */
  children: CleanCategory[];
  _source: 'sorftime';
}

// 响应: ApiResponse<CleanCategory[]>

数据映射关系:

清洗后字段 Sorftime 原始字段
id CategoryId
name CategoryName
parentId ParentCategoryId
level Level
childCount ChildCount
productCount ProductCount
children Children[] (递归映射)

响应示例:

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": "172282",
      "name": "Electronics",
      "parentId": null,
      "level": 0,
      "childCount": 24,
      "productCount": 5800000,
      "children": [
        {
          "id": "172541",
          "name": "Headphones, Earbuds & Accessories",
          "parentId": "172282",
          "level": 1,
          "childCount": 8,
          "productCount": 320000,
          "children": [],
          "_source": "sorftime"
        }
      ],
      "_source": "sorftime"
    }
  ],
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.4.2 GET /api/clean/categories/:id/products — 类目热销产品

获取指定类目下的热销产品列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | CategoryApi.getCategoryProducts | POST /api/sorftime/forward -> /api/CategoryProducts |

请求参数:

// URL 参数: id = 类目 ID
interface CategoryProductsParams extends PaginationParams {
  domain: string;
  /** 排序字段 */
  sortBy?: 'sales' | 'price' | 'rating' | 'bsr' | 'reviews';
  sortOrder?: 'asc' | 'desc';
  /** 价格范围 */
  minPrice?: number;
  maxPrice?: number;
  /** 评分范围 */
  minRating?: number;
}

响应数据:

interface CleanCategoryProduct {
  /** ASIN */
  id: string;
  /** 产品标题 */
  title: string;
  /** 品牌 */
  brand: string;
  /** 主图 URL */
  imageUrl: string;
  /** 价格 */
  price: number | null;
  /** 货币代码 */
  currency: string;
  /** 评分 */
  rating: number | null;
  /** 评论数 */
  reviewCount: number | null;
  /** BSR 排名 */
  bsrRank: number | null;
  /** 月销量估算 */
  estimatedMonthlySales: number | null;
  /** 月收入估算 */
  estimatedMonthlyRevenue: number | null;
  /** 上架时间 */
  listedAt: string | null;
  /** 卖家数量 */
  sellerCount: number | null;
  _source: 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanCategoryProduct>>

数据映射关系:

清洗后字段 Sorftime 原始字段
id ASIN
title Title
brand Brand
imageUrl ImageUrl
price Price
rating Rating
reviewCount Reviews
bsrRank BSR
estimatedMonthlySales MonthlySales
estimatedMonthlyRevenue MonthlyRevenue
listedAt DateFirstAvailable
sellerCount SellerNum

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": "B0EXAMPLE1",
        "title": "Wireless Bluetooth Headphones",
        "brand": "ExampleBrand",
        "imageUrl": "https://m.media-amazon.com/images/I/example.jpg",
        "price": 29.99,
        "currency": "USD",
        "rating": 4.5,
        "reviewCount": 12580,
        "bsrRank": 1523,
        "estimatedMonthlySales": 8500,
        "estimatedMonthlyRevenue": 254915,
        "listedAt": "2024-03-15T00:00:00.000Z",
        "sellerCount": 3,
        "_source": "sorftime"
      }
    ],
    "total": 500,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.4.3 GET /api/clean/categories/:id/keywords — 类目关键词

获取指定类目下的热门关键词。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | CategoryApi.getCategoryKeywords | POST /api/sorftime/forward -> /api/CategoryKeywords |

请求参数:

// URL 参数: id = 类目 ID
interface CategoryKeywordsParams extends PaginationParams {
  domain: string;
  /** 排序字段 */
  sortBy?: 'searchVolume' | 'growth' | 'competition';
  sortOrder?: 'asc' | 'desc';
}

响应数据:

interface CleanCategoryKeyword {
  /** 关键词 */
  keyword: string;
  /** 月搜索量 */
  searchVolume: number;
  /** 搜索量增长率(百分比) */
  growthRate: number | null;
  /** 竞争度 0-1 */
  competition: number | null;
  /** 点击集中度 */
  clickConcentration: number | null;
  /** 关联产品数 */
  productCount: number | null;
  _source: 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanCategoryKeyword>>

数据映射关系:

清洗后字段 Sorftime 原始字段
keyword Keyword
searchVolume SearchVolume
growthRate GrowthRate
competition Competition
clickConcentration ClickConcentration
productCount ProductCount

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "keyword": "wireless headphones",
        "searchVolume": 1250000,
        "growthRate": 12.5,
        "competition": 0.85,
        "clickConcentration": 0.42,
        "productCount": 50000,
        "_source": "sorftime"
      },
      {
        "keyword": "bluetooth headphones noise cancelling",
        "searchVolume": 680000,
        "growthRate": 18.3,
        "competition": 0.72,
        "clickConcentration": 0.38,
        "productCount": 28000,
        "_source": "sorftime"
      }
    ],
    "total": 150,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.5 关键词相关(Sorftime)

6.5.1 GET /api/clean/keywords/search — 关键词查询

搜索关键词并返回搜索量、竞争度等数据。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | KeywordApi.getKeywordSearch | POST /api/sorftime/forward -> /api/KeywordSearch |

请求参数:

interface KeywordSearchParams extends PaginationParams {
  /** 搜索关键词 */
  keyword: string;
  /** 市场域名 */
  domain: string;
  /** 匹配模式 */
  matchType?: 'exact' | 'broad' | 'phrase';
  /** 最小搜索量 */
  minSearchVolume?: number;
}

响应数据:

interface CleanKeyword {
  /** 关键词 */
  keyword: string;
  /** 月搜索量 */
  searchVolume: number;
  /** 搜索量趋势(近3个月) */
  searchTrend: 'up' | 'down' | 'stable';
  /** 搜索量增长率(百分比) */
  growthRate: number | null;
  /** 竞争度 0-1 */
  competition: number | null;
  /** 推荐出价(美元) */
  suggestedBid: number | null;
  /** 点击集中度 */
  clickConcentration: number | null;
  /** 关联产品数 */
  productCount: number | null;
  /** 相关关键词 */
  relatedKeywords: string[];
  _source: 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanKeyword>>

数据映射关系:

清洗后字段 Sorftime 原始字段
keyword Keyword
searchVolume SearchVolume
searchTrend 根据 SearchVolumeHistory 计算
growthRate GrowthRate
competition Competition
suggestedBid SuggestedBid
clickConcentration ClickConcentration
productCount ProductCount
relatedKeywords RelatedKeywords[]

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "keyword": "wireless headphones",
        "searchVolume": 1250000,
        "searchTrend": "up",
        "growthRate": 12.5,
        "competition": 0.85,
        "suggestedBid": 2.35,
        "clickConcentration": 0.42,
        "productCount": 50000,
        "relatedKeywords": ["bluetooth headphones", "wireless earbuds", "noise cancelling headphones"],
        "_source": "sorftime"
      }
    ],
    "total": 85,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.5.2 GET /api/clean/keywords/:keyword/products — 关键词产品排名

获取指定关键词下的产品排名列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | KeywordApi.getKeywordProducts | POST /api/sorftime/forward -> /api/KeywordProducts |

请求参数:

// URL 参数: keyword = 关键词(需 URL 编码)
interface KeywordProductsParams extends PaginationParams {
  domain: string;
  /** 排名类型 */
  rankType?: 'organic' | 'sponsored' | 'all';
}

响应数据:

interface CleanKeywordProduct {
  /** 排名位置 */
  rank: number;
  /** 排名类型 */
  rankType: 'organic' | 'sponsored';
  /** ASIN */
  id: string;
  /** 产品标题 */
  title: string;
  /** 品牌 */
  brand: string;
  /** 主图 URL */
  imageUrl: string;
  /** 价格 */
  price: number | null;
  /** 货币代码 */
  currency: string;
  /** 评分 */
  rating: number | null;
  /** 评论数 */
  reviewCount: number | null;
  /** BSR 排名 */
  bsrRank: number | null;
  /** 月销量估算 */
  estimatedMonthlySales: number | null;
  _source: 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanKeywordProduct>>

数据映射关系:

清洗后字段 Sorftime 原始字段
rank Position
rankType Type (organic / sponsored)
id ASIN
title Title
brand Brand
imageUrl ImageUrl
price Price
rating Rating
reviewCount Reviews
bsrRank BSR
estimatedMonthlySales MonthlySales

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "rank": 1,
        "rankType": "organic",
        "id": "B0EXAMPLE1",
        "title": "Wireless Bluetooth Headphones",
        "brand": "ExampleBrand",
        "imageUrl": "https://m.media-amazon.com/images/I/example.jpg",
        "price": 29.99,
        "currency": "USD",
        "rating": 4.5,
        "reviewCount": 12580,
        "bsrRank": 1523,
        "estimatedMonthlySales": 8500,
        "_source": "sorftime"
      }
    ],
    "total": 300,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.5.3 GET /api/clean/keywords/reverse/:asin — ASIN 反查关键词

通过 ASIN 反查该产品排名的关键词列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | KeywordApi.getReverseAsin | POST /api/sorftime/forward -> /api/ReverseAsin |

请求参数:

// URL 参数: asin = ASIN
interface ReverseAsinParams extends PaginationParams {
  domain: string;
  /** 最小搜索量筛选 */
  minSearchVolume?: number;
  /** 排序字段 */
  sortBy?: 'searchVolume' | 'rank' | 'competition';
  sortOrder?: 'asc' | 'desc';
}

响应数据:

interface CleanReverseKeyword {
  /** 关键词 */
  keyword: string;
  /** 该 ASIN 在此关键词下的排名 */
  rank: number;
  /** 排名类型 */
  rankType: 'organic' | 'sponsored';
  /** 月搜索量 */
  searchVolume: number;
  /** 竞争度 0-1 */
  competition: number | null;
  /** 点击集中度 */
  clickConcentration: number | null;
  /** 搜索量增长率 */
  growthRate: number | null;
  _source: 'sorftime';
}

// 响应: ApiResponse<PaginatedResponse<CleanReverseKeyword>>

数据映射关系:

清洗后字段 Sorftime 原始字段
keyword Keyword
rank Position
rankType Type
searchVolume SearchVolume
competition Competition
clickConcentration ClickConcentration
growthRate GrowthRate

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "keyword": "wireless headphones",
        "rank": 5,
        "rankType": "organic",
        "searchVolume": 1250000,
        "competition": 0.85,
        "clickConcentration": 0.42,
        "growthRate": 12.5,
        "_source": "sorftime"
      },
      {
        "keyword": "bluetooth headphones noise cancelling",
        "rank": 3,
        "rankType": "organic",
        "searchVolume": 680000,
        "competition": 0.72,
        "clickConcentration": 0.38,
        "growthRate": 18.3,
        "_source": "sorftime"
      }
    ],
    "total": 420,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.5.4 GET /api/clean/keywords/:keyword/trend — 关键词趋势

获取关键词的搜索量历史趋势数据。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | KeywordApi.getKeywordTrend | POST /api/sorftime/forward -> /api/KeywordTrend |

请求参数:

// URL 参数: keyword = 关键词(需 URL 编码)
interface KeywordTrendParams {
  domain: string;
  /** 时间范围 */
  period?: '3m' | '6m' | '12m' | '24m';
  /** 时间粒度 */
  granularity?: 'day' | 'week' | 'month';
}

响应数据:

interface CleanKeywordTrend {
  /** 关键词 */
  keyword: string;
  /** 当前月搜索量 */
  currentSearchVolume: number;
  /** 搜索量变化率 */
  changeRate: number;
  /** 趋势方向 */
  trend: 'up' | 'down' | 'stable';
  /** 历史数据 */
  history: Array<{
    date: string;
    searchVolume: number;
    rank: number | null;
  }>;
  /** 季节性指数(1-12月) */
  seasonality: Array<{
    month: number;
    index: number;
  }> | null;
  _source: 'sorftime';
}

// 响应: ApiResponse<CleanKeywordTrend>

数据映射关系:

清洗后字段 Sorftime 原始字段
keyword Keyword
currentSearchVolume CurrentSearchVolume
changeRate ChangeRate
trend 根据 ChangeRate 计算
history[].date History[].Date
history[].searchVolume History[].SearchVolume
seasonality[].month Seasonality[].Month
seasonality[].index Seasonality[].Index

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "keyword": "wireless headphones",
    "currentSearchVolume": 1250000,
    "changeRate": 12.5,
    "trend": "up",
    "history": [
      { "date": "2024-11-01", "searchVolume": 980000, "rank": null },
      { "date": "2024-12-01", "searchVolume": 1150000, "rank": null },
      { "date": "2025-01-01", "searchVolume": 1250000, "rank": null }
    ],
    "seasonality": [
      { "month": 1, "index": 1.05 },
      { "month": 2, "index": 0.92 },
      { "month": 11, "index": 1.35 },
      { "month": 12, "index": 1.58 }
    ],
    "_source": "sorftime"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.6 监控相关(Sorftime)

6.6.1 POST /api/clean/monitoring/bestseller/subscribe — BS 榜单订阅

订阅 Best Seller 榜单监控任务。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | MonitorApi.subscribeBestSeller | POST /api/sorftime/forward -> /api/BestSellerSubscribe |

请求参数:

interface BestSellerSubscribeParams {
  /** 市场域名 */
  domain: string;
  /** 类目 ID */
  categoryId: string;
  /** 监控频率 */
  frequency: 'hourly' | 'daily' | 'weekly';
  /** 通知方式 */
  notifyType?: 'email' | 'webhook' | 'none';
  /** 通知地址 */
  notifyUrl?: string;
}

响应数据:

interface CleanSubscription {
  /** 订阅任务 ID */
  id: string;
  /** 订阅类型 */
  type: 'bestseller' | 'asin';
  /** 状态 */
  status: 'active' | 'paused' | 'expired';
  /** 监控目标 */
  target: {
    domain: string;
    categoryId?: string;
    categoryName?: string;
    asin?: string;
  };
  /** 监控频率 */
  frequency: string;
  /** 创建时间 */
  createdAt: string;
  /** 下次执行时间 */
  nextRunAt: string;
  _source: 'sorftime';
}

// 响应: ApiResponse<CleanSubscription>

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "SUB_BS_001",
    "type": "bestseller",
    "status": "active",
    "target": {
      "domain": "amazon.com",
      "categoryId": "172282",
      "categoryName": "Electronics"
    },
    "frequency": "daily",
    "createdAt": "2025-01-01T12:00:00.000Z",
    "nextRunAt": "2025-01-02T12:00:00.000Z",
    "_source": "sorftime"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.6.2 GET /api/clean/monitoring/bestseller/tasks — BS 榜单任务

获取 Best Seller 榜单监控任务列表及结果。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | MonitorApi.getBestSellerTasks | POST /api/sorftime/forward -> /api/BestSellerTasks |

请求参数:

interface BestSellerTasksParams extends PaginationParams {
  /** 按状态筛选 */
  status?: 'active' | 'paused' | 'expired';
  domain?: string;
}

响应数据:

interface CleanBestSellerTask extends CleanSubscription {
  /** 最近一次执行结果 */
  lastResult: {
    executedAt: string;
    /** 榜单产品列表(前 N 名) */
    products: Array<{
      rank: number;
      asin: string;
      title: string;
      price: number | null;
      rating: number | null;
      reviewCount: number | null;
    }>;
    /** 与上次对比的变化 */
    changes: {
      newEntries: number;
      removedEntries: number;
      rankChanges: number;
    };
  } | null;
}

// 响应: ApiResponse<PaginatedResponse<CleanBestSellerTask>>

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": "SUB_BS_001",
        "type": "bestseller",
        "status": "active",
        "target": {
          "domain": "amazon.com",
          "categoryId": "172282",
          "categoryName": "Electronics"
        },
        "frequency": "daily",
        "createdAt": "2025-01-01T12:00:00.000Z",
        "nextRunAt": "2025-01-02T12:00:00.000Z",
        "lastResult": {
          "executedAt": "2025-01-01T12:00:00.000Z",
          "products": [
            { "rank": 1, "asin": "B0EXAMPLE1", "title": "Wireless Headphones", "price": 29.99, "rating": 4.5, "reviewCount": 12580 },
            { "rank": 2, "asin": "B0EXAMPLE2", "title": "Bluetooth Speaker", "price": 39.99, "rating": 4.6, "reviewCount": 8900 }
          ],
          "changes": {
            "newEntries": 3,
            "removedEntries": 2,
            "rankChanges": 15
          }
        },
        "_source": "sorftime"
      }
    ],
    "total": 5,
    "page": 1,
    "pageSize": 20,
    "hasMore": false
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.6.3 POST /api/clean/monitoring/asin/subscribe — ASIN 订阅

订阅单个 ASIN 的数据变化监控。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Sorftime | MonitorApi.subscribeAsin | POST /api/sorftime/forward -> /api/AsinSubscribe |

请求参数:

interface AsinSubscribeParams {
  /** ASIN */
  asin: string;
  /** 市场域名 */
  domain: string;
  /** 监控频率 */
  frequency: 'hourly' | 'daily' | 'weekly';
  /** 监控指标 */
  metrics: Array<'price' | 'bsr' | 'rating' | 'reviews' | 'sales' | 'sellers'>;
  /** 通知方式 */
  notifyType?: 'email' | 'webhook' | 'none';
  /** 通知地址 */
  notifyUrl?: string;
  /** 变化阈值(百分比),超过阈值才通知 */
  threshold?: number;
}

响应数据:

// 响应: ApiResponse<CleanSubscription>
// 复用 CleanSubscription 类型,target 中包含 asin 字段

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "SUB_ASIN_001",
    "type": "asin",
    "status": "active",
    "target": {
      "domain": "amazon.com",
      "asin": "B0EXAMPLE1"
    },
    "frequency": "daily",
    "createdAt": "2025-01-01T12:00:00.000Z",
    "nextRunAt": "2025-01-02T12:00:00.000Z",
    "_source": "sorftime"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.7 TikTok 社交媒体(TikHub)

6.7.1 GET /api/clean/tiktok/users/:uniqueId — 用户资料

获取 TikTok 用户公开资料信息。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | TikHub | TikTokUserApi.getUserProfile | GET /api/tikhub/tiktok/user/profile |

请求参数:

// URL 参数: uniqueId = TikTok 用户名
interface TikTokUserParams {
  /** 无额外参数 */
}

响应数据:

interface CleanTikTokUser {
  /** 用户 ID */
  id: string;
  /** 用户名 */
  uniqueId: string;
  /** 昵称 */
  nickname: string;
  /** 头像 URL */
  avatarUrl: string;
  /** 个人简介 */
  bio: string;
  /** 是否已认证 */
  verified: boolean;
  /** 粉丝数 */
  followerCount: number;
  /** 关注数 */
  followingCount: number;
  /** 获赞数 */
  likeCount: number;
  /** 视频数 */
  videoCount: number;
  /** 主页链接 */
  profileUrl: string;
  /** 关联商业信息 */
  commerce: {
    /** 是否开通商品橱窗 */
    hasShop: boolean;
    /** 商品数量 */
    productCount: number | null;
  } | null;
  _source: 'tikhub';
}

// 响应: ApiResponse<CleanTikTokUser>

数据映射关系:

清洗后字段 TikHub 原始字段
id user.id
uniqueId user.uniqueId
nickname user.nickname
avatarUrl user.avatarLarger
bio user.signature
verified user.verified
followerCount stats.followerCount
followingCount stats.followingCount
likeCount stats.heartCount
videoCount stats.videoCount
commerce.hasShop user.commerceUserInfo.commerceUser

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "6890000000000000000",
    "uniqueId": "exampleuser",
    "nickname": "Example Creator",
    "avatarUrl": "https://p16-sign.tiktokcdn.com/example-avatar.jpg",
    "bio": "Content creator | Product reviews",
    "verified": true,
    "followerCount": 1250000,
    "followingCount": 320,
    "likeCount": 45000000,
    "videoCount": 580,
    "profileUrl": "https://www.tiktok.com/@exampleuser",
    "commerce": {
      "hasShop": true,
      "productCount": 25
    },
    "_source": "tikhub"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.7.2 GET /api/clean/tiktok/videos/:id — 视频详情

获取 TikTok 视频详细信息。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | TikHub | TikTokVideoApi.getVideoDetail | GET /api/tikhub/tiktok/video/detail |

请求参数:

// URL 参数: id = 视频 ID
interface TikTokVideoParams {
  /** 无额外参数 */
}

响应数据:

interface CleanTikTokVideo {
  /** 视频 ID */
  id: string;
  /** 视频描述 */
  description: string;
  /** 视频封面 URL */
  coverUrl: string;
  /** 视频播放 URL */
  videoUrl: string;
  /** 视频时长(秒) */
  duration: number;
  /** 创建时间 */
  createdAt: string;
  /** 作者信息 */
  author: {
    id: string;
    uniqueId: string;
    nickname: string;
    avatarUrl: string;
  };
  /** 互动数据 */
  stats: {
    playCount: number;
    likeCount: number;
    commentCount: number;
    shareCount: number;
    collectCount: number;
  };
  /** 标签列表 */
  hashtags: string[];
  /** 音乐信息 */
  music: {
    id: string;
    title: string;
    author: string;
    duration: number;
  } | null;
  /** 关联商品(如有) */
  products: Array<{
    id: string;
    title: string;
    price: number | null;
    currency: string;
    imageUrl: string;
  }>;
  _source: 'tikhub';
}

// 响应: ApiResponse<CleanTikTokVideo>

数据映射关系:

清洗后字段 TikHub 原始字段
id itemInfo.itemStruct.id
description itemInfo.itemStruct.desc
coverUrl itemInfo.itemStruct.video.cover
videoUrl itemInfo.itemStruct.video.playAddr
duration itemInfo.itemStruct.video.duration
createdAt itemInfo.itemStruct.createTime (Unix → ISO)
author.id itemInfo.itemStruct.author.id
author.uniqueId itemInfo.itemStruct.author.uniqueId
stats.playCount itemInfo.itemStruct.stats.playCount
stats.likeCount itemInfo.itemStruct.stats.diggCount
stats.commentCount itemInfo.itemStruct.stats.commentCount
stats.shareCount itemInfo.itemStruct.stats.shareCount
stats.collectCount itemInfo.itemStruct.stats.collectCount
hashtags itemInfo.itemStruct.textExtra[].hashtagName
music.id itemInfo.itemStruct.music.id
music.title itemInfo.itemStruct.music.title

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "7300000000000000000",
    "description": "Best wireless headphones under $30! #tech #headphones #review",
    "coverUrl": "https://p16-sign.tiktokcdn.com/example-cover.jpg",
    "videoUrl": "https://v16-webapp.tiktok.com/example-video.mp4",
    "duration": 45,
    "createdAt": "2025-01-10T15:30:00.000Z",
    "author": {
      "id": "6890000000000000000",
      "uniqueId": "exampleuser",
      "nickname": "Example Creator",
      "avatarUrl": "https://p16-sign.tiktokcdn.com/example-avatar.jpg"
    },
    "stats": {
      "playCount": 2500000,
      "likeCount": 185000,
      "commentCount": 3200,
      "shareCount": 12000,
      "collectCount": 45000
    },
    "hashtags": ["tech", "headphones", "review"],
    "music": {
      "id": "7200000000000000000",
      "title": "Original Sound",
      "author": "exampleuser",
      "duration": 45
    },
    "products": [
      {
        "id": "PROD001",
        "title": "Wireless Bluetooth Headphones",
        "price": 29.99,
        "currency": "USD",
        "imageUrl": "https://p16-sign.tiktokcdn.com/product1.jpg"
      }
    ],
    "_source": "tikhub"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.7.3 GET /api/clean/tiktok/videos/:id/comments — 视频评论

获取 TikTok 视频评论列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | TikHub | TikTokVideoApi.getVideoComments | GET /api/tikhub/tiktok/video/comments |

请求参数:

// URL 参数: id = 视频 ID
interface TikTokCommentsParams extends PaginationParams {
  /** 排序方式 */
  sortBy?: 'likes' | 'date';
}

响应数据:

interface CleanTikTokComment {
  /** 评论 ID */
  id: string;
  /** 评论内容 */
  content: string;
  /** 评论时间 */
  createdAt: string;
  /** 点赞数 */
  likeCount: number;
  /** 回复数 */
  replyCount: number;
  /** 评论者信息 */
  author: {
    id: string;
    uniqueId: string;
    nickname: string;
    avatarUrl: string;
  };
  _source: 'tikhub';
}

// 响应: ApiResponse<PaginatedResponse<CleanTikTokComment>>

数据映射关系:

清洗后字段 TikHub 原始字段
id cid
content text
createdAt create_time (Unix → ISO)
likeCount digg_count
replyCount reply_comment_total
author.id user.uid
author.uniqueId user.unique_id
author.nickname user.nickname
author.avatarUrl user.avatar_thumb

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": "7300000000000000001",
        "content": "Just bought these, they're amazing!",
        "createdAt": "2025-01-10T16:00:00.000Z",
        "likeCount": 520,
        "replyCount": 12,
        "author": {
          "id": "6890000000000000001",
          "uniqueId": "commenter1",
          "nickname": "Happy Buyer",
          "avatarUrl": "https://p16-sign.tiktokcdn.com/commenter1.jpg"
        },
        "_source": "tikhub"
      }
    ],
    "total": 3200,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.7.4 GET /api/clean/tiktok/shop/products/:id — 商品详情

获取 TikTok Shop 商品详情。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | TikHub | TikTokShopApi.getProductDetail | GET /api/tikhub/tiktok/shop/product/detail |

请求参数:

// URL 参数: id = TikTok Shop 商品 ID
interface TikTokShopProductParams {
  /** 无额外参数 */
}

响应数据:

interface CleanTikTokShopProduct {
  /** 商品 ID */
  id: string;
  /** 商品标题 */
  title: string;
  /** 商品描述 */
  description: string;
  /** 商品图片列表 */
  images: string[];
  /** 价格 */
  price: number;
  /** 原价 */
  originalPrice: number | null;
  /** 货币代码 */
  currency: string;
  /** 销量 */
  soldCount: number;
  /** 评分 */
  rating: number | null;
  /** 评论数 */
  reviewCount: number | null;
  /** 店铺信息 */
  shop: {
    id: string;
    name: string;
    rating: number | null;
    followerCount: number;
  };
  /** SKU 变体 */
  skus: Array<{
    id: string;
    name: string;
    price: number;
    stock: number | null;
    attributes: Record<string, string>;
  }>;
  /** 关联视频数 */
  videoCount: number;
  _source: 'tikhub';
}

// 响应: ApiResponse<CleanTikTokShopProduct>

数据映射关系:

清洗后字段 TikHub 原始字段
id product_id
title product_name
description description
images images[].url_list[0]
price price.min_price / 100
originalPrice price.original_price / 100
soldCount sold_count
rating star_rating.average
reviewCount star_rating.count
shop.id shop_info.shop_id
shop.name shop_info.shop_name
skus[].id skus[].sku_id
skus[].name skus[].sku_name
skus[].price skus[].price.original_price / 100

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "1729000000000000000",
    "title": "Wireless Bluetooth Headphones V5.3",
    "description": "Premium wireless headphones with ANC...",
    "images": [
      "https://p16-oec-ttp.tiktokcdn.com/product1.jpg",
      "https://p16-oec-ttp.tiktokcdn.com/product2.jpg"
    ],
    "price": 25.99,
    "originalPrice": 49.99,
    "currency": "USD",
    "soldCount": 15800,
    "rating": 4.7,
    "reviewCount": 2350,
    "shop": {
      "id": "SHOP001",
      "name": "TechGadgets Official",
      "rating": 4.8,
      "followerCount": 85000
    },
    "skus": [
      { "id": "SKU001", "name": "Black", "price": 25.99, "stock": 500, "attributes": { "color": "Black" } },
      { "id": "SKU002", "name": "White", "price": 25.99, "stock": 320, "attributes": { "color": "White" } }
    ],
    "videoCount": 45,
    "_source": "tikhub"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.7.5 GET /api/clean/tiktok/ads/:id — 广告详情

获取 TikTok 广告详情数据。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | TikHub | TikTokAdsApi.getAdDetail | GET /api/tikhub/tiktok/ads/detail |

请求参数:

// URL 参数: id = 广告 ID
interface TikTokAdParams {
  /** 无额外参数 */
}

响应数据:

interface CleanTikTokAd {
  /** 广告 ID */
  id: string;
  /** 广告标题 */
  title: string;
  /** 广告描述 */
  description: string;
  /** 广告素材 URL */
  mediaUrl: string;
  /** 素材类型 */
  mediaType: 'video' | 'image';
  /** 广告主信息 */
  advertiser: {
    id: string;
    name: string;
    region: string;
  };
  /** 投放时间 */
  startDate: string;
  endDate: string | null;
  /** 投放地区 */
  targetRegions: string[];
  /** 互动数据 */
  stats: {
    impressions: number | null;
    clicks: number | null;
    likeCount: number;
    commentCount: number;
    shareCount: number;
  };
  /** 落地页 URL */
  landingPageUrl: string | null;
  /** CTA 按钮文案 */
  callToAction: string | null;
  _source: 'tikhub';
}

// 响应: ApiResponse<CleanTikTokAd>

数据映射关系:

清洗后字段 TikHub 原始字段
id ad_id
title ad_title
description ad_text
mediaUrl video_urlimage_url
mediaType 根据素材类型判断
advertiser.id advertiser_id
advertiser.name advertiser_name
advertiser.region advertiser_region
startDate first_shown_date
endDate last_shown_date
targetRegions target_countries[]
stats.likeCount digg_count
stats.commentCount comment_count
stats.shareCount share_count
landingPageUrl landing_page_url
callToAction cta_text

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "AD_001",
    "title": "Best Wireless Headphones 2025",
    "description": "Experience premium sound quality at an unbeatable price!",
    "mediaUrl": "https://v16-webapp.tiktok.com/ad-video.mp4",
    "mediaType": "video",
    "advertiser": {
      "id": "ADV001",
      "name": "TechGadgets Inc.",
      "region": "US"
    },
    "startDate": "2025-01-01T00:00:00.000Z",
    "endDate": null,
    "targetRegions": ["US", "CA", "GB"],
    "stats": {
      "impressions": null,
      "clicks": null,
      "likeCount": 8500,
      "commentCount": 320,
      "shareCount": 1200
    },
    "landingPageUrl": "https://www.tiktok.com/shop/product/1729000000000000000",
    "callToAction": "Shop Now",
    "_source": "tikhub"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.8 卖家信息(Amazon)

6.8.1 GET /api/clean/sellers/account — 卖家账户

获取当前卖家的账户信息。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | SellersApi.getMarketplaceParticipations | GET /api/amazon/sellers/participations |

请求参数:

interface SellerAccountParams {
  /** 无额外参数 */
}

响应数据:

interface CleanSellerAccount {
  /** 卖家 ID */
  id: string;
  /** 卖家名称 */
  name: string;
  /** 账户类型 */
  accountType: 'individual' | 'professional';
  /** 已开通的市场列表 */
  marketplaces: Array<{
    id: string;
    name: string;
    country: string;
    domain: string;
    isActive: boolean;
  }>;
  /** 主要市场 */
  primaryMarketplace: {
    id: string;
    name: string;
    country: string;
  };
  _source: 'amazon';
}

// 响应: ApiResponse<CleanSellerAccount>

数据映射关系:

清洗后字段 Amazon 原始字段
id participation.sellerId
name marketplace.name (主市场)
marketplaces[].id marketplace.id
marketplaces[].name marketplace.name
marketplaces[].country marketplace.countryCode
marketplaces[].domain marketplace.domainName
marketplaces[].isActive participation.isParticipating

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "A1EXAMPLE",
    "name": "ExampleBrand Store",
    "accountType": "professional",
    "marketplaces": [
      { "id": "ATVPDKIKX0DER", "name": "Amazon.com", "country": "US", "domain": "amazon.com", "isActive": true },
      { "id": "A2EUQ1WTGCTBG2", "name": "Amazon.ca", "country": "CA", "domain": "amazon.ca", "isActive": true },
      { "id": "A1F83G8C2ARO7P", "name": "Amazon.co.uk", "country": "GB", "domain": "amazon.co.uk", "isActive": false }
    ],
    "primaryMarketplace": {
      "id": "ATVPDKIKX0DER",
      "name": "Amazon.com",
      "country": "US"
    },
    "_source": "amazon"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.8.2 GET /api/clean/sellers/marketplaces — 市场列表

获取卖家已开通的市场列表及状态。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | SellersApi.getMarketplaceParticipations | GET /api/amazon/sellers/participations |

请求参数:

interface MarketplaceListParams {
  /** 是否只返回已激活的市场 */
  activeOnly?: boolean;
}

响应数据:

interface CleanMarketplace {
  /** 市场 ID */
  id: string;
  /** 市场名称 */
  name: string;
  /** 国家代码 */
  country: string;
  /** 域名 */
  domain: string;
  /** 默认语言 */
  language: string;
  /** 默认货币 */
  currency: string;
  /** 是否已激活 */
  isActive: boolean;
  /** 是否有 FBA 服务 */
  hasFBA: boolean;
  _source: 'amazon';
}

// 响应: ApiResponse<CleanMarketplace[]>

数据映射关系:

清洗后字段 Amazon 原始字段
id marketplace.id
name marketplace.name
country marketplace.countryCode
domain marketplace.domainName
language marketplace.defaultLanguageCode
currency marketplace.defaultCurrencyCode
isActive participation.isParticipating
hasFBA participation.hasFulfillmentByAmazon

响应示例:

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": "ATVPDKIKX0DER",
      "name": "Amazon.com",
      "country": "US",
      "domain": "amazon.com",
      "language": "en_US",
      "currency": "USD",
      "isActive": true,
      "hasFBA": true,
      "_source": "amazon"
    },
    {
      "id": "A2EUQ1WTGCTBG2",
      "name": "Amazon.ca",
      "country": "CA",
      "domain": "amazon.ca",
      "language": "en_CA",
      "currency": "CAD",
      "isActive": true,
      "hasFBA": true,
      "_source": "amazon"
    }
  ],
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.9 退货相关(Amazon)

6.9.1 GET /api/clean/returns — 退货列表

获取 Amazon 退货/退款列表。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | FBAReturnsApi.getReturns | GET /api/amazon/fba/returns |

请求参数:

interface ReturnListParams extends PaginationParams {
  marketplaceId?: string;
  /** 退货状态 */
  status?: 'pending' | 'approved' | 'completed' | 'rejected';
  /** 开始日期 */
  startDate?: string;
  /** 结束日期 */
  endDate?: string;
  /** 按 ASIN 筛选 */
  asin?: string;
  /** 按订单号筛选 */
  orderId?: string;
}

响应数据:

interface CleanReturn {
  /** 退货 ID */
  id: string;
  /** 关联订单号 */
  orderId: string;
  /** ASIN */
  asin: string;
  /** SKU */
  sku: string;
  /** 商品标题 */
  title: string;
  /** 退货数量 */
  quantity: number;
  /** 退货状态 */
  status: string;
  /** 退货原因 */
  reason: string;
  /** 退货原因详情 */
  reasonDetail: string | null;
  /** 退款金额 */
  refundAmount: number | null;
  /** 货币代码 */
  currency: string;
  /** 退货发起时间 */
  createdAt: string;
  /** 退货完成时间 */
  completedAt: string | null;
  /** 商品状态 */
  itemCondition: string | null;
  _source: 'amazon';
}

// 响应: ApiResponse<PaginatedResponse<CleanReturn>>

数据映射关系:

清洗后字段 Amazon 原始字段
id returnIdrmaId
orderId orderId
asin asin
sku sellerSKU
title productName
quantity quantity
status status
reason returnReason
reasonDetail customerComments
refundAmount refundAmount.Amount
currency refundAmount.CurrencyCode
createdAt returnRequestDate
completedAt returnClosedDate
itemCondition itemDisposition

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [
      {
        "id": "RET001",
        "orderId": "111-1234567-1234567",
        "asin": "B0EXAMPLE1",
        "sku": "WH-BT-001",
        "title": "Wireless Bluetooth Headphones",
        "quantity": 1,
        "status": "completed",
        "reason": "DEFECTIVE",
        "reasonDetail": "Left ear speaker not working",
        "refundAmount": 29.99,
        "currency": "USD",
        "createdAt": "2025-01-20T10:00:00.000Z",
        "completedAt": "2025-01-25T14:30:00.000Z",
        "itemCondition": "Damaged",
        "_source": "amazon"
      }
    ],
    "total": 23,
    "page": 1,
    "pageSize": 20,
    "hasMore": true
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

6.9.2 GET /api/clean/returns/:id — 退货详情

获取单个退货记录的详细信息。

数据来源: | 平台 | 原始接口 | 原始路由 | |------|---------|---------| | Amazon | FBAReturnsApi.getReturnDetail | GET /api/amazon/fba/returns/:returnId |

请求参数:

// URL 参数: id = 退货 ID
interface ReturnDetailParams {
  marketplaceId?: string;
}

响应数据:

interface CleanReturnDetail extends CleanReturn {
  /** 退货物流信息 */
  shipping: {
    carrier: string | null;
    trackingNumber: string | null;
    returnedAt: string | null;
    receivedAt: string | null;
  };
  /** 退款明细 */
  refundBreakdown: {
    itemPrice: number;
    shippingFee: number;
    tax: number;
    total: number;
    currency: string;
  } | null;
  /** 处理记录 */
  timeline: Array<{
    date: string;
    status: string;
    description: string;
  }>;
  /** 替换订单号(如有) */
  replacementOrderId: string | null;
}

// 响应: ApiResponse<CleanReturnDetail>

响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "id": "RET001",
    "orderId": "111-1234567-1234567",
    "asin": "B0EXAMPLE1",
    "sku": "WH-BT-001",
    "title": "Wireless Bluetooth Headphones",
    "quantity": 1,
    "status": "completed",
    "reason": "DEFECTIVE",
    "reasonDetail": "Left ear speaker not working",
    "refundAmount": 29.99,
    "currency": "USD",
    "createdAt": "2025-01-20T10:00:00.000Z",
    "completedAt": "2025-01-25T14:30:00.000Z",
    "itemCondition": "Damaged",
    "shipping": {
      "carrier": "UPS",
      "trackingNumber": "1Z999AA10123456784",
      "returnedAt": "2025-01-22T09:00:00.000Z",
      "receivedAt": "2025-01-24T16:00:00.000Z"
    },
    "refundBreakdown": {
      "itemPrice": 29.99,
      "shippingFee": 0,
      "tax": 2.70,
      "total": 32.69,
      "currency": "USD"
    },
    "timeline": [
      { "date": "2025-01-20T10:00:00.000Z", "status": "requested", "description": "退货申请已提交" },
      { "date": "2025-01-20T10:05:00.000Z", "status": "approved", "description": "退货申请已批准" },
      { "date": "2025-01-22T09:00:00.000Z", "status": "shipped", "description": "买家已寄出退货商品" },
      { "date": "2025-01-24T16:00:00.000Z", "status": "received", "description": "仓库已收到退货商品" },
      { "date": "2025-01-25T14:30:00.000Z", "status": "completed", "description": "退款已处理完成" }
    ],
    "replacementOrderId": null,
    "_source": "amazon"
  },
  "timestamp": "2025-01-01T12:00:00.000Z"
}

7. 前端调用示例

7.1 创建统一请求客户端

import axios, { AxiosInstance, AxiosResponse } from 'axios';

/** 创建清洗接口专用客户端 */
const cleanApiClient: AxiosInstance = axios.create({
  baseURL: 'https://server-msq.fmode.cn/api/clean',
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json',
  },
});

/** 响应拦截器:统一错误处理 */
cleanApiClient.interceptors.response.use(
  (response: AxiosResponse<ApiResponse<any>>) => {
    const { data } = response;
    if (data.code !== 0) {
      return Promise.reject(new CleanApiError(data.code, data.message));
    }
    return response;
  },
  (error) => {
    if (error.response) {
      const { data } = error.response;
      return Promise.reject(
        new CleanApiError(data?.code || error.response.status, data?.message || '请求失败')
      );
    }
    return Promise.reject(new CleanApiError(50001, '网络连接失败'));
  }
);

/** 自定义错误类 */
class CleanApiError extends Error {
  code: number;
  constructor(code: number, message: string) {
    super(message);
    this.code = code;
    this.name = 'CleanApiError';
  }
}

export { cleanApiClient, CleanApiError };

7.2 产品相关调用

import { cleanApiClient } from './cleanApiClient';

/** 搜索产品 */
async function searchProducts(keyword: string, page = 1) {
  const { data } = await cleanApiClient.get('/products/search', {
    params: { keyword, page, pageSize: 20, source: 'all' },
  });
  return data.data; // PaginatedResponse<CleanProduct>
}

/** 获取产品详情(聚合多平台) */
async function getProductDetail(asin: string) {
  const { data } = await cleanApiClient.get(`/products/${asin}`, {
    params: { source: 'all', includeTrend: true, trendStartDate: '2024-10-01', trendEndDate: '2025-01-01' },
  });
  return data.data; // CleanProductDetail
}

/** 获取产品销量数据 */
async function getProductSales(asin: string, startDate: string, endDate: string) {
  const { data } = await cleanApiClient.get(`/products/${asin}/sales`, {
    params: { startDate, endDate, granularity: 'day', source: 'sorftime' },
  });
  return data.data; // CleanProductSales
}

/** 获取同类产品 */
async function getSimilarProducts(asin: string) {
  const { data } = await cleanApiClient.get(`/products/${asin}/similar`, {
    params: { domain: 'amazon.com', page: 1, pageSize: 10 },
  });
  return data.data; // PaginatedResponse<CleanSimilarProduct>
}

7.3 订单相关调用

/** 获取订单列表 */
async function getOrders(params: {
  status?: string;
  createdAfter?: string;
  page?: number;
}) {
  const { data } = await cleanApiClient.get('/orders', {
    params: { marketplaceId: 'ATVPDKIKX0DER', pageSize: 20, ...params },
  });
  return data.data; // PaginatedResponse<CleanOrder>
}

/** 获取订单详情 */
async function getOrderDetail(orderId: string) {
  const { data } = await cleanApiClient.get(`/orders/${orderId}`);
  return data.data; // CleanOrderDetail
}

/** 获取订单统计 */
async function getOrderMetrics(startDate: string, endDate: string) {
  const { data } = await cleanApiClient.get('/orders/metrics', {
    params: {
      marketplaceId: 'ATVPDKIKX0DER',
      granularity: 'week',
      startDate,
      endDate,
    },
  });
  return data.data; // CleanOrderMetrics
}

7.4 关键词相关调用

/** 搜索关键词 */
async function searchKeywords(keyword: string) {
  const { data } = await cleanApiClient.get('/keywords/search', {
    params: { keyword, domain: 'amazon.com', matchType: 'broad', page: 1, pageSize: 20 },
  });
  return data.data; // PaginatedResponse<CleanKeyword>
}

/** ASIN 反查关键词 */
async function getReverseKeywords(asin: string) {
  const { data } = await cleanApiClient.get(`/keywords/reverse/${asin}`, {
    params: { domain: 'amazon.com', sortBy: 'searchVolume', sortOrder: 'desc' },
  });
  return data.data; // PaginatedResponse<CleanReverseKeyword>
}

/** 获取关键词趋势 */
async function getKeywordTrend(keyword: string) {
  const { data } = await cleanApiClient.get(`/keywords/${encodeURIComponent(keyword)}/trend`, {
    params: { domain: 'amazon.com', period: '12m', granularity: 'month' },
  });
  return data.data; // CleanKeywordTrend
}

7.5 TikTok 相关调用

/** 获取 TikTok 用户资料 */
async function getTikTokUser(uniqueId: string) {
  const { data } = await cleanApiClient.get(`/tiktok/users/${uniqueId}`);
  return data.data; // CleanTikTokUser
}

/** 获取 TikTok 视频详情 */
async function getTikTokVideo(videoId: string) {
  const { data } = await cleanApiClient.get(`/tiktok/videos/${videoId}`);
  return data.data; // CleanTikTokVideo
}

/** 获取 TikTok 视频评论 */
async function getTikTokComments(videoId: string, page = 1) {
  const { data } = await cleanApiClient.get(`/tiktok/videos/${videoId}/comments`, {
    params: { page, pageSize: 20, sortBy: 'likes' },
  });
  return data.data; // PaginatedResponse<CleanTikTokComment>
}

/** 获取 TikTok Shop 商品详情 */
async function getTikTokShopProduct(productId: string) {
  const { data } = await cleanApiClient.get(`/tiktok/shop/products/${productId}`);
  return data.data; // CleanTikTokShopProduct
}

7.6 错误处理最佳实践

import { CleanApiError } from './cleanApiClient';

async function fetchWithErrorHandling() {
  try {
    const products = await searchProducts('wireless headphones');
    console.log('产品列表:', products.items);
  } catch (error) {
    if (error instanceof CleanApiError) {
      switch (error.code) {
        case 40001:
          console.error('参数错误:', error.message);
          break;
        case 40101:
        case 40102:
          console.error('认证失败,请重新登录');
          // 跳转登录页
          break;
        case 42901:
          console.error('请求过于频繁,请稍后重试');
          break;
        case 50002:
        case 50003:
        case 50004:
          console.error('上游服务异常:', error.message);
          // 显示降级提示
          break;
        default:
          console.error('未知错误:', error.code, error.message);
      }
    } else {
      console.error('网络错误:', error);
    }
  }
}

附录:数据来源映射总表

以下表格汇总了所有 /api/clean/ 接口与原始平台接口的对应关系:

清洗接口 方法 平台 原始接口 原始路由
/api/clean/products/search GET Amazon CatalogItemsApi.searchCatalogItems GET /api/amazon/catalog/items
/api/clean/products/search GET Sorftime ProductApi.getProductQuery POST /api/sorftime/forward/api/ProductQuery
/api/clean/products/:id GET Amazon CatalogItemsApi.getCatalogItem GET /api/amazon/catalog/items/:asin
/api/clean/products/:id GET Sorftime ProductApi.getProductRequest POST /api/sorftime/forward/api/ProductRequest
/api/clean/products/:id/sales GET Amazon SalesApi.getOrderMetrics GET /api/amazon/sales/orderMetrics
/api/clean/products/:id/sales GET Sorftime ProductApi.getAsinSalesVolume POST /api/sorftime/forward/api/AsinSalesVolume
/api/clean/products/:id/reviews GET Amazon SellersApi.getCustomerFeedback GET /api/amazon/sellers/feedback
/api/clean/products/:id/reviews GET Sorftime ProductApi.getProductReviewsQuery POST /api/sorftime/forward/api/ProductReviewsQuery
/api/clean/products/:id/similar GET Sorftime ProductApi.getSimilarProductRealtime POST /api/sorftime/forward/api/SimilarProductRealtimeRequest
/api/clean/orders GET Amazon OrdersApi.getOrders GET /api/amazon/orders
/api/clean/orders/:id GET Amazon OrdersApi.getOrder + getOrderItems GET /api/amazon/orders/:orderId + /items
/api/clean/orders/metrics GET Amazon SalesApi.getOrderMetrics GET /api/amazon/sales/orderMetrics
/api/clean/listings GET Amazon ListingsApi.getListingsItems GET /api/amazon/listings
/api/clean/listings/:sku GET Amazon ListingsApi.getListingsItem GET /api/amazon/listings/:sku
/api/clean/categories/tree GET Sorftime CategoryApi.getCategoryTree POST /api/sorftime/forward/api/CategoryTree
/api/clean/categories/:id/products GET Sorftime CategoryApi.getCategoryProducts POST /api/sorftime/forward/api/CategoryProducts
/api/clean/categories/:id/keywords GET Sorftime CategoryApi.getCategoryKeywords POST /api/sorftime/forward/api/CategoryKeywords
/api/clean/keywords/search GET Sorftime KeywordApi.getKeywordSearch POST /api/sorftime/forward/api/KeywordSearch
/api/clean/keywords/:keyword/products GET Sorftime KeywordApi.getKeywordProducts POST /api/sorftime/forward/api/KeywordProducts
/api/clean/keywords/reverse/:asin GET Sorftime KeywordApi.getReverseAsin POST /api/sorftime/forward/api/ReverseAsin
/api/clean/keywords/:keyword/trend GET Sorftime KeywordApi.getKeywordTrend POST /api/sorftime/forward/api/KeywordTrend
/api/clean/monitoring/bestseller/subscribe POST Sorftime MonitorApi.subscribeBestSeller POST /api/sorftime/forward/api/BestSellerSubscribe
/api/clean/monitoring/bestseller/tasks GET Sorftime MonitorApi.getBestSellerTasks POST /api/sorftime/forward/api/BestSellerTasks
/api/clean/monitoring/asin/subscribe POST Sorftime MonitorApi.subscribeAsin POST /api/sorftime/forward/api/AsinSubscribe
/api/clean/tiktok/users/:uniqueId GET TikHub TikTokUserApi.getUserProfile GET /api/tikhub/tiktok/user/profile
/api/clean/tiktok/videos/:id GET TikHub TikTokVideoApi.getVideoDetail GET /api/tikhub/tiktok/video/detail
/api/clean/tiktok/videos/:id/comments GET TikHub TikTokVideoApi.getVideoComments GET /api/tikhub/tiktok/video/comments
/api/clean/tiktok/shop/products/:id GET TikHub TikTokShopApi.getProductDetail GET /api/tikhub/tiktok/shop/product/detail
/api/clean/tiktok/ads/:id GET TikHub TikTokAdsApi.getAdDetail GET /api/tikhub/tiktok/ads/detail
/api/clean/sellers/account GET Amazon SellersApi.getMarketplaceParticipations GET /api/amazon/sellers/participations
/api/clean/sellers/marketplaces GET Amazon SellersApi.getMarketplaceParticipations GET /api/amazon/sellers/participations
/api/clean/returns GET Amazon FBAReturnsApi.getReturns GET /api/amazon/fba/returns
/api/clean/returns/:id GET Amazon FBAReturnsApi.getReturnDetail GET /api/amazon/fba/returns/:returnId