Vai al contenuto

Webhook

Sappi quando il denaro si muove

Notifiche in tempo reale per incassi, payout, conti virtuali, abbonamenti, cambio valuta, Wire In e Wire Out, ognuna firmata con HMAC-SHA256 così puoi verificare ogni richiesta prima di agire.

  • Firme HMAC-SHA256
  • Retry con backoff
  • Filtrati per paese e conto

Configurazione

Configura le notifiche nel Business Portal

Per registrare un endpoint non serve codice. Ogni voce può essere limitata per paese e conto.

  1. 01

    Apri le notifiche

    Nel Business Portal vai su Configurations → Clients → Notifications.

  2. 02

    Aggiungi il tuo URL HTTPS

    Registra l’endpoint HTTPS pubblico dei tuoi server che riceverà gli eventi.

  3. 03

    Definisci l’ambito

    Scegli un paese, o All, e il conto a cui appartengono le notifiche.

  4. 04

    Aggiungi header e testa

    Se vuoi, aggiungi header personalizzati per il tuo gateway, poi esegui una transazione di test su Stage.

Payload

Un’unica busta per ogni evento

Tutte le notifiche condividono gli stessi campi radice, quindi un solo handler può instradarle tutte. Il body è JSON, consegnato con Content-Type text/plain.

  • transactionType: PayIn, PayOut, VirtualAccount, Subscription, CurrencyExchange, WireIn o WireOut
  • transactionFlow: il flusso di elaborazione, utile per il routing
  • data: la transazione vera e propria, con externalId, internalId e stato

Eventi

Su cosa ricevi notifiche

  • Incasso con carta

    transactionType
    PayIn
    Cosa ti dice
    Approvato, completato, rifiutato, rimborsato o soggetto a chargeback
  • Incasso tramite bonifico o metodo locale

    transactionType
    PayIn
    Cosa ti dice
    Stato finale dopo la conferma del pagatore nella sua app bancaria o wallet
  • Conto virtuale

    transactionType
    VirtualAccount
    Cosa ti dice
    Conto creato e ogni pagamento ricevuto
  • Abbonamento

    transactionType
    Subscription
    Cosa ti dice
    Ciclo di vita dell’abbonamento; ogni addebito arriva anche come evento PayIn
  • Payout

    transactionType
    PayOut
    Cosa ti dice
    Cambi di stato lungo il flusso del payout, fino al completamento
  • Cambio valuta

    transactionType
    CurrencyExchange
    Cosa ti dice
    Esito di una conversione tra i tuoi saldi
  • Wire In

    transactionType
    WireIn
    Cosa ti dice
    Fondi accreditati sul tuo conto, in fiat o in USDC/USDT
  • Wire Out

    transactionType
    WireOut
    Cosa ti dice
    Prelievo inviato; i Wire Out in crypto includono l’hash della transazione on-chain

Schemi completi e codici di stato di ogni evento sono nella reference dei webhook su docs.localpayment.com.

Sicurezza

Verifica ogni firma

Ogni richiesta contiene x-Signature: HMAC-SHA256 seguito dal digest esadecimale del body grezzo, calcolato con il tuo segreto webhook. Ricalcolalo e confrontalo prima di fidarti del payload.

  • Leggi il body grezzo: è JSON inviato come Content-Type text/plain
  • Rimuovi il prefisso “HMAC-SHA256 ”, poi confronta con una funzione a tempo costante
  • Rifiuta le discrepanze con 401 e non loggare mai il payload completo
webhook.js
// Ricevitore Express per i webhook di Localpayment (Node.js 18+).
import crypto from 'node:crypto';
import express from 'express';
import { jobQueue } from './queue.js'; // la tua coda di job asincroni

const app = express();

// Carica il segreto del webhook dal tuo secrets manager all’avvio. Mai scriverlo nel codice.
const WEBHOOK_SECRET = process.env.LP_WEBHOOK_SECRET;
if (!WEBHOOK_SECRET) throw new Error('LP_WEBHOOK_SECRET is not configured');

