agricole
S'inscrire

Si vous choisissez de ne pas utiliser nos SDK pour envoyer des requêtes à nos endpoints, vous devez implémenter vous même le mécanisme d'authentification.

L'API CAWL ecommerce utilise une signature de requête HMAC SHA256, un type d'algorithme de hachage à clé construit à partir de la fonction de hachage SHA-256 : vous calculez une signature cryptographique et vous l'incluez dans la requête. Cette signature est basée sur

  • Vos identifiants (API Key/Secret).
  • Les informations clés de la requête que vous envoyez.

À la réception de votre requête, notre plateforme recalcule cette même signature. ISi les deux signature correspondent, nous authentifions la requête.

Implementation

Pour implémenter le mécanisme d'authentification, vous devez

  • Créer une API Key/Secret comme décrit dans le chapitre "Configuration de l'API Key/Secret" de notre guide Authentification..
  • Préparer les informations de la requête : méthode HTTP, chemin de la requête et en-têtes de requête requis.
  • Hacher les informations de la requête avec le API Secret afin de calculer la signature.
  • Envoyer la requête en incluant les informations clés de la requête, la signature et la API Key.

Suivez ces instructions pas à pas pour implémenter le mécanisme d'authentification.

  1. Collecter les informations clés de la requête
  2. Préparer les en-têtes de date
  3. Préparer les en-têtes canoniques
  4. Construire le sujet de la signature (créer la chaîne à hacher)
  5. Calculer la signature (calculer le hash)
  6. Construire l'en‑tête d’autorisation
  7. Envoyer la requête

Collecter les informations clés de la requête

Collectez les informations clés de la requête que vous envoyez à l'API CAWL ecommerce:

Propriété Description
Méthode HTTP En fonction de l'endpoint auquel vous souhaitez envoyer la requête, c'est à dire POST, GET etc.
En-tête Content-type

Valeur fixe « application/json » pour les requêtes avec un corps (par exemple POST).

Chaîne vide pour les requêtes sans corps (par exemple GET).

En-tête Date Horodatage UTC au format RFC 1123. Il doit être identique à la fois dans l'en‑tête de la requête et dans la chaîne à hacher (string‑to‑hash) pour calculer la signature.
En-têtes x-gcs-* Tous les en têtes personnalisés canoniques x-gcs-* que vous souhaitez envoyer, triés par ordre alphabétique dans la chaîne à hacher pour calculer la signature.
Chemin de la requête Le chemin relatif de l'API CAWL ecommerce à laquelle vous envoyez la requête, incluant la version de l'API et votre merchantId par exemple "/v2/merchantId/hostedcheckouts"


Préparer les en-têtes de date

Pour l'en-tête de date, créez un horodatage UTC au format RFC 1123. Utilisez la même valeur à la fois pour l'en-tête et pour le sujet de la signature (la chaîne à hacher).
Notre plateforme rejettera les requêtes dont l'horodatage est antérieur de plus de 5 minutes.


Préparer les en-têtes canoniques

Si vous incluez des en-têtes x-gcs-* spécifiques à CAWL dans votre requête, vous devez les normaliser selon les conventions suivantes :

  • Mettre la clé de l'en-tête en minuscules.
  • Supprimer les espaces en début et fin de valeur de l'en‑tête.
  • Réduire toute séquence d'espaces internes dans la valeur de l'en‑tête à un seul espace.
  • Formater chaque paire clé‑valeur d'en‑tête comme {lowercased-key}:{normalized-value}.
  • Trier les paires clé‑valeur canoniques par ordre alphabétique de la clé.

Si vous incluez un en‑tête x-gcs-* dans le sujet de la signature, veillez à aussi l'ajouter dans la requête envoyée.

Convention Valeur brute Clé/valeur normalisée
Clé d'en-tête en minuscules X-GCS-Idempotency-Key x-gcs-idempotency-key
Suppression des espaces en début et fin de valeur de l'en-tête ··header value·· header value
Réduction des espaces multiples dans la valeur de l'en-tête header··value header value
Formatage des paires clé-valeur {raw-key}={raw-value} {lowercased-key}:{normalized-value}
Ordre alphabétique des paires clé-valeur canoniques x-gcs-serverdatetime:2026-05-18T10:00:00Z
x-gcs-idempotency-key:abc 123
x-gcs-date:Mon, 18 May 2026 10:00:00 GMT
x-gcs-date:Mon, 18 May 2026 10:00:00 GMT
x-gcs-idempotency-key:abc 123
x-gcs-serverdatetime:2026-05-18T10:00:00Z

