Absenderpruefung bei PayPal-Mails entfernen
This commit is contained in:
@@ -4,9 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Regressionstest fuer die Verarbeitung eingehender PayPal-Mails - alles
|
||||
* ausser der IMAP-Verbindung selbst: Absenderpruefung, Mandant per
|
||||
* Plus-Token, Parser, Zuordnung, Buchung, Dedup, das Parken bei
|
||||
* abgeschalteter PayPal-Funktion und die schreibfreie Vorschau (--dry-run).
|
||||
* ausser der IMAP-Verbindung selbst: Mandant per Plus-Token der
|
||||
* Empfangsadresse, Parser, Zuordnung (Mailadresse, Name, Mitteilung),
|
||||
* Buchung, Dedup, das Parken bei abgeschalteter PayPal-Funktion und die
|
||||
* schreibfreie Vorschau (--dry-run).
|
||||
*
|
||||
* Der IMAP-Teil laesst sich nur gegen ein echtes Postfach pruefen (siehe
|
||||
* docs/deployment.md, Abschnitt PayPal-Postfach).
|
||||
@@ -109,26 +110,26 @@ try {
|
||||
$mailA = paypal_flow_mail("Erika Musterfrau {$namensSuffix}", '12,50', $codeA, 'Kaffeekasse', '12,15');
|
||||
|
||||
// Erst die Vorschau: sie darf nichts anlegen.
|
||||
$vorschau = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailA, true);
|
||||
$vorschau = paypal_process_raw($pdo, $empfaengerA, $mailA, true);
|
||||
paypal_flow_assert('Vorschau meldet die geplante Buchung', ($vorschau['status'] ?? '') === 'would_book', $failures, $passes);
|
||||
paypal_flow_assert('Vorschau nennt das Mitglied', str_contains((string) ($vorschau['participant'] ?? ''), 'Erika'), $failures, $passes);
|
||||
$zahlungenNachVorschau = (int) $pdo->query('SELECT COUNT(*) FROM paypal_payments')->fetchColumn();
|
||||
|
||||
$ergebnisA = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailA);
|
||||
$ergebnisA = paypal_process_raw($pdo, $empfaengerA, $mailA);
|
||||
paypal_flow_assert('eindeutiger Name wird automatisch gebucht', ($ergebnisA['status'] ?? '') === 'booked', $failures, $passes);
|
||||
paypal_flow_assert('Vorschau hat nichts gespeichert', $zahlungenNachVorschau + 1 === (int) $pdo->query('SELECT COUNT(*) FROM paypal_payments')->fetchColumn(), $failures, $passes);
|
||||
// Gebucht wird die "Summe" (nach Gebuehr), nicht der Sendebetrag.
|
||||
paypal_flow_assert('gebucht wird der Netto-Betrag (12,15 EUR)', paypal_flow_balance($pdo, $participantA) === 1215, $failures, $passes);
|
||||
|
||||
// --- Dedup: dieselbe Mail ein zweites Mal
|
||||
$ergebnisDoppelt = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailA);
|
||||
$ergebnisDoppelt = paypal_process_raw($pdo, $empfaengerA, $mailA);
|
||||
paypal_flow_assert('dieselbe Transaktion wird nicht doppelt gebucht', ($ergebnisDoppelt['status'] ?? '') === 'duplicate', $failures, $passes);
|
||||
paypal_flow_assert('Guthaben bleibt nach der Dublette unveraendert', paypal_flow_balance($pdo, $participantA) === 1215, $failures, $passes);
|
||||
|
||||
// --- Fall 2: unbekannter Zahler -> Warteschlange
|
||||
$codeB = 'TXNQUEUE' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailB = paypal_flow_mail('Unbekannter Zahler', '5,00', $codeB, 'ohne Zuordnung');
|
||||
$ergebnisB = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailB);
|
||||
$ergebnisB = paypal_process_raw($pdo, $empfaengerA, $mailB);
|
||||
paypal_flow_assert('unbekannter Zahler landet in der Warteschlange', ($ergebnisB['status'] ?? '') === 'unmatched', $failures, $passes);
|
||||
paypal_flow_assert('Warteschlange enthaelt die Zahlung', paypal_count_unmatched($pdo, $tenantA) === 1, $failures, $passes);
|
||||
|
||||
@@ -138,7 +139,7 @@ try {
|
||||
$perMailAdresse = strtolower("karin-kassierer-{$namensSuffix}") . '-' . $suffix . 'm@test.local';
|
||||
$codeM = 'TXNMAIL' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailM = paypal_flow_mail('Voellig Anderer Name', '6,00', $codeM, 'per Adresse', null, $perMailAdresse);
|
||||
$ergebnisM = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailM);
|
||||
$ergebnisM = paypal_process_raw($pdo, $empfaengerA, $mailM);
|
||||
paypal_flow_assert('Zahlung wird ueber die Mailadresse zugeordnet', ($ergebnisM['status'] ?? '') === 'booked', $failures, $passes);
|
||||
paypal_flow_assert('Betrag landet beim Mitglied mit dieser Adresse', paypal_flow_balance($pdo, $perMailId) === 600, $failures, $passes);
|
||||
|
||||
@@ -164,7 +165,7 @@ try {
|
||||
// Mail wird verworfen.
|
||||
$codeSelf = 'TXNSELF' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailSelf = paypal_flow_mail('Noch Ein Zahler', '1,00', $codeSelf, 'eigene Adresse', null, $empfaengerA);
|
||||
$ergebnisSelf = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailSelf);
|
||||
$ergebnisSelf = paypal_process_raw($pdo, $empfaengerA, $mailSelf);
|
||||
paypal_flow_assert('eigene Empfaengeradresse wird nicht zur Zahleradresse', ($ergebnisSelf['status'] ?? '') === 'unmatched', $failures, $passes);
|
||||
$selfAdresse = $pdo->prepare('SELECT payer_email FROM paypal_payments WHERE transaction_code = ?');
|
||||
$selfAdresse->execute([$codeSelf]);
|
||||
@@ -178,7 +179,7 @@ try {
|
||||
$codeE = 'TXNLERN' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$zahlername = "Bernd B. Beispiel-Handel {$namensSuffix}";
|
||||
$mailE = paypal_flow_mail($zahlername, '4,00', $codeE, 'erste Zahlung');
|
||||
$ergebnisE = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailE);
|
||||
$ergebnisE = paypal_process_raw($pdo, $empfaengerA, $mailE);
|
||||
paypal_flow_assert('abweichender Zahlername landet zunaechst in der Warteschlange', ($ergebnisE['status'] ?? '') === 'unmatched', $failures, $passes);
|
||||
|
||||
$zuordnung = paypal_assign_payment($pdo, $tenantA, (int) $ergebnisE['payment_id'], $abweichend, null);
|
||||
@@ -187,14 +188,14 @@ try {
|
||||
|
||||
$codeF = 'TXNAUTO2' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailF = paypal_flow_mail($zahlername, '4,00', $codeF, 'zweite Zahlung');
|
||||
$ergebnisF = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailF);
|
||||
$ergebnisF = paypal_process_raw($pdo, $empfaengerA, $mailF);
|
||||
paypal_flow_assert('zweite Zahlung desselben Zahlers wird automatisch gebucht', ($ergebnisF['status'] ?? '') === 'booked', $failures, $passes);
|
||||
paypal_flow_assert('beide Zahlungen sind gutgeschrieben', paypal_flow_balance($pdo, $abweichend) === 800, $failures, $passes);
|
||||
|
||||
// Ein bereits gepflegter PayPal-Name wird nicht ueberschrieben.
|
||||
$codeG = 'TXNKEEP' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailG = paypal_flow_mail('Ganz Anderer Name', '2,00', $codeG, 'fremder Name');
|
||||
$ergebnisG = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', $mailG);
|
||||
$ergebnisG = paypal_process_raw($pdo, $empfaengerA, $mailG);
|
||||
$zuordnungG = paypal_assign_payment($pdo, $tenantA, (int) $ergebnisG['payment_id'], $abweichend, null);
|
||||
paypal_flow_assert('gepflegter PayPal-Name bleibt unveraendert', ($zuordnungG['learned_paypal_name'] ?? null) === null, $failures, $passes);
|
||||
$gespeichert = $pdo->prepare('SELECT paypal_name FROM participants WHERE id = ?');
|
||||
@@ -210,10 +211,10 @@ try {
|
||||
|
||||
$codeC = 'TXNPARK' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailC = paypal_flow_mail("Max Mustermann {$namensSuffix}", '7,00', $codeC, 'trotzdem gezahlt');
|
||||
$vorschauC = paypal_process_raw($pdo, $empfaengerB, 'service@paypal.de', $mailC, true);
|
||||
$vorschauC = paypal_process_raw($pdo, $empfaengerB, $mailC, true);
|
||||
paypal_flow_assert('Vorschau meldet das Parken', ($vorschauC['status'] ?? '') === 'would_park', $failures, $passes);
|
||||
|
||||
$ergebnisC = paypal_process_raw($pdo, $empfaengerB, 'service@paypal.de', $mailC);
|
||||
$ergebnisC = paypal_process_raw($pdo, $empfaengerB, $mailC);
|
||||
paypal_flow_assert('abgeschaltetes PayPal parkt die Zahlung', ($ergebnisC['status'] ?? '') === 'parked', $failures, $passes);
|
||||
paypal_flow_assert('geparkte Zahlung wird nicht gebucht', paypal_flow_balance($pdo, $participantB) === 0, $failures, $passes);
|
||||
paypal_flow_assert('geparkte Zahlung steht in der Warteschlange', paypal_count_unmatched($pdo, $tenantB) === 1, $failures, $passes);
|
||||
@@ -227,15 +228,18 @@ try {
|
||||
|
||||
$codeD = 'TXNLOCK' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailD = paypal_flow_mail("Lisa Beispiel {$namensSuffix}", '3,00', $codeD, 'gesperrt');
|
||||
$ergebnisD = paypal_process_raw($pdo, "zahlungen+{$tokenC}@kaffeeliste.de", 'service@paypal.de', $mailD);
|
||||
$ergebnisD = paypal_process_raw($pdo, "zahlungen+{$tokenC}@kaffeeliste.de", $mailD);
|
||||
paypal_flow_assert('Betreiber-Sperre parkt die Zahlung ebenfalls', ($ergebnisD['status'] ?? '') === 'parked', $failures, $passes);
|
||||
|
||||
// --- Fall 5: alles, was gar nicht erst verarbeitet werden darf
|
||||
$fremd = paypal_process_raw($pdo, $empfaengerA, 'no-reply@beispiel.de', $mailA);
|
||||
paypal_flow_assert('Mail von fremdem Absender wird abgelehnt', ($fremd['status'] ?? '') === 'not_from_paypal', $failures, $passes);
|
||||
// Der Absender wird bewusst nicht geprueft: eine von Hand weitergeleitete
|
||||
// Mail traegt die Adresse des Weiterleitenden, soll aber ankommen.
|
||||
$codeW = 'TXNFWD' . strtoupper(bin2hex(random_bytes(4)));
|
||||
$mailW = paypal_flow_mail("Erika Musterfrau {$namensSuffix}", '3,50', $codeW, 'weitergeleitet');
|
||||
$weitergeleitet = paypal_process_raw($pdo, $empfaengerA, $mailW);
|
||||
paypal_flow_assert('weitergeleitete Mail wird unabhaengig vom Absender verarbeitet', ($weitergeleitet['status'] ?? '') === 'booked', $failures, $passes);
|
||||
|
||||
// Absenderpruefung: PayPal verschickt aus mehreren Domains, eine
|
||||
// Lookalike-Domain darf aber nie durchgehen.
|
||||
// Die Absendererkennung dient nur noch der Diagnose-Anzeige.
|
||||
foreach ([
|
||||
'"PayPal" <service@paypal.de>' => true,
|
||||
'service@paypal.com' => true,
|
||||
@@ -255,13 +259,13 @@ try {
|
||||
);
|
||||
}
|
||||
|
||||
$ohneToken = paypal_process_raw($pdo, 'zahlungen@kaffeeliste.de', 'service@paypal.de', $mailA);
|
||||
$ohneToken = paypal_process_raw($pdo, 'zahlungen@kaffeeliste.de', $mailA);
|
||||
paypal_flow_assert('Adresse ohne Token wird abgelehnt', ($ohneToken['status'] ?? '') === 'no_token', $failures, $passes);
|
||||
|
||||
$falscherToken = paypal_process_raw($pdo, 'zahlungen+gibtesnicht@kaffeeliste.de', 'service@paypal.de', $mailA);
|
||||
$falscherToken = paypal_process_raw($pdo, 'zahlungen+gibtesnicht@kaffeeliste.de', $mailA);
|
||||
paypal_flow_assert('unbekannter Token wird abgelehnt', ($falscherToken['status'] ?? '') === 'unknown_tenant', $failures, $passes);
|
||||
|
||||
$keineZahlung = paypal_process_raw($pdo, $empfaengerA, 'service@paypal.de', '<html><body>Newsletter von PayPal</body></html>');
|
||||
$keineZahlung = paypal_process_raw($pdo, $empfaengerA, '<html><body>Newsletter von PayPal</body></html>');
|
||||
paypal_flow_assert('Werbemail wird nicht als Zahlung erkannt', ($keineZahlung['status'] ?? '') === 'not_a_payment', $failures, $passes);
|
||||
} finally {
|
||||
foreach ($tenantIds as $tenantId) {
|
||||
|
||||
Reference in New Issue
Block a user