function hasValidSignature(rawBody, header) {
  if (typeof rawBody !== 'string') return false;
  // Formato dell’header: "x-Signature: HMAC-SHA256 <hex>". Rimuovi prima il prefisso.
  const received = String(header ?? '').replace(/^HMAC-SHA256\s+/i, '').trim();
  if (!/^[0-9a-f]{64}$/i.test(received)) return false;

  const expected = crypto.createHmac('sha256', WEBHOOK_SECRET).update(rawBody, 'utf8').digest();
  return crypto.timingSafeEqual(Buffer.from(received, 'hex'), expected);
}

// Il body è JSON inviato come Content-Type text/plain: conserva il testo grezzo per l’HMAC.
app.post('/webhooks/localpayment', express.text({ type: '*/*', limit: '1mb' }), (req, res) => {
  if (!hasValidSignature(req.body, req.get('x-signature'))) return res.sendStatus(401);

  let event;
  try {
    event = JSON.parse(req.body);
  } catch {
    return res.sendStatus(400);
  }

  res.sendStatus(200); // conferma subito, prima di qualsiasi elaborazione pesante
  // Elabora in modo asincrono. Deduplica per internalId/externalId + stato
  // così un nuovo invio viene applicato una sola volta. Non loggare mai il payload completo.
  jobQueue.enqueue(event);
});

Elaborazione affidabile

Pensato per i retry e le reti reali

  • Conferma subito

    Rispondi 200 appena la firma è valida e sposta il lavoro pesante in un job in background.

  • Aspettati i retry

    Se non riceviamo un 200, riproviamo con backoff esponenziale. Il tuo handler deve poter girare più volte senza effetti collaterali.

  • Deduplica

    Basa l’elaborazione su internalId o externalId più lo stato, così un nuovo invio viene applicato una sola volta.

  • Non dare per scontato l’ordine

    Confronta lo stato in arrivo con quello salvato prima di applicarlo e non far mai tornare indietro una transazione.

  • Conferma con l’API

    Nel dubbio, interroga GET /api/transactions/{externalId}/status per lo stato attuale di una transazione.

  • Logga in sicurezza

    Logga tipi di evento, ID e stati, mai payload completi, token o dati personali.

Operations

Vedi ogni invio nel Business Portal

I report delle notifiche mostrano cosa è stato inviato ai tuoi endpoint, così supporto e engineering risolvono i problemi senza scavare nei log dei server.

  • Log degli invii delle notifiche ai tuoi endpoint
  • Ricerca delle transazioni e report di attività dettagliati
  • Webhook, allow-list degli IP e utenti gestiti in un unico posto

FAQ sui webhook

Come faccio a sapere che un webhook arriva davvero da Localpayment?

Verifica l’header x-Signature: ricalcola l’HMAC-SHA256 del body grezzo con il tuo segreto webhook e confronta i due valori con una funzione a tempo costante. Puoi anche aggiungere header personalizzati a ogni voce di notifica per il tuo gateway.

Ogni quanto vengono ripetuti gli invii falliti?

Gli invii che non ricevono un 200 vengono ripetuti con backoff esponenziale. Progetta il tuo handler per più tentativi e controlla lo storico degli invii nei report delle notifiche del Business Portal.

Perché il Content-Type è text/plain?

Il body è JSON inviato come text/plain. Leggilo come testo grezzo, verifica la firma su quegli esatti byte e solo dopo fai il parsing.

Posso inviare paesi diversi a endpoint diversi?

Sì. Ogni voce di notifica è limitata per paese (o All) e conto, quindi puoi instradare mercati o business unit verso URL separati.

Cosa deve restituire il mio endpoint?

Uno stato 200, il più rapidamente possibile e prima di qualsiasi elaborazione lunga. Senza 200, l’invio è considerato fallito e viene ripetuto.

Collega il tuo primo webhook

Configura un endpoint Stage, genera un incasso di test e verifica la firma end-to-end.

Come possiamo aiutarti?

Scarica la tua copia

Lasciaci i tuoi dati e ricevi subito l’edizione completa.