Nos exemples utilisent uniquement l'en-tête x-gcs-idempotency-key pour illustrer la manière de gérer les en-têtes x-gcs-* spécifiques à CAWL.
Si vous utilisez nos SDK Serveur pour appeler l'API CAWL ecommerce, ils ajoutent et traitent automatiquement d'autres en-têtes x-gcs-* supplémentaires.
Ces en-têtes supplémentaires ne sont pas pertinents pour le processus d'authentification manuelle, c'est pourquoi nous ne les détaillons pas ici.


Construire le sujet de la signature (créer la chaîne à hacher)

Concaténez les éléments suivants (méthode de la requête, en‑têtes, en‑têtes canoniques, chemin de la requête) dans cet ordre, chacun terminé par un caractère de nouvelle ligne \n :

{HTTP_METHOD}\n
{Content-Type}\n
{Date}\n
{canonical-x-gcs-header-1}\n
{canonical-x-gcs-header-N}\n
{request-path}\n

  • Si vous incluez des en-têtes canoniques x-gcs-* veillez à les ordonner par clé comme décrit ci‑dessus.
  • Content-Type est toujours une chaîne vide pour les requêtes sans corps.

Des exemples typiques de requêtes avec ou sans corps ressemblent à ceci :

Requête avec un corps (par exemple POST, PUT, PATCH)

POST\n
application/json\n
Mon, 18 May 2026 10:00:00 GMT\n
x-gcs-date:Mon, 18 May 2026 10:00:00 GMT\n
x-gcs-idempotency-key:<unique-idempotency-key>\n
/v1/{merchantId}/payments\n

Requête sans corps (par exemple GET, DELETE)

GET\n
\n
Mon, 18 May 2026 10:00:00 GMT\n
x-gcs-date:Mon, 18 May 2026 10:00:00 GMT\n
/v1/{merchantId}/payments/{paymentId}\n


Calculer la signature (calculer le hash)

Hachez le sujet de la signature (string-to-hash) en utilisant HMAC-SHA256 (encodage UTF-8) avec votre API Secret. Puis encodez en Base64-encode la signature obtenue:

Skip code example Copy
import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 
 // The following code should be placed inside a method that declares: throws Exception
 String apiSecret = "YourAPISecret";
 String signatureSubject =
     "POST" + "\n" +
     "application/json" + "\n" +
     "Mon, 18 May 2026 10:00:00 GMT" + "\n" +
     "x-gcs-date:Mon, 18 May 2026 10:00:00 GMT" + "\n" +
     "x-gcs-idempotency-key:" + "\n" +
     "/v1/{merchantId}/payments" + "\n";
 
 // Convert apiSecret / signatureSubject into byte arrays
 byte[] keyBytes = apiSecret.getBytes(StandardCharsets.UTF_8);
 byte[] subjectBytes = signatureSubject.getBytes(StandardCharsets.UTF_8);
 
 // Hash the signatureSubject
 Mac hmac = Mac.getInstance("HmacSHA256");
 hmac.init(new SecretKeySpec(keyBytes, "HmacSHA256"));
 String signature = Base64.getEncoder().encodeToString(hmac.doFinal(subjectBytes));
using System;
 using System.Security.Cryptography;
 using System.Text;
 
 string apiSecret = "YourAPISecret";
 string signatureSubject =
     "POST" + "\n" +
     "application/json" + "\n" +
     "Mon, 18 May 2026 10:00:00 GMT" + "\n" +
     "x-gcs-date:Mon, 18 May 2026 10:00:00 GMT" + "\n" +
     "x-gcs-idempotency-key:" + "\n" +
     "/v1/{merchantId}/payments" + "\n";
 
 // Convert apiSecret / signatureSubject into byte arrays
 byte[] keyBytes = Encoding.UTF8.GetBytes(apiSecret);
 byte[] subjectBytes = Encoding.UTF8.GetBytes(signatureSubject);
 
 // Hash the signatureSubject
 using HMACSHA256 hmac = new HMACSHA256(keyBytes);
 string signature = Convert.ToBase64String(hmac.ComputeHash(subjectBytes));
import crypto from 'crypto';
 
 const apiSecret = 'YourAPISecret';
 const signatureSubject =
     'POST' + '\n' +
     'application/json' + '\n' +
     'Mon, 18 May 2026 10:00:00 GMT' + '\n' +
     'x-gcs-date:Mon, 18 May 2026 10:00:00 GMT' + '\n' +
     'x-gcs-idempotency-key:' + '\n' +
     '/v1/{merchantId}/payments' + '\n';
 
 // Hash the signatureSubject
 const signature = crypto
     .createHmac('SHA256', apiSecret)
     .update(signatureSubject)
     .digest('base64');
