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