Vai al contenuto

Quickstart

Il tuo primo pagamento di test, passo dopo passo

Esegui un pagamento di test nell’ambiente Stage dopo l’onboarding e la configurazione iniziale.

  • Stage: niente denaro reale
  • cURL e Node.js
  • Dati di test fittizi

Panoramica

Tre fasi, sei passaggi

Tutto ciò che segue gira su Stage, la sandbox che rispecchia la produzione. L’accesso alla produzione arriva alla fine, dopo i controlli del passaggio 6.

  1. 01

    Configura l’accesso

    Ricevi le credenziali Stage, salvale in un secrets manager e autorizza gli IP dei tuoi server.

    Passaggi 1–2

  2. 02

    Fai le prime chiamate

    Ottieni un token, crea un incasso di test e verifica il webhook che lo conferma.

    Passaggi 3–5

  3. 03

    Vai live

    Completa la security review e la verifica aziendale (KYB), poi passa alle credenziali di produzione.

    Passaggio 6

Passaggio 1 di 6

Ottieni le credenziali Stage

Le credenziali Stage, un utente e una password API per api.stage.localpayment.com, vengono rilasciate all’avvio della tua partnership con Localpayment. Trattale come segreti di produzione fin dal primo giorno.

  • Carica le credenziali da un secrets manager o da variabili d’ambiente: non committarle mai
  • Stage e Produzione usano credenziali e base URL diversi
  • Usa solo dati di test fittizi, mai dati reali dei clienti
secrets.js
// Carica le credenziali di Stage da AWS Secrets Manager all’avvio (AWS SDK v3).
// Va bene qualsiasi vault: l’importante è che i segreti non stiano mai nel codice sorgente.
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';

const client = new SecretsManagerClient({ region: process.env.AWS_REGION });

export async function loadMerchantSecrets() {
  const { SecretString } = await client.send(
    new GetSecretValueCommand({ SecretId: 'localpayment/stage/api' }),
  );
  // JSON atteso: { "username": "…", "password": "…", "webhookSecret": "…" }
  return JSON.parse(SecretString);
}

Passaggio 2 di 6

Autorizza gli IP dei tuoi server

L’API accetta solo chiamate dagli indirizzi IP che hai autorizzato. Aggiungi gli IP in uscita dei tuoi server nel Business Portal di Stage prima della prima richiesta.

  • Business Portal → Whitelist your IP
  • Le richieste da qualsiasi altro IP vengono rifiutate
  • Serverless o autoscaling? Instrada il traffico in uscita attraverso un IP di egress fisso (NAT)
  • Ripeti la configurazione per la produzione prima del go-live

Passaggio 3 di 6

Ottieni un token di accesso

Scambia utente e password API con una coppia di JWT. Invia il token di accesso come bearer token in ogni chiamata e rinnovalo prima che scada.

  • Token di accesso: valido 5 minuti
  • Refresh token: valido 24 ore, usa POST /api/token/refresh/
  • Tieni i token in memoria e non scriverli mai nei log
# Ottieni un token di accesso su Stage (valido 5 minuti)
curl -X POST https://api.stage.localpayment.com/api/token/ \
  -H "Content-Type: application/json" \
  -d "{\"username\": \"$LP_API_USER\", \"password\": \"$LP_API_PASSWORD\"}"

Passaggio 4 di 6

Crea un incasso di test

Questo esempio crea un incasso Pix in Brasile. La risposta restituisce un codice QR e una stringa Pix Copia e Cola, con stato 100 INPROGRESS finché il pagatore non completa il pagamento.

  • Genera un nuovo UUID come externalId per ogni transazione
  • Ripetere con lo stesso externalId restituisce 409 Conflict invece di creare un secondo incasso
  • Importo in USD: la risposta indica l’importo in BRL pagato dal pagatore e il tasso di cambio applicato
# Incasso Pix di esempio su Stage (Brasile). Valori fittizi;
# consulta docs.localpayment.com per il contratto completo.
curl -X POST https://api.stage.localpayment.com/api/payin/ \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "paymentMethod": { "type": "BankTransfer", "code": "1314", "flow": "DIRECT" },
    "externalId": "7c1e2f7a-0000-4000-8000-000000000001",
    "country": "BRA",
    "currency": "USD",
    "amount": 100,
    "accountNumber": "<your-account-number>",
    "conceptCode": "0003",
    "merchant": { "type": "COMPANY", "name": "Nortia Commerce Ltda" },
    "payer": {
      "type": "INDIVIDUAL",
      "name": "Maria",
      "lastname": "Silva",
      "document": { "type": "CPF", "id": "000.000.000-00" }
    }
  }'

Passaggio 5 di 6

Gestisci il webhook

Quando il pagamento si completa, Localpayment invia una notifica firmata al tuo endpoint HTTPS. Verifica la firma sul body grezzo, rispondi subito 200 ed elabora in modo asincrono.

  • Registra il tuo URL in Business Portal → Configurations → Clients → Notifications
  • Confronta x-Signature con il tuo HMAC-SHA256 usando un confronto a tempo costante
  • Gli invii senza risposta 200 vengono ripetuti con backoff esponenziale
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);
});

Passaggio 6 di 6

Checklist per il go-live

Le credenziali di produzione vengono rilasciate solo dopo questi controlli. Pianificali per tempo: proteggono tutti i merchant della piattaforma, te compreso.

  • Completa i test su Stage

    Copri i casi di successo, rifiuto, attesa ed errore per ogni metodo e paese che lancerai.

  • Supera la security review

    Il nostro team esamina e certifica la tua integrazione prima di concedere l’accesso alla produzione.

  • Completa la verifica aziendale

    Il team compliance verifica la tua azienda, la struttura proprietaria e il caso d’uso (KYB) durante l’onboarding.

  • Conserva al sicuro le credenziali di produzione

    Tienile in un secrets manager, separate da Stage, e limita l’accesso ai soli servizi che ne hanno bisogno.

  • Autorizza gli IP di produzione

    Aggiungi gli IP in uscita dei tuoi server di produzione nel Business Portal di produzione.

  • Configura i webhook di produzione

    Registra il tuo endpoint HTTPS di produzione e verifica che il controllo della firma passi prima della prima transazione reale.

Risoluzione dei problemi

Problemi comuni alle prime chiamate

Ricevo 401 Unauthorized. Cosa devo controllare?

I token di accesso scadono dopo 5 minuti. Rinnovali con POST /api/token/refresh/ o richiedi un nuovo token, e verifica che l’header sia Authorization: Bearer seguito dal token di accesso.

La mia richiesta viene rifiutata anche con un token valido.

Verifica che l’IP in uscita del server chiamante sia autorizzato nel Business Portal per quell’ambiente. Stage e Produzione si configurano separatamente.

Perché ho ricevuto 409 Conflict?

Quell’externalId è già stato usato. Consulta la transazione esistente con GET /api/transactions/{externalId}/status invece di crearne una nuova.

L’incasso resta in 100 INPROGRESS.

È normale per i metodi asincroni come Pix, bonifici e conti virtuali: lo stato cambia quando il pagatore paga e lo stato finale arriva via webhook.

La firma del mio webhook non corrisponde.

Calcola l’HMAC sul body grezzo della richiesta esattamente come lo ricevi, prima di qualsiasi parsing JSON, e rimuovi il prefisso "HMAC-SHA256 " dall’header prima del confronto.

Ti servono le credenziali Stage?

Raccontaci il tuo caso d’uso e i tuoi mercati. Il nostro team ti guiderà nell’onboarding e attiverà l’accesso a Stage all’avvio della partnership.

Come possiamo aiutarti?

Scarica la tua copia

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