Auf dieser Seite
Inhalte
Den versionierten Webhook-Umschlag lesen und die vollständige Momentaufnahme von Rechnung, Auszahlung oder Kanaleinzahlung in data auswerten.
Jeder Webhook-Inhalt ist ein versionierter Umschlag. Das Objekt data folgt demselben händlerseitigen Ressourcenvertrag wie die zugehörige Status-API, sodass Ihr Handler eine vollständige Momentaufnahme übernehmen kann, statt Teiländerungen zusammenzuführen. Das gilt für alle drei Ressourcen: Rechnungen, Auszahlungen und Kanaleinzahlungen teilen sich einen Umschlag und dieselbe Regel für den Inhalt.
Umschlag
| Feld | Typ | Vertrag |
|---|---|---|
event_id |
Zeichenkette | Stabile Kennung mit Präfix (evt_…), identisch mit X-Webhook-Id und unverändert über Wiederholungen und Nachsendungen |
event_type |
Zeichenkette | Ein Wert aus dem Ereigniskatalog |
version |
Ganzzahl | Schemaversion des Inhalts. Die aktuelle Version ist 1 |
occurred_at |
Unix-Sekunden | Zeitpunkt des Zustandsübergangs der Ressource; anders als der Zeitstempel der Zustellung ändert er sich bei einer Wiederholung nicht |
data |
Objekt | Vollständige Momentaufnahme der Rechnung, Auszahlung oder Kanaleinzahlung zu diesem Ereignis |
event_id ist die Kennung einer Zustellung: die Kopie eines Übergangs bei genau einem Endpunkt. Zwei Endpunkte, die dasselbe Ereignis abonniert haben, erhalten für dieselbe Zahlung zwei verschiedene evt_-Werte. Die fachliche Kennung ist die Ressourcen-ID in data — inv_…, wdr_… oder pcd_… — und sie bleibt über Endpunkte, Übergänge und Nachsendungen hinweg dieselbe. Geld deduplizieren Sie über die fachliche Kennung, Verarbeitungsversuche über event_id.
Speichern Sie event_id, event_type, version und den Rohtext, bevor Sie aufwendige Arbeit beginnen. Weisen Sie eine Schemaversion, die Ihre Anbindung nicht unterstützt, lieber ab, als ihre Form zu erraten.
Inhalt bei Rechnungen
Beispiel: invoice.paid.
{
"event_id": "evt_J7EEYeL9pZJukfj2c5OQ44",
"event_type": "invoice.paid",
"version": 1,
"occurred_at": 1739281200,
"data": {
"invoice_id": "inv_5CcyDYmMUGtzYL10q0Iimr",
"project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
"status": "paid",
"is_final": true,
"is_test": false,
"payment_url": "https://checkout.paymos.io/invoice/inv_5CcyDYmMUGtzYL10q0Iimr",
"order": {
"external_id": "order-12345",
"client_id": "customer-67890",
"amount": "100.00",
"currency": "USD"
},
"payment": {
"currency": "USDT",
"network": "TRC20",
"chain_id": 728126428,
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"expected": "50.00",
"address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
"exchange_rate": "2.00",
"paid": "50.00",
"remaining": "0",
"fee": "0.50",
"net": "49.50",
"transfers": [
{
"tx_hash": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"amount": "50.00",
"status": "confirmed",
"created_at": 1739281020,
"confirmed_at": 1739281200,
"required_confirmations": 19,
"estimated_confirmation_at": 1739281080,
"explorer_url": "https://tronscan.org/#/transaction/abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
}
]
},
"expires_at": 1739284200,
"completed_at": 1739281200,
"created_at": 1739277600,
"updated_at": 1739281200
}
}
Das data einer Rechnung folgt der Antwort von Rechnung abrufen. Felder, die es für den aktuellen Zustand noch nicht gibt, sind laut JSON-Vertrag null oder fehlen; maßgeblich für den Zustand sind status und is_final.
Inhalt bei Auszahlungen
Beispiel: withdrawal.completed.
{
"event_id": "evt_CbYeOgBp9Kt2U3j74fxxLl",
"event_type": "withdrawal.completed",
"version": 1,
"occurred_at": 1739281200,
"data": {
"withdrawal_id": "wdr_7K2M9P4Q8R1X5Z3A0bC2dE",
"external_order_id": "payout-12345",
"status": "completed",
"is_final": true,
"is_test": false,
"amount": "25.00",
"fee": "0.50",
"currency": "USDT",
"network": "TRC20",
"destination_address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
"tx_hash": "7f8a9b0c1d2e3f4a5b6c7d8e9f00112233445566778899aabbccddeeff001122",
"explorer_url": "https://tronscan.org/#/transaction/7f8a9b0c1d2e3f4a5b6c7d8e9f00112233445566778899aabbccddeeff001122",
"created_at": 1739277600,
"completed_at": 1739281200
}
}
Das data einer Auszahlung folgt der Antwort von Auszahlung abrufen. tx_hash und explorer_url sind gefüllt, sobald eine verfolgte On-Chain-Transaktion vorliegt; sie ersetzen status nicht.
Inhalt bei Kanaleinzahlungen
Beispiel: payment_channel.deposit.confirmed.
{
"event_id": "evt_J7EEYeL9pZJukfj2c5OQ44",
"event_type": "payment_channel.deposit.confirmed",
"version": 1,
"occurred_at": 1767225930,
"data": {
"id": "pcd_8ScRvL4jNq2XkB7mTfZdWu",
"payment_channel_id": "pc_2QhKZv6mRt9WdA3nYpLbXf",
"project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
"payment_channel_external_id": "customer-42",
"status": "confirmed",
"is_final": true,
"is_test": false,
"currency": "USDT",
"network": "TRC20",
"chain_id": 728126428,
"contract_address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"gross": "100",
"fee": "1",
"net": "99",
"applied_fee_percent": 1.0,
"customer_fee_percent": 0,
"tx_hash": "9f4c1b7e30ad52c8ef6a1d84b0c39f27a5e6d138f4b90c72ae51d63b8407fc25",
"transfer_id": "9f4c1b7e30ad52c8ef6a1d84b0c39f27a5e6d138f4b90c72ae51d63b8407fc25:41a614f803b6fd780986a42c78ec9c7f77e6ded13c:41c9f6a2b7d0138e54ca3b91f6072ed48a5c1e93b7:0",
"source_address": "TW9s4RkAqBnLpVdX2ChYzUeGm7QfKt3NbZ",
"destination_address": "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
"block_height": 68421905,
"first_included_block_timestamp": 1767225900,
"explorer_url": "https://tronscan.org/#/transaction/9f4c1b7e30ad52c8ef6a1d84b0c39f27a5e6d138f4b90c72ae51d63b8407fc25",
"created_at": 1767225870,
"updated_at": 1767225930,
"confirmed_at": 1767225930
}
}
Das data einer Einzahlung folgt der Antwort von Einzahlung eines Kanals abrufen. Maßgeblich für den Zustand sind status und is_final; applied_fee_percent und customer_fee_percent sind die für diese Einzahlung eingefrorenen Sätze und bewegen sich nicht, wenn Sie Ihre Konditionen ändern.
Alle drei Ereignisse zu Einzahlungen tragen dasselbe Objekt. Schon ein Inhalt mit confirming nennt also den Kanal, die Kennung des Kunden, den Betrag und die Belege aus der Chain. confirming und reorged sind Hinweise und können in beliebiger Reihenfolge eintreffen — lassen Sie keines von beiden eine Einzahlung zurücksetzen, die Sie bereits als confirmed kennen.
Verträglichkeit
- Zusätzliche Felder können ohne Versionswechsel auftauchen. Ignorieren Sie Felder, die Ihr Handler nicht nutzt.
- Die Bedeutung bestehender Felder ändert sich innerhalb einer Version des Inhalts nicht.
- Behandeln Sie Kennungen und Dezimalbeträge als Zeichenketten. Lesen Sie IDs mit Präfix nicht als UUID und Geldbeträge nicht als binäre Gleitkommazahl.
- Prüfen Sie die Signatur gegen die rohen Bytes, bevor Sie das JSON zerlegen. Ein erneutes Serialisieren des Objekts verändert die signierte Eingabe.