Zum Inhalt springen

Quickstart

Ihre erste Testzahlung, Schritt für Schritt

Führen Sie nach dem Onboarding und der Ersteinrichtung eine Testzahlung in der Stage-Umgebung durch.

  • Stage: kein echtes Geld
  • cURL und Node.js
  • Fiktive Testdaten

Überblick

Drei Phasen, sechs Schritte

Alles Folgende läuft auf Stage, der Sandbox, die die Produktion abbildet. Der Produktionszugang kommt am Ende, nach den Prüfungen in Schritt 6.

  1. 01

    Zugang einrichten

    Stage-Zugangsdaten erhalten, in einem Secrets Manager ablegen und die IPs Ihrer Server freigeben.

    Schritte 1–2

  2. 02

    Erste Aufrufe ausführen

    Token abrufen, eine Testeinzahlung anlegen und den bestätigenden Webhook prüfen.

    Schritte 3–5

  3. 03

    Live gehen

    Sicherheits-Review und Unternehmensverifizierung (KYB) abschließen, dann auf Produktionszugangsdaten umstellen.

    Schritt 6

Schritt 1 von 6

Stage-Zugangsdaten erhalten

Stage-Zugangsdaten – ein API-Benutzer und ein Passwort für api.stage.localpayment.com – werden zu Beginn Ihrer Partnerschaft mit Localpayment ausgestellt. Behandeln Sie sie vom ersten Tag an wie Produktions-Secrets.

  • Zugangsdaten aus einem Secrets Manager oder aus Umgebungsvariablen laden – niemals committen
  • Stage und Produktion nutzen unterschiedliche Zugangsdaten und Base-URLs
  • Ausschließlich fiktive Testdaten verwenden, niemals echte Kundendaten
secrets.js
// Stage-Zugangsdaten beim Start aus AWS Secrets Manager laden (AWS SDK v3).
// Jeder Vault funktioniert: Entscheidend ist, dass Secrets nie im Quellcode liegen.
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' }),
  );
  // Erwartetes JSON: { "username": "…", "password": "…", "webhookSecret": "…" }
  return JSON.parse(SecretString);
}

Schritt 2 von 6

Server-IPs freigeben

Die API akzeptiert nur Aufrufe von IP-Adressen, die Sie freigegeben haben. Hinterlegen Sie die ausgehenden IPs Ihrer Server im Stage-Business-Portal, bevor Sie den ersten Request senden.

  • Business Portal → Whitelist your IP
  • Requests von anderen IPs werden abgelehnt
  • Serverless oder Autoscaling? Leiten Sie ausgehenden Traffic über eine feste Egress-IP (NAT)
  • Wiederholen Sie die Einrichtung vor dem Go-live für die Produktion

Schritt 3 von 6

Access-Token abrufen

Tauschen Sie API-Benutzer und Passwort gegen ein JWT-Paar. Senden Sie den Access-Token bei jedem Aufruf als Bearer-Token und erneuern Sie ihn, bevor er abläuft.

  • Access-Token: 5 Minuten gültig
  • Refresh-Token: 24 Stunden gültig – nutzen Sie POST /api/token/refresh/
  • Tokens im Arbeitsspeicher halten und niemals in Logs schreiben
# Access-Token auf Stage abrufen (5 Minuten gültig)
curl -X POST https://api.stage.localpayment.com/api/token/ \
  -H "Content-Type: application/json" \
  -d "{\"username\": \"$LP_API_USER\", \"password\": \"$LP_API_PASSWORD\"}"

Schritt 4 von 6

Testeinzahlung anlegen

Dieses Beispiel legt eine Pix-Einzahlung in Brasilien an. Die Antwort liefert einen QR-Code und einen Pix-Copia-e-Cola-String, mit Status 100 INPROGRESS, bis der Zahler die Zahlung abschließt.

  • Erzeugen Sie für jede Transaktion eine neue UUID als externalId
  • Eine Wiederholung mit derselben externalId liefert 409 Conflict statt einer zweiten Einzahlung
  • Betrag in USD: Die Antwort nennt den BRL-Betrag, den der Zahler zahlt, und den angewandten Devisenkurs
# Beispielhafte Pix-Einzahlung auf Stage (Brasilien). Fiktive Werte;
# den vollständigen Vertrag finden Sie auf docs.localpayment.com.
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" }
    }
  }'

Schritt 5 von 6

Webhook verarbeiten

