# Authentification et signature

Les requêtes Weydub API utilisent les en-têtes `AppKey` et `AppSign`. Conservez `AppSecret` uniquement côté serveur.

## Structure de la requête

| Élément | Valeur |
| --- | --- |
| URL de base | `https://api.zhaoli.com` |
| Protocole | HTTPS |
| Méthode | `POST` pour les appels API documentés |
| Encodage | UTF-8 |
| Type de contenu | `application/json` |
| Corps de la requête | JSON, sérialisé de manière compacte pour garantir la stabilité des signatures |

## En-têtes

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

`AppSecret` n’est jamais envoyé dans un en-tête ni dans un champ du corps. Il est utilisé uniquement sur votre serveur pour calculer `AppSign`.

## Formule de signature

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

La signature doit être calculée à partir du corps JSON exact envoyé sur le réseau. Pour garantir la stabilité des signatures, sérialisez JSON sans espaces supplémentaires.

Si un point de terminaison autorise un corps vide, signez exactement les octets que vous envoyez. Dans la plupart des intégrations, préférez envoyer `{}` et signer `{}` pour les appels sans corps.

## Point de terminaison non signé

Le point de terminaison enum ne nécessite pas de signature :

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

Utilisez-le pour récupérer les énumérations dynamiques de langue et de statut, telles que `sourceLang`, `Lang`, `ProcessStatus` et `ImageTaskStatus`.

## Assistant de signature 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,
    }
```

## Assistant de signature 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,
    },
  };
}
```

## Modèle cURL

Utilisez votre backend pour calculer `AppSign`, puis envoyez le corps exact :

```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]}'
```

## Signature des callbacks

Lorsque Weydub envoie un callback, celui-ci inclut :

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

Vérifiez les callbacks avec la même formule, en utilisant le corps brut de la requête du callback :

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

Comparez `expected` à `Callback-Sign`. Rejetez ou mettez en quarantaine les charges utiles des callbacks qui ne passent pas la vérification.

## Erreurs courantes

- Signer JSON avec une mise en forme lisible, mais envoyer JSON sous forme compacte.
- Modifier la charge utile après l’avoir signée.
- Utiliser un échappement de chaînes différent lors de la signature et de l’envoi.
- Signer un objet en mémoire au lieu des octets finaux envoyés via HTTP.
- Oublier que `extraOptions`, `wyVoiceParam`, `videoInpaintMasks`, `downloadInfo` et redo `result` peuvent devoir rester des chaînes JSON compactes à l’intérieur du corps JSON externe.
- Placer les identifiants dans le code frontal.
- Partager `AppSecret` avec des extensions de navigateur, des applications côté client, des captures d’écran, des journaux ou des prompts publics.

## Règles pour les agents

- Lire les identifiants depuis des variables d’environnement ou un gestionnaire de secrets.
- Ne jamais afficher `AppSecret`.
- Ne jamais écrire les identifiants dans des fichiers d’exemple générés.
- Lors de la production d’exemples exécutables, utiliser des espaces réservés ou des variables d’environnement.
- Lors du débogage d’une erreur de signature, comparer les octets du corps et les hachages non secrets du corps sans afficher les secrets.
- Vérifiez `Callback-Sign` pour les gestionnaires de webhooks.
