| .. | ||
| ConcurrentPaymentTest.php | ||
| PayoneRaceConditionTest.php | ||
| README.md | ||
Payment Race Condition Tests
Diese Test-Suite überprüft die Behebung von Race Conditions bei der Zahlungsabwicklung und Rechnungsnummernvergabe.
Übersicht
Problem
Wenn mehrere Zahlungen fast gleichzeitig über die Payone API eingehen, konnte es zu Race Conditions kommen:
- Doppelte Rechnungsnummern
- Mehrfache Verarbeitung derselben Zahlung
- Inkonsistente Datenbank-Zustände
Lösung
3-Stufen-Absicherung implementiert:
- Database Locking im PayoneController mit
lockForUpdate() - Atomic Invoice Number Vergabe mit Transaction + Lock
- Double-Check Pattern zur zusätzlichen Absicherung
Test-Dateien
1. ConcurrentPaymentTest.php
Tests für gleichzeitige Rechnungsnummernvergabe:
- ✅
it_generates_unique_invoice_numbers_under_concurrent_load()- Eindeutigkeit bei hoher Last - ✅
it_atomically_increments_invoice_numbers()- Atomare Inkrementierung - ✅
it_does_not_skip_invoice_numbers_on_transaction_rollback()- Keine Lücken - ✅
it_uses_database_locking_for_invoice_numbers()- Lock-Mechanismus - ✅
it_prevents_double_processing_of_same_payment()- Doppelverarbeitung verhindern - ✅
it_can_lock_settings_for_update()- Setting-Lock funktioniert - ✅
it_creates_invoice_numbers_with_correct_format()- Korrekte Formatierung - ✅
it_handles_rapid_sequential_invoice_creation()- Schnelle Sequenzen - ✅
it_initializes_invoice_number_if_not_exists()- Initialisierung - ✅
it_handles_concurrent_transaction_commits()- Gleichzeitige Commits
2. PayoneRaceConditionTest.php
Tests für Payone-spezifische Race Conditions:
- ✅
it_locks_shopping_order_during_payment_processing()- Order wird gelockt - ✅
it_prevents_double_payment_processing()- Doppelte Zahlung verhindern - ✅
it_serializes_concurrent_payment_requests()- Serialisierung - ✅
it_rolls_back_payment_on_error()- Rollback bei Fehler - ✅
it_tracks_payment_status_transitions()- Status-Übergänge - ✅
it_handles_concurrent_payments_for_different_orders()- Verschiedene Orders - ✅
it_isolates_payment_transactions()- Transaction Isolation - ✅
it_prevents_concurrent_modifications()- Gleichzeitige Änderungen verhindern - ✅
it_enforces_unique_payment_references()- Eindeutige Referenzen
3. InvoiceServiceTest.php (Unit Tests)
Unit-Tests für Invoice Service:
- ✅
it_gets_current_invoice_number()- Nummer abrufen - ✅
it_increments_invoice_number()- Inkrementierung - ✅
it_increments_sequentially()- Sequenzielle Inkrementierung - ✅
it_formats_invoice_number_with_year_prefix()- Formatierung - ✅
it_generates_correct_storage_paths()- Storage-Pfade - ✅
it_generates_correct_filenames()- Dateinamen - ✅
it_initializes_invoice_number_when_not_exists()- Initialisierung - ✅
it_uses_transaction_for_invoice_number_increment()- Transaction Usage - ✅
it_locks_setting_during_increment()- Lock während Increment - ✅
it_pads_invoice_numbers_correctly()- Korrekte Padding - ✅
it_returns_zero_when_invoice_number_not_set()- Default-Wert - ✅
it_handles_rapid_increments_without_gaps()- Keine Lücken - ✅
it_returns_integer_invoice_number()- Typ-Sicherheit
Tests ausführen
Alle Payment-Tests
./vendor/bin/phpunit tests/Feature/Payment/
Einzelne Test-Datei
./vendor/bin/phpunit tests/Feature/Payment/ConcurrentPaymentTest.php
./vendor/bin/phpunit tests/Feature/Payment/PayoneRaceConditionTest.php
./vendor/bin/phpunit tests/Unit/Services/InvoiceServiceTest.php
Einzelner Test
./vendor/bin/phpunit --filter it_generates_unique_invoice_numbers_under_concurrent_load
Mit Coverage
./vendor/bin/phpunit --coverage-html coverage/ tests/Feature/Payment/
Mit Pest (falls verwendet)
./vendor/bin/pest tests/Feature/Payment/
Wichtige Hinweise
Database Transactions
Alle Tests verwenden DatabaseTransactions Trait:
- Änderungen werden nach jedem Test automatisch zurückgerollt
- Tests sind isoliert und beeinflussen sich nicht gegenseitig
- Keine manuelle Datenbank-Bereinigung nötig
Test-Daten
Tests erstellen eigene Test-Daten:
- ShoppingOrder, ShoppingPayment, ShoppingUser
- Setting für invoice-number
- Alle Daten werden nach Test automatisch entfernt
Performance
Tests simulieren Concurrent Scenarios:
- Verwenden separate DB-Transactions
- Testen Lock-Mechanismen
- Prüfen auf Race Conditions
Continuous Integration
Diese Tests sollten Teil der CI/CD Pipeline sein:
# .github/workflows/tests.yml
- name: Run Payment Tests
run: ./vendor/bin/phpunit tests/Feature/Payment/
Monitoring in Production
Nach Deployment überwachen:
-
Log-Einträge prüfen:
grep "Error:2008" storage/logs/laravel.log -
Rechnungsnummern auf Lücken prüfen:
SELECT * FROM user_invoices ORDER BY number -- Prüfe auf Lücken in der Sequenz -
Doppelte Rechnungsnummern prüfen:
SELECT full_number, COUNT(*) FROM user_invoices GROUP BY full_number HAVING COUNT(*) > 1;
Troubleshooting
Test schlägt fehl: "Database not configured"
cp .env.example .env.testing
php artisan key:generate --env=testing
Test schlägt fehl: "Setting not found"
Tests initialisieren automatisch - prüfe Migration:
php artisan migrate --env=testing
Test schlägt fehl: "Foreign key constraint"
Prüfe, ob alle Referenzen korrekt erstellt werden:
php artisan migrate:fresh --env=testing
Weiterführende Informationen
- Code-Änderungen: Siehe Git Commit mit Tag
race-condition-fix - Dokumentation:
/dev/[DATUM]/payment-race-condition-fix.md - Issue: Siehe entsprechendes GitHub Issue
Erstellt: Januar 2026 Autor: Claude AI Assistant Status: ✅ Production Ready