'POST', 'callback' => [$this, 'rest_generate_order_number'], 'permission_callback' => ['Skrift_Konfigurator_Admin_Settings', 'rest_api_key_permission'], ]); // Bestellung registrieren (nach erfolgreicher Zahlung) register_rest_route('skrift/v1', '/order/register', [ 'methods' => 'POST', 'callback' => [$this, 'rest_register_order'], 'permission_callback' => ['Skrift_Konfigurator_Admin_Settings', 'rest_api_key_permission'], ]); } /** * Generiert die nächste fortlaufende Bestellnummer * Format: S-YYYY-MM-DD-XXX (z.B. S-2026-01-12-001) * Verwendet Transient-Lock um Race Conditions zu vermeiden */ public static function generate_order_number() { $lock_key = 'skrift_order_number_lock'; $max_attempts = 10; $attempt = 0; // Versuche Lock zu bekommen (einfaches Locking mit Transients) while ($attempt < $max_attempts) { // Prüfe ob Lock existiert if (get_transient($lock_key) === false) { // Setze Lock (5 Sekunden Timeout) set_transient($lock_key, time(), 5); // Aktuellen Counter holen $counter_data = get_option(self::COUNTER_OPTION_KEY, [ 'date' => '', 'counter' => 0 ]); $today = date('Y-m-d'); // Counter zurücksetzen wenn neuer Tag if ($counter_data['date'] !== $today) { $counter_data = [ 'date' => $today, 'counter' => 0 ]; } // Counter erhöhen $counter_data['counter']++; // Speichern update_option(self::COUNTER_OPTION_KEY, $counter_data); // Lock freigeben delete_transient($lock_key); // Format: S-YYYY-MM-DD-XXX $year = date('Y'); $month = date('m'); $day = date('d'); $number = str_pad($counter_data['counter'], 3, '0', STR_PAD_LEFT); return "S-{$year}-{$month}-{$day}-{$number}"; } // Warte kurz und versuche erneut usleep(100000); // 100ms $attempt++; } // Fallback wenn Lock nicht bekommen werden konnte // Verwende Microtime für Eindeutigkeit $year = date('Y'); $month = date('m'); $day = date('d'); $micro = substr(str_replace('.', '', microtime(true)), -6); return "S-{$year}-{$month}-{$day}-{$micro}"; } /** * REST API Endpoint: Neue Bestellnummer generieren */ public function rest_generate_order_number($request) { $order_number = self::generate_order_number(); return [ 'success' => true, 'orderNumber' => $order_number ]; } /** * REST API Endpoint: Bestellung registrieren */ public function rest_register_order($request) { $order_number = $request->get_param('orderNumber'); $customer = $request->get_param('customer'); $quote = $request->get_param('quote'); $payment_method = $request->get_param('paymentMethod'); $payment_id = $request->get_param('paymentId'); if (empty($order_number)) { return new WP_Error('missing_order_number', 'Bestellnummer fehlt', ['status' => 400]); } // Bestellung speichern $orders = get_option(self::ORDERS_OPTION_KEY, []); $orders[$order_number] = [ 'orderNumber' => $order_number, 'customer' => $customer, 'quote' => $quote, 'paymentMethod' => $payment_method, 'paymentId' => $payment_id, 'createdAt' => current_time('mysql'), 'status' => 'pending' ]; update_option(self::ORDERS_OPTION_KEY, $orders); return [ 'success' => true, 'orderNumber' => $order_number, 'message' => 'Bestellung erfolgreich registriert' ]; } /** * Bestellung als bezahlt markieren */ public static function mark_order_paid($order_number, $payment_id = null) { $orders = get_option(self::ORDERS_OPTION_KEY, []); if (isset($orders[$order_number])) { $orders[$order_number]['status'] = 'paid'; $orders[$order_number]['paidAt'] = current_time('mysql'); if ($payment_id) { $orders[$order_number]['paymentId'] = $payment_id; } update_option(self::ORDERS_OPTION_KEY, $orders); return true; } return false; } /** * Alle Bestellungen abrufen */ public static function get_orders() { return get_option(self::ORDERS_OPTION_KEY, []); } /** * Einzelne Bestellung abrufen */ public static function get_order($order_number) { $orders = self::get_orders(); return $orders[$order_number] ?? null; } } new Skrift_Konfigurator_Orders();