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); |
35 | $data->userid = $custom[0]; |
36 | $data->courseid = $custom[1]; |
04f47a89 |
37 | $data->payment_amount = $data->mc_gross; |
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 | |
53 | |
04f47a89 |
54 | /// Open a connection back to PayPal to validate the data |
55 | |
56 | $header = ''; |
57 | $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n"; |
58 | $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; |
59 | $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; |
60 | $fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30); |
61 | |
62 | if (!$fp) { /// Could not open a socket to Paypal - FAIL |
63 | echo "<p>Error: could not access paypal.com</p>"; |
64 | email_paypal_error_to_admin("Could not access paypal.com to verify payment", $data); |
65 | die; |
66 | } |
67 | |
68 | /// Connection is OK, so now we post the data to validate it |
69 | |
70 | fputs ($fp, $header.$req); |
71 | |
72 | /// Now read the response and check if everything is OK. |
73 | |
74 | while (!feof($fp)) { |
75 | $result = fgets($fp, 1024); |
76 | if (strcmp($result, "VERIFIED") == 0) { // VALID PAYMENT! |
77 | |
04f47a89 |
78 | |
597342b0 |
79 | // check the payment_status and payment_reason |
80 | |
81 | // If status is not completed or pending then unenrol the student if already enrolled |
82 | // and notify admin |
83 | |
84 | if ($data->payment_status != "Completed" and $data->payment_status != "Pending") { |
85 | unenrol_student($data->userid, $data->courseid); |
86 | email_paypal_error_to_admin("Status not completed or pending. User unenrolled from course", $data); |
04f47a89 |
87 | die; |
88 | } |
89 | |
597342b0 |
90 | // If status is pending and reason is other than echeck then we are on hold until further notice |
91 | // Email user to let them know. Email admin. |
92 | |
93 | if ($data->payment_status == "Pending" and $data->pending_reason != "echeck") { |
94 | email_to_user($user, getadmin(), "Moodle: Paypal payment", "Your Paypal payment is pending."); |
95 | email_paypal_error_to_admin("Payment pending", $data); |
96 | die; |
97 | } |
98 | |
99 | // If our status is not completed or not pending on an echeck clearance then ignore and die |
100 | // This check is redundant at present but may be useful if paypal extend the return codes in the future |
101 | |
102 | if (! ( $data->payment_status == "Completed" or |
103 | ($data->payment_status == "Pending" and $data->pending_reason == "echeck") ) ) { |
104 | die; |
105 | } |
106 | |
107 | // At this point we only proceed with a status of completed or pending with a reason of echeck |
108 | |
109 | |
110 | |
04f47a89 |
111 | if ($existing = get_record("enrol_paypal", "txn_id", $data->txn_id)) { // Make sure this transaction doesn't exist already |
3d970777 |
112 | email_paypal_error_to_admin("Transaction $data->txn_id is being repeated!", $data); |
113 | die; |
04f47a89 |
114 | |
115 | } |
116 | |
3d970777 |
117 | if ($data->business != $CFG->enrol_paypalbusiness) { // Check that the email is the one we want it to be |
118 | email_paypal_error_to_admin("Business email is $data->business (not $CFG->enrol_paypalbusiness)", $data); |
119 | die; |
04f47a89 |
120 | |
121 | } |
122 | |
123 | if (!$user = get_record('user', 'id', $data->userid)) { // Check that user exists |
124 | email_paypal_error_to_admin("User $data->userid doesn't exist", $data); |
3d970777 |
125 | die; |
04f47a89 |
126 | } |
127 | |
631cba64 |
128 | if (!$course = get_record('course', 'id', $data->courseid)) { // Check that course exists |
3d970777 |
129 | email_paypal_error_to_admin("Course $data->courseid doesn't exist", $data);; |
130 | die; |
04f47a89 |
131 | } |
132 | |
3d970777 |
133 | // Check that amount paid is the correct amount |
134 | if ( (float) $course->cost < 0 ) { |
135 | $cost = (float) $CFG->enrol_cost; |
136 | } else { |
137 | $cost = (float) $course->cost; |
138 | } |
139 | $cost = format_float($cost, 2); |
140 | |
141 | if ($data->payment_gross < $cost) { |
142 | email_paypal_error_to_admin("Amount paid is not enough ($data->payment_gross < $cost))", $data); |
143 | die; |
04f47a89 |
144 | |
145 | } |
146 | |
147 | // ALL CLEAR ! |
148 | |
149 | if (!insert_record("enrol_paypal", $data)) { // Insert a transaction record |
150 | email_paypal_error_to_admin("Error while trying to insert valid transaction", $data); |
151 | } |
152 | |
153 | if (!enrol_student($user->id, $course->id)) { // Enrol the student |
154 | email_paypal_error_to_admin("Error while trying to enrol ".fullname($user)." in '$course->fullname'", $data); |
3d970777 |
155 | die; |
04f47a89 |
156 | } else { |
70beecd4 |
157 | $teacher = get_teacher($course->id); |
158 | |
159 | if (!empty($CFG->enrol_paypalmailstudents)) { |
160 | $a->coursename = "$course->fullname"; |
631cba64 |
161 | $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id"; |
597342b0 |
162 | email_to_user($user, $teacher, get_string("enrolmentnew", '', $course->shortname), get_string('welcometocoursetext', '', $a)); |
70beecd4 |
163 | } |
164 | |
165 | if (!empty($CFG->enrol_paypalmailteachers)) { |
597342b0 |
166 | email_to_user($teacher, $user, get_string("enrolmentnew", '', $course->shortname), "I have enrolled in your class via Paypal"); |
04f47a89 |
167 | } |
168 | } |
169 | |
170 | |
171 | } else if (strcmp ($result, "INVALID") == 0) { // ERROR |
172 | insert_record("enrol_paypal", $data); |
173 | email_paypal_error_to_admin("Received an invalid payment notification!! (Fake payment?)", $data); |
174 | } |
175 | } |
176 | |
177 | fclose($fp); |
178 | exit; |
179 | |
180 | |
181 | |
182 | /// FUNCTIONS ////////////////////////////////////////////////////////////////// |
183 | |
184 | |
185 | function email_paypal_error_to_admin($subject, $data) { |
186 | $admin = get_admin(); |
187 | $site = get_admin(); |
188 | |
189 | $message = "$site->fullname: Transaction failed.\n\n$subject\n\n"; |
190 | |
191 | foreach ($data as $key => $value) { |
192 | $message .= "$key => $value\n"; |
193 | } |
194 | |
195 | email_to_user($admin, $admin, "PAYPAL ERROR: ".$subject, $message); |
196 | |
197 | } |
198 | |
199 | ?> |