mivita/resources/views/web/templates/checkout-final.blade.php
Kevin 6f21845607 Stripe-Integration (S0–S3): Einmalzahlungen über Stripe Checkout + Notfall-Go-Live
Wegen PAYONE-Ausfall vorgezogen live geschaltet: alle Einmalzahlungen
(Shop + Salescenter) laufen über Stripe Hosted Checkout, Abos sind bis
Phase S4 eingefroren.

- Provider-Abstraktion: PaymentProvider-Enum, PaymentGatewayInterface,
  PaymentProviderManager (Settings-Schalter, provider-treu je Bestand),
  PayoneGateway als unveränderter Adapter
- StripePaymentService: Checkout Session (eine Gesamtposition, Metadata,
  success/cancel-Redirects), StripeClientWrapper (lazy, Dark Launch),
  StripeCustomerService, StripeTransactionRecorder (client_secret-Redaction)
- Webhook /stripe/webhook: Signaturprüfung, Idempotenz über
  stripe_webhook_events (Crash-Retry-Reprocessing), txaction-Prioritäten,
  Betrags-Guard, lockForUpdate-Paid-Pfad, genau eine Bestätigungsmail
- Zahlungsmethoden-Anzeige aus charge.succeeded (carddata inkl. Wallet,
  auftragsunabhängiges Backfill aus dem Event-Store)
- Checkout: Wartungsmodus mit Admin-Bypass, Abo-Freeze-Hinweis,
  Stripe-Option (Online-Zahlung) statt Zahlartenwahl, Vorkasse ausblendbar
- Abo-Freeze-Guards: Cron user:make_abo_order, Retry, Kartenupdate
- Admin-Settings-Karte Zahlungen (Provider, Wartung, Freeze, Vorkasse)
- Hotfix: 500 bei Vorkasse ohne Clearing-Daten in admin/sales/_detail
  und checkout-final (PAYONE-Ausfall)
- Doku dev/2026-07-08-stripe/ (Plan S0–S8, Konzept, IST-Analyse)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 15:56:41 +00:00

229 lines
9.4 KiB
PHP

