1 | <?php |
||||
2 | /************************************************************************/ |
||||
3 | /* Donations - Paypal financial management module for Xoops 2 */ |
||||
4 | /* Copyright (c) 2016 XOOPS Project */ |
||||
5 | /* http://dev.xoops.org/modules/xfmod/project/?group_id=1060 */ |
||||
6 | /* |
||||
7 | /************************************************************************/ |
||||
8 | /* */ |
||||
9 | /* Based on NukeTreasury for PHP-Nuke - by Dave Lawrence AKA Thrash */ |
||||
10 | /* NukeTreasury - Financial management for PHP-Nuke */ |
||||
11 | /* Copyright (c) 2004 by Dave Lawrence AKA Thrash */ |
||||
12 | /* [email protected] */ |
||||
13 | /* [email protected] */ |
||||
14 | /* */ |
||||
15 | /************************************************************************/ |
||||
16 | /* */ |
||||
17 | /* This program is free software; you can redistribute it and/or modify */ |
||||
18 | /* it under the terms of the GNU General Public License as published by */ |
||||
19 | /* the Free Software Foundation; either version 2 of the License. */ |
||||
20 | /* */ |
||||
21 | /* This program is distributed in the hope that it will be useful, but */ |
||||
22 | /* WITHOUT ANY WARRANTY; without even the implied warranty of */ |
||||
23 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ |
||||
24 | /* General Public License for more details. */ |
||||
25 | /* */ |
||||
26 | /* You should have received a copy of the GNU General Public License */ |
||||
27 | /* along with this program; if not, write to the Free Software */ |
||||
28 | /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ |
||||
29 | /* USA */ |
||||
30 | /************************************************************************/ |
||||
31 | |||||
32 | //$xoopsOption['nocommon'] = 1; |
||||
33 | require_once __DIR__ . '/header.php'; |
||||
34 | require_once __DIR__ . '/class/Utility.php'; |
||||
35 | require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php'; |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
36 | |||||
37 | $tr_config = $utility::getConfigInfo(); |
||||
38 | $paypal_url = explode('|', $tr_config['paypal_url']); |
||||
39 | $paypal_url = $paypal_url[0]; |
||||
40 | //determine the currency |
||||
41 | $PP_CURR_CODE = explode('|', $tr_config['pp_curr_code']); // [USD,GBP,JPY,CAD,EUR] |
||||
42 | $PP_CURR_CODE = $PP_CURR_CODE[0]; |
||||
43 | $currencySign = $utility::defineCurrency($PP_CURR_CODE); |
||||
44 | |||||
45 | $pp_varlist = $utility::runSimpleQuery($xoopsDB->prefix('donations_transactions'), '', '', ['id']); |
||||
46 | |||||
47 | define('_ERR', 1); |
||||
48 | define('_INF', 2); |
||||
49 | $ERR = 0; |
||||
50 | $log = ''; |
||||
51 | $loglvl = $tr_config['ipn_dbg_lvl']; |
||||
52 | |||||
53 | // creates a log file in the XOOPS uploads directory |
||||
54 | $lpFile = XOOPS_UPLOAD_PATH . '/xdonations_ipn.log'; |
||||
0 ignored issues
–
show
|
|||||
55 | if (false !== ($lp = fopen($lpFile, 'wb+'))) { |
||||
56 | dprt(_MD_XDONATION_LOGFILE_CREATED, _INF); |
||||
57 | } else { |
||||
58 | dprt(_MD_XDONATION_LOGFILE_NOT_CREATED, _ERR); |
||||
59 | } |
||||
60 | dprt(date('r'), _INF); |
||||
61 | $dbg = (isset($_GET['dbg']) && $_GET['dbg']); |
||||
62 | |||||
63 | if ($dbg) { |
||||
64 | dprt(_MD_XDONATION_DEBUGACTIVE, _INF); |
||||
65 | echo _MD_XDONATION_DEBUGHEADER; |
||||
66 | $pp_varlist['receiver_email'] = $tr_config['receiver_email']; |
||||
67 | } |
||||
68 | |||||
69 | // read the post from PayPal system and add 'cmd' |
||||
70 | $req = 'cmd=_notify-validate'; |
||||
71 | |||||
72 | foreach ($_POST as $key => $value) { |
||||
73 | $value = urlencode(stripslashes($value)); |
||||
74 | $req .= "&$key=$value"; |
||||
75 | } |
||||
76 | |||||
77 | // post back to PayPal system to validate |
||||
78 | dprt(_MD_XDONATION_OPENCONN, _INF); |
||||
79 | $fp = fsockopen($paypal_url, 80, $errno, $errstr, 30); |
||||
80 | |||||
81 | if (!$fp) { // HTTP ERROR |
||||
0 ignored issues
–
show
|
|||||
82 | //TODO: use CURL if fsockopen fails |
||||
83 | dprt('<style="color: #00CC00;">' . _MD_XDONATION_CONNFAIL . '</span>', _ERR); |
||||
84 | die(sprintf(_MD_XDONATION_POSTBACK_FAIL, $errno, $errstr)); |
||||
85 | } else { |
||||
86 | dprt(_MD_XDONATION_POSTBACK_OK, _INF); |
||||
87 | $header = "POST /cgi-bin/webscr HTTP/1.0\r\n"; |
||||
88 | $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; |
||||
89 | $header .= 'Content-Length: ' . strlen($req) . "\r\n\r\n"; |
||||
90 | } |
||||
91 | |||||
92 | // assign posted variables to local variables |
||||
93 | $pp_varname = array_values(array_intersect(array_keys($pp_varlist), array_keys($_POST))); |
||||
94 | for ($i = 0, $iMax = count($pp_varname); $i < $iMax; ++$i) { |
||||
95 | $pp_varlist[$pp_varname[$i]] = $_POST[$pp_varname[$i]]; |
||||
96 | } |
||||
97 | |||||
98 | if ('' == $pp_varlist['payment_date']) { //set blank date to proper format |
||||
99 | $pp_varlist['payment_date'] = '0000-00-00 00:00:00'; |
||||
100 | } |
||||
101 | |||||
102 | $writeOk = fwrite($fp, $header . $req); |
||||
103 | if (!$writeOk) { // HTTP ERROR |
||||
104 | dprt('<style="font-weight: bold; color: #00CC00;">' . _MD_XDONATION_WRITEFAIL . '</span>', _ERR); |
||||
105 | die(sprintf(_MD_XDONATION_ERR_FAILED_WRITE, $errno, $errstr)); |
||||
106 | } else { |
||||
107 | dprt(_MD_XDONATION_WRITEOK, _INF); |
||||
108 | } |
||||
109 | |||||
110 | // Perform PayPal email account verification |
||||
111 | if (!$dbg && (0 != strcasecmp($pp_varlist['business'], $tr_config['receiver_email']))) { |
||||
112 | dprt(sprintf(_MD_XDONATION_BUSINVALID, $pp_varlist['business']), _ERR); |
||||
113 | dprt(sprintf(_MD_XDONATION_RCVINVALID, $pp_varlist['receiver_email']), _ERR); |
||||
114 | $ERR = 1; |
||||
115 | } |
||||
116 | |||||
117 | $insertSQL = ''; |
||||
118 | // Look for duplicate txn_id's |
||||
119 | if ($pp_varlist['txn_id']) { |
||||
120 | $sql = 'SELECT COUNT(*) FROM ' . $xoopsDB->prefix('donations_transactions') . " WHERE txn_id = '" . addslashes($pp_varlist['txn_id']) . "'"; |
||||
121 | $Recordset1 = $xoopsDB->query($sql); |
||||
122 | list($NumDups) = $xoopsDB->fetchRow($Recordset1); |
||||
123 | } |
||||
124 | if ($pp_varlist['parent_txn_id']) { |
||||
125 | $parent_sql = 'SELECT * FROM ' . $xoopsDB->prefix('donations_transactions') . " WHERE txn_id = '" . addslashes($pp_varlist['parent_txn_id']) . "'"; |
||||
126 | $parent_Recordset1 = $xoopsDB->query($parent_sql); |
||||
127 | $parent_row_Recordset1 = $xoopsDB->fetchArray($parent_Recordset1); |
||||
128 | $parent_NumDups = $xoopsDB->getRowsNum($parent_Recordset1); |
||||
129 | } |
||||
130 | |||||
131 | while (!$dbg && !$ERR && !feof($fp)) { |
||||
132 | $res = fgets($fp, 1024); |
||||
133 | if (0 == strcmp($res, 'VERIFIED')) { |
||||
134 | // Ok - PayPal has told us we have a valid IPN here |
||||
135 | dprt(_MD_XDONATION_VERIFIED, _INF); |
||||
136 | |||||
137 | // Check for a reversal for a refund |
||||
138 | if (0 == strcmp($pp_varlist['payment_status'], 'Refunded') |
||||
139 | || 0 == strcmp($pp_varlist['txn_type'], 'Reversal')) { |
||||
140 | // Verify the reversal |
||||
141 | dprt(_MD_XDONATION_REFUND, _INF); |
||||
142 | if ((0 == $parent_NumDups) || strcmp($parent_row_Recordset1['payment_status'], 'Completed') |
||||
143 | || (0 != strcmp($parent_row_Recordset1['txn_type'], 'web_accept') |
||||
144 | && 0 != strcmp($parent_row_Recordset1['txn_type'], 'send_money'))) { |
||||
145 | // This is an error. A reversal implies a pre-existing completed transaction |
||||
146 | dprt(_MD_XDONATION_TRANSMISSING, _ERR); |
||||
147 | foreach ($_POST as $key => $val) { |
||||
148 | dprt("$key => $val", _ERR); |
||||
149 | } |
||||
150 | break; |
||||
151 | } |
||||
152 | if (1 != $parent_NumDups) { |
||||
153 | dprt(_MD_XDONATION_MULTITXNS, _ERR); |
||||
154 | foreach ($_POST as $key => $val) { |
||||
155 | dprt("$key => $val", _ERR); |
||||
156 | } |
||||
157 | break; |
||||
158 | } |
||||
159 | |||||
160 | /* TODO: Need to add info to database. If user donates, then cancels a subsequent |
||||
161 | * donation then they are removed from group - need a counter to see how many times a |
||||
162 | * user has donated and only remove from group if 'everything' donated has been reversed. |
||||
163 | */ |
||||
164 | |||||
165 | // remove xoopsUsers (not anon) from group selected by Admin in config |
||||
166 | if (!empty($pp_varlist['custom'])) { |
||||
167 | $memberHandler = xoops_getHandler('member'); |
||||
0 ignored issues
–
show
The function
xoops_getHandler was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
168 | $edituser = $memberHandler->getUser($pp_varlist['custom']); |
||||
169 | |||||
170 | // remove the user from the specified group |
||||
171 | if ($tr_config['assign_group']) { // admin has selected a group in admin |
||||
172 | $groupHandler = xoops_getHandler('group'); |
||||
173 | $validGroup = $groupHandler->get((int)$tr_config['assign_group']); // make sure this is a valid group id |
||||
174 | if ($validGroup) { |
||||
175 | $thisUserGroups = $memberHandler->getGroupsByUser((int)$edituser->getVar('uid')); |
||||
176 | if (!in_array($validGroup->getVar('groupid'), $thisUserGroups)) { |
||||
177 | |||||
178 | // now find out if user is in the group |
||||
179 | $isMember = $memberHandler->getGroupsByUser($edituser->getVar('uid')); |
||||
180 | if ($isMember) { |
||||
181 | $success = $memberHandler->removeUserFromGroup($tr_config['assign_group'], $edituser->getVar('uid')); |
||||
182 | if ($success) { |
||||
183 | dprt('User ' . $edituser->getVar('uname') . ' was removed from the ' . $validGroup->getVar('name') . ' group', _INF); |
||||
184 | } else { |
||||
185 | dprt('User ' . $edituser->getVar('uname') . ' could not be removed from the ' . $validGroup->getVar('name') . ' group', _ERR); |
||||
186 | } |
||||
187 | } |
||||
188 | } else { |
||||
189 | dprt($edituser->getVar('uname') . ' was not in the ' . $validGroup->getVar('name') . ' group', _INF); |
||||
190 | } |
||||
191 | } else { |
||||
192 | dprt('Group isn\'t valid - change Admin configs option<br>', _ERR); |
||||
193 | } |
||||
194 | } |
||||
195 | /* |
||||
196 | * TODO: Need to add a db table variable to 'demote' the user's rank back to where |
||||
197 | * it was prior to the reversal |
||||
198 | */ |
||||
199 | } |
||||
200 | $pp_varlist['payment_date'] = strftime('%Y-%m-%d %H:%M:%S', strtotime($pp_varlist['payment_date'])); |
||||
201 | $field_values = $field_names = ''; |
||||
202 | for ($i = 0, $iMax = count($pp_varname); $i < $iMax; ++$i) { |
||||
203 | if (0 != $i) { |
||||
204 | $field_names .= ','; |
||||
205 | $field_values .= ','; |
||||
206 | } |
||||
207 | $field_names .= '`' . $pp_varname[$i] . '`'; |
||||
208 | $field_values .= "'" . $pp_varlist[$pp_varname[$i]] . "'"; |
||||
209 | } |
||||
210 | $insertSQL = 'INSERT INTO ' . $xoopsDB->prefix('donations_transactions') . " ($field_names) VALUES ($field_values)"; |
||||
211 | |||||
212 | // We're cleared to add this record |
||||
213 | dprt($insertSQL, _INF); |
||||
214 | $Result1 = $xoopsDB->queryF($insertSQL); |
||||
215 | dprt('SQL result = ' . $Result1, _INF); |
||||
216 | |||||
217 | break; |
||||
218 | // Look for a normal payment |
||||
219 | } elseif ((0 == strcmp($pp_varlist['payment_status'], 'Completed')) |
||||
220 | && ((0 == strcmp($pp_varlist['txn_type'], 'web_accept')) |
||||
221 | || (0 == strcmp($pp_varlist['txn_type'], 'send_money')))) { |
||||
222 | dprt(_MD_XDONATION_NORMAL_TXN, _INF); |
||||
223 | if ($lp) { |
||||
224 | fwrite($lp, $pp_varlist['payer_email'] . ' ' . $pp_varlist['payment_status'] . ' ' . $pp_varlist['payment_date'] . "\n"); |
||||
225 | } |
||||
226 | |||||
227 | if (0 != $NumDups) { // Check for a duplicate txn_id |
||||
228 | dprt(_MD_XDONATION_DUPLICATETXN, _ERR); |
||||
229 | foreach ($_POST as $key => $val) { |
||||
230 | dprt("$key => $val", _ERR); |
||||
231 | } |
||||
232 | break; |
||||
233 | } |
||||
234 | |||||
235 | $pp_varlist['payment_date'] = strftime('%Y-%m-%d %H:%M:%S', strtotime($pp_varlist['payment_date'])); |
||||
236 | $field_values = $field_names = ''; |
||||
237 | for ($i = 0, $iMax = count($pp_varname); $i < $iMax; ++$i) { |
||||
238 | if (0 != $i) { |
||||
239 | $field_names .= ','; |
||||
240 | $field_values .= ','; |
||||
241 | } |
||||
242 | $field_names .= '`' . $pp_varname[$i] . '`'; |
||||
243 | $field_values .= "'" . $pp_varlist[$pp_varname[$i]] . "'"; |
||||
244 | } |
||||
245 | $insertSQL = 'INSERT INTO ' . $xoopsDB->prefix('donations_transactions') . " ($field_names) VALUES ($field_values)"; |
||||
246 | |||||
247 | // We're cleared to add this record |
||||
248 | dprt($insertSQL, _INF); |
||||
249 | $Result1 = $xoopsDB->queryF($insertSQL); |
||||
250 | dprt('SQL result = ' . $Result1, _INF); |
||||
251 | |||||
252 | // add xoopsUsers (not anon) to group if selected by Admin in config |
||||
253 | if (!empty($pp_varlist['custom']) |
||||
254 | && (('Yes' === $pp_varlist['option_selection1']) |
||||
255 | || ('1' == $tr_config['don_forceadd']))) { |
||||
256 | $memberHandler = xoops_getHandler('member'); |
||||
257 | $edituser = $memberHandler->getUser($pp_varlist['custom']); |
||||
258 | |||||
259 | // add the user to specified group |
||||
260 | if ($tr_config['assign_group']) { // config option set to add users to a group |
||||
261 | $groupHandler = xoops_getHandler('group'); |
||||
262 | $validGroup = $groupHandler->get((int)$tr_config['assign_group']); // make sure this is a valid group id |
||||
263 | if ($validGroup) { |
||||
264 | $thisUserGroups = $memberHandler->getGroupsByUser((int)$edituser->getVar('uid')); |
||||
265 | if (!in_array($validGroup->getVar('groupid'), $thisUserGroups)) { |
||||
266 | $success = $memberHandler->addUserToGroup($validGroup->getVar('groupid'), $edituser->getVar('uid')); |
||||
267 | if ($success) { |
||||
268 | dprt('User ' . $edituser->getVar('uname') . ' was added to the ' . $validGroup->getVar('name') . ' group', _INF); |
||||
269 | } else { |
||||
270 | dprt('User ' . $edituser->getVar('uname') . ' could not be addded to the ' . $validGroup->getVar('name') . ' group', _ERR); |
||||
271 | } |
||||
272 | } else { |
||||
273 | dprt($edituser->getVar('uname') . ' is already in the ' . $validGroup->getVar('name') . ' group', _INF); |
||||
274 | } |
||||
275 | } else { |
||||
276 | dprt('Group isn\'t valid - change Admin configs option<br>', _ERR); |
||||
277 | } |
||||
278 | } |
||||
279 | |||||
280 | // add the user to a specific rank |
||||
281 | if ($tr_config['assign_rank']) { // config option set to add users to a rank |
||||
282 | $urank = $edituser->rank(); |
||||
283 | if (0 != $urank['id']) { |
||||
284 | $result = $xoopsDB->query('SELECT COUNT(*) FROM ' . $xoopsDB->prefix('ranks') . " WHERE rank_id='" . $urank['id'] . "' AND rank_special=0"); |
||||
285 | list($rank_check) = $xoopsDB->fetchRow($result); |
||||
286 | $xoopsDB->freeRecordSet($result); |
||||
287 | } else { |
||||
288 | $rank_check = 1; |
||||
289 | } |
||||
290 | if ($rank_check > 0) { |
||||
291 | // set user's new rank |
||||
292 | $edituser->setVar('rank', $tr_config['assign_rank']); |
||||
293 | $memberHandler->insertUser($edituser); |
||||
294 | } |
||||
295 | } |
||||
296 | } |
||||
297 | break; |
||||
298 | } else { // We're not interested in this transaction, so we're done |
||||
299 | dprt(_MD_XDONATION_NOTINTERESTED, _ERR); |
||||
300 | foreach ($_POST as $key => $val) { |
||||
301 | dprt("$key => $val", _ERR); |
||||
302 | } |
||||
303 | dprt('pp_varlist:', _ERR); |
||||
304 | foreach ($pp_varlist as $key => $val) { |
||||
305 | dprt("$key => $val", _ERR); |
||||
306 | } |
||||
307 | dprt('strcmp payment_status: ' . strcmp($pp_varlist['payment_status'], 'Completed'), _ERR); |
||||
308 | dprt('strcmp txn_type: ' . strcmp($pp_varlist['txn_type'], 'web_accept'), _ERR); |
||||
309 | dprt('strcmp txn_type: ' . strcmp($pp_varlist['txn_type'], 'send_money'), _ERR); |
||||
310 | break; |
||||
311 | } |
||||
312 | } elseif (0 == strcmp($res, 'INVALID')) { |
||||
313 | // log for manual investigation |
||||
314 | dprt(_MD_XDONATION_INVALIDIPN, _ERR); |
||||
315 | foreach ($_POST as $key => $val) { |
||||
316 | dprt("$key => $val", _ERR); |
||||
317 | } |
||||
318 | break; |
||||
319 | } else { |
||||
320 | dprt(_MD_XDONATION_ERR_UNKNOWN_IPN_STAT, _ERR); |
||||
321 | } |
||||
322 | } |
||||
323 | |||||
324 | if ($dbg) { |
||||
325 | $sql = 'SELECT * FROM ' . $xoopsDB->prefix('donations_transactions') . ' LIMIT 10'; |
||||
326 | dprt(_MD_XDONATION_EXECUTING_QUERY, _INF); |
||||
327 | $Result1 = $xoopsDB->query($sql); |
||||
328 | if ($Result1) { |
||||
329 | dprt('<span style="font-weight: bold; color: #00CC00;">' . _MD_XDONATION_DEBUGPASS . '</span>', _INF); |
||||
330 | } else { |
||||
331 | dprt('<span style="font-weight: bold; color: #CC0000;">' . _MD_XDONATION_DEBUGFAIL . '</span>', _ERR); |
||||
332 | } |
||||
333 | dprt(sprintf(_MD_XDONATION_RCVEMAIL, $tr_config['receiver_email']), _INF); |
||||
334 | } |
||||
335 | |||||
336 | if ($log) { |
||||
337 | dprt('<br>' . _MD_XDONATION_LOGBEGIN . "<br>\n", _INF); |
||||
338 | // Insert the log entry |
||||
339 | $currentDate = strftime('%Y-%m-%d %H:%M:%S', time()); |
||||
340 | $paymentDate = isset($_POST['payment_date']) ? strftime('%Y-%m-%d %H:%M:%S', strtotime($_POST['payment_date'])) : $currentDate; |
||||
341 | $sql = 'INSERT INTO ' . $xoopsDB->prefix('donations_translog') . " VALUES (NULL,'{$currentDate}', '{$paymentDate}','" . addslashes($log) . "')"; |
||||
342 | $Result1 = $xoopsDB->queryF($sql); |
||||
343 | |||||
344 | // Clear out old log entries |
||||
345 | $sql = 'SELECT COUNT(*) FROM ' . $xoopsDB->prefix('donations_translog'); |
||||
346 | $Result1 = $xoopsDB->query($sql); |
||||
347 | list($countLogs) = $xoopsDB->fetchRow($Result1); |
||||
348 | if ($countLogs == $tr_config['ipn_log_entries']) { |
||||
349 | $sql = 'DELETE FROM ' . $xoopsDB->prefix('donations_translog'); |
||||
350 | $Result1 = $xoopsDB->queryF($sql); |
||||
351 | if (false === $Result1) { |
||||
352 | dprt(_MD_XDONATION_ERR_TXN_NOCLEAR, _ERR); |
||||
353 | } else { |
||||
354 | dprt(_MD_XDONATION_ERR_TXN_CLEAR, _INF); |
||||
355 | } |
||||
356 | } |
||||
357 | } |
||||
358 | |||||
359 | fclose($fp); |
||||
360 | if ($lp) { |
||||
361 | fwrite($lp, _MD_XDONATION_EXITING . "\n"); |
||||
362 | fclose($lp); |
||||
363 | } |
||||
364 | |||||
365 | if ($dbg) { |
||||
366 | echo '<hr>'; |
||||
367 | echo _MD_XDONATION_IFNOERROR . "<br>\n"; |
||||
368 | echo "<a href='javascript:window.close();'>Close Window</a>"; |
||||
369 | } |
||||
370 | |||||
371 | /** |
||||
372 | * |
||||
373 | * Debug Message Store/Display |
||||
374 | * @param string $str string to store/display |
||||
375 | * @param int $clvl error reporting level (1 = error, 2= info) |
||||
376 | */ |
||||
377 | function dprt($str, $clvl) |
||||
378 | { |
||||
379 | global $dbg, $lp, $log, $loglvl; |
||||
380 | |||||
381 | if (isset($dbg) && $dbg) { |
||||
382 | echo $str . '<br>'; |
||||
383 | } |
||||
384 | |||||
385 | if (isset($loglvl) && ($clvl <= $loglvl)) { |
||||
386 | $log .= $str . "\n"; |
||||
387 | if (isset($lp) && $lp) { |
||||
388 | fwrite($lp, strip_tags($str) . "\r\n"); |
||||
389 | } |
||||
390 | } |
||||
391 | } |
||||
392 |