<?php

/******************************************************************************
 *  
 *  PROJECT: Flynax Classifieds Software
 *  VERSION: 4.5.2
 *  LICENSE: FL4HLD2A8696 - http://www.flynax.com/license-agreement.html
 *  PRODUCT: Real Estate Classifieds
 *  DOMAIN: savingrack.com
 *  FILE: RLPAYPAL.CLASS.PHP
 *  
 *  The software is a commercial product delivered under single, non-exclusive,
 *  non-transferable license for one domain or IP address. Therefore distribution,
 *  sale or transfer of the file in whole or in part without permission of Flynax
 *  respective owners is considered to be illegal and breach of Flynax License End
 *  User Agreement.
 *  
 *  You are not allowed to remove this information from the file without permission
 *  of Flynax respective owners.
 *  
 *  Flynax Classifieds Software 2017 | All copyrights reserved.
 *  
 *  http://www.flynax.com/
 ******************************************************************************/

class rlPaypal extends rlGateway
{
	/**
	* @var $api_host
	*/
	protected $api_host;
	
	/**
	* @var $rlSubscription
	*/
	protected $rlSubscription;

	/**
	* Conrtructor
	* 
	* @param mixed $gateway
	* @param mixed $plugin
	* @return rlPaypal
	*/
	public function __construct($gateway = false, $plugin = null)
	{
		parent::__construct($gateway, $plugin);
		$this->setTestMode($GLOBALS['config']['paypal_sandbox'] ? true : false);
		
		$this->api_host = 'https://' . ($this->isTestMode() ? 'www.sandbox' : 'www') . '.paypal.com/cgi-bin/webscr';
		
		$this->reefless->loadClass('Subscription');
		$this->rlSubscription = &$GLOBALS['rlSubscription'];
		if (!defined('REALM')) {
			$this->gateway_info = $this->rlPayment->getGatewayDetails();
		}
	}

	/**
	* run payment process
	* 
	*/
	public function call()
	{
		if ($this->rlPayment->isRecurring()) {
			$subscription_current = $this->rlSubscription->getActiveSubscription($this->rlPayment->getOption('item_id'), $this->rlPayment->getOption('service'));
			
			if (!$subscription_current) {
				$insert = array(
						'Service' => $this->rlPayment->getOption('service'),           
						'Account_ID' => $this->rlPayment->getOption('account_id'),
						'Item_ID' => $this->rlPayment->getOption('item_id'),
						'Plan_ID' => $this->rlPayment->getOption('plan_id'),
						'Total' => $this->rlPayment->getOption('total'),
						'Gateway_ID' => $this->gateway_info['ID'],
						'Item_name' => $this->rlPayment->getOption('item_name'),
						'Count' => 1
					);
					
				$action = $this->rlActions->insertOne($insert, 'subscriptions');
				$this->rlPayment->setOption('subscription_id', $this->reefless->insertID());
			} else {
				if (!$this->rlPayment->getOption('subscription_id')) {
					$this->rlPayment->setOption('subscription_id', $subscription_current['ID']);	
				}
			}
		}
		$this->beforeProcess();
		$this->buildPage($this->buildForm());
	}
	
	/**
	* complete payment process
	* 
	*/
	public function callBack()
	{
		return $this->afterProcess();	
	}

	protected function beforeProcess()
	{
		$subscription_plan = $this->rlSubscription->getPlan($this->rlPayment->getOption('service'), $this->rlPayment->getOption('plan_id'));

		$this->setOption('business', $GLOBALS['config']['paypal_account_email']);
		$this->setOption('currency_code', $GLOBALS['config']['system_currency_code']);
		$this->setOption('item_number', $this->rlPayment->getTransactionID());
		$this->setOption('custom', str_replace(' ', '+', $this->rlPayment->buildItemData(false)));

		if ($this->rlPayment->isRecurring() && $subscription_plan['Period']) {
			$this->setOption('cmd', '_xclick-subscriptions');
			$this->setOption('a3', $this->rlPayment->getOption('total'));
			$this->setOption('p3', (int)$subscription_plan['Period_total']);
			$this->setOption('t3', $this->getPeriodSubscription($subscription_plan['Period']));
			$this->setOption('src', 1);
			$this->setOption('sra', 1);
			$this->setOption('no_note', 1);
			if (RL_LANG_CODE != 'en') {
				$this->setOption('lc', RL_LANG_CODE);	
			}
		} else {
			$this->setOption('cmd', '_xclick');	
			$this->setOption('amount', $this->rlPayment->getOption('total'));
		}

		$this->setOption('rm', 2);
		$this->setOption('no_shipping', 1);
		$this->setOption('item_name', $this->rlPayment->getOption('item_name'));
		$this->setOption('return', $this->rlPayment->getOption('success_url') ? $this->rlPayment->getOption('success_url') : $this -> rlPayment->getDefaultSuccessURL()); // $this->rlPayment->getNotifyURL() . '?gateway=paypal'  $this->rlPayment->getOption('success_url') ? $this->rlPayment->getOption('success_url') : $this -> rlPayment->getDefaultSuccessURL()
		$this->setOption('cancel_return', $this->rlPayment->getOption('cancel_url') ? $this->rlPayment->getOption('cancel_url') : $this->rlPayment->getDefaultFailURL());
		$url_divider = strpos($this->rlPayment->getNotifyURL(), '?') > 0 ? '&' : '?';
		$this->setOption('notify_url', $this->rlPayment->getNotifyURL() . $url_divider . 'gateway=paypal');

		$this->setOption('charset', 'utf-8');
		$this->setOption('image_url', RL_TPL_BASE . 'img/logo.png');
	}

