This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | // This file is part of Moodle - http://moodle.org/ |
||
3 | // |
||
4 | // Moodle is free software: you can redistribute it and/or modify |
||
5 | // it under the terms of the GNU General Public License as published by |
||
6 | // the Free Software Foundation, either version 3 of the License, or |
||
7 | // (at your option) any later version. |
||
8 | // |
||
9 | // Moodle is distributed in the hope that it will be useful, |
||
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
12 | // GNU General Public License for more details. |
||
13 | // |
||
14 | // You should have received a copy of the GNU General Public License |
||
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. |
||
16 | |||
17 | /** |
||
18 | * Listens for Instant Payment Notification from pagseguro |
||
19 | * |
||
20 | * This script waits for Payment notification from pagseguro, |
||
21 | * then double checks that data by sending it back to pagseguro. |
||
22 | * If pagseguro verifies this then it sets up the enrolment for that |
||
23 | * user. |
||
24 | * |
||
25 | * @package enrol |
||
26 | * @subpackage pagseguro |
||
27 | * @copyright 2010 Eugene Venter |
||
28 | * @author Eugene Venter - based on code by others |
||
29 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
||
30 | */ |
||
31 | |||
32 | //header("access-control-allow-origin: https://ws.pagseguro.uol.com.br"); |
||
33 | require('../../config.php'); |
||
34 | require_once("lib.php"); |
||
35 | require_once($CFG->libdir.'/eventslib.php'); |
||
36 | require_once($CFG->libdir.'/enrollib.php'); |
||
37 | |||
38 | define('COMMERCE_PAGSEGURO_STATUS_AWAITING', 1); |
||
39 | define('COMMERCE_PAGSEGURO_STATUS_IN_ANALYSIS', 2); |
||
40 | define('COMMERCE_PAGSEGURO_STATUS_PAID', 3); |
||
41 | define('COMMERCE_PAGSEGURO_STATUS_AVAILABLE', 4); |
||
42 | define('COMMERCE_PAGSEGURO_STATUS_DISPUTED', 5); |
||
43 | define('COMMERCE_PAGSEGURO_STATUS_REFUNDED', 6); |
||
44 | define('COMMERCE_PAGSEGURO_STATUS_CANCELED', 7); |
||
45 | define('COMMERCE_PAYMENT_STATUS_SUCCESS', 'success'); |
||
46 | define('COMMERCE_PAYMENT_STATUS_FAILURE', 'failure') ; |
||
47 | define('COMMERCE_PAYMENT_STATUS_PENDING', 'pending'); |
||
48 | |||
49 | $userid = $USER->id; |
||
50 | $plugin = enrol_get_plugin('pagseguro'); |
||
51 | $email = $plugin->get_config('pagsegurobusiness'); |
||
52 | $token = $plugin->get_config('pagsegurotoken'); |
||
53 | |||
54 | $error_returnurl = $CFG->wwwroot.'/enrol/pagseguro/return.php'; |
||
55 | $success_returnurl = $CFG->wwwroot.'/enrol/pagseguro/return.php'; |
||
56 | |||
57 | $instanceid = optional_param('instanceid', 0, PARAM_INT); |
||
58 | |||
59 | $plugin_instance = $DB->get_record("enrol", array("id" => $instanceid, "status" => 0)); |
||
60 | $courseid = $plugin_instance->courseid; |
||
61 | $course = $DB->get_record('course', array('id' => $courseid)); |
||
62 | $currency = $plugin->get_config('currency'); |
||
63 | $encoding = 'UTF-8'; |
||
64 | $item_id = $courseid; |
||
65 | $item_desc = empty($course->fullname) ? null : $course->fullname; |
||
66 | $item_qty = (int)1; |
||
67 | $item_cost = empty($plugin_instance->cost) ? 0.00 : number_format($plugin_instance->cost, 2); |
||
68 | $item_cost = str_replace(',', '', $item_cost); |
||
69 | $item_amount = $item_cost; |
||
70 | |||
71 | $redirect_url = $CFG->wwwroot.'/enrol/pagseguro/process.php?instanceid='.$instanceid; |
||
72 | $submitValue = get_string("sendpaymentbutton", "enrol_pagseguro"); |
||
73 | |||
74 | $submited = optional_param('submitbutton', '', PARAM_RAW); |
||
75 | |||
76 | $notificationType = optional_param('notificationType', '', PARAM_RAW); |
||
77 | $notificationCode = optional_param('notificationCode', '', PARAM_RAW); |
||
78 | |||
79 | $transactionid = optional_param('transaction_id', '', PARAM_RAW); |
||
80 | |||
81 | if ($submited) { |
||
82 | $url = "https://ws.pagseguro.uol.com.br/v2/checkout/?email=" . urlencode($email) . "&token=" . $token; |
||
83 | |||
84 | $xml = "<?xml version=\"1.0\" encoding=\"$encoding\" standalone=\"yes\"?> |
||
85 | <checkout> |
||
86 | <currency>$currency</currency> |
||
87 | <redirectURL>$redirect_url</redirectURL> |
||
88 | <items> |
||
89 | <item> |
||
90 | <id>$item_id</id> |
||
91 | <description>$item_desc</description> |
||
92 | <amount>$item_amount</amount> |
||
93 | <quantity>$item_qty</quantity> |
||
94 | </item> |
||
95 | </items> |
||
96 | </checkout>"; |
||
97 | |||
98 | $curl = curl_init($url); |
||
99 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
||
100 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
||
101 | curl_setopt($curl, CURLOPT_HTTPHEADER, Array("Content-Type: application/xml; charset=UTF-8")); |
||
102 | curl_setopt($curl, CURLOPT_POSTFIELDS, trim($xml)); |
||
103 | $xml = curl_exec($curl); |
||
104 | |||
105 | curl_close($curl); |
||
106 | |||
107 | if ($xml == 'Unauthorized') { |
||
108 | // Error=1 Não autorizado. |
||
109 | $error_returnurl .= "?id={$courseid}&error=1"; |
||
110 | header("Location: $error_returnurl"); |
||
111 | exit; |
||
112 | } |
||
113 | |||
114 | $xml = simplexml_load_string($xml); |
||
115 | |||
116 | if (count($xml->error) > 0) { |
||
117 | $error_returnurl .= "?id={$courseid}&error=2"; |
||
118 | header("Location: $error_returnurl"); |
||
119 | exit; |
||
120 | } |
||
121 | |||
122 | header('Location: https://pagseguro.uol.com.br/v2/checkout/payment.html?code='.$xml->code); |
||
123 | } |
||
124 | |||
125 | // Here the user was redirected back from PagSeguro with transaction_id informed on GET. |
||
126 | if ($transactionid) { |
||
127 | $url = "https://ws.pagseguro.uol.com.br/v2/transactions/{$transactionid}?email={$email}&token={$token}"; |
||
128 | |||
129 | $curl = curl_init($url); |
||
130 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
||
131 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
||
132 | $transaction = curl_exec($curl); |
||
133 | curl_close($curl); |
||
134 | |||
135 | View Code Duplication | if ($transaction == 'Unauthorized'){ |
|
136 | // Error=1 Não autorizado. |
||
137 | $error_returnurl .= "?id={$courseid}&error=1"; |
||
138 | header("Location: $error_returnurl"); |
||
139 | exit;//Mantenha essa linha |
||
140 | } else { |
||
141 | $transaction_data = serialize(trim($transaction)); |
||
142 | process_moodle($transaction_data, $instanceid, $courseid); |
||
143 | } |
||
144 | |||
145 | } |
||
146 | |||
147 | // Here is old notification system the return from PagSeguro. |
||
148 | if (!empty($notificationCode)) { |
||
149 | $transaction = null; |
||
150 | // Sets the web service URL. |
||
151 | $url = "https://ws.pagseguro.uol.com.br/v2/transactions/notifications/" . $notificationCode . "?email=".$email."&token=".$token; |
||
152 | |||
153 | $curl = curl_init($url); |
||
154 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); |
||
155 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); |
||
156 | $transaction = curl_exec($curl); |
||
157 | curl_close($curl); |
||
158 | |||
159 | View Code Duplication | if ($transaction == 'Unauthorized'){ |
|
160 | // Error=1 Não autorizado. |
||
161 | $error_returnurl .= "?id={$courseid}&error=1"; |
||
162 | header("Location: $error_returnurl"); |
||
163 | exit;//Mantenha essa linha |
||
164 | } else { |
||
165 | $transaction_data = serialize(trim($transaction)); |
||
166 | process_moodle($transaction_data, $instanceid, $courseid); |
||
167 | } |
||
168 | } |
||
169 | |||
170 | function process_moodle($transaction_data, $instanceid, $cid) { |
||
171 | global $CFG,$USER,$DB,$course; |
||
0 ignored issues
–
show
|
|||
172 | |||
173 | /// Read all the data from pagseguro and get it ready for later; |
||
174 | /// we expect only valid UTF-8 encoding, it is the responsibility |
||
175 | /// of user to set it up properly in pagseguro business account, |
||
176 | /// it is documented in docs wiki. |
||
177 | |||
178 | $data = new stdClass(); |
||
179 | $a = new stdClass(); |
||
180 | |||
181 | $transaction = array(); |
||
182 | |||
183 | $plugin = enrol_get_plugin('pagseguro'); |
||
184 | |||
185 | $userid = (int) isset($USER->id) && !empty($USER->id) ? $USER->id : null; |
||
186 | $courseid = (int) isset($course->id) && !empty($course->id) ? $course->id : $cid; |
||
187 | |||
188 | $transaction_xml = unserialize($transaction_data); |
||
189 | $transaction = json_decode(json_encode(simplexml_load_string($transaction_xml))); |
||
190 | |||
191 | if($transaction) { |
||
192 | foreach ($transaction as $trans_key => $trans_value) { |
||
193 | $trans_key = strtolower($trans_key); |
||
194 | if(!is_object($trans_value)) { |
||
195 | $data->$trans_key = $trans_value; |
||
196 | } else { |
||
197 | foreach($trans_value as $key => $value) { |
||
198 | $key = strtolower($key); |
||
199 | if(is_object($value)) { |
||
200 | foreach($value as $k => $v) { |
||
201 | $k = strtolower($k); |
||
202 | $k = $trans_key.'_'.$key.'_'.$k; |
||
203 | $data->$k = $v; |
||
204 | } |
||
205 | } else { |
||
206 | $key = $trans_key.'_'.$key; |
||
207 | $data->$key = $value; |
||
208 | } |
||
209 | } |
||
210 | } |
||
211 | } |
||
212 | } else { |
||
213 | return false; |
||
214 | } |
||
215 | |||
216 | $data->xmlstring = trim(htmlentities($transaction_xml)); |
||
217 | $data->business = $plugin->get_config('pagsegurobusiness'); |
||
218 | $data->receiver_email = $plugin->get_config('pagsegurobusiness'); |
||
219 | $data->userid = $userid; |
||
220 | $data->courseid = $courseid; |
||
221 | $data->instanceid = $instanceid; |
||
222 | $data->timeupdated = time(); |
||
223 | |||
224 | if(!isset($data->reference) && empty($data->reference)) { |
||
225 | $data->reference = $plugin->get_config('pagsegurobusiness'); |
||
226 | } |
||
227 | |||
228 | // Get the user and course records. |
||
229 | |||
230 | if (!$user = $DB->get_record("user", array("id" => $data->userid))) { |
||
231 | message_pagseguro_error_to_admin("Not a valid user id", $data); |
||
232 | return false; |
||
233 | } |
||
234 | |||
235 | if (!$course = $DB->get_record("course", array("id" => $data->courseid))) { |
||
236 | message_pagseguro_error_to_admin("Not a valid course id", $data); |
||
237 | return false; |
||
238 | } |
||
239 | |||
240 | if (!$context = get_context_instance(CONTEXT_COURSE, $course->id)) { |
||
241 | message_pagseguro_error_to_admin("Not a valid context id", $data); |
||
242 | return false; |
||
243 | } |
||
244 | |||
245 | if (!$plugin_instance = $DB->get_record("enrol", array("id" => $data->instanceid, "status" => 0))) { |
||
246 | message_pagseguro_error_to_admin("Not a valid instance id", $data); |
||
247 | return false; |
||
248 | } |
||
249 | |||
250 | /* |
||
251 | Transaction Status - |
||
252 | -- Waiting for Payment - 1 |
||
253 | -- In analysis - 2 |
||
254 | -- PAID - 3 |
||
255 | -- Available - 4 |
||
256 | -- In dispute - 5 |
||
257 | -- Returned - 6 |
||
258 | -- Cancelled - 7 |
||
259 | */ |
||
260 | |||
261 | switch ($data->status) { |
||
262 | case COMMERCE_PAGSEGURO_STATUS_AWAITING: // Awaiting payment. |
||
263 | $data->payment_status = COMMERCE_PAYMENT_STATUS_PENDING; |
||
264 | break; |
||
265 | case COMMERCE_PAGSEGURO_STATUS_IN_ANALYSIS: // Payment in analysis. |
||
266 | $data->payment_status = COMMERCE_PAYMENT_STATUS_PENDING; |
||
267 | break; |
||
268 | case COMMERCE_PAGSEGURO_STATUS_PAID: // Paid. |
||
269 | $data->payment_status = COMMERCE_PAYMENT_STATUS_SUCCESS; |
||
270 | break; |
||
271 | case COMMERCE_PAGSEGURO_STATUS_AVAILABLE: // Available. |
||
272 | $data->payment_status = COMMERCE_PAYMENT_STATUS_SUCCESS; |
||
273 | break; |
||
274 | case COMMERCE_PAGSEGURO_STATUS_DISPUTED: // Payment disputed. |
||
275 | $data->payment_status = COMMERCE_PAYMENT_STATUS_FAILURE; |
||
276 | break; |
||
277 | case COMMERCE_PAGSEGURO_STATUS_REFUNDED: // Payment refunded. |
||
278 | $data->payment_status = COMMERCE_PAYMENT_STATUS_FAILURE; |
||
279 | break; |
||
280 | case COMMERCE_PAGSEGURO_STATUS_CANCELED: // Payment canceled. |
||
281 | $data->payment_status = COMMERCE_PAYMENT_STATUS_FAILURE; |
||
282 | break; |
||
283 | } |
||
284 | |||
285 | if (!in_array($data->status, array(COMMERCE_PAGSEGURO_STATUS_IN_ANALYSIS, COMMERCE_PAGSEGURO_STATUS_PAID, COMMERCE_PAGSEGURO_STATUS_AVAILABLE))) { |
||
286 | $plugin->unenrol_user($plugin_instance, $data->userid); |
||
287 | message_pagseguro_error_to_admin("Status not completed or pending. User unenrolled from course", $data); |
||
288 | $error_returnurl .= "?id={$courseid}&waiting=1"; |
||
289 | header("Location: $error_returnurl"); |
||
290 | } |
||
291 | |||
292 | /*if ($existing = $DB->get_record("enrol_pagseguro", array("txn_id" => $data->txn_id))) { // Make sure this transaction doesn't exist already |
||
293 | message_pagseguro_error_to_admin("Transaction $data->txn_id is being repeated!", $data); |
||
294 | return false; |
||
295 | }*/ |
||
296 | |||
297 | $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); |
||
298 | |||
299 | // Check that amount paid is the correct amount |
||
300 | if ( (float) $plugin_instance->cost <= 0 ) { |
||
301 | $cost = (float) $plugin->get_config('cost'); |
||
302 | } else { |
||
303 | $cost = (float) $plugin_instance->cost; |
||
304 | } |
||
305 | |||
306 | if ($data->grossamount < $cost) { |
||
307 | $cost = format_float($cost, 2); |
||
308 | message_pagseguro_error_to_admin("Amount paid is not enough ($data->payment_gross < $cost))", $data); |
||
309 | return false; |
||
310 | } |
||
311 | |||
312 | // All clear! |
||
313 | $DB->insert_record("enrol_pagseguro", $data); |
||
314 | |||
315 | if ($plugin_instance->enrolperiod) { |
||
316 | $timestart = time(); |
||
317 | $timeend = $timestart + $plugin_instance->enrolperiod; |
||
318 | } else { |
||
319 | $timestart = 0; |
||
320 | $timeend = 0; |
||
321 | } |
||
322 | |||
323 | // Enrol user |
||
324 | $plugin->enrol_user($plugin_instance, $userid, $plugin_instance->roleid, $timestart, $timeend); |
||
325 | |||
326 | // Pass $view=true to filter hidden caps if the user cannot see them |
||
327 | View Code Duplication | if ($users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC', |
|
328 | '', '', '', '', false, true)) { |
||
329 | $users = sort_by_roleassignment_authority($users, $context); |
||
330 | $teacher = array_shift($users); |
||
331 | } else { |
||
332 | $teacher = get_admin(); |
||
333 | } |
||
334 | |||
335 | $mailstudents = $plugin->get_config('mailstudents'); |
||
336 | $mailteachers = $plugin->get_config('mailteachers'); |
||
337 | $mailadmins = $plugin->get_config('mailadmins'); |
||
338 | $shortname = format_string($course->shortname, true, array('context' => $context)); |
||
339 | |||
340 | View Code Duplication | if (!empty($mailstudents)) { |
|
341 | $a->coursename = format_string($course->fullname, true, array('context' => $coursecontext)); |
||
342 | $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id"; |
||
343 | |||
344 | $eventdata = new stdClass(); |
||
345 | $eventdata->modulename = 'moodle'; |
||
346 | $eventdata->component = 'enrol_pagseguro'; |
||
347 | $eventdata->name = 'pagseguro_enrolment'; |
||
348 | $eventdata->userfrom = $teacher; |
||
349 | $eventdata->userto = $user; |
||
350 | $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); |
||
351 | $eventdata->fullmessage = get_string('welcometocoursetext', '', $a); |
||
352 | $eventdata->fullmessageformat = FORMAT_PLAIN; |
||
353 | $eventdata->fullmessagehtml = ''; |
||
354 | $eventdata->smallmessage = ''; |
||
355 | message_send($eventdata); |
||
356 | } |
||
357 | |||
358 | View Code Duplication | if (!empty($mailteachers)) { |
|
359 | $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); |
||
360 | $a->user = fullname($user); |
||
361 | |||
362 | $eventdata = new stdClass(); |
||
363 | $eventdata->modulename = 'moodle'; |
||
364 | $eventdata->component = 'enrol_pagseguro'; |
||
365 | $eventdata->name = 'pagseguro_enrolment'; |
||
366 | $eventdata->userfrom = $user; |
||
367 | $eventdata->userto = $teacher; |
||
368 | $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); |
||
369 | $eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a); |
||
370 | $eventdata->fullmessageformat = FORMAT_PLAIN; |
||
371 | $eventdata->fullmessagehtml = ''; |
||
372 | $eventdata->smallmessage = ''; |
||
373 | message_send($eventdata); |
||
374 | } |
||
375 | |||
376 | if (!empty($mailadmins)) { |
||
377 | $a->course = format_string($course->fullname, true, array('context' => $coursecontext)); |
||
378 | $a->user = fullname($user); |
||
379 | $admins = get_admins(); |
||
380 | foreach ($admins as $admin) { |
||
381 | $eventdata = new stdClass(); |
||
382 | $eventdata->modulename = 'moodle'; |
||
383 | $eventdata->component = 'enrol_pagseguro'; |
||
384 | $eventdata->name = 'pagseguro_enrolment'; |
||
385 | $eventdata->userfrom = $user; |
||
386 | $eventdata->userto = $admin; |
||
387 | $eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname); |
||
388 | $eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a); |
||
389 | $eventdata->fullmessageformat = FORMAT_PLAIN; |
||
390 | $eventdata->fullmessagehtml = ''; |
||
391 | $eventdata->smallmessage = ''; |
||
392 | |||
393 | message_send($eventdata); |
||
394 | } |
||
395 | } |
||
396 | |||
397 | $success_returnurl = $CFG->wwwroot.'/enrol/pagseguro/return.php?id='.$courseid; |
||
398 | header("Location: $success_returnurl"); |
||
399 | } |
||
400 | |||
401 | function message_pagseguro_error_to_admin($subject, $data) { |
||
402 | $admin = get_admin(); |
||
403 | $site = get_site(); |
||
404 | |||
405 | $message = "$site->fullname: Transaction failed.\n\n$subject\n\n"; |
||
406 | |||
407 | $message .= serialize($data); |
||
408 | |||
409 | $eventdata = new stdClass(); |
||
410 | $eventdata->modulename = 'moodle'; |
||
411 | $eventdata->component = 'enrol_pagseguro'; |
||
412 | $eventdata->name = 'pagseguro_enrolment'; |
||
413 | $eventdata->userfrom = $admin; |
||
414 | $eventdata->userto = $admin; |
||
415 | $eventdata->subject = "pagseguro ERROR: ".$subject; |
||
416 | $eventdata->fullmessage = $message; |
||
417 | $eventdata->fullmessageformat = FORMAT_PLAIN; |
||
418 | $eventdata->fullmessagehtml = ''; |
||
419 | $eventdata->smallmessage = ''; |
||
420 | message_send($eventdata); |
||
421 | } |
||
422 |
Instead of relying on
global
state, we recommend one of these alternatives:1. Pass all data via parameters
2. Create a class that maintains your state