' . "\n" .
     '/v1/{merchantId}/payments' . "\n";
 
 // Hash the signatureSubject
 $signature = base64_encode(hash_hmac('sha256', $signatureSubject, $apiSecret, true));
import hmac
 import hashlib
 from base64 import b64encode
 
 api_secret = 'YourAPISecret'
 signature_subject = (
     'POST' + '\n' +
     'application/json' + '\n' +
     'Mon, 18 May 2026 10:00:00 GMT' + '\n' +
     'x-gcs-date:Mon, 18 May 2026 10:00:00 GMT' + '\n' +
     'x-gcs-idempotency-key:' + '\n' +
     '/v1/{merchantId}/payments' + '\n'
 )
 
 # Hash the signature_subject
 signature = b64encode(
     hmac.new(api_secret.encode('utf-8'), signature_subject.encode('utf-8'), hashlib.sha256).digest()
 ).decode('utf-8')
require 'openssl'
 require 'base64'
 
 api_secret = 'YourAPISecret'
 signature_subject =
   'POST' + "\n" +
   'application/json' + "\n" +
   'Mon, 18 May 2026 10:00:00 GMT' + "\n" +
   'x-gcs-date:Mon, 18 May 2026 10:00:00 GMT' + "\n" +
   'x-gcs-idempotency-key:' + "\n" +
   '/v1/{merchantId}/payments' + "\n"
 
 # Hash the signature_subject
 digest    = OpenSSL::Digest.new('SHA256')
 signature = Base64.strict_encode64(OpenSSL::HMAC.digest(digest, api_secret, signature_subject)).strip


Construire l'en‑tête d’autorisation

Ajoutez l'en-tête  Authorisation GCS v1HMAC à votre requête, composé de la signature calculée et de votre API Key:
Authorization: GCS v1HMAC:<your-api-key>:<base64-encoded-signature>


Envoyer la requête

Lorsque vous envoyez votre requête à l'API CAWL ecommerce, incluez tous les en têtes utilisés dans le sujet de la signature (chaîne à hacher) ainsi que l'en tête Authorisation.

Requête HTTP brute avec corps

POST /v1/{merchantId}/payments HTTP/1.1
Host: api.example.com
Authorization: GCS v1HMAC:<your-api-key>:<base64-encoded-signature>
Date: Mon, 18 May 2026 10:00:00 GMT
Content-Type: application/json
x-gcs-date: Mon, 18 May 2026 10:00:00 GMT
x-gcs-idempotency-key: <unique-idempotency-key>

{ ... request body ... }

Requête HTTP brute sans corps

GET /v1/{merchantId}/payments/{paymentId} HTTP/1.1
Host: api.example.com
Authorization: GCS v1HMAC:<your-api-key>:<base64-encoded-signature>
Date: Mon, 18 May 2026 10:00:00 GMT
x-gcs-date: Mon, 18 May 2026 10:00:00 GMT


Dépannage des écarts de signature

À la réception de votre requête, notre plateforme tente de faire correspondre la signature et la API Key figurant dans l'en tête  Authorisation header. Si cette correspondance échoue, notre plateforme rejettera votre requête et renverra un message d’erreur de ce type :

{
  "errorId": "error-id",
  "errors": [
    {
      "code": "9007",
      "id": "ACCESS_TO_MERCHANT_NOT_ALLOWED",
      "category": "DIRECT_PLATFORM_ERROR",
      "message": "ACCESS_TO_MERCHANT_NOT_ALLOWED",
      "httpStatusCode": 403
    }
  ],
  "status": 403
}

Pour résoudre ce type d'erreurs, veillez à respecter les consignes suivantes :

  • Utilisez le bon environnement : ne mélangez pas les API Keys/Secrets/comptes des environnements de test et de production.
  • Évitez d’utiliser des API Keys/Secrets.
  • Conservez un en-tête Date avec un décalage maximal de 5 minutes et utilisez la même date dans l’en-tête et dans la signature.
  • Pour les requêtes sans corps, définissez Content-Type sur une string vide. Ne l'omettez pas et ne le définissez pas à null.
  • Appliquez les règles de formatage/normalisation pour les en-têtes x-gcs-*.
  • Envoyez dans la requête exactement les mêmes en-têtes que ceux utilisés pour concaténer le sujet de la signature (string-to-hash).

Consultez notre guide dédié Dépannage de l'API guide pour analyser et résoudre d'autres erreurs de la plateforme.

Exemple de code complet

