annotate forum/subscriptions.php @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
rev   line source
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 ?>