# 身分驗證與簽章

Weydub API 請求使用 `AppKey` 與 `AppSign` 標頭。`AppSecret` 僅限保存在伺服器端。

## 請求結構

| 項目 | 值 |
| --- | --- |
| 基底 URL | `https://api.zhaoli.com` |
| 通訊協定 | HTTPS |
| 方法 | 文件記載的 API 呼叫使用 `POST` |
| 編碼 | UTF-8 |
| 內容類型 | `application/json` |
| 請求本文 | JSON，以精簡格式序列化，以維持簽章穩定性 |

## 標頭

```text
Content-Type: application/json
AppKey: your_app_key
AppSign: computed_signature
```

`AppSecret` 絕不會作為標頭或本文欄位傳送，僅會在您的伺服器上用於計算 `AppSign`。

## 簽章公式

```text
AppSign = md5(md5(request_body) + AppSecret)
```

簽章必須根據實際透過網路傳送的確切 JSON 本文計算。為使簽章保持穩定，序列化 JSON 時請勿加入多餘的空格。

若端點允許空本文，請對實際傳送的確切位元組計算簽章。在大多數整合情境中，對於無本文呼叫，建議優先傳送 `{}` 並對 `{}` 計算簽章。

## 免簽章端點

列舉端點不需要簽章：

```text
POST /v-w-c/enum/query2
```

使用此端點取得動態語言／狀態列舉，例如 `sourceLang`、`Lang`、`ProcessStatus` 和 `ImageTaskStatus`。

## Python 簽章輔助函式

```python
import hashlib
import json


def signed_body_and_headers(payload: dict, app_key: str, app_secret: str):
    body = json.dumps(payload, ensure_ascii=False, separators=(",", ":"))
    body_md5 = hashlib.md5(body.encode("utf-8")).hexdigest()
    app_sign = hashlib.md5((body_md5 + app_secret).encode("utf-8")).hexdigest()
    return body, {
        "Content-Type": "application/json",
        "AppKey": app_key,
        "AppSign": app_sign,
    }
```

## Node 簽章輔助函式

```js
import crypto from "node:crypto";

export function signedBodyAndHeaders(payload, appKey, appSecret) {
  const body = JSON.stringify(payload);
  const bodyMd5 = crypto.createHash("md5").update(body).digest("hex");
  const appSign = crypto.createHash("md5").update(bodyMd5 + appSecret).digest("hex");
  return {
    body,
    headers: {
      "Content-Type": "application/json",
      AppKey: appKey,
      AppSign: appSign,
    },
  };
}
```

## cURL 模式

使用您的後端計算 `AppSign`，接著傳送完全一致的本文：

```bash
curl -X POST "https://api.zhaoli.com/v-w-c/gateway/ve/work/status" \
  -H "Content-Type: application/json" \
  -H "AppKey: $WEYDUB_APP_KEY" \
  -H "AppSign: $WEYDUB_APP_SIGN" \
  --data '{"idWorks":[488026661]}'
```

## 回呼簽章

Weydub 傳送回呼時，回呼中會包含：

```text
Callback-Sign: computed_callback_signature
```

使用原始回呼請求本文，依相同公式驗證回呼：

```text
expected = md5(md5(raw_callback_body) + AppSecret)
```

比較 `expected` 與 `Callback-Sign`。拒絕或隔離未通過驗證的回呼酬載。

## 常見錯誤

- 對美化排版後的 JSON 計算簽章，卻傳送精簡格式的 JSON。
- 簽章後變更酬載。
- 簽章與傳送時使用不同的字串逸出方式。
- 對記憶體中的物件計算簽章，而非最終透過 HTTP 傳送的位元組。
- 忘記 `extraOptions`、`wyVoiceParam`、`videoInpaintMasks`、`downloadInfo` 以及重做的 `result`，可能需要在外層 JSON 本文中保持為精簡格式的 JSON 字串。
- 將認證資訊放入前端程式碼。
- 將 `AppSecret` 分享給瀏覽器擴充功能、用戶端應用程式、螢幕截圖、日誌或公開提示詞。

## 代理程式規則

- 從環境變數或機密管理工具讀取認證資訊。
- 絕不回顯 `AppSecret`。
- 絕不將認證資訊寫入產生的範例檔案。
- 產生可執行的範例時，請使用預留位置或環境變數。
- 偵錯簽章錯誤時，請在不輸出機密資訊的情況下，比較本文位元組與非機密的本文雜湊值。
- 在 webhook 處理常式中驗證 `Callback-Sign`。