Reportez vous à notre guide de dépannage dédié pour analyser et résoudre les autres erreurs de plateforme : 

Classe utilitaire

Skip code example Copy
import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import java.util.List;
 import java.util.stream.Collectors;
 
 public class HmacAuthHelper {
 
     private static final List METHODS_WITHOUT_BODY = List.of("GET", "DELETE");
 
     /**
      * Builds the GCS v1HMAC Authorization header value.
      *
      * @param method      HTTP method (e.g. "POST")
      * @param path        Request path (e.g. "/v1/{entityId}/payments")
      * @param contentType Content-Type header value; ignored for body-less methods
      * @param date        RFC 1123 UTC date string — must match the Date header sent with the request
      * @param apiKeyId    Your API Key ID
      * @param apiSecret   Your API Secret
      * @param xGcsHeaders Optional x-gcs-* headers as raw "Key: Value" strings
      */
     public static String buildAuthorizationHeader(
             String method, String path, String contentType, String date,
             String apiKeyId, String apiSecret, List xGcsHeaders) throws Exception {
 
         // Normalize Content-Type — body-less methods always use empty string
         if (METHODS_WITHOUT_BODY.contains(method.toUpperCase())) {
             contentType = "";
         }
 
         // Canonicalize x-gcs-* headers
         List canonicalHeaders = xGcsHeaders.stream()
             .map(h -> {
                 int idx = h.indexOf(":");
                 String key = h.substring(0, idx).trim().toLowerCase();
                 String value = h.substring(idx + 1).trim().replaceAll("\\s+", " ");
                 return key + ":" + value;
             })
             .sorted()
             .collect(Collectors.toList());
 
         // Build the signature subject
         StringBuilder subject = new StringBuilder();
         subject.append(method.toUpperCase()).append("\n"); // method\n
         subject.append(contentType).append("\n");          // content-type\n
         subject.append(date).append("\n");                 // date\n
         for (String header : canonicalHeaders) {
             subject.append(header).append("\n");           // x-gcs-header\n (one per line)
         }
         subject.append(path).append("\n");                 // path\n
 
         // Sign with HMAC-SHA256 and Base64-encode
         byte[] keyBytes = apiSecret.trim().getBytes(StandardCharsets.UTF_8);
         byte[] subjectBytes = subject.toString().getBytes(StandardCharsets.UTF_8);
         Mac hmac = Mac.getInstance("HmacSHA256");
         hmac.init(new SecretKeySpec(keyBytes, "HmacSHA256"));
         String signature = Base64.getEncoder().encodeToString(hmac.doFinal(subjectBytes));
 
         return "GCS v1HMAC:" + apiKeyId.trim() + ":" + signature;
     }
 }
using System.Linq;
 using System.Security.Cryptography;
 using System.Text;
 using System.Text.RegularExpressions;
 
 public static class HmacAuthHelper
 {
     private static readonly string[] MethodsWithoutBody = ["GET", "DELETE"];
 
     public static string BuildAuthorizationHeader(
         string method,
         string path,
         string contentType,
         string date,
         string apiKeyId,
         string apiSecret,
         params string[] xGcsHeaders)
     {
         // Content-Type is empty for methods without a request body
         if (MethodsWithoutBody.Contains(method.ToUpperInvariant()))
             contentType = string.Empty;
 
         // Normalize and sort x-gcs-* headers: lowercase key, collapse whitespace in value
         string[] canonicalHeaders = xGcsHeaders
             .Select(h => {
                 int separatorIndex = h.IndexOf(":");
                 string key   = h[..separatorIndex].Trim().ToLowerInvariant();
                 string value = Regex.Replace(h[(separatorIndex + 1)..].Trim(), @"\s+", " ");
                 return $"{key}:{value}";
             })
             .OrderBy(h => h)
             .ToArray();
 
         // Build the signature subject string (each element followed by \n)
         StringBuilder subject = new StringBuilder();
         subject.Append(method.ToUpperInvariant() + "\n"); // method\n
         subject.Append(contentType + "\n");               // content-type\n
         subject.Append(date + "\n");                      // date\n
         foreach (string header in canonicalHeaders)
             subject.Append(header + "\n");                // x-gcs-header\n (one per line)
         subject.Append(path + "\n");                      // path\n
 
         // Convert apiSecret / signatureSubject into byte arrays
         byte[] keyBytes     = Encoding.UTF8.GetBytes(apiSecret.Trim());
         byte[] subjectBytes = Encoding.UTF8.GetBytes(subject.ToString());
 
         // Hash the signatureSubject and Base64-encode the result
         using HMACSHA256 hmac = new HMACSHA256(keyBytes);
         string signature = Convert.ToBase64String(hmac.ComputeHash(subjectBytes));
 
         return $"GCS v1HMAC:{apiKeyId.Trim()}:{signature}";
     }
 }


