MDL-14741: better default layout for buttons and added new moodlenolink plugin
[moodle.git] / enrol / paypal / ipn.php
CommitLineData
04f47a89 1<?php // $Id$
2
3/**
5599d142 4* Listens for Instant Payment Notification from PayPal
04f47a89 5*
5599d142 6* This script waits for Payment notification from PayPal,
7* then double checks that data by sending it back to PayPal.
8* If PayPal verifies this then it sets up the enrolment for that
934bdbee 9*
04f47a89 10* Set the $user->timeaccess course array
11*
12* @param user referenced object, must contain $user->id already set
13*/
14
15
3d970777 16 require("../../config.php");
17 require("enrol.php");
18
04f47a89 19/// Keep out casual intruders
3d970777 20 if (empty($_POST) or !empty($_GET)) {
5a2a5331 21 print_error("Sorry, you can not use the script that way.");
04f47a89 22 }
23
934bdbee 24/// Read all the data from PayPal and get it ready for later;
25/// we expect only valid UTF-8 encoding, it is the responsibility
26/// of user to set it up properly in PayPal business acount,
27/// it is documented in docs wiki.
04f47a89 28
29 $req = 'cmd=_notify-validate';
30
934bdbee 31 $data = new object();
32
04f47a89 33 foreach ($_POST as $key => $value) {
934bdbee 34 $req .= "&$key=".urlencode($value);
35 $data->$key = $value;
04f47a89 36 }
37
3d970777 38 $custom = explode('-', $data->custom);
2c61c740 39 $data->userid = (int)$custom[0];
40 $data->courseid = (int)$custom[1];
ec11cd9c 41 $data->payment_gross = $data->mc_gross;
04f47a89 42 $data->payment_currency = $data->mc_currency;
470accb7 43 $data->timeupdated = time();
04f47a89 44
45
597342b0 46/// get the user and course records
47
50c5bef4 48 if (! $user = $DB->get_record("user", array("id"=>$data->userid))) {
597342b0 49 email_paypal_error_to_admin("Not a valid user id", $data);
50 die;
51 }
52
50c5bef4 53 if (! $course = $DB->get_record("course", array("id"=>$data->courseid))) {
597342b0 54 email_paypal_error_to_admin("Not a valid course id", $data);
55 die;
56 }
57
22003ada 58 if (! $context = get_context_instance(CONTEXT_COURSE, $course->id)) {
59 email_paypal_error_to_admin("Not a valid context id", $data);
60 die;
61 }
597342b0 62
04f47a89 63/// Open a connection back to PayPal to validate the data
64
65 $header = '';
66 $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
67 $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
68 $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
48494310 69 $paypaladdr = empty($CFG->usepaypalsandbox) ? 'www.paypal.com' : 'www.sandbox.paypal.com';
70 $fp = fsockopen ($paypaladdr, 80, $errno, $errstr, 30);
04f47a89 71
5599d142 72 if (!$fp) { /// Could not open a socket to PayPal - FAIL
04f47a89 73 echo "<p>Error: could not access paypal.com</p>";
74 email_paypal_error_to_admin("Could not access paypal.com to verify payment", $data);
75 die;
76 }
77
78/// Connection is OK, so now we post the data to validate it
79
80 fputs ($fp, $header.$req);
81
82/// Now read the response and check if everything is OK.
83
84 while (!feof($fp)) {
85 $result = fgets($fp, 1024);
86 if (strcmp($result, "VERIFIED") == 0) { // VALID PAYMENT!
87
04f47a89 88
597342b0 89 // check the payment_status and payment_reason
90
91 // If status is not completed or pending then unenrol the student if already enrolled
92 // and notify admin
93
94 if ($data->payment_status != "Completed" and $data->payment_status != "Pending") {
22003ada 95 role_unassign(0, $data->userid, 0, $context->id);
597342b0 96 email_paypal_error_to_admin("Status not completed or pending. User unenrolled from course", $data);
04f47a89 97 die;
98 }
99
597342b0 100 // If status is pending and reason is other than echeck then we are on hold until further notice
101 // Email user to let them know. Email admin.
102
103 if ($data->payment_status == "Pending" and $data->pending_reason != "echeck") {
5599d142 104 email_to_user($user, get_admin(), "Moodle: PayPal payment", "Your PayPal payment is pending.");
597342b0 105 email_paypal_error_to_admin("Payment pending", $data);
106 die;
107 }
108
109 // If our status is not completed or not pending on an echeck clearance then ignore and die
110 // This check is redundant at present but may be useful if paypal extend the return codes in the future
111
934bdbee 112 if (! ( $data->payment_status == "Completed" or
597342b0 113 ($data->payment_status == "Pending" and $data->pending_reason == "echeck") ) ) {
114 die;
115 }
116
117 // At this point we only proceed with a status of completed or pending with a reason of echeck
118
119
120
50c5bef4 121 if ($existing = $DB->get_record("enrol_paypal", array("txn_id"=>$data->txn_id))) { // Make sure this transaction doesn't exist already
3d970777 122 email_paypal_error_to_admin("Transaction $data->txn_id is being repeated!", $data);
123 die;
04f47a89 124
934bdbee 125 }
126
3d970777 127 if ($data->business != $CFG->enrol_paypalbusiness) { // Check that the email is the one we want it to be
128 email_paypal_error_to_admin("Business email is $data->business (not $CFG->enrol_paypalbusiness)", $data);
129 die;
04f47a89 130
934bdbee 131 }
132
50c5bef4 133 if (!$user = $DB->get_record('user', array('id'=>$data->userid))) { // Check that user exists
04f47a89 134 email_paypal_error_to_admin("User $data->userid doesn't exist", $data);
3d970777 135 die;
04f47a89 136 }
137
50c5bef4 138 if (!$course = $DB->get_record('course', array('id'=>$data->courseid))) { // Check that course exists
3d970777 139 email_paypal_error_to_admin("Course $data->courseid doesn't exist", $data);;
140 die;
04f47a89 141 }
142
3d970777 143 // Check that amount paid is the correct amount
144 if ( (float) $course->cost < 0 ) {
145 $cost = (float) $CFG->enrol_cost;
146 } else {
147 $cost = (float) $course->cost;
148 }
3d970777 149
934bdbee 150 if ($data->payment_gross < $cost) {
76317c73 151 $cost = format_float($cost, 2);
3d970777 152 email_paypal_error_to_admin("Amount paid is not enough ($data->payment_gross < $cost))", $data);
153 die;
04f47a89 154
155 }
156
157 // ALL CLEAR !
158
50c5bef4 159 if (!$DB->insert_record("enrol_paypal", $data)) { // Insert a transaction record
04f47a89 160 email_paypal_error_to_admin("Error while trying to insert valid transaction", $data);
161 }
162
8f425a8f 163 if (!enrol_into_course($course, $user, 'paypal')) {
04f47a89 164 email_paypal_error_to_admin("Error while trying to enrol ".fullname($user)." in '$course->fullname'", $data);
3d970777 165 die;
04f47a89 166 } else {
70beecd4 167 $teacher = get_teacher($course->id);
168
0f093efa 169 if (!empty($CFG->enrol_mailstudents)) {
6ba65fa0 170 $a->coursename = $course->fullname;
631cba64 171 $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id";
934bdbee 172 email_to_user($user, $teacher, get_string("enrolmentnew", '', $course->shortname),
0f093efa 173 get_string('welcometocoursetext', '', $a));
70beecd4 174 }
175
0f093efa 176 if (!empty($CFG->enrol_mailteachers)) {
6ba65fa0 177 $a->course = $course->fullname;
0f093efa 178 $a->user = fullname($user);
934bdbee 179 email_to_user($teacher, $user, get_string("enrolmentnew", '', $course->shortname),
0f093efa 180 get_string('enrolmentnewuser', '', $a));
04f47a89 181 }
0f093efa 182
183 if (!empty($CFG->enrol_mailadmins)) {
6ba65fa0 184 $a->course = $course->fullname;
0f093efa 185 $a->user = fullname($user);
186 $admins = get_admins();
187 foreach ($admins as $admin) {
934bdbee 188 email_to_user($admin, $user, get_string("enrolmentnew", '', $course->shortname),
0f093efa 189 get_string('enrolmentnewuser', '', $a));
190 }
191 }
192
04f47a89 193 }
194
195
196 } else if (strcmp ($result, "INVALID") == 0) { // ERROR
50c5bef4 197 $DB->insert_record("enrol_paypal", $data, false);
04f47a89 198 email_paypal_error_to_admin("Received an invalid payment notification!! (Fake payment?)", $data);
199 }
200 }
201
202 fclose($fp);
203 exit;
204
205
206
207/// FUNCTIONS //////////////////////////////////////////////////////////////////
208
209
210function email_paypal_error_to_admin($subject, $data) {
211 $admin = get_admin();
8f425a8f 212 $site = get_site();
04f47a89 213
214 $message = "$site->fullname: Transaction failed.\n\n$subject\n\n";
215
216 foreach ($data as $key => $value) {
217 $message .= "$key => $value\n";
218 }
219
220 email_to_user($admin, $admin, "PAYPAL ERROR: ".$subject, $message);
221
222}
223
224?>