Files
shop-old/core/paymentmethods/molliepaymentmethod.class.php
T
Thomas Bartelt b8111a1e7f feat(payments): Mollie-Provider -- getrennte Zahlarten je Methode (Klarna, Kreditkarte, Apple Pay, Google Pay)
- core/payments/providers/mollie: Client (Bearer API-Key, Idempotency-Key), Provider nach dem
  PayPal-v2-Vertrag: start (POST /v2/payments mit method aus payment_methods.argument),
  onReturn/onCancel (Status per GET, Rueckkehr-URL traegt o=<orders.id>), onWebhook
  (id=tr_..., Wahrheit per GET), reconcile (paid/canceled/expired/failed, >24h abbrechen)
- Klarna: lines aus order_item (brutto je Stueck), Versand, Zahlartgebuehr, Gutschein, Rabatt,
  Rundungsausgleich; billing/shippingAddress mit E-Mail und Telefon (E.164)
- core/paymentmethods/molliepaymentmethod.class.php: Kassen-Adapter ohne Express
- install_mollie.sql: 16 Spalten in shipping_area (4 helperjoinkeys), Einstellungen Gruppe
  mollie, 4 Zahlarten (module mollie, argument = Methode), Freischaltung/Leichen als Kommentar
- Kasse neu: Mollie-Logos je Methode, Apple Pay nur auf faehigen Geraeten
- cli.php status: mehrere Zahlarten je Anbieter, Modus generisch
2026-09-27 10:39:23 +02:00

123 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
/**
* Zahlart-Adapter fuer den Cashdesk: payment_methods.module = 'mollie'.
*
* Gilt fuer ALLE Mollie-Zahlarten (Klarna, Kreditkarte, Apple Pay, Google Pay ...): welche
* Methode gemeint ist, steht in payment_methods.argument der gewaehlten Zahlart; der
* Provider liest sie ueber die Bestellung. Kopie des PayPal-v2-Adapters ohne Express.
*/
require_once __DIR__ . '/../payments/Registry.php';
class MolliePaymentMethod
{
private const MODULE = 'mollie';
private $base_object;
private $layout_object;
private $customer_data;
private $payment_method;
private $gift_certificate = false;
private $order_id = false;
public function __construct($base_object, $layout_object)
{
$this->base_object = $base_object;
$this->layout_object = $layout_object;
}
public function set_data($customer, $shipping, $billing, $shoppingcart, $delivery, $payment, $order_id = false)
{
$this->customer_data = $customer;
$this->payment_method = $payment;
$this->order_id = $order_id;
}
public function set_gift_certificate($gift_certificate)
{
$this->gift_certificate = $gift_certificate;
}
public function set_order_id($order_id)
{
$this->order_id = $order_id;
}
/** Vor dem Speichern: Anbieter einsatzbereit und Methode gesetzt? Sonst Fehlertext fuer die Kasse. */
public function before_order($argument = null)
{
$provider = \Payments\Registry::get(self::MODULE, $this->base_object);
if (!$provider) {
return 'Diese Zahlart ist derzeit nicht verfuegbar. Bitte waehlen Sie eine andere Zahlart.';
}
$method = \strtolower(\trim((string) $argument));
if ($method === '' || !\preg_match('/^[a-z0-9]{2,30}$/', $method)) {
\error_log('Mollie: Zahlart ohne Methode im Feld argument (payment_methods.id ' . ($this->payment_method->id ?? '?') . ')');
return 'Diese Zahlart ist nicht richtig eingerichtet. Bitte waehlen Sie eine andere Zahlart.';
}
return '';
}
public function during_order($argument = null)
{
return '';
}
/**
* Nach dem Speichern: Zahlung bei Mollie anlegen, Kunde per 302 zur Checkout-Seite.
*/
public function after_order($order_total = false)
{
$amount = (float) $order_total;
if ($this->gift_certificate && isset($this->gift_certificate->with_vat)) {
$amount -= (float) $this->gift_certificate->with_vat;
}
$amount = \round($amount, 2);
$label = $this->label();
try {
$provider = \Payments\Registry::get(self::MODULE, $this->base_object);
if (!$provider) {
throw new \RuntimeException('Provider mollie nicht installiert');
}
$url = $provider->start((int) $this->order_id, $amount);
} catch (\Throwable $e) {
\error_log('Mollie after_order (Order ' . $this->order_id . '): ' . $e->getMessage());
if (\function_exists('shop_event')) {
\shop_event('failed', [
'order_id' => $this->order_id, 'betrag' => $amount,
'customer_id' => $this->customer_data->id ?? null,
'detail' => 'mollie: start fehlgeschlagen -- ' . $e->getMessage(),
]);
}
$this->layout_object->assign('call', 'payment_error');
$this->layout_object->assign('provider_label', $label);
$this->layout_object->assign('message', 'Die Zahlung ueber ' . \htmlspecialchars($label) . ' konnte nicht gestartet werden. Ihr Warenkorb ist noch da &ndash; bitte versuchen Sie es erneut oder waehlen Sie eine andere Zahlart.');
return $this->layout_object->_fetch('content_cash_desk/payment_result.tpl');
}
if (!\headers_sent()) {
\header('Location: ' . $url, true, 302);
exit;
}
$this->layout_object->assign('call', 'payment_open');
$this->layout_object->assign('provider_label', $label);
$this->layout_object->assign('payment_link', $url);
return $this->layout_object->_fetch('content_cash_desk/payment_result.tpl');
}
/** Rueckkehr laeuft ueber website_cashdesk::run() (?payment_return=mollie), nicht hier. */
public function change_order()
{
return '';
}
/** Anzeigename der gewaehlten Zahlart (z.B. "Klarna"), Rueckfall "Mollie". */
private function label(): string
{
$name = \trim((string) ($this->payment_method->name ?? ''));
return $name !== '' ? $name : 'Mollie';
}
}