Signature HMAC
Un second verrou, en plus de la clé. Facultatif — et vous devriez quand même l'activer sur les appels qui écrivent.
Ce que ça ajoute
La clé prouve qui appelle. La signature prouve que le corps n'a pas été modifié et que l'appel n'est pas un rejeu d'un appel plus ancien. Les deux répondent à des questions différentes, et une clé volée reste inutilisable sans le secret de signature.
Les deux en-têtes
X-PartnerCut-Timestamp: 1755691200 X-PartnerCut-Signature: v1=3f8a…
La signature se calcule sur timestamp + "." + corps brut, en HMAC-SHA256,
avec le secret de signature du projet :
$timestamp = (string) time();
$signature = 'v1=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);
La fenêtre de tolérance
Un horodatage trop ancien ou trop lointain est refusé. La tolérance couvre la dérive normale d'une horloge serveur, pas des heures. Si vos appels sont rejetés pour cette raison, le problème est presque toujours l'horloge de la machine appelante : vérifiez que NTP y tourne.
Exemple complet
$body = json_encode([
'externalId' => 'pay_9f2c4',
'customerId' => 'cus_demo_003',
'revenueType' => 'paid_offer',
'amountCents' => 12000,
], JSON_THROW_ON_ERROR);
$timestamp = (string) time();
$response = $client->request('POST', 'https://partnercut.fr/api/v1/events', [
'headers' => [
'Authorization' => 'Bearer ' . $key,
'Content-Type' => 'application/json',
'X-PartnerCut-Timestamp' => $timestamp,
'X-PartnerCut-Signature' => 'v1=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret),
],
// Le corps EXACT qui a été signé, pas un tableau que le client
// re-sérialiserait à sa façon.
'body' => $body,
]);
Le préfixe de version
La signature commence par v1=. Le jour où l'algorithme changera, les deux
formats coexisteront le temps que chacun migre : votre intégration ne cassera pas du jour
au lendemain.