Krypto-Zahlungen in Laravel empfangen — Anleitung
Schritt-für-Schritt-Anleitung: Krypto-Zahlungsgateway in Laravel bauen, das TRX und USDT (TRC20) über die Chaingateway-API empfängt.
Dieses Tutorial führt Sie durch den Aufbau eines Payment-Gateways in Laravel, das Tron- (TRC) und JST-Zahlungen (TRC20) unterstützt. Es umfasst Funktionen wie das Generieren von Wallets für Payment-Sessions, die Verarbeitung von Webhooks für Transaktionsbenachrichtigungen und die Prüfung des Transaktionsstatus vor der Verarbeitung.
Am Ende dieses Tutorials haben Sie ein funktionierendes Payment-Gateway, das für Blockchain-Interaktionen die API von Chaingateway nutzt.
Dieses Tutorial soll nur den grundlegenden Ablauf der Implementierung beschreiben. Mit einigen kleinen Anpassungen funktioniert es genauso für Bitcoin, Ethereum, Binance Smart Chain und Polygon.
Einführung
Bevor wir in die Implementierung einsteigen, verschaffen wir uns einen Überblick über die verwendeten Werkzeuge:
Was ist Chaingateway?
Chaingateway ist ein Blockchain-API-Dienst, der die Interaktion mit Blockchain-Netzwerken wie Tron vereinfacht. Er ermöglicht Ihnen:
- Wallet-Adressen zu generieren.
- Transaktionen zu überwachen.
- Transaktionen programmatisch auszuführen.
Besuchen Sie die offizielle Dokumentation für weitere Details:
- Developer Portal: Erfahren Sie, wie Sie die Funktionen von Chaingateway nutzen.
- API-Dokumentation: Erkunden Sie die API-Endpoints im Detail.
- API-Key-Erstellung: Generieren Sie die für die Authentifizierung erforderlichen API-Keys.
Schritte zur Erstellung eines API-Keys
Um mit der Chaingateway-API zu interagieren, benötigen Sie einen API-Key. Folgen Sie diesen Schritten:
- Loggen Sie sich bei Chaingateway ein.
- Navigieren Sie zu User Settings > API Tokens.
- Klicken Sie auf Create Token, geben Sie Ihrem Token einen Namen (z. B. „Payment Gateway”) und kopieren Sie ihn. Diesen Key verwenden Sie in Ihrer Laravel-Anwendung.
Voraussetzungen
Bevor Sie fortfahren, stellen Sie sicher, dass Sie Folgendes haben:
- Eine Laravel-Installation: Ein frisch aufgesetztes Laravel-Projekt. Folgen Sie bei Bedarf dem Laravel-Installationsguide.
- Datenbank-Konfiguration: Aktualisieren Sie Ihre
.env-Datei mit Ihren Datenbank-Zugangsdaten. - Grundkenntnisse in Laravel: Vertrautheit mit Models, Migrations, Controllern und Routen ist hilfreich.
Funktionen dieses Tutorials
Dieses Tutorial baut ein Payment-Gateway mit den folgenden Funktionen:
- Ein dynamisches Formular zum Starten von Payment-Sessions:
- Nutzer können den Zahlungsbetrag eingeben.
- Nutzer können die Währung wählen (TRX oder USDT).
- Jeder Session ist eine generierte Wallet-Adresse zugeordnet.
- Eine Session-Seite, die zeigt:
- Die Wallet-Adresse.
- Den Session-Status.
- Den zu sendenden Betrag, den empfangenen Betrag und die Währung.
- Ein Webhook, der Folgendes übernimmt:
- Die Prüfung eingehender Transaktionen.
- Die Aktualisierung des Session-Status.
- Die Weiterleitung der Gelder an eine Cold Wallet bei erfolgreicher Zahlung (optional).
Schritt 1: Chaingateway-API konfigurieren
Zunächst konfigurieren wir Laravel für die Nutzung der Chaingateway-API.
Warum ist das wichtig?
Um mit Chaingateway zu interagieren, müssen Sie jeden Request mit einem API-Key authentifizieren und angeben, mit welchem Blockchain-Netzwerk Sie arbeiten (z. B. Testnet oder Mainnet). Dieser Schritt stellt sicher, dass Ihre Anwendung nahtlos mit Chaingateway kommunizieren kann.
Konfiguration aktualisieren
Fügen Sie die Chaingateway-Konfiguration zu config/app.php hinzu:
'Chaingateway' => [ 'api_url' => env('Chaingateway_API_URL', 'https://app.chaingateway.io/api/v2'), 'api_key' => env('Chaingateway_API_KEY'), 'network' => env('Chaingateway_NETWORK', 'testnet'), // Für Produktion 'mainnet' verwenden 'cold_wallet' => env('COLD_WALLET'),],Öffnen Sie als Nächstes Ihre .env-Datei und fügen Sie Folgendes hinzu:
Chaingateway_API_URL=https://api.Chaingateway.io/api/v2Chaingateway_API_KEY=your_api_key_hereChaingateway_NETWORK=testnetCOLD_WALLET=your_cold_wallet_addressErklärung
api_url: Die Basis-URL der Chaingateway-API.api_key: Ihr persönlicher API-Key zur Authentifizierung von Requests.network: Geben Sie an, ob Sie das Testnet (für die Entwicklung) oder das Mainnet (für die Produktion) verwenden.cold_wallet: Die sichere Wallet, an die Gelder nach der Verifizierung weitergeleitet werden.
Schritt 2: Routen definieren
Routen legen fest, wie Nutzer mit Ihrer Anwendung interagieren. Wir richten Routen ein für:
- Die Anzeige der Payment-Seite.
- Das Starten einer neuen Payment-Session.
- Das Anzeigen einer Payment-Session.
- Die Verarbeitung von Webhooks.
Routen zu routes/web.php hinzufügen
use App\Http\Controllers\PaymentController;
Route::get('/payment', [PaymentController::class, 'showPaymentPage']);Route::post('/start-payment-session', [PaymentController::class, 'startPaymentSession']);Route::get('/payment-session/{id}', [PaymentController::class, 'showPaymentSession'])->name('showPaymentSession');Route::post('/webhook', [PaymentController::class, 'handleWebhook']);Erklärung
/payment: Zeigt eine Seite mit einem Button zum Starten einer neuen Payment-Session./start-payment-session: Erstellt eine neue Session und generiert eine Wallet-Adresse./payment-session/{id}: Zeigt die Wallet-Adresse und den Session-Status./webhook: Empfängt Benachrichtigungen über eingehende Transaktionen von Chaingateway.
Um den CSRF-Schutz für den Webhooks-Endpoint zu deaktivieren, müssen wir ihn in bootstrap/app.php ausschließen. Falls Sie eine ältere Laravel-Version verwenden, finden Sie unter https://laravel.com/docs/11.x/csrf#csrf-excluding-uris, wie es für Ihre Version funktioniert
use Illuminate\Foundation\Application;use Illuminate\Foundation\Configuration\Exceptions;use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { // Webhook-Route vom CSRF-Schutz ausschließen $middleware->validateCsrfTokens(except: [ 'webhook', ]); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();Schritt 3: Models und Migrations erstellen
Wir benötigen zwei Datenbanktabellen:
- Wallets: Speichert Wallet-Adressen und Private Keys.
- Payment Sessions: Verfolgt den Status jeder Session (z. B. Pending, Completed oder Failed).
Models und Migrations generieren
Führen Sie die folgenden Befehle aus:
php artisan make:model Wallet -mphp artisan make:model PaymentSession -mMigrations definieren
Wallet-Migration
In database/migrations/<timestamp>_create_wallets_table.php:
Schema::create('wallets', function (Blueprint $table) { $table->id(); $table->string('address')->unique(); // Wallet-Adresse $table->string('private_key'); // Private Key für Transaktionen $table->timestamps();});PaymentSession-Migration
In database/migrations/<timestamp>_create_payment_sessions_table.php:
Schema::create('payment_sessions', function (Blueprint $table) { $table->id(); $table->string('status')->default('Pending'); // Pending, Completed oder Failed $table->foreignId('wallet_id')->constrained()->onDelete('cascade'); // Verknüpfung zur Wallet $table->decimal('amount', 18, 8)->nullable(); // An diese Session gesendeter Betrag $table->string('currency')->default('TRX'); // Währung des Betrags $table->decimal('received_amount', 18, 8)->nullable(); // An diese Session gesendeter Betrag $table->string('webhook_id')->nullable(); $table->timestamps(); });Führen Sie die Migrations aus:
php artisan migrateWir sollten außerdem sicherstellen, dass die Felder fillable sind und die Relationen korrekt aufgebaut sind. Dazu passen wir die Models an.
Wallet-Model
in app\Models\Wallet.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Wallet extends Model{ protected $fillable = ['address', 'private_key'];
public function paymentSessions() { return $this->hasMany(PaymentSession::class); }}PaymentSession
in app\Models\PaymentSession.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PaymentSession extends Model{ protected $fillable = ['wallet_id', 'status', 'amount', 'currency', 'received_amount', 'webhook_id'];
public function wallet() { return $this->belongsTo(Wallet::class); }}Schritt 4: PaymentController implementieren
Der PaymentController übernimmt die gesamte Logik unserer Anwendung:
- Das Generieren von Wallets.
- Das Erstellen und Anzeigen von Payment-Sessions.
- Die Verarbeitung von Webhook-Benachrichtigungen.
Generieren Sie den Controller:
php artisan make:controller PaymentControllerController-Logik hinzufügen
Hier ist die vollständige Implementierung von PaymentController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;use Illuminate\Support\Facades\Http;use App\Models\PaymentSession;use App\Models\Transaction;use App\Models\Wallet;
class PaymentController extends Controller{ private $apiUrl; private $apiKey; private $network; private $coldWallet;
public function __construct() { $this->apiUrl = config('app.Chaingateway.api_url'); $this->apiKey = config('app.Chaingateway.api_key'); $this->network = config('app.Chaingateway.network'); $this->coldWallet = config('app.Chaingateway.cold_wallet'); }
public function showPaymentPage() { return view('payment'); }
/** * Payment-Session starten * * Diese Funktion erstellt eine neue Wallet-Adresse und einen Webhook in Chaingateway. * */
public function startPaymentSession(Request $request) { $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", 'Content-Type' => 'application/json', 'X-Network' => $this->network, ])->post("{$this->apiUrl}/tron/addresses");
if ($response->successful()) { $walletData = $response->json()['data'];
$wallet = Wallet::create([ 'address' => $walletData['address'], 'private_key' => $walletData['privateKey'], ]);
$wbhookUrl = route('handleWebhook'); $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", 'Content-Type' => 'application/json', 'X-Network' => $this->network, ])->post("{$this->apiUrl}/tron/webhooks", [ 'to' => $wallet->address, 'url' => $wbhookUrl, ]); $webhookData = $response->json()['data'];
$paymentSession = PaymentSession::create([ 'wallet_id' => $wallet->id, 'webhook_id' => $webhookData['id'], 'status' => 'Pending', ]);
return redirect()->route('showPaymentSession', ['id' => $paymentSession->id]); }
return back()->withErrors(['error' => 'Failed to create payment session.']); }
public function showPaymentSession($id) { $paymentSession = PaymentSession::with('wallet')->findOrFail($id); return view('payment-session', compact('paymentSession')); }
public function handleWebhook(Request $request) { $transactionData = $request->all();
$wallet = Wallet::where('address', $transactionData['to'])->first(); if (!$wallet) { return response()->json(['error' => 'Wallet not found'], 404); }
$paymentSession = PaymentSession::where('wallet_id', $wallet->id)->first(); if (!$paymentSession) { return response()->json(['error' => 'Payment session not found'], 404); }
/** * Wir sollten immer die Transaction-Receipt prüfen, ob die Transaktion wirklich erfolgreich war */ $receiptResponse = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", 'Content-Type' => 'application/json', 'X-Network' => $this->network, ])->get("{$this->apiUrl}/tron/transactions/{$transactionData['txid']}/receipt/decoded");
if ($receiptResponse->successful() && $receiptResponse->json()['data']['status'] == 'SUCCESS') { $paymentSession->status = 'Completed'; $paymentSession->received_amount = $transactionData['amount'];
/** * Sie sollten prüfen, ob der empfangene Betrag dem angeforderten Betrag entspricht. * Falls nicht, sollten Sie den Nutzer erstatten oder anderweitig reagieren. * Beträge können variieren, zum Beispiel durch die Transaktionsgebühr. Berücksichtigen Sie das mit einer Marge. * Sie sollten außerdem prüfen, ob es sich um eine TRC20-Token-Transaktion handelt und ob der Contract der erwartete ist. * */ $amountDifference = abs($paymentSession->amount - $transactionData['amount']); $allowedDifference = $paymentSession->amount * 0.10; // 10% des Payment-Session-Betrags
if ($amountDifference >= $allowedDifference) { // Eine Abweichung von bis zu 10% erlauben, Contract-Adresse aktualisieren // Falls der Betrag um mehr als 10% über- oder unterzahlt wurde if ($transactionData['amount'] > $paymentSession->amount) { $paymentSession->status = 'overpaid'; } else { $paymentSession->status = 'underpaid'; } }
if($paymentSession->currency == 'JST' && $transactionData['contractaddress'] != 'TF17BgPaZYbz8oxbjhriubPDsA7ArKoLX3'){ $paymentSession->status = 'Wrong currency received'; }
/** * Tun Sie dies, wenn Sie Ihre Gelder ausschließlich zu einer Cold Wallet bewegen möchten. * Sie können die Gelder auch an eine andere Wallet senden oder gar nichts tun. * Bei TRC20-Token müssen Sie sicherstellen, dass genug TRX für die Transaktionsgebühr vorhanden ist. * Chaingateways Tron-Paymaster-Feature ist deprecated. Nutzen Sie TronFuel (https://tronfuel.dev), wenn Sie sich nicht um die Gebühren kümmern möchten.
$endpoint = $transactionData['contractaddress'] ? "{$this->apiUrl}/tron/transactions/trc20" : "{$this->apiUrl}/tron/transactions";
Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", 'Content-Type' => 'application/json', 'X-Network' => $this->network, ])->post($endpoint, [ 'amount' => $transactionData['amount'], 'privatekey' => $wallet->private_key, 'to' => $this->coldWallet, 'from' => $transactionData['to'], 'contractaddress' => $transactionData['contractaddress'], ]); */ } else { $paymentSession->status = 'Failed'; }
/** * Webhook in Chaingateway löschen * Tun Sie das nur, wenn Sie die Adresse nicht erneut verwenden */ $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", 'Content-Type' => 'application/json', 'X-Network' => $this->network, ])->delete("{$this->apiUrl}/tron/webhooks/{$paymentSession->webhook_id}");
$paymentSession->save(); return response()->json(['status' => 'success']); }}Was macht jede Methode?
showPaymentPage: Zeigt die Haupt-Payment-Seite mit einem Formular zum Starten einer neuen Session.startPaymentSession: Generiert eine Wallet-Adresse, erstellt eine neue Payment-Session und leitet den Nutzer zur Session-Seite weiter.showPaymentSession: Zeigt die Wallet-Adresse und den Session-Status.handleWebhook: Verarbeitet Benachrichtigungen von Chaingateway, prüft den Transaktionserfolg, aktualisiert den Session-Status und leitet Gelder an die Cold Wallet weiter (optional).
Schritt 5: Views erstellen
Um eine neue Payment-Session zu erstellen, verwendet dieses Tutorial ein einfaches Formular, in das Betrag und Währung eingegeben werden. Normalerweise sollte das durch Ihren Checkout-Prozess erledigt werden.
Payment-Seite
In resources/views/payment.blade.php:
<!DOCTYPE html><html> <head> <title>Start Payment Session</title> </head> <body> <h1>Start a New Payment Session</h1> <form action="/start-payment-session" method="POST"> @csrf <label for="amount">Amount:</label> <input type="number" step="0.01" name="amount" id="amount" required /> <br /> <label for="currency">Currency:</label> <select name="currency" id="currency" required> <option value="TRX">TRX</option> <option value="JST">JST (TRC20)</option> </select> <br /> <button type="submit">Start Payment Session</button> </form> </body></html>Auf der Payment-Session-Seite können Nutzer ihren Zahlungsstatus prüfen. Auch das ist ein sehr einfaches Beispiel. In einem realen Szenario würden Sie eher interaktives Polling oder WebSockets nutzen, um den Zahlungsstatus zu aktualisieren.
Payment-Session-Seite
In resources/views/payment-session.blade.php:
<!DOCTYPE html><html> <head> <title>Payment Session</title> </head> ```html <body> <h1>Payment Session</h1> <p> Send <strong >{{ '{{' }} $paymentSession->amount }} {{ '{{' }} $paymentSession->currency }}</strong > to the address below: </p> <p><strong>{{ '{{' }} $paymentSession->wallet->address }}</strong></p> <p>Status: <strong>{{ '{{' }} $paymentSession->status }}</strong></p> <p> Received: <strong >{{ '{{' }} $paymentSession->received_amount }} {{ '{{' }} $paymentSession->currency }}</strong > </p> </body></html>---
## **Schritt 6: Testen**
### **Server starten**
Starten Sie den Laravel-Entwicklungsserver:
```bashphp artisan serveAnwendung testen
- Besuchen Sie
/payment, um eine neue Payment-Session zu starten. - Notieren Sie sich die Wallet-Adresse und senden Sie Gelder dorthin (falls Sie im Testnet testen).
- Simulieren Sie eine Webhook-Benachrichtigung, indem Sie einen POST-Request an
/webhooksenden. - Prüfen Sie, ob sich der Status der Session korrekt aktualisiert.
Wir hoffen, dieses Tutorial zeigt Ihnen, wie einfach es ist, unsere API zum Empfangen von Krypto-Zahlungen zu implementieren. Bei weiteren Fragen oder wenn Sie während der Implementierung Hilfe brauchen, sind wir immer für Sie da! Wenden Sie sich gerne an unsere sehr hilfsbereite Community oder schreiben Sie uns eine E-Mail. So bleiben Sie mit uns in Kontakt: https://Chaingateway.io/support
Möchten Sie das selbst umsetzen? API-Key erhalten — 7 Tage kostenlos testen, keine Karte nötig — oder werfen Sie einen Blick auf Tron-API für die vollständige Endpoint-Referenz.