import crypto from 'crypto';
 
 const METHODS_WITHOUT_BODY = ['GET', 'DELETE'];
 
 function buildAuthorizationHeader(method, path, contentType, date, apiKeyId, apiSecret, xGcsHeaders = []) {
     // Normalize Content-Type — body-less methods always use empty string
     if (METHODS_WITHOUT_BODY.includes(method.toUpperCase())) {
         contentType = '';
     }
 
     // Canonicalize x-gcs-* headers
     const canonicalHeaders = xGcsHeaders
         .map(h => {
             const idx = h.indexOf(':');
             const key = h.substring(0, idx).trim().toLowerCase();
             const value = h.substring(idx + 1).trim().replace(/\s+/g, ' ');
             return `${key}:${value}`;
         })
         .sort();
 
     // Build the signature subject
     let subject = method.toUpperCase() + '\n'; // method\n
     subject += contentType + '\n';             // content-type\n
     subject += date + '\n';                    // date\n
     for (const header of canonicalHeaders) {
         subject += header + '\n';              // x-gcs-header\n (one per line)
     }
     subject += path + '\n';                    // path\n
 
     // Sign with HMAC-SHA256 and Base64-encode
     const signature = crypto
         .createHmac('SHA256', apiSecret.trim())
         .update(subject)
         .digest('base64');
 
     return `GCS v1HMAC:${apiKeyId.trim()}:${signature}`;
 }


<?php
 
 class HmacAuthHelper
 {
     private static array $methodsWithoutBody = ['GET', 'DELETE'];
 
     public static function buildAuthorizationHeader(
         string $method,
         string $path,
         string $contentType,
         string $date,
         string $apiKeyId,
         string $apiSecret,
         array $xGcsHeaders = []
     ): string {
         // Normalize Content-Type — body-less methods always use empty string
         if (in_array(strtoupper($method), self::$methodsWithoutBody)) {
             $contentType = '';
         }
 
         // Canonicalize x-gcs-* headers
         $canonicalHeaders = [];
         foreach ($xGcsHeaders as $h) {
             $idx = strpos($h, ':');
             $key = strtolower(trim(substr($h, 0, $idx)));
             $value = preg_replace('/\s+/', ' ', trim(substr($h, $idx + 1)));
             $canonicalHeaders[] = $key . ':' . $value;
         }
         sort($canonicalHeaders);
 
         // Build the signature subject
         $subject  = strtoupper($method) . "\n"; // method\n
         $subject .= $contentType . "\n";        // content-type\n
         $subject .= $date . "\n";               // date\n
         foreach ($canonicalHeaders as $header) {
             $subject .= $header . "\n";         // x-gcs-header\n (one per line)
         }
         $subject .= $path . "\n";               // path\n
 
         // Sign with HMAC-SHA256 and Base64-encode
         $signature = base64_encode(hash_hmac('sha256', $subject, trim($apiSecret), true));
 
         return 'GCS v1HMAC:' . trim($apiKeyId) . ':' . $signature;
     }
 }

import hmac
 import hashlib
 import re
 from base64 import b64encode
 
 class HmacAuthHelper:
 
     METHODS_WITHOUT_BODY = {'GET', 'DELETE'}
 
     @staticmethod
     def build_authorization_header(
             method: str,
             path: str,
             content_type: str,
             date: str,
             api_key_id: str,
             api_secret: str,
             x_gcs_headers: list[str] = None) -> str:
 
         if x_gcs_headers is None:
             x_gcs_headers = []
 
         # Normalize Content-Type — body-less methods always use empty string
         if method.upper() in HmacAuthHelper.METHODS_WITHOUT_BODY:
             content_type = ''
 
         # Canonicalize x-gcs-* headers
         canonical_headers = []
         for h in x_gcs_headers:
             idx = h.index(':')
             key = h[:idx].strip().lower()
             value = re.sub(r'\s+', ' ', h[idx + 1:].strip())
             canonical_headers.append(f'{key}:{value}')
         canonical_headers.sort()
 
         # Build the signature subject
         subject = method.upper() + '\n'  # method\n
         subject += content_type + '\n'   # content-type\n
         subject += date + '\n'           # date\n
         for header in canonical_headers:
             subject += header + '\n'     # x-gcs-header\n (one per line)
         subject += path + '\n'           # path\n
 
         # Sign with HMAC-SHA256 and Base64-encode
         signature = b64encode(
             hmac.new(api_secret.strip().encode('utf-8'), subject.encode('utf-8'), hashlib.sha256).digest()
         ).decode('utf-8')
 
         return f'GCS v1HMAC:{api_key_id.strip()}:{signature}'
