/** * Validate this is valid for this transaction type. * * - If valid returns the subscription and member IDs we are going to process. */ public function precheck() { global $modSettings, $txt; // Is this the right hash? if (empty($modSettings['2co_password']) || $_POST['x_MD5_Hash'] !== strtoupper(md5($modSettings['2co_password'] . $modSettings['2co_id'] . $_POST['x_trans_id'] . $_POST['x_amount']))) { generateSubscriptionError($txt['2co_password_wrong']); } // Verify the currency list(, $currency) = explode(':', $_POST['x_invoice_num']); // Verify the currency! if (strtolower($currency) != $modSettings['currency_code']) { exit; } // Return the ID_SUB/ID_MEMBER return explode('+', $_POST['x_invoice_num']); }
public function precheck() { global $modSettings, $txt; // Put this to some default value. if (!isset($_POST['txn_type'])) { $_POST['txn_type'] = ''; } // Build the request string - starting with the minimum requirement. $requestString = 'cmd=_notify-validate'; // Now my dear, add all the posted bits. foreach ($_POST as $k => $v) { $requestString .= '&' . $k . '=' . urlencode($v); } // Can we use curl? if (function_exists('curl_init') && ($curl = curl_init('http://www.', !empty($modSettings['paidsubs_test']) ? 'sandbox.' : '', 'paypal.com/cgi-bin/webscr'))) { // Set the post data. curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDSIZE, 0); curl_setopt($curl, CURLOPT_POSTFIELDS, $requestString); // Fetch the data returned as a string. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Fetch the data. $this->return_data = curl_exec($curl); // Close the session. curl_close($curl); } else { // Setup the headers. $header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n"; $header .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n"; $header .= 'Content-Length: ' . strlen($requestString) . "\r\n\r\n"; // Open the connection. $fp = fsockopen('www.' . (!empty($modSettings['paidsubs_test']) ? 'sandbox.' : '') . 'paypal.com', 80, $errno, $errstr, 30); // Did it work? if (!$fp) { generateSubscriptionError($txt['paypal_could_not_connect']); } // Put the data to the port. fputs($fp, $header . $requestString); // Get the data back... while (!feof($fp)) { $this->return_data = fgets($fp, 1024); if (strcmp($this->return_data, 'VERIFIED') == 0) { break; } } // Clean up. fclose($fp); } // If this isn't verified then give up... // !! This contained a comment "send an email", but we don't appear to send any? if (strcmp($this->return_data, 'VERIFIED') != 0) { exit; } // Check that this is intended for us. if ($modSettings['paypal_email'] != $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails'])))) { exit; } // Is this a subscription - and if so it's it a secondary payment that we need to process? if ($this->isSubscription() && (empty($_POST['item_number']) || strpos($_POST['item_number'], '+') === false)) { // Calculate the subscription it relates to! $this->_findSubscription(); } // Verify the currency! if (strtolower($_POST['mc_currency']) != $modSettings['paid_currency_code']) { exit; } // Can't exist if it doesn't contain anything. if (empty($_POST['item_number'])) { exit; } // Return the id_sub and id_member return explode('+', $_POST['item_number']); }
AND id_member = {int:current_member} AND status = {int:status}', array('current_time' => $subscription_act, 'current_subscription' => $subscription_id, 'current_member' => $member_id, 'status' => $status)); // Receipt? if (!empty($modSettings['paid_email']) && $modSettings['paid_email'] == 2) { $replacements = array('NAME' => $subscription_info['name'], 'REFUNDNAME' => $member_info['member_name'], 'REFUNDUSER' => $member_info['real_name'], 'PROFILELINK' => $scripturl . '?action=profile;u=' . $member_id, 'DATE' => timeformat(time(), false)); emailAdmins('paid_subscription_refund', $replacements, $notify_users); } } elseif ($gatewayClass->isPayment() || $gatewayClass->isSubscription()) { $cost = unserialize($subscription_info['cost']); $total_cost = $gatewayClass->getCost(); $notify = false; // For one off's we want to only capture them once! if (!$gatewayClass->isSubscription()) { $real_details = @unserialize($subscription_info['pending_details']); if (empty($real_details)) { generateSubscriptionError(sprintf($txt['paid_count_not_find_outstanding_payment'], $member_id, $subscription_id)); } // Now we just try to find anything pending. // We don't really care which it is as security happens later. foreach ($real_details as $id => $detail) { unset($real_details[$id]); if ($detail[3] == 'payback' && $subscription_info['payments_pending']) { $subscription_info['payments_pending']--; } break; } $subscription_info['pending_details'] = empty($real_details) ? '' : serialize($real_details); $smcFunc['db_query']('', ' UPDATE {db_prefix}log_subscribed SET payments_pending = {int:payments_pending}, pending_details = {string:pending_details} WHERE id_sublog = {int:current_subscription_item}', array('payments_pending' => $subscription_info['payments_pending'], 'current_subscription_item' => $subscription_info['id_sublog'], 'pending_details' => $subscription_info['pending_details']));
/** * Post the IPN data received back to paypal for validation * * - Sends the complete unaltered message back to PayPal. * - The message must contain the same fields in the same order and be encoded in the same way as the original message * - PayPal will respond back with a single word, which is either VERIFIED if the message originated with PayPal or INVALID * - If valid returns the subscription and member IDs we are going to process if it passes * * @return string */ public function precheck() { global $modSettings, $txt; $my_post = array(); // Reading POSTed data directly from $_POST may causes serialization issues with array data // in the POST. Instead, read raw POST data from the input stream. $raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); // Process it foreach ($raw_post_array as $keyval) { $keyval = explode('=', $keyval); if (count($keyval) === 2) { $my_post[$keyval[0]] = urldecode($keyval[1]); } } // Put this to some default value. if (!isset($my_post['txn_type'])) { $my_post['txn_type'] = ''; } // Build the request string - starting with the minimum requirement. $requestString = 'cmd=_notify-validate'; // Now my dear, add all the posted bits back in the exact order we got them foreach ($my_post as $key => $value) { $requestString .= '&' . $key . '=' . urlencode($value); } // Post IPN data back to PayPal to validate the IPN data is genuine // First we try cURL if (function_exists('curl_init') && ($curl = curl_init((!empty($modSettings['paidsubs_test']) ? 'https://www.sandbox.' : 'http://www.') . 'paypal.com/cgi-bin/webscr'))) { // Set the post data. curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDSIZE, 0); curl_setopt($curl, CURLOPT_POSTFIELDS, $requestString); // Set up the headers so paypal will accept the post curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); // Set TCP timeout to 30 seconds curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); // Set the http headers curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($requestString), 'Host: www.' . (!empty($modSettings['paidsubs_test']) ? 'sandbox.' : '') . 'paypal.com', 'Connection: close')); // The data returned as a string. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Fetch the data. $this->return_data = curl_exec($curl); // Close the session. curl_close($curl); } else { // Setup the headers. $header = 'POST /cgi-bin/webscr HTTP/1.1' . "\r\n"; $header .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n"; $header .= 'Host: www.' . (!empty($modSettings['paidsubs_test']) ? 'sandbox.' : '') . 'paypal.com' . "\r\n"; $header .= 'Content-Length: ' . strlen($requestString) . "\r\n"; $header .= 'Connection: close' . "\r\n\r\n"; // Open the connection. if (!empty($modSettings['paidsubs_test'])) { $fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); } else { $fp = fsockopen('www.paypal.com', 80, $errno, $errstr, 30); } // Did it work? if (!$fp) { generateSubscriptionError($txt['paypal_could_not_connect']); } // Put the data to the port. fputs($fp, $header . $requestString); // Get the data back... while (!feof($fp)) { $this->return_data = fgets($fp, 1024); if (strcmp(trim($this->return_data), 'VERIFIED') === 0) { break; } } // Clean up. fclose($fp); } // If PayPal IPN does not return verified then give up... if (strcmp(trim($this->return_data), 'VERIFIED') !== 0) { exit; } // Now that we have received a VERIFIED response from PayPal, we perform some checks // before we assume that the IPN is legitimate. First check that this is intended for us. if ($modSettings['paypal_email'] !== $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails'])))) { exit; } // Is this a subscription - and if so is it a secondary payment that we need to process? if ($this->isSubscription() && (empty($_POST['item_number']) || strpos($_POST['item_number'], '+') === false)) { // Calculate the subscription it relates to! $this->_findSubscription(); } // Verify the currency! if (trim(strtolower($_POST['mc_currency'])) !== strtolower($modSettings['paid_currency_code'])) { generateSubscriptionError(sprintf($txt['paypal_currency_unkown'], $_POST['mc_currency'], $modSettings['paid_currency_code'])); } // Can't exist if it doesn't contain anything. if (empty($_POST['item_number'])) { exit; } // Return the id_sub and id_member return explode('+', $_POST['item_number']); }