@extends($user_shop ? 'web.user.layouts.layout' : 'web.layouts.layout')
@section('content')
<section class="page-header page-header-xlg parallax parallax-3"
style="background-image:url('/assets/images/vision-min.jpg')">
<div class="overlay dark-1"><!-- dark overlay [1 to 9 opacity] --></div>
<div class="container">
</div>
</section>
<!-- /PAGE HEADER -->
<style>
div.shop-item {
margin-bottom: 30px;
border: 1px solid #ddd;
}
div.shop-item>.thumbnail,
.thumbnail {
border: none;
}
div.shop-item-summary {
padding: 8px;
}
div.shop-item-summary h2 a {
color: #9aa983;
font-size: 1.2em;
margin: 0 0 10px 0;
}
div.shop-item-buttons {
padding: 0 8px 10px 8px;
}
div.shop-item-buttons .btn-xs {
padding: 4px;
}
.cartContent a.remove_item {
background: transparent;
}
.cartContent .product_name {
font-size: 1.15em;
}
.cartContent .product_name>small {
line-height: 20px;
}
@media only screen and (max-width: 1200px) {
.cartContent .product_name {
padding-bottom: 0;
min-height: 60px;
width: 60%;
}
.cartContent .remove_item {
clear: right;
}
.cartContent .total_price {
width: auto;
padding-top: 30px;
clear: right;
}
.cartContent .item .qty {
float: left;
text-align: left;
}
.cartContent .item.head {
display: none;
}
}
@media only screen and (min-width: 768px) {
.cartContent .total_price {
padding-top: 10px;
}
}
@media only screen and (min-width: 992px) {
.cartContent .total_price {
padding-top: 30px;
}
}
@media only screen and (min-width: 1200px) {
.cartContent .total_price {
padding-top: 10px;
}
}
</style>
<!-- -->
<!-- -->
<section>
<div class="container">
<!-- CHECKOUT FINAL MESSAGE -->
<div class="panel panel-default">
<div class="panel-body">
<h3>{{ __('payment.thank_you_very_much') }}</h3>
<p>{{ __('payment.we_have_received_your_order_get_email') }}</p>
<h4>{{ __('payment.your_order_number_is') }}: {{ $order_reference }}</h4>
<hr />
@if ($pay_trans && $pay_trans->shopping_payment)
@if ($pay_trans->shopping_payment->clearingtype === 'vor')
{{-- Prominenter Vorkasse-Hinweis mit TXID und Bankdaten --}}
<div class="alert alert-warning" style="border: 3px solid #ffc107; background-color: #fff8e1;">
<h4 class="alert-heading"><i class="fa fa-exclamation-triangle"></i>
{{ __('payment.prepayment_important_notice') }}</h4>
<h5 class="mb-3"><i class="fa fa-university"></i>
{{ __('payment.prepayment_bank_details') }}:</h5>
<div style="background: #fff; border-radius: 8px; padding: 15px;">
<table style="width: 100%;">
<tr>
<td style="padding: 5px 10px 5px 0; width: 140px;">
<strong>{{ __('payment.account_holder') }}:</strong>
</td>
<td style="padding: 5px 0;">
{{ $pay_trans->transmitted_data['clearing_bankaccountholder'] ?? '—' }}</td>
</tr>
<tr>
<td style="padding: 5px 10px 5px 0;"><strong>{{ __('payment.IBAN') }}:</strong>
</td>
<td style="padding: 5px 0; font-family: monospace; letter-spacing: 1px;">
{{ $pay_trans->transmitted_data['clearing_bankiban'] ?? '—' }}</td>
</tr>
<tr>
<td style="padding: 5px 10px 5px 0;"><strong>{{ __('payment.BIC') }}:</strong>
</td>
<td style="padding: 5px 0; font-family: monospace;">
{{ $pay_trans->transmitted_data['clearing_bankbic'] ?? '—' }}</td>
</tr>
<tr>
<td style="padding: 5px 10px 5px 0;"><strong>{{ __('payment.bank') }}:</strong>
</td>
<td style="padding: 5px 0;">
{{ $pay_trans->transmitted_data['clearing_bankname'] ?? '—' }}</td>
</tr>
<tr style="border-top: 1px solid #ffc107;">
<td style="padding: 10px 10px 5px 0;">
<strong>{{ __('payment.total_amount') }}:</strong>
</td>
<td
style="padding: 10px 0 5px 0; font-size: 18px; font-weight: bold; color: #d35400;">
{{ number_format(floatval($pay_trans->shopping_payment->amount / 100), 2, ',', '.') }}
EUR</td>
</tr>
</table>
</div>
<hr style="border-color: #ffc107;">
<p>{{ __('payment.prepayment_reference_notice') }}</p>
@if (isset($pay_trans->transmitted_data['txid']))
<div class="text-center p-4 my-3"
style="background: #fff; border: 3px dashed #ffc107; border-radius: 8px;">
<strong style="font-size: 16px;">{{ __('payment.prepayment_txid') }}:</strong><br>
<span
style="font-size: 32px; font-weight: bold; color: #d35400; letter-spacing: 3px;">{{ $pay_trans->transmitted_data['txid'] }}</span>
</div>
@endif
<p><strong>{{ __('payment.prepayment_reference_only') }}</strong></p>
</div>
<hr />
@endif
@if ($pay_trans->shopping_payment->clearingtype === 'cc')
<h4>{{ __('payment.payment_by_credit_card') }}:</h4>
<p>{{ __('payment.payment_by_credit_card_info') }}</p>
<hr />
@endif
@if ($pay_trans->shopping_payment->clearingtype === 'elv')
<h4>{{ __('payment.payment_by_SEPA') }}:</h4>
<p>{{ __('payment.payment_by_SEPA_info') }}</p>
<hr />
@endif
@if (
$pay_trans->shopping_payment->clearingtype === 'fnc' &&
$pay_trans->shopping_payment->onlinebanktransfertype === 'MIV')
<h4>{{ __('payment.payment_by_invoice') }}:</h4>
<p>{{ __('payment.payment_by_invoice_info') }}</p>
<hr />
@endif
@endif
<p>
<strong>{{ __('payment.your_mivita_team') }}</strong>
</p>
<hr />
<div class="clearfix">
<a href="{{ ($back_url ?? null) ?: Util::getUserShopBackUrl($order_reference) }}"
class="btn float-left btn-primary btn-text-500">
<i class="fa fa-shopping-bag"></i>
{{ ($back_url ?? null) ? __('abo.back_to_abo') : __('payment.back_to_shop') }}
</a>
<a href="{{ route('withdrawal.create') }}" class="btn float-right btn-xs btn-default btn-text-500">
<i class="fa fa-undo"></i> {{ __('withdrawal.button_label') }}
</a>
</div>
</div>
</div>
<!-- /CHECKOUT FINAL MESSAGE -->
</div>
</section>
<!-- / -->
@endsection