# TikTok Campaign 商品不可购买排查材料

更新时间：2026-06-19  
环境：BeeX `id-test`  
目的：整理 BeeX 首页「高返佣」商品从 TikTok Partner Campaign 拉取、缓存、展示、跳转的完整链路，并向 TikTok 确认为什么接口返回了看起来可推广、可用、库存大于 0，但买家端实际不可购买的商品。

## 1. 当前现象

BeeX 首页「高返佣」Tab 展示了 TikTok Partner Campaign 商品，例如：

| 字段 | 值 |
| --- | --- |
| product_id | `1732020740450649354` |
| 商品名 | `Medicube AGE-R Booster Pro Black Duo` |
| 店铺 | `Medicube Indonesia` |
| Campaign ID | `7638897877893990160` |
| Campaign 状态 | `ONGOING` |
| 商品审核状态 | `APPROVED` |
| TikTok 返回可用状态 | `is_available=true` |
| TikTok 返回库存 | `inventory=473` |

但用户在 TikTok / Tokopedia 侧打开同类商品时，会出现类似：

```text
Product not available yet
This is an affiliate product and you don't have access to selling it.
```

或：

```text
This seller is currently on vacation.
Save the product to Favorites and buy when the seller is back.
```

问题点：TikTok Open API 返回的字段显示商品可用，但 C 端买家实际不能购买。BeeX 目前无法仅凭已返回字段稳定过滤这类商品。

## 2. BeeX 前端如何请求高返佣商品

H5 首页「高返佣」Tab 调用 BeeX 后端：

```http
POST https://api-id-test.beexofficial.com/api/v1/products/high-commission
Content-Type: application/json

{
  "countryCode": "ID",
  "limit": 6,
  "source": "PARTNER_CAMPAIGN"
}
```

BeeX 后端真实返回示例：

```json
{
  "success": true,
  "code": "OK",
  "data": {
    "products": [
      {
        "id": "tiktok-1732020740450649354",
        "platformProductId": "1732020740450649354",
        "name": "Medicube AGE-R Booster Pro Black Duo",
        "brand": "Medicube Indonesia",
        "platform": "TIKTOK",
        "imageUrl": "https://p16-oec-sg.ibyteimg.com/...",
        "description": "BeeX Partner campaign high-commission product.",
        "shopName": "Medicube Indonesia",
        "cashbackMinor": 26676000,
        "priceMinor": 741000000,
        "currency": "IDR",
        "productUrl": "https://shop-id.tokopedia.com/view/product/1732020740450649354?region=ID&local=en",
        "source": "tiktok.partner_campaign_cache"
      }
    ],
    "pageInfo": {
      "hasNext": true,
      "nextCursor": "page:2",
      "pageSize": 6
    }
  }
}
```

说明：

- `source=tiktok.partner_campaign_cache` 表示该商品来自 BeeX 定时同步的 TikTok Partner Campaign 商品池。
- `productUrl` 如果 TikTok Campaign API 没有返回，BeeX 会用 `product_id` 兜底生成：

```text
https://shop-id.tokopedia.com/view/product/{product_id}?region=ID&local=en
```

这个链接只是 TikTok/Tokopedia PDP 商品详情页地址，不等于 TikTok 已确认该商品当前可购买。

## 3. BeeX 后端同步 TikTok Campaign 的接口

### 3.1 查询 Campaign 列表

BeeX 调用 TikTok Partner API：

```http
GET https://open-api.tiktokglobalshop.com/affiliate_partner/202405/campaigns
```

关键 Query 参数：

```text
app_key=<redacted>
timestamp=<generated>
sign=<generated>
category_asset_cipher=ROW_fyGlKwAAAAB6jCmj_Z8Zc6uknZJUdZAi
type=MY_CAMPAIGNS
query_type_filter=DEFAULT
status=ONGOING
page_size=3
```

Header：

```text
x-tts-access-token=<redacted>
content-type=application/json
```

TikTok 当前返回示例：

```json
{
  "campaigns": [
    {
      "campaign_end_time": 1809104399,
      "campaign_start_time": 1778518800,
      "id": "7638897877893990160",
      "name": "Endless sea - Linkshare",
      "registration_end_time": 1809104399,
      "registration_start_time": 1778518800,
      "status": "ONGOING"
    }
  ],
  "next_page_token": "cGFnZV9udW1iZXI9Mg==",
  "total_count": 18
}
```

BeeX 当前只同步 `ONGOING` Campaign。

### 3.2 查询 Campaign 商品列表

BeeX 调用 TikTok Partner API：

```http
GET https://open-api.tiktokglobalshop.com/affiliate_partner/202405/campaigns/{campaign_id}/products
```

当前请求：

```http
GET /affiliate_partner/202405/campaigns/7638897877893990160/products
```

关键 Query 参数：

```text
app_key=<redacted>
timestamp=<generated>
sign=<generated>
category_asset_cipher=ROW_fyGlKwAAAAB6jCmj_Z8Zc6uknZJUdZAi
review_status=APPROVED
page_size=3
```

Header：

