# 認証と署名

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 をシリアライズしてください。

エンドポイントで空のボディが許可されている場合は、実際に送信するバイト列に署名してください。ほとんどの統合では、ボディなしの呼び出しに対して `{}` を送信し、`{}` に署名することを推奨します。

## 署名不要のエンドポイント

enum エンドポイントには署名は不要です:

```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`を検証する。
