<?php

/******************************************************************************
 *
 *	PROJECT: Flynax Classifieds Software
 *	VERSION: 4.X
 *	LICENSE: FL4HLD2A8696 - http://www.flynax.com/license-agreement.html
 *	PRODUCT: Real Estate Agency
 *	DOMAIN: gevimmo.com
 *	FILE: RLCCBILL.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 rlCcbill extends rlGateway
{        
	/**
	* @var $api_host
	*/
	protected $api_host;
	
	/**
	* @var $errors
	*/
	protected $errors;
	
	/**
	* @var $account_info
	*/
	protected $account_info;
	
	/**
	* @var $transaction_id
	*/
	protected $transaction_id;
	
	/**
	* list object items by group
	* 
	* @var array
	*/
	protected $object_items;
	
	/**
	* @var $rlSubscription
	*/
	protected $rlSubscription;
	
	/**
	* available plugins which using in the plugin
	* 
	* @var array
	*/
	protected $plugins;
	
	/**
	* available currencies on payment server
	* 
	* @var array
	*/
	protected static $currencies = array(
		'AUD' => '036',
		'CAD' => '124',
		'JPY' => '392',
		'GBP' => '826',
		'USD' => '840',
		'EUR' => '978'
	);
	
	/**
	* available languages on payment server
	* 
	* @var mixed
	*/
	protected static $languages = array(
		'en' => 'English',
		'es' => 'Español',
		'fr' => 'Français',
		'de' => 'Deutsch',
		'it' => 'Italiano',
		'ja' => 'Japanese',
		'ko' => 'Korean',
		'zh' => 'Traditional Chinese',
		'pt' => 'Português Brasileiro',
		'in' => 'Hindi',
		'sv' => 'Svenska',
		'dk' => 'Dansk',
		'no' => 'Norsk'
	);

	/**
	* class constructor
	* 
	*/
	public function __construct()
	{  
		global $account_info;

		parent::__construct();
		$this->setTestMode($GLOBALS['config']['ccbill_test_mode'] ? true : false);
		$this->api_host = 'https://bill.ccbill.com/jpost/signup.cgi';
        $this->account_info = &$account_info;

		if (!defined('REALM')) {
			$this->gateway_info = $this->rlPayment->getGatewayDetails();
		}
		if (isset($_SESSION['ccbill_txn_id'])) {
			$this->transaction_id = $_SESSION['ccbill_txn_id'];
		}
		$this->reefless->loadClass('Subscription');
		$this->rlSubscription = &$GLOBALS['rlSubscription'];
	}
	
	/**
 	* go payment process
 	* 
 	*/
	public function call()
	{
		// set payment options
		if (!$this->getTransactionID()) {
			$this->setTransactionID();
		}

		$settings = $this->getSettingsItem();
		$subscription_plan = $this->rlSubscription->getPlan($this->rlPayment->getOption('service'), $this->rlPayment->getOption('plan_id'));
		$currency = isset(self::$currencies[$GLOBALS['config']['system_currency_code']]) ? self::$currencies[$GLOBALS['config']['system_currency_code']] : '840';
		if (strpos($settings['Allowed_types'], ',') > 0) {
			foreach (explode(',', $settings['Allowed_types']) as $item) {
				$allowed_types[] = $item . ':' . $currency;
			}
			$subscriptionTypeId = false;
			$allowed_types = implode(',', $allowed_types);
		} else {
			$allowed_types = $settings['Allowed_types'] . ':' . $currency;
			$subscriptionTypeId = $settings['Allowed_types'];
		}
		$lang = isset(self::$languages[strtolower(RL_LANG_CODE)]) ? self::$languages[strtolower(RL_LANG_CODE)] : 'English';
		
		$this->setOption('clientAccnum', $GLOBALS['config']['ccbill_clientAccnum']);
		$this->setOption('clientSubacc', $GLOBALS['config']['ccbill_clientSubacc']);
		$this->setOption('formName', $settings['Form']);
		$this->setOption('item_number', $this->rlPayment->buildItemData());
		$this->setOption('transactionId', $this->getTransactionID());
		$this->setOption('language', $lang);
		$this->setOption('allowedTypes', $allowed_types);
		if ($subscriptionTypeId) {
			$this->setOption('subscriptionTypeId', $subscriptionTypeId);	
		}
		// customer info
		$this->setOption('customer_fname', $this->account_info['First_name']);
		$this->setOption('customer_lname', $this->account_info['Last_name']);
		$this->setOption('email', $this->account_info['Mail']);
		$this->setOption('address1', $this->account_info['address']);
		$this->setOption('city', $this->account_info['city']);
		$this->setOption('state', $this->account_info['state']);
		$this->setOption('zipcode', $this->account_info['zip_code']);
		$this->setOption('country', $this->account_info['country']);

		if (!$this->hasErrors()) {
			$this->updateTransaction(array('Txn_ID' => $this->getTransactionID(), 'Item_data' => $this->rlPayment->buildItemData()));
			$this->buildPage($this->buildForm());
		}
	}
	
	/**
	* handle callback response from payment server and complete payment on site
	* 
	*/
	public function callBack()
	{
		if ($GLOBALS['config']['ccbill_test_mode']) {
			$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' && isset($_POST['clientAccnum'])) {
			$txn_id = $GLOBALS['rlValid']->xSql($_POST['subscription_id']);
			$errors = false;
			
			$items = explode("|", base64_decode($_POST['item_number']));
			
			if ($GLOBALS['config']['ccbill_clientAccnum'] != $_POST['clientAccnum'] || $GLOBALS['config']['ccbill_clientSubacc'] != $_POST['clientSubacc']) {
				$this->rlDebug->logger("CCBill: account number doesn't match {$_POST['clientAccnum']},{$_POST['clientSubacc']}");
				$errors = true;
			}

			if ($items) {
				if (!$errors) {
					$subscription_id = $items[11];
					$transaction_id = (int)$items[10];
					$txn_info = $this->reefless->getRow("SELECT * FROM `".RL_DBPREFIX."transactions` WHERE `ID` = '{$transaction_id}' LIMIT 1");
					
					$response = array(
						'plan_id' => $items[0],
						'item_id' => $items[1],
						'account_id' => $items[2],
						'total' => $txn_info['Total'],
						'txn_id' => $transaction_id,
						'txn_gateway' => $txn_id,
						'params' => $items[12]
					);
					$this->rlPayment->complete($response, $items[4], $items[5], $items[9] ? $items[9] : false);
					
					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');
						}
					}

					// clear item data field in system transaction
					$update = array(
							'Item_data' => ''	
						);
					$this->updateTransaction($update);	
				} 
			}
		}
		exit;
	}
	
	/**
	* check settings of the gateway
	* 
	*/
	public function isConfigured()
	{
		$settings = self::getSettingsItem();
		if ($GLOBALS['config']['ccbill_clientAccnum'] && $GLOBALS['config']['ccbill_clientSubacc'] && $settings['Form'] && $settings['Allowed_types']) {
			return true;
		}
		return false;
	}
	
	/**
	* check if has any errors in payment process
	* 
	* @return boolean;
	* 
	*/
	public function hasErrors()
	{
		if ($this->errors) {
			return true;
		}
		return false;
	}
	
	/**
	* get errors
	* 
	* @return array;
	* 
	*/
	public function getErrors()
	{
		if ($this->errors) {
			return $this->errors;
		}
		return false;
	}

	/**
	* get transaction ID
	* @return string
	* 
	*/
	public function getTransactionID()
	{
		return $this->transaction_id;		
	}
	
	/**
	* set transaction ID
	* 
	*/
	public function setTransactionID($txn_id = false)
	{
		if ($txn_id) {
			$this->transaction_id = $txn_id;
			return;
		}
		$this->transaction_id = $_SESSION['ccbill_txn_id'] = rand(100000, 999999);
	}
	
	/**
	*  update system transaction
	* 
	* @param array $data
	*/
	public function updateTransaction(array $data)
	{
		if (!$data) {
			 return;
		}
		$update = false;
		foreach ($data as $key => $value) {
			$update['fields'][$key] = $value;
		}
		
		if ($update) {
			$update['where'] = array(
					'ID' => $this->rlPayment->getTransactionID()
				);
			$this->rlActions->updateOne($update, 'transactions');
		}
	}
        
	/**
	* build payment form
	* 
	*/
	protected function buildForm()
	{
		$form = '<form name="payment_form" action="'. $this->api_host .'" method="post">' . PHP_EOL; // name="payment_form"

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

		echo $form;
	}
	
	/**
	* get system transaction by reference code
	* 
	* @param string $transaction_id
	* @return array
	*/
	public function getTransactionByReference($transaction_id = false)
	{
		if (!$transaction_id) {
			return false;
		}

		$sql = "SELECT * FROM `" . RL_DBPREFIX . "transactions` WHERE `Txn_ID` = '".$transaction_id."' LIMIT 1";
		return $this->reefless->getRow($sql);
	}
	
	/**
	* clear payment data
	* 
	*/
	public function clear()
	{
		$this->request_data = array();
		unset($_SESSION['ccbill_txn_id']);
	}

	/**
	* set dealer credentials 
	* 
	*/
	public function setDealerCredentials(&$dealer_info)
	{}
	
	/**
	* get ccbill package item settings
	* 
	* @param integer $item_id
	* @param string $service
	* @return data
	*/
	public static function getSettingsItem()
	{
		$service = $GLOBALS['rlPayment']->getOption('service');
		switch ($service) {
			case 'featured' :
			case 'package' :
			case 'listing' :
				$plan_id = $GLOBALS['rlPayment']->getOption('plan_id');
				break;
				
			case 'membership' :
				$plan_id = $GLOBALS['rlPayment']->getOption('plan_id');
				break;
				
			case 'banners' :
				$plan_id = $GLOBALS['rlPayment']->getOption('plan_id');
				break;

			case 'credits' :
				$plan_id = $GLOBALS['rlPayment']->getOption('item_id');
				break;
		};
		$sql = "SELECT * FROM `".RL_DBPREFIX."ccbill_settings` WHERE `Item_ID` = '{$plan_id}' AND `service` = '{$service}' LIMIT 1";
		return $GLOBALS['reefless']->getRow($sql);
	}
	
	
	/**
	* save ccbill settings by object
	* 
	* @param array $data
	*/
	public function saveSettings(array $data)
	{
		if (!$data) {
			return;
		}

		foreach ($data as $key => $value) {
			foreach ($value as $iKey => $iVal) {
				if (isset($this->object_items[$key]['items'][$iKey])) {
					$service = $this->object_items[$key]['service'] ? $this->object_items[$key]['service'] : $this->object_items[$key]['items'][$iKey]['service'];
					if ($this->reefless->getOne('ID', "`Service` = '{$service}' AND `Item_ID` = '".(int)$iKey."'", 'ccbill_settings')) {
						$update[] = array(
							'fields' => array('Form' => $iVal['form'], 'Allowed_types' => $iVal['allowed_types']),
							'where' => array('Service' => $service, 'Item_ID' => $iKey)
						);
					} else {
						$insert[] = array(
							'Service' => $service,
							'Item_ID' => $iKey,
							'Form' => $iVal['form'],
							'Allowed_types' => $iVal['allowed_types']
						);
					}
				}
			}	
		}
		if ($update) {
			$this->rlActions->update($update, 'ccbill_settings');
		}
		if ($insert) {
			$this->rlActions->insert($insert, 'ccbill_settings');
		}
	}
	
	/**
	* get ccbill settings
	* 
	* @param array $object_items
	*/
	public function getSettings(&$object_items)
	{
		$settings_tmp = $this->reefless->getAll("SELECT * FROM `".RL_DBPREFIX."ccbill_settings`");
		
		foreach ($settings_tmp as $value) {
			$settings[$value['Service'] . '_' . $value['Item_ID']] = $value;		
		}

		foreach ($object_items as $gKey => $group) {
			foreach ($group['items'] as $iKey => $item) {
				$service = $object_items[$gKey]['service'] ? $object_items[$gKey]['service'] : $item['Type'];
				if (isset($settings[$service . '_' . $item['ID']])) {
					$object_items[$gKey]['items'][$iKey]['form'] = $settings[$service . '_' . $item['ID']]['Form'];
					$object_items[$gKey]['items'][$iKey]['allowed_types'] = $settings[$service . '_' . $item['ID']]['Allowed_types'];
				}
			}
		}
	}
	
	/**
	* set object items
	* 
	* @param array $items
	*/
	public function setObjectItems(array $items)
	{
		foreach ($items as $gKey => $gVal) {
			$tmp_items = array();
			if ($gVal['items']) {
				foreach ($gVal['items'] as $iKey => $iVal) {
					if (!$gVal['service']) {
						$iVal['service'] = $iVal['Type'];	
					}
					$tmp_items[$iVal['ID']] = $iVal;		
				}
				$items[$gKey]['items'] = $tmp_items;
			}
		}
		$this->object_items = $items;	
	}
	
	/**
	* get object items
	* 
	* @return array
	*/
	public function getObjectItems()
	{
		return $this->object_items;
	}
	
	/**
	* check if plugin installed
	* 
	* @param string $key
	* @return boolean
	*/
	public function isPluginInstalled($key = '')
	{
		if (!$key) {
			return false;
		}
		
		if (isset($this->plugins[$key])) {
			if ($this->plugins[$key]) {
				return true;
			} else {
				return false;
			}
		}
		$sql = "SELECT * FROM `".RL_DBPREFIX."plugins` WHERE `Key` = '{$key}' AND `Install` = '1' AND `Status` = 'active' LIMIT 1";
		$plugin = $this->reefless->getRow($sql);
		$this->plugins[$key] = $plugin['ID'] ? true : false;
		return $this->plugins[$key];
	}
}