Sobald die Zahlung abgeschlossen ist, sendet Localpayment eine signierte Benachrichtigung an Ihren HTTPS-Endpunkt. Prüfen Sie die Signatur über den Roh-Body, antworten Sie sofort mit 200 und verarbeiten Sie asynchron.

  • Registrieren Sie Ihre URL unter Business Portal → Configurations → Clients → Notifications
  • Vergleichen Sie x-Signature mit Ihrem eigenen HMAC-SHA256 über einen timing-sicheren Vergleich
  • Zustellungen ohne 200-Antwort werden mit exponentiellem Backoff wiederholt
webhook.js
// Express-Empfänger für Localpayment-Webhooks (Node.js 18+).
import crypto from 'node:crypto';
import express from 'express';
import { jobQueue } from './queue.js'; // Ihre eigene asynchrone Job-Queue

const app = express();

// Webhook-Secret beim Start aus Ihrem Secrets Manager laden. Niemals hartcodieren.
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;
  // Header-Format: "x-Signature: HMAC-SHA256 <hex>". Zuerst das Präfix entfernen.
  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);
}

// Der Body ist JSON mit Content-Type text/plain: Behalten Sie den Rohtext für den 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); // schnell bestätigen, vor jeder aufwendigen Verarbeitung
  // Asynchron verarbeiten. Nach internalId/externalId + Status deduplizieren,
  // damit eine erneute Zustellung nur einmal angewendet wird. Nie den vollständigen Payload loggen.
  jobQueue.enqueue(event);
});

Schritt 6 von 6

Go-live-Checkliste

Produktionszugangsdaten werden erst nach diesen Prüfungen ausgestellt. Planen Sie sie früh ein: Sie schützen alle Händler auf der Plattform, auch Sie.

  • Stage-Tests abschließen

    Decken Sie Erfolgs-, Ablehnungs-, Pending- und Fehlerpfade für jede Methode und jedes Land ab, das Sie starten.

  • Sicherheits-Review bestehen

    Unser Team prüft und zertifiziert Ihre Integration, bevor der Produktionszugang freigeschaltet wird.

  • Unternehmensverifizierung abschließen

    Compliance prüft im Rahmen des Onboardings Ihr Unternehmen, die Eigentümerstruktur und den Anwendungsfall (KYB).

  • Produktionszugangsdaten sicher ablegen

    Bewahren Sie sie in einem Secrets Manager auf, getrennt von Stage, und beschränken Sie den Zugriff auf die Dienste, die sie benötigen.

  • Produktions-IPs freigeben

    Hinterlegen Sie die ausgehenden IPs Ihrer Produktionsserver im Business Portal der Produktion.

  • Produktions-Webhooks konfigurieren

    Registrieren Sie Ihren HTTPS-Endpunkt für die Produktion und stellen Sie vor der ersten Live-Transaktion sicher, dass die Signaturprüfung besteht.

Fehlerbehebung

Häufige Probleme bei den ersten Aufrufen

Ich erhalte 401 Unauthorized. Was sollte ich prüfen?

Access-Tokens laufen nach 5 Minuten ab. Erneuern Sie mit POST /api/token/refresh/ oder fordern Sie einen neuen Token an, und stellen Sie sicher, dass der Header Authorization: Bearer gefolgt vom Access-Token lautet.

Mein Request wird trotz gültigem Token abgelehnt.

Prüfen Sie, ob die ausgehende IP des aufrufenden Servers im Business Portal für diese Umgebung freigegeben ist. Stage und Produktion werden getrennt konfiguriert.

Warum habe ich 409 Conflict erhalten?

Diese externalId wurde bereits verwendet. Fragen Sie die bestehende Transaktion mit GET /api/transactions/{externalId}/status ab, statt eine neue anzulegen.

Die Einzahlung bleibt auf 100 INPROGRESS.

Das ist bei asynchronen Methoden wie Pix, Banküberweisungen und virtuellen Konten zu erwarten: Der Status ändert sich, wenn der Zahler bezahlt, und der finale Status kommt per Webhook.

Meine Webhook-Signatur stimmt nicht überein.

Berechnen Sie den HMAC über den Roh-Body genau so, wie er ankommt, vor jedem JSON-Parsing, und entfernen Sie vor dem Vergleich das Präfix „HMAC-SHA256 “ aus dem Header.

Sie brauchen Stage-Zugangsdaten?

Erzählen Sie uns von Ihrem Anwendungsfall und Ihren Märkten. Unser Team begleitet Sie durch das Onboarding und schaltet den Stage-Zugang zum Start der Partnerschaft frei.

Wie können wir helfen?

Ihr Exemplar herunterladen

Hinterlassen Sie Ihre Daten und erhalten Sie sofort die vollständige Ausgabe.