```text
x-tts-access-token=<redacted>
content-type=application/json
```

TikTok 当前返回示例：

```json
{
  "next_page_token": "cGFnZV9udW1iZXI9Mg==",
  "products": [
    {
      "category": {
        "id": "601990",
        "name": "Earphone & Headphone"
      },
      "creator_commission_rate": 0,
      "highest_price": {
        "amount": "419000",
        "currency": "IDR"
      },
      "id": "1731880550514853709",
      "inventory": 4014,
      "is_available": true,
      "lowest_price": {
        "amount": "409000",
        "currency": "IDR"
      },
      "main_image_url": "https://p16-oec-sg.ibyteimg.com/...",
      "name": "[OWS DAILY] Baseus Bass BC1 Open Ear Fit Wireless Stereo...",
      "open_collaboration_commission_rate": 800,
      "partner_commission_rate": 1000,
      "product_sales": 4923,
      "review_status": "APPROVED",
      "sample_quota": 0,
      "shop_name": "Baseus official store",
      "sku_information_list": [
        {
          "base_price": {
            "currency": "IDR",
            "list_price": "1498000",
            "region_code": "",
            "sale_price": "1498000"
          },
          "inventory": {
            "available_quantity": "868"
          },
          "region_prices": [
            {
              "currency": "IDR",
              "region_code": "ID",
              "sale_price": "1498000"
            }
          ],
          "sku_id": "1731880554428663629"
        }
      ],
      "total_commission_rate": 1000
    }
  ],
  "total_count": 1295
}
```

### 3.3 问题商品在 BeeX 缓存里的 TikTok 原始字段

以下字段来自 BeeX 数据库保存的 TikTok Campaign Product `raw_json`，均由 TikTok Partner Campaign Product List 接口返回。

| product_id | campaign_status | review_status | is_available | inventory | product_sales | shop_name | lowest_price | highest_price | open_collaboration_commission_rate | partner_commission_rate |
| --- | --- | --- | --- | ---: | ---: | --- | ---: | ---: | ---: | ---: |
| `1732020425528018186` | `ONGOING` | `APPROVED` | `true` | 397 | 2 | Medicube Indonesia | 7410000 | 7410000 | 500 | 600 |
| `1732020611159065866` | `ONGOING` | `APPROVED` | `true` | 198 | 10 | Medicube Indonesia | 7410000 | 7410000 | 500 | 600 |
| `1732020740450649354` | `ONGOING` | `APPROVED` | `true` | 473 | 1 | Medicube Indonesia | 7410000 | 7410000 | 500 | 600 |
| `1732273369392711032` | `ONGOING` | `APPROVED` | `true` | 9933 | 55617 | Scarlett Whitening | 41999 | 89900 | 600 | 1000 |

其中 `1732020740450649354` 的关键原始 JSON 片段：

```json
{
  "category": {
    "id": "601733",
    "name": "Alat Skincare"
  },
  "creator_commission_rate": 0,
  "highest_price": {
    "amount": "7410000",
    "currency": "IDR"
  },
  "id": "1732020740450649354",
  "inventory": 473,
  "is_available": true,
  "lowest_price": {
    "amount": "7410000",
    "currency": "IDR"
  },
  "main_image_url": "https://p16-oec-sg.ibyteimg.com/...",
  "name": "Medicube AGE-R Booster Pro Black Duo",
  "open_collaboration_commission_rate": 500,
  "partner_commission_rate": 600,
  "product_sales": 1,
  "review_status": "APPROVED",
  "sample_quota": 0,
  "shop_name": "Medicube Indonesia",
  "sku_information_list": [
    {
      "inventory": {
        "available_quantity": "473"
      },
      "region_prices": [
        {
          "currency": "IDR",
          "region_code": "ID",
          "sale_price": "7410000"
        }
      ]
    }
  ]
}
```

注意：该返回里没有看到以下能够解释 C 端不可购买的字段：

- `can_buy`
- `can_purchase`
- `purchasable`
- `buyer_available`
- `seller_vacation`
- `is_seller_on_vacation`
- `shop_vacation`
- `unavailable_reason`
- `not_available_reason`
- `product_status`
- `seller_status`
- `shop_status`
- `sale_status`
- `listing_status`
- `is_buyable`

## 4. BeeX 当前过滤逻辑

### 4.1 同步入库阶段

当前同步逻辑：

1. 拉 Campaign 列表，只同步 `status=ONGOING` 的 Campaign。
2. 对每个 Campaign 拉商品列表，请求固定带 `review_status=APPROVED`。
3. 保存 TikTok 返回的字段到 `tiktok_partner_campaign_products`。
4. 如果某个商品下一轮不再出现在 Campaign 商品列表里，会标记为 `CLOSED`。

### 4.2 首页展示阶段

BeeX 首页高返佣商品只从缓存表读取：

```sql
select *
from tiktok_partner_campaign_products
where country_code = ?
  and review_status = 'APPROVED'
  and campaign_status in ('READY', 'ONGOING', 'UNSPECIFIED')
order by coalesce(commission_minor, 0) desc,
         coalesce(commission_rate, 0) desc,
         synced_at desc
limit ?
```

