PayPal-Zahlungen auch ueber die Mailadresse zuordnen
Bisher verglich die Zuordnung ausschliesslich Namen: der Parser las die Adresse des Zahlers gar nicht aus, und die Suche kannte nur paypal_name und display_name. Eine Zahlung von genau der Adresse, die beim Mitglied hinterlegt ist, blieb deshalb liegen. Die Adresse wird jetzt ausgelesen (neue Spalte paypal_payments.payer_email), in der Warteschlange angezeigt und zuerst geprueft - sie ist im Mandanten eindeutig und aendert sich nicht, wenn jemand bei PayPal anders heisst. Der heikle Teil ist das Aussortieren: In einer weitergeleiteten Mail stehen mehrere Adressen. Die falsche zu nehmen wuerde fremdes Geld dem Mitglied hinter dieser Adresse gutschreiben - typischerweise dem Kassenwart. Deshalb fallen paypal.*-Adressen und die eigene Eingangsadresse raus (geprueft gegen die tatsaechliche Empfaengeradresse, Plus-Adressierung ignoriert), und es zaehlt nur eine Adresse in unmittelbarer Naehe des Zahlernamens. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,15 +41,18 @@ function paypal_flow_assert(string $label, bool $condition, array &$failures, in
|
||||
* ankommt: HTML mit Detail-Link (daraus kommt der Transaktionscode) und den
|
||||
* Labels, an denen der Parser sich orientiert.
|
||||
*/
|
||||
function paypal_flow_mail(string $payer, string $betrag, string $code, string $mitteilung, ?string $summe = null): string
|
||||
function paypal_flow_mail(string $payer, string $betrag, string $code, string $mitteilung, ?string $summe = null, ?string $payerEmail = null): string
|
||||
{
|
||||
$summeZeile = $summe !== null
|
||||
? "<tr><td>Gebühr</td><td>-0,35 € EUR</td></tr><tr><td>Summe</td><td>{$summe} € EUR</td></tr>"
|
||||
: '';
|
||||
// PayPal schreibt die Adresse des Zahlers direkt neben seinen Namen.
|
||||
$adresszeile = $payerEmail !== null ? "<p>{$payer} ({$payerEmail})</p>" : '';
|
||||
|
||||
return '<html><body>'
|
||||
. '<p>Hallo,</p>'
|
||||
. "<p>{$payer} hat dir {$betrag} € EUR gesendet</p>"
|
||||
. $adresszeile
|
||||
. "<p>Mitteilung von {$payer} {$mitteilung}</p>"
|
||||
. "<table><tr><td>Erhaltener Betrag</td><td>{$betrag} € EUR</td></tr>"
|
||||
. $summeZeile
|
||||
@@ -129,6 +132,46 @@ try {
|
||||
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);
|
||||
|
||||
// --- Zuordnung ueber die Mailadresse: der Zahler heisst bei PayPal ganz
|
||||
// anders, benutzt aber die Adresse, die beim Mitglied hinterlegt ist.
|
||||
$perMailId = paypal_flow_participant($pdo, $tenantA, "Karin Kassierer {$namensSuffix}", $suffix . 'm');
|
||||
$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);
|
||||
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);
|
||||
|
||||
// Die Adresse wird auch gespeichert, damit in der Warteschlange sichtbar
|
||||
// ist, worauf die Zuordnung beruht.
|
||||
$gespeicherteAdresse = $pdo->prepare('SELECT payer_email FROM paypal_payments WHERE transaction_code = ?');
|
||||
$gespeicherteAdresse->execute([$codeM]);
|
||||
paypal_flow_assert('Mailadresse des Zahlers wird gespeichert', (string) $gespeicherteAdresse->fetchColumn() === $perMailAdresse, $failures, $passes);
|
||||
|
||||
// Fremde Adressen (PayPal selbst, eigene Eingangsadresse) duerfen nie als
|
||||
// Adresse des Zahlers durchgehen - sonst bekaeme das Mitglied hinter der
|
||||
// Eingangsadresse fremdes Geld gutgeschrieben.
|
||||
putenv('PAYPAL_INBOX_BASE=zahlungen@kaffeeliste.de');
|
||||
$nurFremdadressen = paypal_parse_notification(
|
||||
'<html><body><p>Unbekannt Zahler hat dir 1,00 € EUR gesendet</p>'
|
||||
. '<p>service@paypal.de – zahlungen+abc123@kaffeeliste.de</p>'
|
||||
. '<p><a href="https://www.paypal.com/activities/details/TXNONLYFOREIGN01">Details</a></p></body></html>'
|
||||
);
|
||||
paypal_flow_assert('PayPal- und Eingangsadresse werden nicht als Zahleradresse genommen', ($nurFremdadressen['payer_email'] ?? null) === null, $failures, $passes);
|
||||
putenv('PAYPAL_INBOX_BASE');
|
||||
|
||||
// Auch ohne gesetzte Basisadresse: die tatsaechliche Empfaengeradresse der
|
||||
// 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);
|
||||
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]);
|
||||
paypal_flow_assert('eigene Empfaengeradresse wird nicht gespeichert', (string) $selfAdresse->fetchColumn() === '', $failures, $passes);
|
||||
paypal_flow_assert('Plus-Adressierung wird beim Vergleich ignoriert', paypal_same_mailbox('zahlungen@kaffeeliste.de', 'zahlungen+ab12cd@kaffeeliste.de'), $failures, $passes);
|
||||
paypal_flow_assert('fremde Adresse gilt nicht als eigenes Postfach', !paypal_same_mailbox('erika@example.com', 'zahlungen+ab12cd@kaffeeliste.de'), $failures, $passes);
|
||||
|
||||
// --- Der PayPal-Name wird aus der manuellen Zuordnung gelernt: beim
|
||||
// naechsten Mal soll dieselbe Person automatisch getroffen werden.
|
||||
$abweichend = paypal_flow_participant($pdo, $tenantA, "Bernd Beispiel {$namensSuffix}", $suffix . 'x');
|
||||
|
||||
Reference in New Issue
Block a user