These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This file is the file which all subscription gateways should call |
||
5 | * when a payment has been received - it sorts out the user status. |
||
6 | * |
||
7 | * @name ElkArte Forum |
||
8 | * @copyright ElkArte Forum contributors |
||
9 | * @license BSD http://opensource.org/licenses/BSD-3-Clause |
||
10 | * |
||
11 | * This file contains code covered by: |
||
12 | * copyright: 2011 Simple Machines (http://www.simplemachines.org) |
||
13 | * license: BSD, See included LICENSE.TXT for terms and conditions. |
||
14 | * |
||
15 | * @version 1.1.4 |
||
16 | * |
||
17 | */ |
||
18 | |||
19 | // Start things rolling by getting the forum alive... |
||
20 | if (!file_exists(dirname(__FILE__) . '/bootstrap.php')) |
||
21 | die('Unable to initialize'); |
||
22 | |||
23 | global $ssi_guest_access; |
||
24 | |||
25 | require_once(dirname(__FILE__) . '/bootstrap.php'); |
||
26 | $ssi_guest_access = true; |
||
27 | new Bootstrap(true); |
||
28 | |||
29 | global $txt, $modSettings, $context; |
||
30 | |||
31 | // Need lots of help |
||
32 | require_once(SUBSDIR . '/PaidSubscriptions.subs.php'); |
||
33 | require_once(SUBSDIR . '/Admin.subs.php'); |
||
34 | require_once(SUBSDIR . '/Members.subs.php'); |
||
35 | |||
36 | loadLanguage('ManagePaid'); |
||
37 | |||
38 | // If there's literally nothing coming in, let's take flight! |
||
39 | if (empty($_POST)) |
||
40 | { |
||
41 | header('Content-Type: text/html; charset=UTF-8'); |
||
42 | die($txt['paid_no_data']); |
||
43 | } |
||
44 | |||
45 | // I assume we're even active? |
||
46 | if (empty($modSettings['paid_enabled'])) |
||
47 | exit; |
||
48 | |||
49 | // If we have some custom people who find out about problems load them here. |
||
50 | $notify_users = array(); |
||
51 | if (!empty($modSettings['paid_email_to'])) |
||
52 | { |
||
53 | foreach (explode(',', $modSettings['paid_email_to']) as $email) |
||
54 | $notify_users[] = array( |
||
55 | 'email' => $email, |
||
56 | 'name' => $txt['who_member'], |
||
57 | 'id' => 0, |
||
58 | ); |
||
59 | } |
||
60 | |||
61 | $db = database(); |
||
62 | |||
63 | // We need to see whether we can find the correct payment gateway, |
||
64 | // Go through all our gateway scripts and find out if they are happy with what we have. |
||
65 | $txnType = ''; |
||
66 | $gatewayHandles = loadPaymentGateways(); |
||
67 | foreach ($gatewayHandles as $gateway) |
||
68 | { |
||
69 | $gatewayClass = new $gateway['payment_class'](); |
||
70 | if ($gatewayClass->isValid()) |
||
71 | { |
||
72 | $txnType = $gateway['code']; |
||
73 | break; |
||
74 | } |
||
75 | } |
||
76 | |||
77 | if (empty($txnType)) |
||
78 | generateSubscriptionError($txt['paid_unknown_transaction_type']); |
||
79 | |||
80 | // Get the subscription and member ID amongst others... |
||
81 | @list($subscription_id, $member_id) = $gatewayClass->precheck(); |
||
82 | |||
83 | // Integer these just in case. |
||
84 | $subscription_id = (int) $subscription_id; |
||
85 | $member_id = (int) $member_id; |
||
86 | |||
87 | // This would be bad... |
||
88 | if (empty($member_id)) |
||
89 | generateSubscriptionError($txt['paid_empty_member']); |
||
90 | |||
91 | // Verify the member. |
||
92 | $member_info = getBasicMemberData($member_id); |
||
93 | |||
94 | // Didn't find them? |
||
95 | if (empty($member_info)) |
||
96 | generateSubscriptionError(sprintf($txt['paid_could_not_find_member'], $member_id)); |
||
97 | |||
98 | // Get the subscription details. |
||
99 | $request = $db->query('', ' |
||
100 | SELECT cost, length, name |
||
101 | FROM {db_prefix}subscriptions |
||
102 | WHERE id_subscribe = {int:current_subscription}', |
||
103 | array( |
||
104 | 'current_subscription' => $subscription_id, |
||
105 | ) |
||
106 | ); |
||
107 | |||
108 | // Didn't find it? |
||
109 | if ($db->num_rows($request) === 0) |
||
110 | generateSubscriptionError(sprintf($txt['paid_count_not_find_subscription'], $member_id, $subscription_id)); |
||
111 | |||
112 | $subscription_info = $db->fetch_assoc($request); |
||
113 | $db->free_result($request); |
||
114 | |||
115 | // We wish to check the pending payments to make sure we are expecting this. |
||
116 | $request = $db->query('', ' |
||
117 | SELECT id_sublog, id_subscribe, payments_pending, pending_details, end_time |
||
118 | FROM {db_prefix}log_subscribed |
||
119 | WHERE id_subscribe = {int:current_subscription} |
||
120 | AND id_member = {int:current_member} |
||
121 | LIMIT 1', |
||
122 | array( |
||
123 | 'current_subscription' => $subscription_id, |
||
124 | 'current_member' => $member_id, |
||
125 | ) |
||
126 | ); |
||
127 | if ($db->num_rows($request) == 0) |
||
128 | generateSubscriptionError(sprintf($txt['paid_count_not_find_subscription_log'], $member_id, $subscription_id)); |
||
129 | $subscription_info += $db->fetch_assoc($request); |
||
130 | $db->free_result($request); |
||
131 | |||
132 | // Is this a refund? |
||
133 | if ($gatewayClass->isRefund()) |
||
134 | { |
||
135 | handleRefund($subscription_info, $member_id, $context['subscriptions'][$subscription_id]['num_length']); |
||
136 | |||
137 | // Receipt? |
||
138 | if (!empty($modSettings['paid_email']) && $modSettings['paid_email'] == 2) |
||
139 | { |
||
140 | $replacements = array( |
||
141 | 'NAME' => $subscription_info['name'], |
||
142 | 'REFUNDNAME' => $member_info['member_name'], |
||
143 | 'REFUNDUSER' => $member_info['real_name'], |
||
144 | 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member_id, |
||
145 | 'DATE' => standardTime(time(), false), |
||
146 | ); |
||
147 | |||
148 | emailAdmins('paid_subscription_refund', $replacements, $notify_users); |
||
149 | } |
||
150 | } |
||
151 | // Otherwise is it what we want, a purchase? |
||
152 | elseif ($gatewayClass->isPayment() || $gatewayClass->isSubscription()) |
||
153 | { |
||
154 | $cost = Util::unserialize($subscription_info['cost']); |
||
155 | $total_cost = $gatewayClass->getCost(); |
||
156 | $notify = false; |
||
157 | |||
158 | // For one off's we want to only capture them once! |
||
159 | if (!$gatewayClass->isSubscription()) |
||
160 | { |
||
161 | $real_details = Util::unserialize($subscription_info['pending_details']); |
||
162 | if (empty($real_details)) |
||
163 | generateSubscriptionError(sprintf($txt['paid_count_not_find_outstanding_payment'], $member_id, $subscription_id)); |
||
164 | |||
165 | // Now we just try to find anything pending. |
||
166 | // We don't really care which it is as security happens later. |
||
167 | foreach ($real_details as $id => $detail) |
||
168 | { |
||
169 | unset($real_details[$id]); |
||
170 | if ($detail[3] == 'payback' && $subscription_info['payments_pending']) |
||
171 | $subscription_info['payments_pending']--; |
||
172 | break; |
||
173 | } |
||
174 | |||
175 | $subscription_info['pending_details'] = empty($real_details) ? '' : serialize($real_details); |
||
176 | |||
177 | updateNonrecurrent($subscription_info); |
||
178 | } |
||
179 | |||
180 | // Is this flexible? |
||
181 | if ($subscription_info['length'] == 'F') |
||
182 | { |
||
183 | $found_duration = 0; |
||
184 | |||
185 | // This is a little harder, can we find the right duration? |
||
186 | foreach ($cost as $duration => $value) |
||
187 | { |
||
188 | if ($duration == 'fixed') |
||
189 | continue; |
||
190 | elseif ((float) $value == (float) $total_cost) |
||
191 | $found_duration = strtoupper(substr($duration, 0, 1)); |
||
192 | } |
||
193 | |||
194 | // If we have the duration then we're done. |
||
195 | if ($found_duration !== 0) |
||
196 | { |
||
197 | $notify = true; |
||
198 | addSubscription($subscription_id, $member_id, $found_duration); |
||
199 | } |
||
200 | } |
||
201 | else |
||
202 | { |
||
203 | $actual_cost = $cost['fixed']; |
||
204 | |||
205 | // It must be at least the right amount. |
||
206 | if ($total_cost != 0 && $total_cost >= $actual_cost) |
||
207 | { |
||
208 | // Add the subscription. |
||
209 | $notify = true; |
||
210 | addSubscription($subscription_id, $member_id); |
||
211 | } |
||
212 | } |
||
213 | |||
214 | // Send a receipt? |
||
215 | if (!empty($modSettings['paid_email']) && $modSettings['paid_email'] == 2 && $notify) |
||
216 | { |
||
217 | $replacements = array( |
||
218 | 'NAME' => $subscription_info['name'], |
||
219 | 'SUBNAME' => $member_info['member_name'], |
||
220 | 'SUBUSER' => $member_info['real_name'], |
||
221 | 'SUBEMAIL' => $member_info['email_address'], |
||
222 | 'PRICE' => sprintf($modSettings['paid_currency_symbol'], $total_cost), |
||
223 | 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member_id, |
||
224 | 'DATE' => standardTime(time(), false), |
||
225 | ); |
||
226 | |||
227 | emailAdmins('paid_subscription_new', $replacements, $notify_users); |
||
228 | } |
||
229 | } |
||
230 | // Maybe they're cancelling. This allows payment gateways to perform processing if needed |
||
231 | elseif ($gatewayClass->isCancellation()) |
||
232 | { |
||
233 | if (method_exists($gatewayClass, 'processCancelation')) |
||
234 | $gatewayClass->processCancelation($subscription_id, $member_id, $subscription_info); |
||
235 | } |
||
236 | else |
||
0 ignored issues
–
show
|
|||
237 | { |
||
238 | // Some other "valid" transaction such as: |
||
239 | // |
||
240 | // subscr_signup: This IPN response (txn_type) is sent only the first time the user signs up for a subscription. |
||
241 | // It then does not fire in any event later. This response is received somewhere before or after the first payment of |
||
242 | // subscription is received (txn_type=subscr_payment) which is what we do process |
||
243 | // |
||
244 | // Should we log any of these ... |
||
245 | } |
||
246 | |||
247 | // In case we have anything specific to do. |
||
248 | $gatewayClass->close(); |
||
249 | |||
250 | /** |
||
251 | * Log an error then exit |
||
252 | * |
||
253 | * @param string $text |
||
254 | * @throws \Elk_Exception |
||
255 | */ |
||
256 | function generateSubscriptionError($text) |
||
257 | { |
||
258 | global $modSettings, $notify_users; |
||
259 | |||
260 | // Send an email? |
||
261 | if (!empty($modSettings['paid_email'])) |
||
262 | { |
||
263 | $replacements = array( |
||
264 | 'ERROR' => $text, |
||
265 | ); |
||
266 | |||
267 | emailAdmins('paid_subscription_error', $replacements, $notify_users); |
||
268 | } |
||
269 | |||
270 | // Maybe we can try to give them the post data? |
||
271 | if (!empty($_POST)) |
||
272 | { |
||
273 | foreach ($_POST as $key => $val) |
||
274 | $text .= '<br />' . Util::htmlspecialchars($key) . ': ' . Util::htmlspecialchars($val); |
||
275 | } |
||
276 | |||
277 | // Then just log and die. |
||
278 | Errors::instance()->log_error($text); |
||
279 | |||
280 | exit; |
||
0 ignored issues
–
show
The function generateSubscriptionError() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
281 | } |
||
282 |
This check looks for the
else
branches ofif
statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.These
else
branches can be removed.could be turned into
This is much more concise to read.