Chris@76
|
1 <?php
|
Chris@76
|
2
|
Chris@76
|
3 /**
|
Chris@76
|
4 * Simple Machines Forum (SMF)
|
Chris@76
|
5 *
|
Chris@76
|
6 * @package SMF
|
Chris@76
|
7 * @author Simple Machines http://www.simplemachines.org
|
Chris@76
|
8 * @copyright 2011 Simple Machines
|
Chris@76
|
9 * @license http://www.simplemachines.org/about/smf/license.php BSD
|
Chris@76
|
10 *
|
Chris@76
|
11 * @version 2.0.2
|
Chris@76
|
12 */
|
Chris@76
|
13
|
Chris@76
|
14 /*
|
Chris@76
|
15 This file is the file which all subscription gateways should call
|
Chris@76
|
16 when a payment has been received - it sorts out the user status.
|
Chris@76
|
17
|
Chris@76
|
18 void generateSubscriptionError()
|
Chris@76
|
19 // log the error for posterity
|
Chris@76
|
20 */
|
Chris@76
|
21
|
Chris@76
|
22 // Start things rolling by getting SMF alive...
|
Chris@76
|
23 $ssi_guest_access = true;
|
Chris@76
|
24 if (!file_exists(dirname(__FILE__) . '/SSI.php'))
|
Chris@76
|
25 die('Cannot find SSI.php');
|
Chris@76
|
26
|
Chris@76
|
27 require_once(dirname(__FILE__) . '/SSI.php');
|
Chris@76
|
28 require_once($sourcedir . '/ManagePaid.php');
|
Chris@76
|
29
|
Chris@76
|
30 // For any admin emailing.
|
Chris@76
|
31 require_once($sourcedir . '/Subs-Admin.php');
|
Chris@76
|
32
|
Chris@76
|
33 loadLanguage('ManagePaid');
|
Chris@76
|
34
|
Chris@76
|
35 // If there's literally nothing coming in, let's take flight!
|
Chris@76
|
36 if (empty($_POST))
|
Chris@76
|
37 die($txt['paid_no_data']);
|
Chris@76
|
38
|
Chris@76
|
39 // I assume we're even active?
|
Chris@76
|
40 if (empty($modSettings['paid_enabled']))
|
Chris@76
|
41 exit;
|
Chris@76
|
42
|
Chris@76
|
43 // If we have some custom people who find out about problems load them here.
|
Chris@76
|
44 $notify_users = array();
|
Chris@76
|
45 if (!empty($modSettings['paid_email_to']))
|
Chris@76
|
46 foreach (explode(',', $modSettings['paid_email_to']) as $email)
|
Chris@76
|
47 $notify_users[] = array(
|
Chris@76
|
48 'email' => $email,
|
Chris@76
|
49 'name' => $txt['who_member'],
|
Chris@76
|
50 'id' => 0,
|
Chris@76
|
51 );
|
Chris@76
|
52
|
Chris@76
|
53 // We need to see whether we can find the correct payment gateway,
|
Chris@76
|
54 // we'll going to go through all our gateway scripts and find out
|
Chris@76
|
55 // if they are happy with what we have.
|
Chris@76
|
56 $txnType = '';
|
Chris@76
|
57 $gatewayHandles = loadPaymentGateways();
|
Chris@76
|
58 foreach ($gatewayHandles as $gateway)
|
Chris@76
|
59 {
|
Chris@76
|
60 $gatewayClass = new $gateway['payment_class']();
|
Chris@76
|
61 if ($gatewayClass->isValid())
|
Chris@76
|
62 {
|
Chris@76
|
63 $txnType = $gateway['code'];
|
Chris@76
|
64 break;
|
Chris@76
|
65 }
|
Chris@76
|
66 }
|
Chris@76
|
67
|
Chris@76
|
68 if (empty($txnType))
|
Chris@76
|
69 generateSubscriptionError($txt['paid_unknown_transaction_type']);
|
Chris@76
|
70
|
Chris@76
|
71 // Get the subscription and member ID amoungst others...
|
Chris@76
|
72 @list ($subscription_id, $member_id) = $gatewayClass->precheck();
|
Chris@76
|
73
|
Chris@76
|
74 // Integer these just in case.
|
Chris@76
|
75 $subscription_id = (int) $subscription_id;
|
Chris@76
|
76 $member_id = (int) $member_id;
|
Chris@76
|
77
|
Chris@76
|
78 // This would be bad...
|
Chris@76
|
79 if (empty($member_id))
|
Chris@76
|
80 generateSubscriptionError($txt['paid_empty_member']);
|
Chris@76
|
81
|
Chris@76
|
82 // Verify the member.
|
Chris@76
|
83 $request = $smcFunc['db_query']('', '
|
Chris@76
|
84 SELECT id_member, member_name, real_name, email_address
|
Chris@76
|
85 FROM {db_prefix}members
|
Chris@76
|
86 WHERE id_member = {int:current_member}',
|
Chris@76
|
87 array(
|
Chris@76
|
88 'current_member' => $member_id,
|
Chris@76
|
89 )
|
Chris@76
|
90 );
|
Chris@76
|
91 // Didn't find them?
|
Chris@76
|
92 if ($smcFunc['db_num_rows']($request) == 0)
|
Chris@76
|
93 generateSubscriptionError(sprintf($txt['paid_could_not_find_member'], $member_id));
|
Chris@76
|
94 $member_info = $smcFunc['db_fetch_assoc']($request);
|
Chris@76
|
95 $smcFunc['db_free_result']($request);
|
Chris@76
|
96
|
Chris@76
|
97 // Get the subscription details.
|
Chris@76
|
98 $request = $smcFunc['db_query']('', '
|
Chris@76
|
99 SELECT cost, length, name
|
Chris@76
|
100 FROM {db_prefix}subscriptions
|
Chris@76
|
101 WHERE id_subscribe = {int:current_subscription}',
|
Chris@76
|
102 array(
|
Chris@76
|
103 'current_subscription' => $subscription_id,
|
Chris@76
|
104 )
|
Chris@76
|
105 );
|
Chris@76
|
106
|
Chris@76
|
107 // Didn't find it?
|
Chris@76
|
108 if ($smcFunc['db_num_rows']($request) == 0)
|
Chris@76
|
109 generateSubscriptionError(sprintf($txt['paid_count_not_find_subscription'], $member_id, $subscription_id));
|
Chris@76
|
110
|
Chris@76
|
111 $subscription_info = $smcFunc['db_fetch_assoc']($request);
|
Chris@76
|
112 $smcFunc['db_free_result']($request);
|
Chris@76
|
113
|
Chris@76
|
114 // We wish to check the pending payments to make sure we are expecting this.
|
Chris@76
|
115 $request = $smcFunc['db_query']('', '
|
Chris@76
|
116 SELECT id_sublog, payments_pending, pending_details, end_time
|
Chris@76
|
117 FROM {db_prefix}log_subscribed
|
Chris@76
|
118 WHERE id_subscribe = {int:current_subscription}
|
Chris@76
|
119 AND id_member = {int:current_member}
|
Chris@76
|
120 LIMIT 1',
|
Chris@76
|
121 array(
|
Chris@76
|
122 'current_subscription' => $subscription_id,
|
Chris@76
|
123 'current_member' => $member_id,
|
Chris@76
|
124 )
|
Chris@76
|
125 );
|
Chris@76
|
126 if ($smcFunc['db_num_rows']($request) == 0)
|
Chris@76
|
127 generateSubscriptionError(sprintf($txt['paid_count_not_find_subscription_log'], $member_id, $subscription_id));
|
Chris@76
|
128 $subscription_info += $smcFunc['db_fetch_assoc']($request);
|
Chris@76
|
129 $smcFunc['db_free_result']($request);
|
Chris@76
|
130
|
Chris@76
|
131 // Is this a refund etc?
|
Chris@76
|
132 if ($gatewayClass->isRefund())
|
Chris@76
|
133 {
|
Chris@76
|
134 // If the end time subtracted by current time, is not greater
|
Chris@76
|
135 // than the duration (ie length of subscription), then we close it.
|
Chris@76
|
136 if ($subscription_info['end_time'] - time() < $subscription_info['length'])
|
Chris@76
|
137 {
|
Chris@76
|
138 // Delete user subscription.
|
Chris@76
|
139 removeSubscription($subscription_id, $member_id);
|
Chris@76
|
140 $subscription_act = time();
|
Chris@76
|
141 $status = 0;
|
Chris@76
|
142 }
|
Chris@76
|
143 else
|
Chris@76
|
144 {
|
Chris@76
|
145 loadSubscriptions();
|
Chris@76
|
146 $subscription_act = $subscription_info['end_time'] - $context['subscriptions'][$subscription_id]['num_length'];
|
Chris@76
|
147 $status = 1;
|
Chris@76
|
148 }
|
Chris@76
|
149
|
Chris@76
|
150 // Mark it as complete so we have a record.
|
Chris@76
|
151 $smcFunc['db_query']('', '
|
Chris@76
|
152 UPDATE {db_prefix}log_subscribed
|
Chris@76
|
153 SET end_time = {int:current_time}
|
Chris@76
|
154 WHERE id_subscribe = {int:current_subscription}
|
Chris@76
|
155 AND id_member = {int:current_member}
|
Chris@76
|
156 AND status = {int:status}',
|
Chris@76
|
157 array(
|
Chris@76
|
158 'current_time' => $subscription_act,
|
Chris@76
|
159 'current_subscription' => $subscription_id,
|
Chris@76
|
160 'current_member' => $member_id,
|
Chris@76
|
161 'status' => $status,
|
Chris@76
|
162 )
|
Chris@76
|
163 );
|
Chris@76
|
164
|
Chris@76
|
165 // Receipt?
|
Chris@76
|
166 if (!empty($modSettings['paid_email']) && $modSettings['paid_email'] == 2)
|
Chris@76
|
167 {
|
Chris@76
|
168 $replacements = array(
|
Chris@76
|
169 'NAME' => $subscription_info['name'],
|
Chris@76
|
170 'REFUNDNAME' => $member_info['member_name'],
|
Chris@76
|
171 'REFUNDUSER' => $member_info['real_name'],
|
Chris@76
|
172 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member_id,
|
Chris@76
|
173 'DATE' => timeformat(time(), false),
|
Chris@76
|
174 );
|
Chris@76
|
175
|
Chris@76
|
176 emailAdmins('paid_subscription_refund', $replacements, $notify_users);
|
Chris@76
|
177 }
|
Chris@76
|
178
|
Chris@76
|
179 }
|
Chris@76
|
180 // Otherwise is it what we want, a purchase?
|
Chris@76
|
181 elseif ($gatewayClass->isPayment() || $gatewayClass->isSubscription())
|
Chris@76
|
182 {
|
Chris@76
|
183 $cost = unserialize($subscription_info['cost']);
|
Chris@76
|
184 $total_cost = $gatewayClass->getCost();
|
Chris@76
|
185 $notify = false;
|
Chris@76
|
186
|
Chris@76
|
187 // For one off's we want to only capture them once!
|
Chris@76
|
188 if (!$gatewayClass->isSubscription())
|
Chris@76
|
189 {
|
Chris@76
|
190 $real_details = @unserialize($subscription_info['pending_details']);
|
Chris@76
|
191 if (empty($real_details))
|
Chris@76
|
192 generateSubscriptionError(sprintf($txt['paid_count_not_find_outstanding_payment'], $member_id, $subscription_id));
|
Chris@76
|
193 // Now we just try to find anything pending.
|
Chris@76
|
194 // We don't really care which it is as security happens later.
|
Chris@76
|
195 foreach ($real_details as $id => $detail)
|
Chris@76
|
196 {
|
Chris@76
|
197 unset($real_details[$id]);
|
Chris@76
|
198 if ($detail[3] == 'payback' && $subscription_info['payments_pending'])
|
Chris@76
|
199 $subscription_info['payments_pending']--;
|
Chris@76
|
200 break;
|
Chris@76
|
201 }
|
Chris@76
|
202 $subscription_info['pending_details'] = empty($real_details) ? '' : serialize($real_details);
|
Chris@76
|
203
|
Chris@76
|
204 $smcFunc['db_query']('', '
|
Chris@76
|
205 UPDATE {db_prefix}log_subscribed
|
Chris@76
|
206 SET payments_pending = {int:payments_pending}, pending_details = {string:pending_details}
|
Chris@76
|
207 WHERE id_sublog = {int:current_subscription_item}',
|
Chris@76
|
208 array(
|
Chris@76
|
209 'payments_pending' => $subscription_info['payments_pending'],
|
Chris@76
|
210 'current_subscription_item' => $subscription_info['id_sublog'],
|
Chris@76
|
211 'pending_details' => $subscription_info['pending_details'],
|
Chris@76
|
212 )
|
Chris@76
|
213 );
|
Chris@76
|
214 }
|
Chris@76
|
215
|
Chris@76
|
216 // Is this flexible?
|
Chris@76
|
217 if ($subscription_info['length'] == 'F')
|
Chris@76
|
218 {
|
Chris@76
|
219 $found_duration = 0;
|
Chris@76
|
220 // This is a little harder, can we find the right duration?
|
Chris@76
|
221 foreach ($cost as $duration => $value)
|
Chris@76
|
222 {
|
Chris@76
|
223 if ($duration == 'fixed')
|
Chris@76
|
224 continue;
|
Chris@76
|
225 elseif ((float) $value == (float) $total_cost)
|
Chris@76
|
226 $found_duration = strtoupper(substr($duration, 0, 1));
|
Chris@76
|
227 }
|
Chris@76
|
228
|
Chris@76
|
229 // If we have the duration then we're done.
|
Chris@76
|
230 if ($found_duration!== 0)
|
Chris@76
|
231 {
|
Chris@76
|
232 $notify = true;
|
Chris@76
|
233 addSubscription($subscription_id, $member_id, $found_duration);
|
Chris@76
|
234 }
|
Chris@76
|
235 }
|
Chris@76
|
236 else
|
Chris@76
|
237 {
|
Chris@76
|
238 $actual_cost = $cost['fixed'];
|
Chris@76
|
239 // It must be at least the right amount.
|
Chris@76
|
240 if ($total_cost != 0 && $total_cost >= $actual_cost)
|
Chris@76
|
241 {
|
Chris@76
|
242 // Add the subscription.
|
Chris@76
|
243 $notify = true;
|
Chris@76
|
244 addSubscription($subscription_id, $member_id);
|
Chris@76
|
245 }
|
Chris@76
|
246 }
|
Chris@76
|
247
|
Chris@76
|
248 // Send a receipt?
|
Chris@76
|
249 if (!empty($modSettings['paid_email']) && $modSettings['paid_email'] == 2 && $notify)
|
Chris@76
|
250 {
|
Chris@76
|
251 $replacements = array(
|
Chris@76
|
252 'NAME' => $subscription_info['name'],
|
Chris@76
|
253 'SUBNAME' => $member_info['member_name'],
|
Chris@76
|
254 'SUBUSER' => $member_info['real_name'],
|
Chris@76
|
255 'SUBEMAIL' => $member_info['email_address'],
|
Chris@76
|
256 'PRICE' => sprintf($modSettings['paid_currency_symbol'], $total_cost),
|
Chris@76
|
257 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member_id,
|
Chris@76
|
258 'DATE' => timeformat(time(), false),
|
Chris@76
|
259 );
|
Chris@76
|
260
|
Chris@76
|
261 emailAdmins('paid_subscription_new', $replacements, $notify_users);
|
Chris@76
|
262 }
|
Chris@76
|
263 }
|
Chris@76
|
264
|
Chris@76
|
265 // In case we have anything specific to do.
|
Chris@76
|
266 $gatewayClass->close();
|
Chris@76
|
267
|
Chris@76
|
268 // Log an error then die.
|
Chris@76
|
269 function generateSubscriptionError($text)
|
Chris@76
|
270 {
|
Chris@76
|
271 global $modSettings, $notify_users, $smcFunc;
|
Chris@76
|
272
|
Chris@76
|
273 // Send an email?
|
Chris@76
|
274 if (!empty($modSettings['paid_email']))
|
Chris@76
|
275 {
|
Chris@76
|
276 $replacements = array(
|
Chris@76
|
277 'ERROR' => $text,
|
Chris@76
|
278 );
|
Chris@76
|
279
|
Chris@76
|
280 emailAdmins('paid_subscription_error', $replacements, $notify_users);
|
Chris@76
|
281 }
|
Chris@76
|
282
|
Chris@76
|
283 // Maybe we can try to give them the post data?
|
Chris@76
|
284 if (!empty($_POST))
|
Chris@76
|
285 foreach ($_POST as $key => $val)
|
Chris@76
|
286 $text .= '<br />' . $smcFunc['htmlspecialchars']($key) . ': ' . $smcFunc['htmlspecialchars']($val);
|
Chris@76
|
287
|
Chris@76
|
288 // Then just log and die.
|
Chris@76
|
289 log_error($text);
|
Chris@76
|
290
|
Chris@76
|
291 exit;
|
Chris@76
|
292 }
|
Chris@76
|
293
|
Chris@76
|
294 ?> |