	protected function afterProcess()
	{
		/* save response to log */
		if ($GLOBALS['config']['paypal_sandbox']) {
			$file = fopen('response.log', 'a');

			if ($file) {                      
				$line = "\n\n" . date( 'Y.m.d H:i:s' ) . ":\n";
			    fwrite($file, $line);          
                               
				foreach ($_REQUEST as $p_key => $p_val) {                 
					$line = "{$_SERVER['REQUEST_METHOD']}: {$p_key} => {$p_val}\n";
    				fwrite($file, $line);
				}
			}
		}
		if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
			$errors = $response_status = false;
			
			if (extension_loaded('curl')) {
				$response_status = $this->checkResponseCURL();
			} else {
				$response_status = $this->checkResponse();
			}

			if ($response_status && $_POST['txn_id']) {
				/* assign posted variables to local variables */
				$item_name = $_POST['item_name'];
				$txn_id = $GLOBALS['rlValid']->xSql($_POST['item_number']);
				$txn_gateway = $GLOBALS['rlValid']->xSql($_POST['txn_id']);
				$item = $_POST['custom'];
				$payment_status = $_POST['payment_status'];
				$mc_gross = $_POST['mc_gross'];
				$payment_gross = $_POST['payment_gross'];
				$payment_currency = $_POST['mc_currency'];
				$receiver_email = $_POST['receiver_email'];
				$payer_email = $_POST['payer_email'];
				$subscr_id = $GLOBALS['rlValid']->xSql($_POST['subscr_id']);
				$receiver_id = $GLOBALS['rlValid']->xSql($_POST['receiver_id']);
				
				$total = !empty($payment_gross) ? $payment_gross : $mc_gross;

				if (!in_array(trim(strtolower($payment_status)), array('completed', 'pending'))) {
					/* Exit since payment status is not Completed */
					$this->rlDebug->logger("PayPal: Exit since payment status is not Completed or Pending");
					$errors = true;
				}

				$items = $this->explodeItems($item);
				
				$subscription_id = $items[11];

				$response = array(
						'plan_id' => $items[0],
						'item_id' => $items[1],
						'account_id' => $items[2],
						'total' => !empty($payment_gross) ? $payment_gross : $mc_gross,
						'txn_id' => $txn_id,
						'txn_gateway' => $txn_gateway,
						'params' => $items[12]
					);

				$crypted_sum = $items[3]; 
				
				define('RL_LANG_CODE', $lang_code);
				define('RL_DATE_FORMAT', $this->reefless->getOne('Date_format', "`Code` = '{$GLOBALS['config']['lang']}'", 'languages'));
				
				$lang = $this->rlLang->getLangBySide('frontEnd', RL_LANG_CODE);
				$GLOBALS['lang'] = $lang;

				/* Check crypted sum */
				if (strcmp($crypted_sum, crypt(sprintf("%.2f", $total), $GLOBALS['config']['paypal_secret_word'])) != 0) {
					// Exit since crypted sum is invalid
					$this -> rlDebug -> logger("PayPal: Exit since crypted sum is invalid ({$total} -- {$crypted_sum}  {$item})");
					$errors = true;
				}

				if (!$errors) {
					if ($subscription_id) {
						$subscription_info = $GLOBALS['rlSubscription']->getSubscription($subscription_id);

						if ($subscription_info)  {
							$update = array(
								'fields' => array(
										'Txn_ID' => $txn_gateway,
										'Count' => $subscription_info['Count'] + 1,
										'Status' => 'active',
										'Subscription_ID' => $subscr_id,
										'Customer_ID' => $receiver_id,
										'Date' => 'NOW()'
										
									),
								'where' => array('ID' => $subscription_id)
								);
								
							$this->rlActions->updateOne($update, 'subscriptions');
						}
					}					
					$this->rlPayment->complete($response, $items[4], $items[5], $items[9] ? $items[9] : false);
				}
			} else {
				$this -> rlDebug -> logger("PayPal: the response invalid");
			}
		}
	}
	
	/**
	* validate response from paypal service
	* 
	* @return boolean
	*/
	public function checkResponse()
	{
		header('HTTP/1.1 200 OK');
		 
		$req = 'cmd=_notify-validate';

		foreach ($_POST as $key => $value) {
			$value = urlencode(stripslashes($value));
			$req  .= "&$key=$value";
		}
		
		$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
		$header .= "Content-Length: " . strlen($req) . "\r\n";
		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$header .= "Host: www".($this->isTestMode() ? '.sandbox' : '').".paypal.com\r\n";
		$header .= "Connection: close\r\n\r\n";

		$fp = fsockopen('tls://www'.($this->isTestMode() ? '.sandbox' : '').'.paypal.com', 443, $errno, $errstr, 30);

		if ($fp) {
			fputs($fp, $header . $req);

			while (!feof($fp)) {
				$res .= fgets($fp, 1024);
			}
			fclose($fp);

			// Process paypal response
			$arr = explode("\r\n\r\n", $res);
            $arr[1] = trim(preg_replace('/\d/', '', $arr[1]));
			if(strcmp($arr[1], 'VERIFIED') == 0 || (strcmp($arr[1], 'INVALID') == 0 && $this->isTestMode())) {
				return true;
			}
		}

		return false;
	}
	
	/**
	* validate response from paypal service via cURL
	* 
	* @return boolean
	*/
	public function checkResponseCURL()
	{
		$raw_post_data = file_get_contents('php://input');
		$raw_post_array = explode('&', $raw_post_data);
		$myPost = array();

		foreach ($raw_post_array as $keyval) {
			$keyval = explode ('=', $keyval);
			if (count($keyval) == 2) {
				$myPost[$keyval[0]] = urldecode($keyval[1]);
			}
		}

		$req = 'cmd=_notify-validate';
		if(function_exists('get_magic_quotes_gpc')) {
			$get_magic_quotes_exists = true;
		} 
		foreach ($myPost as $key => $value) {        
			if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { 
			    $value = urlencode(stripslashes($value)); 
			} else {
			    $value = urlencode($value);
			}
			$req .= "&$key=$value";
		}

		$ch = curl_init($this->api_host);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // for SSL
		//curl_setopt($ch, CURLOPT_SSLVERSION, 1);   // for NSS
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

		$res = curl_exec($ch);
		
		if (curl_errno($ch) != 0) {
			$this -> rlDebug -> logger("PayPal: Can't connect to PayPal to validate IPN message: " . curl_error($ch));
		}
		curl_close($ch);
		
		if (strcmp($res, "VERIFIED") == 0 || (strcmp($res, 'INVALID') == 0 && $this->isTestMode())) {
			return true;
		}

		return false;
	}

	/**
	* build payment form
	* 
	*/
	protected function buildForm()
	{
		$form = '<form name="payment_form" action="'. $this->api_host .'" method="post">' . PHP_EOL;

		foreach ($this->request_data as $key => $value) {
			$form .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . PHP_EOL;
		}
		
		$form .= '</form>' . PHP_EOL;

		echo $form;
	}
	
	/**
	* get subscription period
	* 
	* @param string $period
	* @return string
	*/
	public function getPeriodSubscription($period = false)
	{
		if (!$period) {
			return null;
		}

		switch ($period) {
			case 'day' :
				$response = 'D';
				break;
				
			case 'week' :
				$response = 'W';
				break;
				
			case 'month' :
				$response = 'M';
				break;
				
			case 'year' :
				$response = 'Y';
				break;
		}

		return $response;
	}
	
	public function cancelSubscription(&$subscription_info)
	{
		if (!$subscription_info) {
			return false;
		}
		$redirect_url = $this->api_host . '?cmd=_subscr-find&alias=' . $subscription_info['Customer_ID']; //$GLOBALS['config']['paypal_merchant_id']
		return $redirect_url;
	}
	
	/**
	* check if paypal configured
	* 
	* @return boolean
	*/
	public static function isConfigured()
	{
		if ($GLOBALS['config']['paypal_account_email']) {
			return true;
		}
		return false;
	}
}