Handle all payment notification requests from PayPal.
POST request (must be validated, HTTP 406 error if other method was used)
URL: https://test.wikimedia.de/spenden/paypal_handler.php
Request model parameters:
- payment_status, see https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNandPDTVariables/#id091EB04C0HS Only some are handled (see below)
- txn_type: Transaction type, see https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNandPDTVariables/#id08CTB0S055Z Of the `txn_type` beginning with `subscr_`, only `subscr_payment` is handled, the others are silently dropped.
- item_number, spenden_id, sid. Donation ID (from GET/POST params), pick first non-null value from this list
- custom: JSON-encoded custom data:
- sid, id. Donation ID. Pick first non-null value from this list if donation id was not in in GET/POST from previous data
- token
- utoken
Values that are being stored for documentation purpose only:
- paypal_payer_id => payer_id
- paypal_subscr_id => subscr_id
- paypal_payer_status => payer_status
- paypal_address_status => address_status
- paypal_mc_gross => mc_gross
- paypal_mc_currency => mc_currency
- paypal_mc_fee => mc_fee
- paypal_settle_amount => settle_amount
Values that are being stored for later export:
- txn_id => ext_payment_id
- payment_type => ext_payment_type
- payment_status => ext_payment_status
- payer_id => ext_payment_account
- ext_payment_timestamp (generated at runtime)
- subscr_id => ext_subscr_id
As the first step, the handler must post back the raw POST data (with the additional field `cmd=_notify-validate`) to the PayPal URL to signal that the request was received (See https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNImplementation/#specs). If posting back was not successful (got no `200 OK` back or response content is not `VERIFIED`), the script has to quit.
Now the script does different things, depending on `payment_status` (see below).
### `Pending`
If we're using the PayPal sandbox, set to `Processed`, otherwise ignore. Check if the sandbox still does not send `Processed`, otherwise just ignore.
### `Completed` and `Processed`
Check if a related donation exists. If not, create a new record from the PayPal data and process it.
If the donation id is not empty and handle according to status. Do nothing except logging for states that don't make sense. Create a new donation record (with data from the old record) when status is "B" (bezahlt) and `txn_type` is `subscr_payment`. Process (new) donation.
The payment processor does **not** check the utoken, only the token, because payments can come in up to 5 days after creating the donation.
### Other status strings
Log and do nothing. In the future we should check with the fundraising team, which states make sense in our context and which are already handled by defaults and Backend Application actions.
See https://github.com/wmde/fundraising/issues/970#issuecomment-164474583