然后转换为前端商品模型。

当前对 TikTok Campaign 商品的有效性判断主要是：

| 过滤项 | 当前是否能过滤 | 说明 |
| --- | --- | --- |
| Campaign 非可用 | 可以 | 只读 `ONGOING/READY/UNSPECIFIED`。 |
| 商品未审核通过 | 可以 | 只读 `review_status=APPROVED`。 |
| 商品没有 product_id/name | 可以 | 无法组成商品卡片。 |
| TikTok 未返回 product_url | 不能过滤 | 当前会用 product_id 生成 PDP 兜底链接。 |
| TikTok 返回 `is_available=false` | 当前未完整接入 Campaign 专用过滤 | 可以补过滤，但本次问题商品是 `is_available=true`。 |
| TikTok 返回库存 0 | 当前未完整接入 Campaign 专用过滤 | 可以补过滤，但本次问题商品库存大于 0。 |
| 卖家休假 | 不能过滤 | TikTok 当前返回没有对应字段。 |
| 买家端不可购买 | 不能过滤 | TikTok 当前返回没有 `can_buy/purchasable/unavailable_reason` 等字段。 |

## 5. 为什么现在过滤不了这类商品

从 BeeX 目前拿到的数据看，TikTok 返回了：

```text
campaign_status = ONGOING
review_status   = APPROVED
is_available    = true
inventory       > 0
sku inventory   > 0
price           > 0
commission      > 0
```

这些字段全部表示“这个商品可以作为 Campaign 商品出现/审核通过/有库存/有佣金”。

但用户端看到的是“不可购买”或“店铺休假”。这说明 TikTok Campaign Product List 的返回，至少在当前字段层面，不能等价于“买家侧可购买”。

BeeX 如果强行过滤，只能过滤明显异常：

- `review_status != APPROVED`
- `campaign_status` 不可用
- `is_available=false`
- `inventory <= 0`
- 所有 SKU `available_quantity <= 0`
- `price <= 0`
- `commission <= 0`
- 如果 TikTok 以后返回 `seller_vacation / can_buy / unavailable_reason`，再按字段过滤

但对于当前这种 TikTok 返回 `is_available=true`、库存大于 0、审核通过的商品，BeeX 没有可靠字段判断它不可购买。

## 6. 需要问 TikTok 的问题

建议把下面问题直接发给 TikTok/TSP 技术支持：

1. `/affiliate_partner/202405/campaigns/{campaign_id}/products?review_status=APPROVED` 返回的 `review_status=APPROVED` 是否只代表 Campaign 商品审核通过，不代表买家端可购买？
2. `is_available=true` 和 `inventory>0` 是否保证买家端可以下单？如果不保证，它们分别代表什么含义？
3. 对于买家端提示 `Product not available yet` 或 `This seller is currently on vacation` 的商品，Partner Campaign Product List 是否有对应字段可以识别？
4. 是否有字段或接口能返回：
   - seller vacation / shop vacation
   - buyer purchasable / can buy
   - unavailable reason
   - product listing status
   - market/region saleability
5. 对于 `campaign_id=7638897877893990160` 下的以下商品，为什么接口返回 `APPROVED + is_available=true + inventory>0`，但买家端不可购买？
   - `1732020425528018186`
   - `1732020611159065866`
   - `1732020740450649354`
6. Partner Campaign Product List 返回中没有 `product_url`，BeeX 只能用 `https://shop-id.tokopedia.com/view/product/{product_id}?region=ID&local=en` 生成 PDP。请确认 TikTok 是否有官方推荐的 buyer-facing PDP / deeplink 字段或生成接口。
7. `generate-affiliate-partner-campaign-product-link` 生成的链接是否应该给买家下单使用？如果该接口生成的是“Add product link / creator 添加商品”而不是买家购买链接，请明确推荐 BeeX 用哪个接口生成买家购买链接。

## 7. BeeX 侧建议处理

短期建议：

1. TikTok Campaign 商品同步时补充显式过滤：
   - `is_available=false`
   - `inventory<=0`
   - 所有 SKU 库存为 0
   - 价格为空或小于等于 0
   - 佣金为空或小于等于 0
   - 如果返回 status 字段包含 `VACATION / UNAVAILABLE / SOLD_OUT / CLOSED / EXPIRED / REJECTED`，过滤
2. 对 TikTok 已知不可购买的 `product_id` 增加 BeeX 本地黑名单，避免线上继续展示。
3. 高返佣列表展示前保留 `raw_json` 和 `synced_at`，方便追溯。

中期建议：

1. 等 TikTok 明确 buyer purchasable 字段或接口后，接入正式过滤。
2. 如果 TikTok 没有字段，只能做异步校验任务：
   - 预生成 Creator buyer link
   - 失败则标记不可用
   - 成功只代表链接生成成功，不一定代表买家端 100% 可下单
3. 管理后台增加“商品不可用反馈”入口，由运营一键下架某个高返佣商品。