require 'openssl'
 require 'base64'
 
 module HmacAuthHelper
   METHODS_WITHOUT_BODY = %w[GET DELETE].freeze
 
   # Builds the GCS v1HMAC Authorization header value.
   #
   # @param method        [String] HTTP method (e.g. 'POST')
   # @param path          [String] Request path (e.g. '/v1/{entityId}/payments')
   # @param content_type  [String] Content-Type header value; ignored for body-less methods
   # @param date          [String] RFC 1123 UTC date string — must match the Date header sent with the request
   # @param api_key_id    [String] Your API Key ID
   # @param api_secret    [String] Your API Secret
   # @param x_gcs_headers [Array] Optional x-gcs-* headers as raw 'Key: Value' strings
   def self.build_authorization_header(method, path, content_type, date, api_key_id, api_secret, x_gcs_headers = [])
     # Normalize Content-Type — body-less methods always use empty string
     content_type = '' if METHODS_WITHOUT_BODY.include?(method.upcase)
 
     # Canonicalize x-gcs-* headers
     canonical_headers = x_gcs_headers.map do |h|
       idx   = h.index(':')
       key   = h[0, idx].strip.downcase
       value = h[(idx + 1)..].strip.gsub(/\s+/, ' ')
       "#{key}:#{value}"
     end.sort
 
     # Build the signature subject
     subject  = "#{method.upcase}\n"  # method\n
     subject += "#{content_type}\n"   # content-type\n
     subject += "#{date}\n"           # date\n
     canonical_headers.each { |header| subject += "#{header}\n" } # x-gcs-header\n (one per line)
     subject += "#{path}\n"           # path\n
 
     # Sign with HMAC-SHA256 and Base64-encode
     digest    = OpenSSL::Digest.new('SHA256')
     signature = Base64.strict_encode64(
       OpenSSL::HMAC.digest(digest, api_secret.strip, subject)
     ).strip
 
     "GCS v1HMAC:#{api_key_id.strip}:#{signature}"
   end
 end

Utilisation — requête avec un corps (POST)

Skip code example Copy
import java.net.URI;
 import java.net.http.HttpClient;
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 // The following code should be placed inside a method that declares: throws Exception
 String date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC));
 // e.g. "Mon, 18 May 2026 10:00:00 GMT"
 
 String authorization = HmacAuthHelper.buildAuthorizationHeader(
     "POST",
     "/v1/{entityId}/payments",
     "application/json",
     date,
     "",
     "",
     List.of(
         "X-GCS-Date: " + date,
         "X-GCS-Idempotency-Key: abc-def-456"
     )
 );
 
 // Send the request — Date header must match exactly what was passed above
 HttpRequest request = HttpRequest.newBuilder()
     .uri(URI.create("/v1/{entityId}/payments"))
     .header("Authorization", authorization)
     .header("Date", date)
     .header("X-GCS-Date", date)
     .header("X-GCS-Idempotency-Key", "abc-def-456")
     .header("Content-Type", "application/json")
     .POST(HttpRequest.BodyPublishers.ofString("{ ... }"))
     .build();
 
 HttpResponse response = HttpClient.newHttpClient()
     .send(request, HttpResponse.BodyHandlers.ofString());
using System;
 using System.Net.Http;
 using System.Text;
 
 string date = DateTime.UtcNow.ToString("R");
 // e.g. "Mon, 18 May 2026 10:00:00 GMT"
 
 string authorization = HmacAuthHelper.BuildAuthorizationHeader(
     method: "POST",
     path: "/v1/{entityId}/payments",
     contentType: "application/json",
     date: date,
     apiKeyId: "",
     apiSecret: "",
     xGcsHeaders:
     [
         $"X-GCS-Date: {date}",
         "X-GCS-Idempotency-Key: abc-def-456"
     ]
 );
 
 // Send the request — Date header must match exactly what was passed above
 HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/v1/{entityId}/payments");
 request.Headers.TryAddWithoutValidation("Authorization", authorization);
 request.Headers.TryAddWithoutValidation("Date", date);
 request.Headers.TryAddWithoutValidation("X-GCS-Date", date);
 request.Headers.TryAddWithoutValidation("X-GCS-Idempotency-Key", "abc-def-456");
 request.Content = new StringContent("{ ... }", Encoding.UTF8, "application/json");
