|
@@ -17,22 +17,40 @@
|
|
|
if (!defined('SMF'))
|
|
|
die('Hacking attempt...');
|
|
|
|
|
|
+
|
|
|
+ * Class for returning available form data for this gateway
|
|
|
+ */
|
|
|
class paypal_display
|
|
|
{
|
|
|
+
|
|
|
+ * Name of this payment gateway
|
|
|
+ */
|
|
|
public $title = 'PayPal';
|
|
|
|
|
|
+
|
|
|
+ * Return the admin settings for this gateway
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
public function getGatewaySettings()
|
|
|
{
|
|
|
global $txt;
|
|
|
|
|
|
$setting_data = array(
|
|
|
- array('text', 'paypal_email', 'subtext' => $txt['paypal_email_desc']),
|
|
|
+ array(
|
|
|
+ 'text', 'paypal_email',
|
|
|
+ 'subtext' => $txt['paypal_email_desc']
|
|
|
+ ),
|
|
|
);
|
|
|
|
|
|
return $setting_data;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * Is this enabled for new payments?
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
public function gatewayEnabled()
|
|
|
{
|
|
|
global $modSettings;
|
|
@@ -40,7 +58,19 @@ class paypal_display
|
|
|
return !empty($modSettings['paypal_email']);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * What do we want?
|
|
|
+ *
|
|
|
+ * Called from Profile-Actions.php to return a unique set of fields for the given gateway
|
|
|
+ * plus all the standard ones for the subscription form
|
|
|
+ *
|
|
|
+ * @param type $unique_id
|
|
|
+ * @param type $sub_data
|
|
|
+ * @param type $value
|
|
|
+ * @param type $period
|
|
|
+ * @param type $return_url
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
public function fetchGatewayFields($unique_id, $sub_data, $value, $period, $return_url)
|
|
|
{
|
|
|
global $modSettings, $txt, $boardurl;
|
|
@@ -99,11 +129,18 @@ class paypal_display
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * Class of functions to validate a IPN response and provide details of the payment
|
|
|
+ */
|
|
|
class paypal_payment
|
|
|
{
|
|
|
private $return_data;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * This function returns true/false for whether this gateway thinks the data is intended for it.
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
public function isValid()
|
|
|
{
|
|
|
global $modSettings;
|
|
@@ -117,12 +154,22 @@ class paypal_payment
|
|
|
|
|
|
if (!isset($_POST['business']))
|
|
|
$_POST['business'] = $_POST['receiver_email'];
|
|
|
- if ($modSettings['paypal_email'] != $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails']))))
|
|
|
+
|
|
|
+ if ($modSettings['paypal_email'] !== $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails']))))
|
|
|
return false;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * Post the IPN data received back to paypal for validaion
|
|
|
+ * 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;
|
|
@@ -134,18 +181,28 @@ class paypal_payment
|
|
|
|
|
|
$requestString = 'cmd=_notify-validate';
|
|
|
|
|
|
-
|
|
|
+
|
|
|
foreach ($_POST as $k => $v)
|
|
|
$requestString .= '&' . $k . '=' . urlencode($v);
|
|
|
|
|
|
|
|
|
- if (function_exists('curl_init') && $curl = curl_init('http://www.', !empty($modSettings['paidsubs_test']) ? 'sandbox.' : '', 'paypal.com/cgi-bin/webscr'))
|
|
|
+ if (function_exists('curl_init') && $curl = curl_init((!empty($modSettings['paidsubs_test']) ? 'https://www.sandbox.' : 'http://www.') . 'paypal.com/cgi-bin/webscr'))
|
|
|
{
|
|
|
|
|
|
curl_setopt($curl, CURLOPT_POST, true);
|
|
|
curl_setopt($curl, CURLOPT_POSTFIELDSIZE, 0);
|
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $requestString);
|
|
|
|
|
|
+
|
|
|
+ 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);
|
|
|
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array(
|
|
|
+ 'Host: www.' . (!empty($modSettings['paidsubs_test']) ? 'sandbox.' : '') . 'paypal.com',
|
|
|
+ 'Connection: close'
|
|
|
+ ));
|
|
|
+
|
|
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
@@ -159,12 +216,17 @@ class paypal_payment
|
|
|
else
|
|
|
{
|
|
|
|
|
|
- $header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n";
|
|
|
+ $header = 'POST /cgi-bin/webscr HTTP/1.1' . "\r\n";
|
|
|
$header .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
|
|
|
- $header .= 'Content-Length: ' . strlen ($requestString) . "\r\n\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";
|
|
|
|
|
|
|
|
|
- $fp = fsockopen('www.' . (!empty($modSettings['paidsubs_test']) ? 'sandbox.' : '') . 'paypal.com', 80, $errno, $errstr, 30);
|
|
|
+ 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);
|
|
|
|
|
|
|
|
|
if (!$fp)
|
|
@@ -177,7 +239,7 @@ class paypal_payment
|
|
|
while (!feof($fp))
|
|
|
{
|
|
|
$this->return_data = fgets($fp, 1024);
|
|
|
- if (strcmp($this->return_data, 'VERIFIED') == 0)
|
|
|
+ if (strcmp(trim($this->return_data), 'VERIFIED') === 0)
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -186,21 +248,20 @@ class paypal_payment
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
- if (strcmp($this->return_data, 'VERIFIED') != 0)
|
|
|
+ if (strcmp(trim($this->return_data), 'VERIFIED') !== 0)
|
|
|
exit;
|
|
|
|
|
|
|
|
|
- if ($modSettings['paypal_email'] != $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails']))))
|
|
|
+ if ($modSettings['paypal_email'] !== $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails']))))
|
|
|
exit;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
if ($this->isSubscription() && (empty($_POST['item_number']) || strpos($_POST['item_number'], '+') === false))
|
|
|
|
|
|
$this->_findSubscription();
|
|
|
|
|
|
|
|
|
- if (strtolower($_POST['mc_currency']) != $modSettings['paid_currency_code'])
|
|
|
+ if (strtolower($_POST['mc_currency']) !== $modSettings['paid_currency_code'])
|
|
|
exit;
|
|
|
|
|
|
|
|
@@ -211,40 +272,59 @@ class paypal_payment
|
|
|
return explode('+', $_POST['item_number']);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * Is this a refund?
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
public function isRefund()
|
|
|
{
|
|
|
- if ($_POST['payment_status'] == 'Refunded' || $_POST['payment_status'] == 'Reversed' || $_POST['txn_type'] == 'Refunded' || ($_POST['txn_type'] == 'reversal' && $_POST['payment_status'] == 'Completed'))
|
|
|
+ if ($_POST['payment_status'] === 'Refunded' || $_POST['payment_status'] === 'Reversed' || $_POST['txn_type'] === 'Refunded' || ($_POST['txn_type'] === 'reversal' && $_POST['payment_status'] === 'Completed'))
|
|
|
return true;
|
|
|
else
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * Is this a subscription?
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
public function isSubscription()
|
|
|
{
|
|
|
- if (substr($_POST['txn_type'], 0, 14) == 'subscr_payment')
|
|
|
+ if (substr($_POST['txn_type'], 0, 14) === 'subscr_payment' && $_POST['payment_status'] === 'Completed')
|
|
|
return true;
|
|
|
else
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * Is this a normal payment?
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
public function isPayment()
|
|
|
{
|
|
|
- if ($_POST['payment_status'] == 'Completed' && $_POST['txn_type'] == 'web_accept')
|
|
|
+ if ($_POST['payment_status'] === 'Completed' && $_POST['txn_type'] === 'web_accept')
|
|
|
return true;
|
|
|
else
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * How much was paid?
|
|
|
+ *
|
|
|
+ * @return float
|
|
|
+ */
|
|
|
public function getCost()
|
|
|
{
|
|
|
- return $_POST['tax'] + $_POST['mc_gross'];
|
|
|
+ return (isset($_POST['tax']) ? $_POST['tax'] : 0) + $_POST['mc_gross'];
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * Record the transaction reference and exit
|
|
|
+ *
|
|
|
+ */
|
|
|
public function close()
|
|
|
{
|
|
|
global $smcFunc, $subscription_id;
|
|
@@ -267,7 +347,11 @@ class paypal_payment
|
|
|
exit();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ * A private function to find out the subscription details.
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
private function _findSubscription()
|
|
|
{
|
|
|
global $smcFunc;
|
|
@@ -303,7 +387,7 @@ class paypal_payment
|
|
|
'payer_email' => $_POST['payer_email'],
|
|
|
)
|
|
|
);
|
|
|
- if ($smcFunc['db_num_rows']($request) == 0)
|
|
|
+ if ($smcFunc['db_num_rows']($request) === 0)
|
|
|
return false;
|
|
|
}
|
|
|
else
|