mivita/resources/views/sys/tools/payone-callback-testbench.blade.php
2026-04-10 17:15:27 +02:00

268 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('layouts.layout-2')
@section('content')
<h4 class="font-weight-bold mb-3">
Payone-Callback Testbench
</h4>
<p class="text-muted mb-4">
<strong>Erstbestellung Abo (realistisch):</strong> Zuerst legt der Checkout das Abo an
(<code>CheckoutController</code> <code>AboHelper::createNewAbo</code>), danach meldet Payone per
<code>POST {{ route('api.payment_status', [], true) }}</code> den Zahlungsstatus dann laufen u. a.
<code>Payment::paymentStatusPaidAction</code>, Abo-Freischaltung (<code>setAboActive</code>) und
<code>IncentiveTracker::trackAboActivated</code>. Die Testbench-Schritte sind in dieser Reihenfolge angeordnet.
Nur außerhalb Production.
</p>
@if (session('error'))
<div class="alert alert-danger">{{ session('error') }}</div>
@endif
<div class="card mb-4">
<div class="card-header font-weight-bold">1. Test-Bestellung anlegen</div>
<div class="card-body">
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}">
@csrf
<input type="hidden" name="action" value="create_fixture">
<div class="form-group row">
<label class="col-md-3 col-form-label">Betrag (Brutto EUR)</label>
<div class="col-md-4">
<input type="number" name="amount_eur" class="form-control" step="0.01" min="0.01"
value="{{ old('amount_eur', '119.00') }}" required>
</div>
</div>
<div class="form-group row">
<label class="col-md-3 col-form-label">Berater (users.id)</label>
<div class="col-md-4">
<input type="number" name="consultant_user_id" class="form-control" min="1"
value="{{ old('consultant_user_id', '454') }}" required>
</div>
<div class="col-md-5">
<small class="form-text text-muted">
Bei <code>is_for = me</code> wird <code>auth_user_id</code> gesetzt; bei <code>ot</code> bleibt
<code>auth_user_id</code> leer und <code>member_id</code> wird auf diese Berater-ID gesetzt.
</small>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 offset-md-3">
<div class="form-check">
<input type="checkbox" name="is_abo" id="is_abo" class="form-check-input" value="1"
{{ old('is_abo') ? 'checked' : '' }}>
<label class="form-check-label" for="is_abo">Als Abo-Bestellung (<code>is_abo</code>)</label>
</div>
<div class="form-check mt-2">
<input type="checkbox" name="is_for_ot" id="is_for_ot" class="form-check-input" value="1"
{{ old('is_for_ot', true) ? 'checked' : '' }}>
<label class="form-check-label" for="is_for_ot">Kundenkontext <code>is_for = ot</code> (für
Incentive <code>trackAboActivated</code>)</label>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 offset-md-3">
<button type="submit" class="btn btn-primary">Bestellung + Zahlung anlegen</button>
</div>
</div>
</form>
</div>
</div>
@if (!empty($fixture))
<div class="card mb-4 border-success">
<div class="card-header font-weight-bold text-success">Angelegte Testdaten</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-sm-3">shopping_order_id</dt>
<dd class="col-sm-9"><code>{{ $fixture['shopping_order_id'] }}</code></dd>
<dt class="col-sm-3">shopping_payment_id</dt>
<dd class="col-sm-9"><code>{{ $fixture['shopping_payment_id'] }}</code></dd>
<dt class="col-sm-3">reference (16)</dt>
<dd class="col-sm-9"><code>{{ $fixture['reference'] }}</code></dd>
<dt class="col-sm-3">amount (Cent)</dt>
<dd class="col-sm-9"><code>{{ $fixture['amount_cents'] }}</code> (=
{{ number_format($fixture['amount_eur'], 2, ',', '.') }} )</dd>
<dt class="col-sm-3">Berater-ID</dt>
<dd class="col-sm-9"><code>{{ $fixture['consultant_user_id'] ?? '' }}</code></dd>
<dt class="col-sm-3">Zuordnung</dt>
<dd class="col-sm-9"><small>{{ $fixture['assignment_note'] ?? '' }}</small></dd>
<dt class="col-sm-3">API-URL</dt>
<dd class="col-sm-9"><small class="text-break">{{ $fixture['api_url'] }}</small></dd>
</dl>
<hr>
<p class="mb-2 font-weight-bold">2. Checkout-Erfolg (nur Abo)</p>
<p class="small text-muted mb-2">
Wie <code>handleSuccessfulTransaction</code> / <code>transactionApproved</code>:
<code>AboHelper::createNewAbo($ShoppingPayment)</code> legt UserAbo + UserAboOrder an.
Ohne vorherige <code>payment_transactions</code> wird eine Minimal-Transaktion angelegt.
</p>
@if (!empty($fixture['is_abo']))
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
class="d-inline">
@csrf
<input type="hidden" name="action" value="simulate_checkout_success">
<input type="hidden" name="shopping_order_id" value="{{ $fixture['shopping_order_id'] }}">
<button type="submit" class="btn btn-success">Abo anlegen (<code>createNewAbo</code>)</button>
</form>
@else
<p class="small text-muted mb-0">Nicht-Abo Schritt entfällt.</p>
@endif
<hr>
<p class="mb-2 font-weight-bold">3. Payone-API: Zahlung bestätigt (<code>paid</code>)</p>
<p class="small text-muted mb-2">
<code>Api\PayoneController::paymentStatus</code> <code>Payment::paymentStatusPaidAction</code>
(Abo freischalten, Incentive, ). Bei Abo-Erstbestellung nur nach Schritt 2 (sonst Fehlermeldung).
</p>
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
class="d-inline mr-2">
@csrf
<input type="hidden" name="action" value="simulate_paid">
<input type="hidden" name="shopping_order_id" value="{{ $fixture['shopping_order_id'] }}">
<button type="submit" class="btn btn-warning">Simulate <code>txaction=paid</code> (Erstbestellung)</button>
</form>
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
class="d-inline">
@csrf
<input type="hidden" name="action" value="clear_fixture">
<button type="submit" class="btn btn-outline-secondary btn-sm">Session-Daten löschen</button>
</form>
@php
$benchUserAboId = $userAboId ?? ($checkoutSuccess['user_abo_id'] ?? null);
@endphp
@if (!empty($fixture['is_abo']) && $benchUserAboId)
<hr>
<p class="mb-2 font-weight-bold">4. Abo-Verlängerung (wie <code>user:make_abo_order</code> / Cron)</p>
<p class="small text-muted mb-2">
Setzt <code>next_date</code> auf heute, entfernt ggf. heutige <code>user_abo_orders</code> (Test-Wiederholung),
führt dann <code>UserMakeAboOrder::makeOrder</code> aus (neue Bestellung + Payone). Anschließend Incentive-Zähler
(z.&nbsp;B. qualifizierte Abos) und Umsatzpunkte prüfen für Rechnung/SV wie in Produktion Schritt 5.
</p>
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
class="mb-3">
@csrf
<input type="hidden" name="action" value="simulate_cron_renewal">
<div class="form-group row align-items-center">
<label class="col-md-3 col-form-label"><code>user_abos.id</code></label>
<div class="col-md-4">
<input type="number" name="user_abo_id" class="form-control" min="1"
value="{{ old('user_abo_id', $benchUserAboId) }}">
</div>
<div class="col-md-5">
<small class="form-text text-muted mb-0">Standard aus Session nach Schritt 2/3; anpassbar.</small>
</div>
</div>
<button type="submit" class="btn btn-outline-primary">Cron-Verlängerung ausführen</button>
</form>
@endif
@if (!empty($cronRenewalOrderId))
<hr>
<p class="mb-2 font-weight-bold">5. Payone-API: Verlängerung bestätigt (<code>paid</code>)</p>
<p class="small text-muted mb-2">
Wie Server-zu-Server-Callback nach Cron-Zahlung: <code>Payment::paymentStatusPaidAction</code> (Rechnung,
<code>createAndSalesVolume</code> <code>IncentiveTracker::trackSalesVolume</code>, ).
</p>
<form method="post" action="{{ route('sysadmin_tool_store', ['payone_callback_testbench']) }}"
class="d-inline">
@csrf
<input type="hidden" name="action" value="simulate_paid">
<input type="hidden" name="shopping_order_id" value="{{ $cronRenewalOrderId }}">
<button type="submit" class="btn btn-warning">Simulate <code>txaction=paid</code> (Verlängerung)</button>
</form>
@endif
<hr>
<p class="mb-2 font-weight-bold">Manuell (z. B. Postman / curl)</p>
<pre class="bg-light p-3 small text-break mb-0" style="white-space: pre-wrap;">{{ $fixture['curl'] }}</pre>
</div>
</div>
@endif
@if (!empty($simulateResult))
<div class="card mb-4 border-info">
<div class="card-header font-weight-bold">Ergebnis Schritt 3 (Payone-API)</div>
<div class="card-body">
@if (!empty($simulateResult['hint']))
<p class="small text-muted mb-3">{{ $simulateResult['hint'] }}</p>
@endif
<dl class="row">
<dt class="col-sm-3">HTTP (Kernel)</dt>
<dd class="col-sm-9"><code>{{ $simulateResult['http_status'] }}</code></dd>
<dt class="col-sm-3">Body</dt>
<dd class="col-sm-9"><code>{{ $simulateResult['body'] }}</code> <span class="text-muted">(Payone
erwartet TSOK)</span></dd>
<dt class="col-sm-3">Order paid</dt>
<dd class="col-sm-9">{{ $simulateResult['order_paid'] ? 'true' : 'false' }}</dd>
<dt class="col-sm-3">Order txaction</dt>
<dd class="col-sm-9"><code>{{ $simulateResult['order_txaction'] ?? 'null' }}</code></dd>
</dl>
<p class="mb-1 font-weight-bold">Gesendeter Payload</p>
<pre class="bg-light p-3 small mb-0">{{ json_encode($simulateResult['payload'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}</pre>
</div>
</div>
@endif
@if (!empty($checkoutSuccess))
<div class="card mb-4 border-success">
<div class="card-header font-weight-bold text-success">Ergebnis Schritt 2 (Checkout / createNewAbo)</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-sm-3">user_abo_id</dt>
<dd class="col-sm-9"><code>{{ $checkoutSuccess['user_abo_id'] ?? '' }}</code></dd>
<dt class="col-sm-3">user_abo_orders.id</dt>
<dd class="col-sm-9"><code>{{ $checkoutSuccess['user_abo_order_id'] ?? '' }}</code></dd>
<dt class="col-sm-3">shopping_order_id</dt>
<dd class="col-sm-9"><code>{{ $checkoutSuccess['shopping_order_id'] ?? '' }}</code></dd>
<dt class="col-sm-3">Order paid (nachher)</dt>
<dd class="col-sm-9">{{ !empty($checkoutSuccess['order_paid_after']) ? 'true' : 'false' }}</dd>
</dl>
@if (!empty($checkoutSuccess['hint']))
<p class="small text-muted mb-0 mt-2">{{ $checkoutSuccess['hint'] }}</p>
@endif
</div>
</div>
@endif
@if (!empty($cronRenewal))
<div class="card mb-4 border-primary">
<div class="card-header font-weight-bold text-primary">Ergebnis Schritt 4 (Cron-Verlängerung)</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-sm-3">Erfolg</dt>
<dd class="col-sm-9">{{ !empty($cronRenewal['success']) ? 'true' : 'false' }}</dd>
@if (!empty($cronRenewal['shopping_order_id']))
<dt class="col-sm-3">Neue shopping_order_id</dt>
<dd class="col-sm-9"><code>{{ $cronRenewal['shopping_order_id'] }}</code></dd>
@endif
@if (!empty($cronRenewal['user_abo_id']))
<dt class="col-sm-3">user_abo_id</dt>
<dd class="col-sm-9"><code>{{ $cronRenewal['user_abo_id'] }}</code></dd>
@endif
@if (!empty($cronRenewal['message']))
<dt class="col-sm-3">Hinweis</dt>
<dd class="col-sm-9">{{ $cronRenewal['message'] }}</dd>
@endif
@if (!empty($cronRenewal['diagnosis']))
<dt class="col-sm-3">Diagnose</dt>
<dd class="col-sm-9">
<pre class="bg-light p-2 small mb-0 text-break"
style="white-space: pre-wrap;">{{ json_encode($cronRenewal['diagnosis'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}</pre>
</dd>
@endif
</dl>
@if (!empty($cronRenewal['hint']))
<p class="small text-muted mb-0 mt-2">{{ $cronRenewal['hint'] }}</p>
@endif
</div>
</div>
@endif
@endsection