const date = new Date().toUTCString();
 // e.g. "Mon, 18 May 2026 10:00:00 GMT"
 
 const authorization = buildAuthorizationHeader(
     'POST',
     '/v1/{entityId}/payments',
     'application/json',
     date,
     '',
     '',
     [
         `X-GCS-Date: Jul 9, 2026, 8:18:16 PM`,
         'X-GCS-Idempotency-Key: abc-def-456',
     ]
 );
 
 // Send the request — Date header must match exactly what was passed above
 const response = await fetch('/v1/{entityId}/payments', {
     method: 'POST',
     headers: {
         'Authorization': authorization,
         'Date': date,
         'X-GCS-Date': date,
         'X-GCS-Idempotency-Key': 'abc-def-456',
         'Content-Type': 'application/json',
     },
     body: '{ ... }',
 });
',
     '',
     [
         "X-GCS-Date: Jul 9, 2026, 8:18:16 PM",
         'X-GCS-Idempotency-Key: abc-def-456',
     ]
 );
 
 // Send the request — Date header must match exactly what was passed above
 $ch = curl_init('/v1/{entityId}/payments');
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_POST, true);
 curl_setopt($ch, CURLOPT_POSTFIELDS, '{ ... }');
 curl_setopt($ch, CURLOPT_HTTPHEADER, [
     "Authorization: $authorization",
     "Date: Jul 9, 2026, 8:18:16 PM",
     "X-GCS-Date: Jul 9, 2026, 8:18:16 PM",
     'X-GCS-Idempotency-Key: abc-def-456',
     'Content-Type: application/json',
 ]);
 org.tuckey.web.filters.urlrewrite.UrlRewriteWrappedResponse@367faffe = curl_exec($ch);
 curl_close($ch);
import urllib.request
 from email.utils import formatdate
 
 date = formatdate(usegmt=True)
 # e.g. "Mon, 18 May 2026 10:00:00 GMT"
 
 authorization = HmacAuthHelper.build_authorization_header(
     method='POST',
     path='/v1/{entityId}/payments',
     content_type='application/json',
     date=date,
     api_key_id='',
     api_secret='',
     x_gcs_headers=[
         f'X-GCS-Date: {date}',
         'X-GCS-Idempotency-Key: abc-def-456',
     ]
 )
 
 # Send the request — Date header must match exactly what was passed above
 request = urllib.request.Request(
     '/v1/{entityId}/payments',
     method='POST',
     data=b'{ ... }',
     headers={
         'Authorization': authorization,
         'Date': date,
         'X-GCS-Date': date,
         'X-GCS-Idempotency-Key': 'abc-def-456',
         'Content-Type': 'application/json',
     }
 )
 response = urllib.request.urlopen(request)
require 'net/http'
 require 'uri'
 
 date = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
 # e.g. "Mon, 18 May 2026 10:00:00 GMT"
 
 authorization = HmacAuthHelper.build_authorization_header(
   'POST',
   '/v1/{entityId}/payments',
   'application/json',
   date,
   '',
   '',
   [
     "X-GCS-Date: #{date}",
     'X-GCS-Idempotency-Key: abc-def-456'
   ]
 )
 
 # Send the request — Date header must match exactly what was passed above
 uri = URI('/v1/{entityId}/payments')
 request = Net::HTTP::Post.new(uri)
 request['Authorization']         = authorization
 request['Date']                  = date
 request['X-GCS-Date']            = date
 request['X-GCS-Idempotency-Key'] = 'abc-def-456'
 request['Content-Type']          = 'application/json'
 request.body = '{ ... }'
 
 response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(request) }

Sujet de la signature résultante (avant la signature) :

POST\n
application/json\n
Mon, 18 May 2026 10:00:00 GMT\n
x-gcs-date:Mon, 18 May 2026 10:00:00 GMT\n
x-gcs-idempotency-key:abc-def-456\n
/v1/{entityId}/payments\n


Requête HTTP brute résultante :

POST /v1/{entityId}/payments HTTP/1.1
Authorization: GCS v1HMAC:<your-api-key-id>:<base64-encoded-signature>
Date: Mon, 18 May 2026 10:00:00 GMT
Content-Type: application/json
X-GCS-Date: Mon, 18 May 2026 10:00:00 GMT
X-GCS-Idempotency-Key: abc-def-456

{ ... request body ... }

Utilisation — requête sans corps (GET)

