Fundraising/Data and flow/PSP integrations/PayPal Express

= Overview =
Our PayPal Express Checkout integration first requests a token from PayPal, then uses that token to send the donor immediately to the PayPal login page. PayPal returns them to our site and we ask for the payment status, then decide whether to capture the payment.
== Accounts ==
paypal.com -> developer.paypal.com
= API calls =
All API calls are made via simple name/value pair POSTS - that is, old-fashioned form data encoded with http_build_query rather than JSON. All calls hit the same endpoint (differing only between sandbox and production). Different API calls are differentiated by the METHOD parameter. Authentication is performed via an SSL certificate on the request. All responses have an ACK parameter which should be Success or SuccessWithWarning if the call succeeded.
== Initial payment setup ==
Our first call uses METHOD=SetExpressCheckout and sends the amount, currency, description, and return and cancel URLs to PayPal. We read the TOKEN parameter from the response. We save the TOKEN as our gateway_session_id and use it to create a redirect URL to send the donor to the PayPal login page.
== Payment status request ==
When the donor returns to our site, we make an API call with METHOD=GetExpressCheckoutDetails. We send the gateway_session_id back (as the TOKEN parameter) and read donor details and payment status from the response. The PAYERID from this response is required (along with the TOKEN) to capture the payment in the next step.
There is a SmashPig maintenance script that you can use to perform this request from the command line.
php PaymentProviders/PayPal/Maintenance/GetPaymentStatus.php <TOKEN>
== Payment capture ==
TODO finish
METHOD=DoExpressCheckoutPayment
== Recurring payment setup ==
When a donor starts a recurring payment profile via PayPal, we use an API call with
METHOD=CreateRecurringPaymentsProfile
to tell PayPal to start charging them monthly, with the scheduling and retries handled at PayPal's side. We read the PROFILEID and PROFILESTATUS from the response to check that it was successful, then send a message to the Pending queue and redirect the donor to the Thank You page.
We do not send any message to the recurring or donations queues from payments-wiki. Instead, we wait for PayPal to send us two IPN messages: one recurring_payment_profile_created and one recurring_payment. The first is processed by the RecurringQueueConsumer to create the donor and a contribution_recur row, and the second is processed by the RecurringQueueConsumer (for now, see this phab) to create the contribution row.
When IPN messages are picked up by the listener, they are sent unchanged to a jobs-paypal queue. The PayPal job queue consumer normalizes the IPNs and adds any matching information in the pending table (found by gateway and order ID). Then it sends the combined message along, generally to the recurring queue. This logic is in the mergePendingDetails function of the PayPal\Message class in SmashPig.
== IPN Listener ==
https://wikitech.wikimedia.org/wiki/Fundraising/Data_and_flow/IPN_listener#PayPal
= Testing = 
Test account information is in Localsettings-private in the PayPal section