course MDL-19794 Upgraded deprecate function calls
[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");
3b120e46 18 require_once($CFG->libdir.'/eventslib.php');
3d970777 19
04f47a89 20/// Keep out casual intruders
3d970777 21 if (empty($_POST) or !empty($_GET)) {
5a2a5331 22 print_error("Sorry, you can not use the script that way.");
04f47a89 23 }
24
934bdbee 25/// Read all the data from PayPal and get it ready for later;
26/// we expect only valid UTF-8 encoding, it is the responsibility
27/// of user to set it up properly in PayPal business acount,
28/// it is documented in docs wiki.
04f47a89 29
30 $req = 'cmd=_notify-validate';
31
934bdbee 32 $data = new object();
33
04f47a89 34 foreach ($_POST as $key => $value) {
934bdbee 35 $req .= "&$key=".urlencode($value);
36 $data->$key = $value;
04f47a89 37 }
38
3d970777 39 $custom = explode('-', $data->custom);
2c61c740 40 $data->userid = (int)$custom[0];
41 $data->courseid = (int)$custom[1];
ec11cd9c 42 $data->payment_gross = $data->mc_gross;
04f47a89 43 $data->payment_currency = $data->mc_currency;
470accb7 44 $data->timeupdated = time();
04f47a89 45
46
597342b0 47/// get the user and course records
48
50c5bef4 49 if (! $user = $DB->get_record("user", array("id"=>$data->userid))) {
3b120e46 50 message_paypal_error_to_admin("Not a valid user id", $data);
597342b0 51 die;
52 }
53
50c5bef4 54 if (! $course = $DB->get_record("course", array("id"=>$data->courseid))) {
3b120e46 55 message_paypal_error_to_admin("Not a valid course id", $data);
597342b0 56 die;
57 }
58
22003ada 59 if (! $context = get_context_instance(CONTEXT_COURSE, $course->id)) {
3b120e46 60 message_paypal_error_to_admin("Not a valid context id", $data);
22003ada 61 die;
62 }
597342b0 63
04f47a89 64/// Open a connection back to PayPal to validate the data
65
66 $header = '';
67 $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
68 $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
69 $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
48494310 70 $paypaladdr = empty($CFG->usepaypalsandbox) ? 'www.paypal.com' : 'www.sandbox.paypal.com';
71 $fp = fsockopen ($paypaladdr, 80, $errno, $errstr, 30);
04f47a89 72
5599d142 73 if (!$fp) { /// Could not open a socket to PayPal - FAIL
04f47a89 74 echo "<p>Error: could not access paypal.com</p>";
3b120e46 75 message_paypal_error_to_admin("Could not access paypal.com to verify payment", $data);
04f47a89 76 die;
77 }
78
79/// Connection is OK, so now we post the data to validate it
80
81 fputs ($fp, $header.$req);
82
83/// Now read the response and check if everything is OK.
84
85 while (!feof($fp)) {
86 $result = fgets($fp, 1024);
87 if (strcmp($result, "VERIFIED") == 0) { // VALID PAYMENT!
88
04f47a89 89
597342b0 90 // check the payment_status and payment_reason
91
92 // If status is not completed or pending then unenrol the student if already enrolled
93 // and notify admin
94
95 if ($data->payment_status != "Completed" and $data->payment_status != "Pending") {
22003ada 96 role_unassign(0, $data->userid, 0, $context->id);
3b120e46 97 message_paypal_error_to_admin("Status not completed or pending. User unenrolled from course", $data);
04f47a89 98 die;
99 }
100
8e605b76 101 // If currency is incorrectly set then someone maybe trying to cheat the system
102
103 if ($data->mc_currency != $course->currency) {
104 email_paypal_error_to_admin("Currency does not match course settings, received: ".addslashes($data->mc_currency), $data);
105 die;
106 }
107
597342b0 108 // If status is pending and reason is other than echeck then we are on hold until further notice
109 // Email user to let them know. Email admin.
110
111 if ($data->payment_status == "Pending" and $data->pending_reason != "echeck") {
3b120e46 112 $eventdata = new object();
113 $eventdata->modulename = 'moodle';
114 $eventdata->userfrom = get_admin();
115 $eventdata->userto = $user;
116 $eventdata->subject = "Moodle: PayPal payment";
117 $eventdata->fullmessage = "Your PayPal payment is pending.";
118 $eventdata->fullmessageformat = FORMAT_PLAIN;
119 $eventdata->fullmessagehtml = '';
120 $eventdata->smallmessage = '';
121 events_trigger('message_send', $eventdata);
122
3b120e46 123 message_paypal_error_to_admin("Payment pending", $data);
597342b0 124 die;
125 }
126
127 // If our status is not completed or not pending on an echeck clearance then ignore and die
128 // This check is redundant at present but may be useful if paypal extend the return codes in the future
129
934bdbee 130 if (! ( $data->payment_status == "Completed" or
597342b0 131 ($data->payment_status == "Pending" and $data->pending_reason == "echeck") ) ) {
132 die;
133 }
134
135 // At this point we only proceed with a status of completed or pending with a reason of echeck
136
137
138
50c5bef4 139 if ($existing = $DB->get_record("enrol_paypal", array("txn_id"=>$data->txn_id))) { // Make sure this transaction doesn't exist already
3b120e46 140 message_paypal_error_to_admin("Transaction $data->txn_id is being repeated!", $data);
3d970777 141 die;
04f47a89 142
934bdbee 143 }
144
3d970777 145 if ($data->business != $CFG->enrol_paypalbusiness) { // Check that the email is the one we want it to be
3b120e46 146 message_paypal_error_to_admin("Business email is $data->business (not $CFG->enrol_paypalbusiness)", $data);
3d970777 147 die;
04f47a89 148
934bdbee 149 }
150
50c5bef4 151 if (!$user = $DB->get_record('user', array('id'=>$data->userid))) { // Check that user exists
3b120e46 152 message_paypal_error_to_admin("User $data->userid doesn't exist", $data);
3d970777 153 die;
04f47a89 154 }
155
50c5bef4 156 if (!$course = $DB->get_record('course', array('id'=>$data->courseid))) { // Check that course exists
3b120e46 157 message_paypal_error_to_admin("Course $data->courseid doesn't exist", $data);;
3d970777 158 die;
04f47a89 159 }
160
3d970777 161 // Check that amount paid is the correct amount
162 if ( (float) $course->cost < 0 ) {
163 $cost = (float) $CFG->enrol_cost;
164 } else {
165 $cost = (float) $course->cost;
166 }
3d970777 167
934bdbee 168 if ($data->payment_gross < $cost) {
76317c73 169 $cost = format_float($cost, 2);
3b120e46 170 message_paypal_error_to_admin("Amount paid is not enough ($data->payment_gross < $cost))", $data);
3d970777 171 die;
04f47a89 172
173 }
174
175 // ALL CLEAR !
176
fc29e51b 177 $DB->insert_record("enrol_paypal", $data);
04f47a89 178
8f425a8f 179 if (!enrol_into_course($course, $user, 'paypal')) {
3b120e46 180 message_paypal_error_to_admin("Error while trying to enrol ".fullname($user)." in '$course->fullname'", $data);
3d970777 181 die;
04f47a89 182 } else {
70beecd4 183 $teacher = get_teacher($course->id);
184
0f093efa 185 if (!empty($CFG->enrol_mailstudents)) {
6ba65fa0 186 $a->coursename = $course->fullname;
631cba64 187 $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id";
3b120e46 188
189 $eventdata = new object();
190 $eventdata->modulename = 'moodle';
191 $eventdata->userfrom = $teacher;
192 $eventdata->userto = $user;
193 $eventdata->subject = get_string("enrolmentnew", '', $course->shortname);
194 $eventdata->fullmessage = get_string('welcometocoursetext', '', $a);
195 $eventdata->fullmessageformat = FORMAT_PLAIN;
196 $eventdata->fullmessagehtml = '';
197 $eventdata->smallmessage = '';
198 events_trigger('message_send', $eventdata);
199
70beecd4 200 }
201
0f093efa 202 if (!empty($CFG->enrol_mailteachers)) {
6ba65fa0 203 $a->course = $course->fullname;
0f093efa 204 $a->user = fullname($user);
3b120e46 205
206 $eventdata = new object();
207 $eventdata->modulename = 'moodle';
208 $eventdata->userfrom = $user;
209 $eventdata->userto = $teacher;
210 $eventdata->subject = get_string("enrolmentnew", '', $course->shortname);
211 $eventdata->fullmessage = get_string('enrolmentnewuser', '', $a);
212 $eventdata->fullmessageformat = FORMAT_PLAIN;
213 $eventdata->fullmessagehtml = '';
214 $eventdata->smallmessage = '';
215 events_trigger('message_send', $eventdata);
04f47a89 216 }
0f093efa 217
218 if (!empty($CFG->enrol_mailadmins)) {
6ba65fa0 219 $a->course = $course->fullname;
0f093efa 220 $a->user = fullname($user);
221 $admins = get_admins();
3b120e46 222 foreach ($admins as $admin) {
223 $eventdata = new object();
224 $eventdata->modulename = 'moodle';
225 $eventdata->userfrom = $user;
226 $eventdata->userto = $admin;
227 $eventdata->subject = get_string("enrolmentnew", '', $course->shortname);
228 $eventdata->fullmessage = get_string('enrolmentnewuser', '', $a);
229 $eventdata->fullmessageformat = FORMAT_PLAIN;
230 $eventdata->fullmessagehtml = '';
231 $eventdata->smallmessage = '';
232 events_trigger('message_send', $eventdata);
0f093efa 233 }
234 }
235
04f47a89 236 }
237
238
239 } else if (strcmp ($result, "INVALID") == 0) { // ERROR
50c5bef4 240 $DB->insert_record("enrol_paypal", $data, false);
3b120e46 241 message_paypal_error_to_admin("Received an invalid payment notification!! (Fake payment?)", $data);
04f47a89 242 }
243 }
244
245 fclose($fp);
246 exit;
247
248
249
250/// FUNCTIONS //////////////////////////////////////////////////////////////////
251
252
3b120e46 253function message_paypal_error_to_admin($subject, $data) {
04f47a89 254 $admin = get_admin();
8f425a8f 255 $site = get_site();
04f47a89 256
257 $message = "$site->fullname: Transaction failed.\n\n$subject\n\n";
258
259 foreach ($data as $key => $value) {
260 $message .= "$key => $value\n";
261 }
262
3b120e46 263 $eventdata = new object();
264 $eventdata->modulename = 'moodle';
265 $eventdata->userfrom = $admin;
266 $eventdata->userto = $admin;
267 $eventdata->subject = "PAYPAL ERROR: ".$subject;
268 $eventdata->fullmessage = $message;
269 $eventdata->fullmessageformat = FORMAT_PLAIN;
270 $eventdata->fullmessagehtml = '';
271 $eventdata->smallmessage = '';
272 events_trigger('message_send', $eventdata);
04f47a89 273}
274
275?>