Skip code example Copy
import java.net.URI;
 import java.net.http.HttpClient;
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 // The following code should be placed inside a method that declares: throws Exception
 String date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC));
 
 String authorization = HmacAuthHelper.buildAuthorizationHeader(
     "GET",
     "/v1/{entityId}/payments/{paymentId}",
     "application/json", // ignored — overridden to "" internally for GET
     date,
     "",
     "",
     List.of("X-GCS-Date: " + date)
 );
 
 HttpRequest request = HttpRequest.newBuilder()
     .uri(URI.create("/v1/{entityId}/payments/{paymentId}"))
     .header("Authorization", authorization)
     .header("Date", date)
     .header("X-GCS-Date", date)
     .GET()
     .build();
 
 HttpResponse response = HttpClient.newHttpClient()
     .send(request, HttpResponse.BodyHandlers.ofString());
using System;
 using System.Net.Http;
 
 string date = DateTime.UtcNow.ToString("R");
 
 string authorization = HmacAuthHelper.BuildAuthorizationHeader(
     method: "GET",
     path: "/v1/{entityId}/payments/{paymentId}",
     contentType: "application/json", // ignored — overridden to "" internally for GET
     date: date,
     apiKeyId: "",
     apiSecret: "",
     xGcsHeaders: [$"X-GCS-Date: {date}"]
 );
 
 HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "/v1/{entityId}/payments/{paymentId}");
 request.Headers.TryAddWithoutValidation("Authorization", authorization);
 request.Headers.TryAddWithoutValidation("Date", date);
 request.Headers.TryAddWithoutValidation("X-GCS-Date", date);
const date = new Date().toUTCString();
 
 const authorization = buildAuthorizationHeader(
     'GET',
     '/v1/{entityId}/payments/{paymentId}',
     'application/json', // ignored — overridden to '' internally for GET
     date,
     '',
     '',
     [`X-GCS-Date: Jul 9, 2026, 8:18:16 PM`]
 );
 
 const response = await fetch('/v1/{entityId}/payments/{paymentId}', {
     method: 'GET',
     headers: {
         'Authorization': authorization,
         'Date': date,
         'X-GCS-Date': date,
     },
 });
',
     '',
     ["X-GCS-Date: Jul 9, 2026, 8:18:16 PM"]
 );
 
 $ch = curl_init('/v1/{entityId}/payments/{paymentId}');
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_HTTPHEADER, [
     "Authorization: $authorization",
     "Date: Jul 9, 2026, 8:18:16 PM",
     "X-GCS-Date: Jul 9, 2026, 8:18:16 PM",
 ]);
 org.tuckey.web.filters.urlrewrite.UrlRewriteWrappedResponse@367faffe = curl_exec($ch);
 curl_close($ch);
import urllib.request
 from email.utils import formatdate
 
 date = formatdate(usegmt=True)
 
 authorization = HmacAuthHelper.build_authorization_header(
     method='GET',
     path='/v1/{entityId}/payments/{paymentId}',
     content_type='application/json',  # ignored — overridden to '' internally for GET
     date=date,
     api_key_id='',
     api_secret='',
     x_gcs_headers=[f'X-GCS-Date: {date}']
 )
 
 request = urllib.request.Request(
     '/v1/{entityId}/payments/{paymentId}',
     method='GET',
     headers={
         'Authorization': authorization,
         'Date': date,
         'X-GCS-Date': date,
     }
 )
 response = urllib.request.urlopen(request)
require 'net/http'
 require 'uri'
 
 date = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
 
 authorization = HmacAuthHelper.build_authorization_header(
   'GET',
   '/v1/{entityId}/payments/{paymentId}',
   'application/json', # ignored — overridden to '' internally for GET
   date,
   '',
   '',
   ["X-GCS-Date: #{date}"]
 )
 
 uri = URI('/v1/{entityId}/payments/{paymentId}')
 request = Net::HTTP::Get.new(uri)
 request['Authorization'] = authorization
 request['Date']          = date
 request['X-GCS-Date']    = date
 
 response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(request) }

Sujet de la signature résultante (avant la signature) :

GET\n
\n
Mon, 18 May 2026 10:00:00 GMT\n
x-gcs-date:Mon, 18 May 2026 10:00:00 GMT\n
/v1/{entityId}/payments/{paymentId}\n

Requête HTTP brute résultante :

GET /v1/{entityId}/payments/{paymentId} HTTP/1.1
Authorization: GCS v1HMAC:<your-api-key-id>:<base64-encoded-signature>
Date: Mon, 18 May 2026 10:00:00 GMT
X-GCS-Date: Mon, 18 May 2026 10:00:00 GMT

Cette page vous a-t-elle été utile ?

Avez-vous des commentaires ?

Merci pour votre réponse.