Sign in
Introduktion/Autentisering

Autentisering och signering av förfrågningar

Signera API-förfrågningar med HMAC-SHA256 med ditt project UUID och din API key.

Varje API-förfrågan (utom inkommande webhooks) måste innehålla ditt project UUID och en signatur av förfrågan. Signaturen bevisar att förfrågan kommer från dig och att ingen har ändrat den på vägen.

API-nycklar

2328.io använder två nycklar som delar samma signeringsalgoritm men täcker olika endpoints:

NyckelAnvänds för
API keyBetalningar, statiska plånböcker, saldo, växelkurser och verifiering av betalnings- / statisk plånbok-webhooks
Payout API keyAlla /v1/payout/* endpoints och verifiering av uttags-webhooks

Båda nycklarna finns i dina projektinställningar på 2328.io. Exemplen nedan säger generiskt "API key" — byt ut till rätt nyckel för den endpoint du anropar.

Blanda aldrig de två nycklarna: att signera en uttagsbegäran med den vanliga API-nyckeln (eller en betalningsbegäran med uttagsnyckeln) returnerar ett signaturfel.

Obligatoriska headers

HeaderTypObligatoriskBeskrivning
Content-TypestringjaAlltid application/json
projectstringjaDitt project UUID
signstringjaHMAC-SHA256-signatur av förfrågan, beräknad med din API key
User-AgentstringjaIdentifierar din applikation (t.ex. MyShop/1.4 (+https://myshop.example)). Förfrågningar utan User-Agent kan blockeras.

Hur signaturen fungerar

Tänk på signaturen som ett fingeravtryck av förfrågans body. Den byggs så här:

  1. Serialisera body till JSON (kompakt — inga extra blanksteg).
  2. Base64-koda den JSON-strängen. Det här steget normaliserar indata mellan språk — när det väl är ren ASCII producerar varje språk samma byte för HMAC.
  3. Beräkna HMAC-SHA256 av Base64-strängen med din API key och konvertera sedan resultatet till hex med små bokstäver.

För GET och andra typer av förfrågningar utan body, signera en tom sträng istället för JSON.

Signaturen för en tom sträng är konstant för en given API key. Du kan cacha den om du gör många GET-anrop.

Implementationer

PHP
<?php
function apiSign(array $data, string $apiKey): string {
    $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $base64 = base64_encode($json);
    return hash_hmac('sha256', $base64, $apiKey);
}

Förfrågningar utan body (GET)

För förfrågningar utan body (t.ex. GET /v1/payout/status/{uuid}), signera en tom sträng:

Shell
SIGN=$(printf '' | openssl dgst -sha256 -hmac "$API_KEY" -hex | awk '{print $NF}')

Fullständigt exempel på förfrågan

Shell
curl -X POST https://api.2328.io/api/v1/payment \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyShop/1.0 (+https://myshop.example)" \
  -H "project: YOUR_PROJECT_UUID" \
  -H "sign: YOUR_HMAC_SIGNATURE" \
  -d '{"amount":"100.00","currency":"USD","order_id":"ORDER-123"}'

Exponera aldrig din API key i klientkod. Signera förfrågningar i din backend. En läckt API key ger vem som helst full åtkomst till ditt handlarkonto.

Verifiera webhook-signaturer

När 2328.io skickar en webhook till dig körs samma algoritm omvänt:

  1. Plocka ut fältet sign ur payloaden.
  2. JSON-koda de återstående fälten (kompakt, utan blanksteg).
  3. Base64-koda den strängen.
  4. Beräkna HMAC-SHA256 med rätt nyckel.
  5. Jämför den med den mottagna sign med en tidskonstant jämförelse (hash_equals, crypto.timingSafeEqual, hmac.compare_digest, subtle.ConstantTimeCompare, OpenSSL.fixed_length_secure_compare).

Signeringsnyckeln beror på webhook-källan:

WebhookNyckel att verifiera med
Betalnings- / statisk plånbok-webhooks (/v1/payment, /v1/static-wallet)API key
Uttags-webhooks (/v1/payout)Payout API key

Vanliga verifieringsfallgropar. Din JSON-kodare måste producera exakt samma bytes som avsändaren producerade — annars skiljer sig Base64 och signaturen matchar inte.

  • Go: använd json.NewEncoder med SetEscapeHTML(false). Standard json.Marshal escapar <, >, & till < och förstör signaturen.
  • Python: skicka ensure_ascii=False till json.dumps. Utan det escapas icke-ASCII (kyrilliska, kinesiska, …) till \uXXXX.
  • Kompakt JSON: inga blanksteg mellan fält (separators=(",", ":") i Python).
  • Fältordning (Go): en vanlig map[string]any randomiserar nycklar vid omkodning. Använd json.RawMessage, en ordnad struct eller ta bort sign ur de råa byten.

Om verifieringen fortsätter att misslyckas, kör apiSign på payloaden själv — den måste producera samma hex-sträng som det mottagna sign.

En giltig signatur förhindrar inte replays. Den bevisar endast att webhooken kom från 2328.io — den hindrar inte en angripare från att skicka en fångad webhook igen senare. Kontrollera alltid idempotens via uuid (eller txid för statiska plånböcker) innan du krediterar medel. Avvisa med HTTP 401 om signaturen saknas eller är fel.

Fullständiga kodexempel finns på Webhook Notifications. Återförsökshantering och idempotensregler finns i Bästa praxis.