diff --git a/paypal_payment_ipn/includes/PayPalPaymentIPNController.inc b/paypal_payment_ipn/includes/PayPalPaymentIPNController.inc index 7eac9a8..f35511f 100644 --- a/paypal_payment_ipn/includes/PayPalPaymentIPNController.inc +++ b/paypal_payment_ipn/includes/PayPalPaymentIPNController.inc @@ -136,29 +136,24 @@ abstract class PayPalPaymentIPNController { * @return boolean */ static function validate(array $ipn_variables) { - if (isset($ipn_variables['txn_id'])) { - // Make sure this IPN was not processed before. - $ipn = PayPalPaymentIPNController::load($ipn_variables['txn_id']); - if (!$ipn) { - // Check if the IPN matches a Payment. - if (isset($ipn_variables['invoice'])) { - $pid = self::PID($ipn_variables['invoice']); - if ($pid) { - $payment = entity_load_single('payment', $pid); - if ($payment) { - // Allow payment method controllers to completely take over validation. - if ($payment->method->controller instanceof PayPalPaymentIPNPaymentMethodControllerInterface) { - return $payment->method->controller->PayPalValidateIPNVariables($payment, $ipn_variables); - } - else { - return TRUE; - } - } - } - } - } + // Verify existance of expected POST data. + if (!isset($ipn_variables['txn_id']) || !isset($ipn_variables['invoice'])) { + return FALSE; } - return FALSE; + // Try to retrieve the payment id. + $pid = self::PID($ipn_variables['invoice']); + if (!$pid) { + return FALSE; + } + // Load the payment entity. + $payment = entity_load_single('payment', $pid); + if (!$payment) { + return FALSE; + } + if ($payment->method->controller instanceof PayPalPaymentIPNPaymentMethodControllerInterface) { + return $payment->method->controller->PayPalValidateIPNVariables($payment, $ipn_variables); + } + return TRUE; } /** @@ -287,7 +282,7 @@ abstract class PayPalPaymentIPNController { else { $status_map = self::statusMap(); return isset($status_map[$paypal_status]) ? $status_map[$paypal_status] : PAYMENT_STATUS_UNKNOWN; - } + } } return PAYMENT_STATUS_UNKNOWN; } diff --git a/paypal_payment_ipn/paypal_payment_ipn.module b/paypal_payment_ipn/paypal_payment_ipn.module index e2f6a0c..aad1374 100644 --- a/paypal_payment_ipn/paypal_payment_ipn.module +++ b/paypal_payment_ipn/paypal_payment_ipn.module @@ -26,16 +26,38 @@ function paypal_payment_ipn_menu() { } /** - * Processes an IPN request based on POST data. + * Handle POST data from an IPN request. */ function paypal_payment_ipn_post() { - $ipn_variables = $_POST; - foreach ($_POST as $ipn_variable => $value) { - $ipn_variables[$ipn_variable] = rawurldecode($value); - } + $ipn_variables = paypal_payment_ipn_get_decoded_data($_POST); if (PayPalPaymentIPNController::acknowledge($ipn_variables) && PayPalPaymentIPNController::validate($ipn_variables)) { - $ipn = new PayPalPaymentIPN($ipn_variables); - PayPalPaymentIPNController::save($ipn); - PayPalPaymentIPNController::process($ipn_variables); + paypal_payment_ipn_process_data($ipn_variables); + } +} + +/** + * Processes an IPN request based on POST data. + */ +function paypal_payment_ipn_process_data($ipn_variables) { + if (PayPalPaymentIPNController::load($ipn_variables['txn_id'])) { + // The transaction record has already been created and processed. + return; } + $ipn = new PayPalPaymentIPN($ipn_variables); + PayPalPaymentIPNController::save($ipn); + PayPalPaymentIPNController::process($ipn_variables); } + +/** + * Decode incoming IPN data. + * + * @param array $ipn_variables + * This is most probably unprocessed POST data. + */ +function paypal_payment_ipn_get_decoded_data($post_data) { + $ipn_variables = array(); + foreach ($post_data as $key => $value) { + $ipn_variables[$key] = rawurldecode($value); + } + return $ipn_variables; +} \ No newline at end of file diff --git a/paypal_payment_ipn_test/paypal_payment_ipn_test.module b/paypal_payment_ipn_test/paypal_payment_ipn_test.module index 5ea6ee4..b5bb659 100644 --- a/paypal_payment_ipn_test/paypal_payment_ipn_test.module +++ b/paypal_payment_ipn_test/paypal_payment_ipn_test.module @@ -60,4 +60,13 @@ function paypal_payment_ipn_test_paypal_server() { print 'INVALID'; } drupal_exit(); +} + +/** + * Dummy finish callback for paypal_payments + * + * @param Payment $payment + */ +function paypal_pament_ipn_finish_callback(Payment $payment) { + $payment->payment_test_finish_callback = TRUE; } \ No newline at end of file diff --git a/paypal_payment_pps/includes/PayPalPaymentPPSPaymentMethodController.inc b/paypal_payment_pps/includes/PayPalPaymentPPSPaymentMethodController.inc index ee05cdb..b26b9f9 100644 --- a/paypal_payment_pps/includes/PayPalPaymentPPSPaymentMethodController.inc +++ b/paypal_payment_pps/includes/PayPalPaymentPPSPaymentMethodController.inc @@ -65,7 +65,7 @@ class PayPalPaymentPPSPaymentMethodController extends PaymentMethodController im // PayPal treats email addresses case-insensitively and returns them in // lowercase in $ipn_variables['business']. Therefore we must perform // a case-insensitive comparison. - return strtolower($ipn_variables['business']) == strtolower($payment->method->controller_data['email_address']); + return strtolower($ipn_variables['receiver_email']) == strtolower($payment->method->controller_data['email_address']); } /** diff --git a/paypal_payment_pps/paypal_payment_pps.info b/paypal_payment_pps/paypal_payment_pps.info index e8aa8f9..0ea3dd8 100644 --- a/paypal_payment_pps/paypal_payment_pps.info +++ b/paypal_payment_pps/paypal_payment_pps.info @@ -7,6 +7,7 @@ core = 7.x PHP = 5.3 files[] = includes/PayPalPaymentPPSPaymentMethodController.inc files[] = tests/PayPalPaymentPPSPaymentExecution.test +files[] = tests/PayPalPaymentPPSPaymentIPNExecution.test files[] = tests/PayPalPaymentPPSPaymentMethodCRUD.test files[] = tests/PayPalPaymentPPSPaymentMethodUI.test files[] = tests/PayPalPaymentWebTestCase.test diff --git a/paypal_payment_pps/paypal_payment_pps.module b/paypal_payment_pps/paypal_payment_pps.module index 9b659bc..508e49d 100644 --- a/paypal_payment_pps/paypal_payment_pps.module +++ b/paypal_payment_pps/paypal_payment_pps.module @@ -251,10 +251,12 @@ function paypal_payment_pps_form_redirect_access(Payment $payment, $account = NU * Return callback. */ function paypal_payment_pps_return() { - $ipn_variables = $_POST; - $ipn = new PayPalPaymentIPN($ipn_variables); - PayPalPaymentIPNController::save($ipn); - PayPalPaymentIPNController::process($ipn_variables); + // Retrieve the POST data that came with this request. + $ipn_variables = paypal_payment_ipn_get_decoded_data($_POST); + // Make sure that ipn data is handled. Normally this is already done when IPN + // calls back in using PAYPAL_IPN_LISTENER_PATH + paypal_payment_ipn_process_data($ipn_variables); + // Now load the payment and perform finishing steps. $payment = entity_load_single('payment', PayPalPaymentIPNController::PID($ipn_variables['invoice'])); $payment->finish(); } @@ -265,7 +267,14 @@ function paypal_payment_pps_return() { * @return bool */ function paypal_payment_pps_return_access() { - return PayPalPaymentIPNController::validate($_POST); + global $user; + $ipn_variables = paypal_payment_ipn_get_decoded_data($_POST); + if (!PayPalPaymentIPNController::validate($ipn_variables)) { + return FALSE; + } + $pid = PayPalPaymentIPNController::PID($ipn_variables['invoice']); + $payment = entity_load_single('payment', $pid); + return $payment->uid == $user->uid; } /**