Skip to content

Commit

Permalink
MDL-61392 enrol_paypal: Improve the IPN notifications handling
Browse files Browse the repository at this point in the history
* Notify administrators once incoming IPN request is verified by PayPal.
* Fix the HTTP status as expected by the IPN protocol.
  • Loading branch information
mudrd8mz authored and andrewnicols committed Mar 14, 2018
1 parent c6f4528 commit 0167ce3
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 35 deletions.
4 changes: 4 additions & 0 deletions enrol/paypal/classes/util.php
Expand Up @@ -81,6 +81,10 @@ public static function get_exception_handler() {
}
error_log($logerrmsg);

if (http_response_code() == 200) {
http_response_code(500);
}

exit(0);
};
}
Expand Down
52 changes: 17 additions & 35 deletions enrol/paypal/ipn.php
Expand Up @@ -32,6 +32,7 @@
// comment out when debugging or better look into error log!
define('NO_DEBUG_DISPLAY', true);

// @codingStandardsIgnoreLine This script does not require login.
require("../../config.php");
require_once("lib.php");
require_once($CFG->libdir.'/eventslib.php');
Expand All @@ -42,9 +43,16 @@
// the custom handler just logs exceptions and stops.
set_exception_handler(\enrol_paypal\util::get_exception_handler());

// Make sure we are enabled in the first place.
if (!enrol_is_enabled('paypal')) {
http_response_code(503);
throw new moodle_exception('errdisabled', 'enrol_paypal');
}

/// Keep out casual intruders
if (empty($_POST) or !empty($_GET)) {
print_error("Sorry, you can not use the script that way.");
http_response_code(400);
throw new moodle_exception('invalidrequest', 'core_error');
}

/// Read all the data from PayPal and get it ready for later;
Expand All @@ -69,36 +77,13 @@
$data->payment_currency = $data->mc_currency;
$data->timeupdated = time();

// Required for message_send.
$PAGE->set_context(context_system::instance());

/// get the user and course records

if (! $user = $DB->get_record("user", array("id"=>$data->userid))) {
\enrol_paypal\util::message_paypal_error_to_admin("Not a valid user id", $data);
die;
}

if (! $course = $DB->get_record("course", array("id"=>$data->courseid))) {
\enrol_paypal\util::message_paypal_error_to_admin("Not a valid course id", $data);
die;
}

if (! $context = context_course::instance($course->id, IGNORE_MISSING)) {
\enrol_paypal\util::message_paypal_error_to_admin("Not a valid context id", $data);
die;
}
$user = $DB->get_record("user", array("id" => $data->userid), "*", MUST_EXIST);
$course = $DB->get_record("course", array("id" => $data->courseid), "*", MUST_EXIST);
$context = context_course::instance($course->id, MUST_EXIST);

// Now that the course/context has been validated, we can set it. Not that it's wonderful
// to set contexts more than once but system->course switches are accepted.
// Required for message_send.
$PAGE->set_context($context);

if (! $plugin_instance = $DB->get_record("enrol", array("id"=>$data->instanceid, "status"=>0))) {
\enrol_paypal\util::message_paypal_error_to_admin("Not a valid instance id", $data);
die;
}

$plugin_instance = $DB->get_record("enrol", array("id" => $data->instanceid, "enrol" => "paypal", "status" => 0), "*", MUST_EXIST);
$plugin = enrol_get_plugin('paypal');

/// Open a connection back to PayPal to validate the data
Expand All @@ -113,10 +98,9 @@
$location = "https://$paypaladdr/cgi-bin/webscr";
$result = $c->post($location, $req, $options);

if (!$result) { /// Could not connect to PayPal - FAIL
echo "<p>Error: could not access paypal.com</p>";
\enrol_paypal\util::message_paypal_error_to_admin("Could not access paypal.com to verify payment", $data);
die;
if ($c->get_errno()) {
throw new moodle_exception('errpaypalconnect', 'enrol_paypal', '', array('url' => $paypaladdr, 'result' => $result),
json_encode($data));
}

/// Connection is OK, so now we post the data to validate it
Expand Down Expand Up @@ -318,8 +302,6 @@

} else if (strcmp ($result, "INVALID") == 0) { // ERROR
$DB->insert_record("enrol_paypal", $data, false);
\enrol_paypal\util::message_paypal_error_to_admin("Received an invalid payment notification!! (Fake payment?)", $data);
throw new moodle_exception('erripninvalid', 'enrol_paypal', '', null, json_encode($data));
}
}

exit;
3 changes: 3 additions & 0 deletions enrol/paypal/lang/en/enrol_paypal.php
Expand Up @@ -39,6 +39,9 @@
$string['enrolperiod_help'] = 'Length of time that the enrolment is valid, starting with the moment the user is enrolled. If disabled, the enrolment duration will be unlimited.';
$string['enrolstartdate'] = 'Start date';
$string['enrolstartdate_help'] = 'If enabled, users can be enrolled from this date onward only.';
$string['errdisabled'] = 'PayPal plugin is disabled and does not handle payment notifications.';
$string['erripninvalid'] = 'Instant payment notification has not been verified by PayPal.';
$string['errpaypalconnect'] = 'Could not connect to {$a->url} to verify the instant payment notification: {$a->result}';
$string['expiredaction'] = 'Enrolment expiry action';
$string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
$string['mailadmins'] = 'Notify admin';
Expand Down

0 comments on commit 0167ce3

Please sign in to comment.