mirror of
https://github.com/moodle/moodle.git
synced 2025-02-25 04:23:22 +01:00
The PHP_CodeSniffer @codingStandardsIgnore annotations are deprecated and, since version 3.x, the new // phpcs:ignore comments should be used instead. This commits just reviews all the uses in core, replacing them for the better new candidate, or removing when no longer needed.
329 lines
14 KiB
PHP
329 lines
14 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* Listens for Instant Payment Notification from PayPal
|
|
*
|
|
* This script waits for Payment notification from PayPal,
|
|
* then double checks that data by sending it back to PayPal.
|
|
* If PayPal verifies this then it sets up the enrolment for that
|
|
* user.
|
|
*
|
|
* @package enrol_paypal
|
|
* @copyright 2010 Eugene Venter
|
|
* @author Eugene Venter - based on code by others
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
// Disable moodle specific debug messages and any errors in output,
|
|
// comment out when debugging or better look into error log!
|
|
define('NO_DEBUG_DISPLAY', true);
|
|
|
|
// This script does not require login.
|
|
require("../../config.php"); // phpcs:ignore
|
|
require_once("lib.php");
|
|
require_once($CFG->libdir.'/enrollib.php');
|
|
require_once($CFG->libdir . '/filelib.php');
|
|
|
|
// PayPal does not like when we return error messages here,
|
|
// 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)) {
|
|
http_response_code(400);
|
|
throw new moodle_exception('invalidrequest', 'core_error');
|
|
}
|
|
|
|
/// Read all the data from PayPal and get it ready for later;
|
|
/// we expect only valid UTF-8 encoding, it is the responsibility
|
|
/// of user to set it up properly in PayPal business account,
|
|
/// it is documented in docs wiki.
|
|
|
|
$req = 'cmd=_notify-validate';
|
|
|
|
$data = new stdClass();
|
|
|
|
foreach ($_POST as $key => $value) {
|
|
if ($key !== clean_param($key, PARAM_ALPHANUMEXT)) {
|
|
throw new moodle_exception('invalidrequest', 'core_error', '', null, $key);
|
|
}
|
|
if (is_array($value)) {
|
|
throw new moodle_exception('invalidrequest', 'core_error', '', null, 'Unexpected array param: '.$key);
|
|
}
|
|
$req .= "&$key=".urlencode($value);
|
|
$data->$key = fix_utf8($value);
|
|
}
|
|
|
|
if (empty($data->custom)) {
|
|
throw new moodle_exception('invalidrequest', 'core_error', '', null, 'Missing request param: custom');
|
|
}
|
|
|
|
$custom = explode('-', $data->custom);
|
|
unset($data->custom);
|
|
|
|
if (empty($custom) || count($custom) < 3) {
|
|
throw new moodle_exception('invalidrequest', 'core_error', '', null, 'Invalid value of the request param: custom');
|
|
}
|
|
|
|
$data->userid = (int)$custom[0];
|
|
$data->courseid = (int)$custom[1];
|
|
$data->instanceid = (int)$custom[2];
|
|
$data->payment_gross = $data->mc_gross;
|
|
$data->payment_currency = $data->mc_currency;
|
|
$data->timeupdated = time();
|
|
|
|
$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);
|
|
|
|
$PAGE->set_context($context);
|
|
|
|
$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
|
|
$paypaladdr = empty($CFG->usepaypalsandbox) ? 'ipnpb.paypal.com' : 'ipnpb.sandbox.paypal.com';
|
|
$c = new curl();
|
|
$options = array(
|
|
'returntransfer' => true,
|
|
'httpheader' => array('application/x-www-form-urlencoded', "Host: $paypaladdr"),
|
|
'timeout' => 30,
|
|
'CURLOPT_HTTP_VERSION' => CURL_HTTP_VERSION_1_1,
|
|
);
|
|
$location = "https://$paypaladdr/cgi-bin/webscr";
|
|
$result = $c->post($location, $req, $options);
|
|
|
|
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
|
|
|
|
/// Now read the response and check if everything is OK.
|
|
|
|
if (strlen($result) > 0) {
|
|
if (strcmp($result, "VERIFIED") == 0) { // VALID PAYMENT!
|
|
|
|
|
|
// check the payment_status and payment_reason
|
|
|
|
// If status is not completed or pending then unenrol the student if already enrolled
|
|
// and notify admin
|
|
|
|
if ($data->payment_status != "Completed" and $data->payment_status != "Pending") {
|
|
$plugin->unenrol_user($plugin_instance, $data->userid);
|
|
\enrol_paypal\util::message_paypal_error_to_admin("Status not completed or pending. User unenrolled from course",
|
|
$data);
|
|
die;
|
|
}
|
|
|
|
// If currency is incorrectly set then someone maybe trying to cheat the system
|
|
|
|
if ($data->mc_currency != $plugin_instance->currency) {
|
|
\enrol_paypal\util::message_paypal_error_to_admin(
|
|
"Currency does not match course settings, received: ".$data->mc_currency,
|
|
$data);
|
|
die;
|
|
}
|
|
|
|
// If status is pending and reason is other than echeck then we are on hold until further notice
|
|
// Email user to let them know. Email admin.
|
|
|
|
if ($data->payment_status == "Pending" and $data->pending_reason != "echeck") {
|
|
$eventdata = new \core\message\message();
|
|
$eventdata->courseid = empty($data->courseid) ? SITEID : $data->courseid;
|
|
$eventdata->modulename = 'moodle';
|
|
$eventdata->component = 'enrol_paypal';
|
|
$eventdata->name = 'paypal_enrolment';
|
|
$eventdata->userfrom = get_admin();
|
|
$eventdata->userto = $user;
|
|
$eventdata->subject = "Moodle: PayPal payment";
|
|
$eventdata->fullmessage = "Your PayPal payment is pending.";
|
|
$eventdata->fullmessageformat = FORMAT_PLAIN;
|
|
$eventdata->fullmessagehtml = '';
|
|
$eventdata->smallmessage = '';
|
|
message_send($eventdata);
|
|
|
|
\enrol_paypal\util::message_paypal_error_to_admin("Payment pending", $data);
|
|
die;
|
|
}
|
|
|
|
// If our status is not completed or not pending on an echeck clearance then ignore and die
|
|
// This check is redundant at present but may be useful if paypal extend the return codes in the future
|
|
|
|
if (! ( $data->payment_status == "Completed" or
|
|
($data->payment_status == "Pending" and $data->pending_reason == "echeck") ) ) {
|
|
die;
|
|
}
|
|
|
|
// At this point we only proceed with a status of completed or pending with a reason of echeck
|
|
|
|
// Make sure this transaction doesn't exist already.
|
|
if ($existing = $DB->get_record("enrol_paypal", array("txn_id" => $data->txn_id), "*", IGNORE_MULTIPLE)) {
|
|
\enrol_paypal\util::message_paypal_error_to_admin("Transaction $data->txn_id is being repeated!", $data);
|
|
die;
|
|
}
|
|
|
|
// Check that the receiver email is the one we want it to be.
|
|
if (isset($data->business)) {
|
|
$recipient = $data->business;
|
|
} else if (isset($data->receiver_email)) {
|
|
$recipient = $data->receiver_email;
|
|
} else {
|
|
$recipient = 'empty';
|
|
}
|
|
|
|
if (core_text::strtolower($recipient) !== core_text::strtolower($plugin->get_config('paypalbusiness'))) {
|
|
\enrol_paypal\util::message_paypal_error_to_admin("Business email is {$recipient} (not ".
|
|
$plugin->get_config('paypalbusiness').")", $data);
|
|
die;
|
|
}
|
|
|
|
if (!$user = $DB->get_record('user', array('id'=>$data->userid))) { // Check that user exists
|
|
\enrol_paypal\util::message_paypal_error_to_admin("User $data->userid doesn't exist", $data);
|
|
die;
|
|
}
|
|
|
|
if (!$course = $DB->get_record('course', array('id'=>$data->courseid))) { // Check that course exists
|
|
\enrol_paypal\util::message_paypal_error_to_admin("Course $data->courseid doesn't exist", $data);
|
|
die;
|
|
}
|
|
|
|
$coursecontext = context_course::instance($course->id, IGNORE_MISSING);
|
|
|
|
// Check that amount paid is the correct amount
|
|
if ( (float) $plugin_instance->cost <= 0 ) {
|
|
$cost = (float) $plugin->get_config('cost');
|
|
} else {
|
|
$cost = (float) $plugin_instance->cost;
|
|
}
|
|
|
|
// Use the same rounding of floats as on the enrol form.
|
|
$cost = format_float($cost, 2, false);
|
|
|
|
if ($data->payment_gross < $cost) {
|
|
\enrol_paypal\util::message_paypal_error_to_admin("Amount paid is not enough ($data->payment_gross < $cost))", $data);
|
|
die;
|
|
|
|
}
|
|
// Use the queried course's full name for the item_name field.
|
|
$data->item_name = $course->fullname;
|
|
|
|
// ALL CLEAR !
|
|
|
|
$DB->insert_record("enrol_paypal", $data);
|
|
|
|
if ($plugin_instance->enrolperiod) {
|
|
$timestart = time();
|
|
$timeend = $timestart + $plugin_instance->enrolperiod;
|
|
} else {
|
|
$timestart = 0;
|
|
$timeend = 0;
|
|
}
|
|
|
|
// Enrol user
|
|
$plugin->enrol_user($plugin_instance, $user->id, $plugin_instance->roleid, $timestart, $timeend);
|
|
|
|
// Pass $view=true to filter hidden caps if the user cannot see them
|
|
if ($users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
|
|
'', '', '', '', false, true)) {
|
|
$users = sort_by_roleassignment_authority($users, $context);
|
|
$teacher = array_shift($users);
|
|
} else {
|
|
$teacher = false;
|
|
}
|
|
|
|
$mailstudents = $plugin->get_config('mailstudents');
|
|
$mailteachers = $plugin->get_config('mailteachers');
|
|
$mailadmins = $plugin->get_config('mailadmins');
|
|
$shortname = format_string($course->shortname, true, array('context' => $context));
|
|
|
|
|
|
if (!empty($mailstudents)) {
|
|
$a = new stdClass();
|
|
$a->coursename = format_string($course->fullname, true, array('context' => $coursecontext));
|
|
$a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id";
|
|
|
|
$eventdata = new \core\message\message();
|
|
$eventdata->courseid = $course->id;
|
|
$eventdata->modulename = 'moodle';
|
|
$eventdata->component = 'enrol_paypal';
|
|
$eventdata->name = 'paypal_enrolment';
|
|
$eventdata->userfrom = empty($teacher) ? core_user::get_noreply_user() : $teacher;
|
|
$eventdata->userto = $user;
|
|
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
|
|
$eventdata->fullmessage = get_string('welcometocoursetext', '', $a);
|
|
$eventdata->fullmessageformat = FORMAT_PLAIN;
|
|
$eventdata->fullmessagehtml = '';
|
|
$eventdata->smallmessage = '';
|
|
message_send($eventdata);
|
|
|
|
}
|
|
|
|
if (!empty($mailteachers) && !empty($teacher)) {
|
|
$a->course = format_string($course->fullname, true, array('context' => $coursecontext));
|
|
$a->user = fullname($user);
|
|
|
|
$eventdata = new \core\message\message();
|
|
$eventdata->courseid = $course->id;
|
|
$eventdata->modulename = 'moodle';
|
|
$eventdata->component = 'enrol_paypal';
|
|
$eventdata->name = 'paypal_enrolment';
|
|
$eventdata->userfrom = $user;
|
|
$eventdata->userto = $teacher;
|
|
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
|
|
$eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a);
|
|
$eventdata->fullmessageformat = FORMAT_PLAIN;
|
|
$eventdata->fullmessagehtml = '';
|
|
$eventdata->smallmessage = '';
|
|
message_send($eventdata);
|
|
}
|
|
|
|
if (!empty($mailadmins)) {
|
|
$a->course = format_string($course->fullname, true, array('context' => $coursecontext));
|
|
$a->user = fullname($user);
|
|
$admins = get_admins();
|
|
foreach ($admins as $admin) {
|
|
$eventdata = new \core\message\message();
|
|
$eventdata->courseid = $course->id;
|
|
$eventdata->modulename = 'moodle';
|
|
$eventdata->component = 'enrol_paypal';
|
|
$eventdata->name = 'paypal_enrolment';
|
|
$eventdata->userfrom = $user;
|
|
$eventdata->userto = $admin;
|
|
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
|
|
$eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a);
|
|
$eventdata->fullmessageformat = FORMAT_PLAIN;
|
|
$eventdata->fullmessagehtml = '';
|
|
$eventdata->smallmessage = '';
|
|
message_send($eventdata);
|
|
}
|
|
}
|
|
|
|
} else if (strcmp ($result, "INVALID") == 0) { // ERROR
|
|
$DB->insert_record("enrol_paypal", $data, false);
|
|
throw new moodle_exception('erripninvalid', 'enrol_paypal', '', null, json_encode($data));
|
|
}
|
|
}
|