<?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: RLSTRIPENEW.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 rlStripe extends rlGateway
{
	/** 
	* @var $subscription
	*/
	protected $subscription;
	
	/**
	* @var $errors
	*/
	protected $errors;
	
	protected $rlSubscription;
	
	protected $account_info;
	
	/**
	* constructor
	* 
	*/
	public function __construct()
	{
		global $account_info;

		parent::__construct();
		Stripe\Stripe::setApiKey($GLOBALS['config']['stripe_secret_key']);

		$this->reefless->loadClass('Subscription');
		$this->rlSubscription = &$GLOBALS['rlSubscription'];
		if (!defined('REALM')) {
			$this->gateway_info = $this->rlPayment->getGatewayDetails();
		}
		$this->account_info = &$account_info;
	}
 	
 	/**
 	* go payment process
 	* 
 	*/
	public function call()
	{
		if ($_POST['form'] == 'checkout') {
			$this->validate();
			if (!$this->hasError()) {
				$this->rlPayment->setOption('token', $_POST['stripe-token']);
				$this->rlPayment->setOption('email', $_POST['f']['email'] ? $_POST['f']['email'] : $this->account_info['Mail']);
				if ($GLOBALS['config']['system_currency_code']) {
					$this->rlPayment->setOption('currency', trim($GLOBALS['config']['system_currency_code']));
				}
				
				$this->callBack();
				if (!$this->hasError()) {
					$this->reefless->redirect(false, str_replace("&amp;", "&", $this->rlPayment->getOption('success_url')));
					exit;
				}
			}
		}
		$this->rlPayment->enableForm();
	}

	/**
	* process payment
	* 
	*/
	public function callBack()
	{
		$this->setOption('currency', $GLOBALS['config']['system_currency_code']);		
		$plan_info = $this->rlSubscription->getPlan($this->rlSubscription->getService($this->rlPayment->getOption('service')), $this->rlPayment->getOption('plan_id'));

		if ($this->rlPayment->isRecurring() && $plan_info['Period']) {
			$plan_info_item = $this->getItemPlan();
			$this->setSubscription();
			$this->setOption('plan', $plan_info_item['Key']);

			$this->createSubscriptionPayment();
		} else {
			$this->createSinglePayment();
		}
	}

	/**
	* create single payment; 
	* 
	*/
	public function createSinglePayment()
	{
		try {
			$charge = Stripe\Charge::create(array(
			  "amount" => $this->rlPayment->getOption('total') * 100,
			  "currency" => $this->getOption('currency'),
			  "card" => $this->rlPayment->getOption('token'),
			  "description" => $this->rlPayment->getOption('item_name') . ' (' . $this->rlPayment->getOption('email') . ')')
			);

			if ($charge->paid == true && $charge->id) { 
				$response = array(
						'plan_id' => $this->rlPayment->getOption('plan_id'),
						'item_id' => $this->rlPayment->getOption('item_id'),
						'account_id' => $this->rlPayment->getOption('account_id'),
						'total' => $this->rlPayment->getOption('total'),
						'txn_id' => $this->rlPayment->getTransactionID(),
						'txn_gateway' => $charge->id,
						'params' => $this->rlPayment->getOption('params')
					);

				$this->rlPayment->complete($response, $this->rlPayment->getOption('callback_class'), $this->rlPayment->getOption('callback_method'), $this->rlPayment->getOption('plugin') ? $this->rlPayment->getOption('plugin') : false);
			}
		} catch(Stripe\Error\Card $e) {
			$this->errors[] = $e->getMessage();
		}	                                                                  
	}

	/**
	* create subscription payment; 
	* 
	*/
	public function createSubscriptionPayment()
	{
		$action = false;
		$sql = "SELECT * FROM `" . RL_DBPREFIX . "listing_plans` WHERE `ID` = '".$this->getOption('plan_id')."' LIMIT 1";
		$plan_info = $this->reefless->getRow($sql);

		try {
			$customer = Stripe\Customer::create(array(
				"card" => $this->rlPayment->getOption('token'),
				"plan" => $this->getOption('plan'),
				"email" => $this->rlPayment->getOption('email'))
			);                                    

			$txn_id = $customer->cards->data[0]->id;

			if ($customer->subscriptions && $customer->id) {
				$sql = "SELECT * FROM `" . RL_DBPREFIX . "subscriptions` WHERE `Subscription_ID` = '" . $customer->subscriptions->data[0]->id . "' LIMIT 1";
				$subscription_info = $this->reefless->getRow($sql);

				if ($subscription_info['Subscription_ID']) {
					$update = array(
						'fields' => array(
							'Date' => 'NOW()',
							'Txn_ID' => $txn_id,
							'Count' => $subscription_info['Count'] + 1
						),
						'where' => array(
							'Subscription_ID' => $customer->subscriptions->data[0]->id
						)
					);
					
					$action = $this->rlActions->updateOne($update, 'subscriptions');
				} else {
					$insert = array(
							'Service' => $this->rlSubscription->getService($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'),
							'Date' => 'NOW()',
							'Txn_ID' => $txn_id,
							'Customer_ID' => $customer->id,
							'Subscription_ID' => $customer->subscriptions->data[0]->id,
							'Stirpe_item_data' => base64_encode($this->rlPayment->getOption('callback_class') . '|' . 
												$this->rlPayment->getOption('callback_method') . '|' . 
												($this->rlPayment->getOption('plugin') ? $this->rlPayment->getOption('plugin') : false) . '|' . 
												$this->rlPayment->getTransactionID()
											),
							'Count' => 0
						);
						
					$action = $this->rlActions->insertOne($insert, 'subscriptions');
				}
			}
		} catch(Stripe\Error\Card $e) {
			$this->errors[] = $e->getMessage();
		}
	}

	/**
	* create subscription plan
	* 
	* @param string $key
	* @param float $total
	* @param string $name
	* @param string $period
	* 
	* @return mixed
	*/
	public function createSubscriptionPlan($key = false, $total = false, $name = false, $period = 'month')
	{
		if (!$key || !$total || !$period) {
			return;
		}

		$plans = $this->getPlans();

		if (in_array($key, $plans)) {
			return;
		}

		$plan = Stripe\Plan::create(array(
			"amount" => (float)$total * 100,
			"interval" => $period,
			"name" => $name,
			"currency" => $GLOBALS['config']['system_currency_code'],
			"id" => $key)
		);

		return $plan;
	}

	/**
	* delete subscription plan
	* 
	* @param string $key
	*/
	public function deleteSubscriptionPlan($key = false)
	{
		if (!$key) {
			return;
		}
		$plans = $this->getPlans();
		if (in_array($key, $plans)) { 
			$plan = Stripe\Plan::retrieve($key);
			$plan->delete();
		}
	}

    /**
	* cancel subscription for specific plan
	* 
	* @param array $subscription
	*/
	public function cancelSubscription($subscription = false)
	{
		if (!$subscription) {
			return;
		}

		$customer = Stripe\Customer::retrieve($subscription['Customer_ID']);
		$action = $customer->subscriptions->retrieve($subscription['Subscription_ID'])->cancel();

		return $action;
	}

	/**
	* get plans available on stripe service
	* 
	*/
	public function getPlans()
	{
		$plans = array();
		$response = Stripe\Plan::all();

		if ($response->data) {
			foreach($response->data as $k => $v) {
				$plans[] = $v->id;
			}
		}

		return $plans;
	}
      
	/**
	* get card types
	* 
	* @param boolean $output
	* @return array
	*/
	public function getCardTypes($output = true)
	{
		$types = array(
				'visa' => "Visa",
				'mastercard' => "MasterCard",
				'american_express' => "American Express",
				'discover' => "Discover",
				'diners_club' => "Diners Club",
				'jcb' => "JCB"
			);

		if ($output) {
			$GLOBALS['rlSmarty']->assign_by_ref('card_types', $types);
			return;
		}

		return $types;
	}

	/**
	* zet subscription mode
	* 
	* @param boolean $mode
	*/
	public function setSubscription($mode = true)
	{
		$this->subscription = (bool)$mode;
	}
	
	/**
	* chack subscription mode
	* 
	* @return boolean
	* 
	*/
	public function isSubscription()
	{
		if ($this->subscription) {
			return true;
		}
		
		return false;
	}
	
	/**
	* check for errors
	* 
	* @return boolean
	* 
	*/
	public function hasError()
	{
		if ($this->errors) {
			return true;
		}
		
		return false;
	}
	
	/**
	* set dealer credentials 
	* 
	*/
	public function setDealerCredentials(&$dealer_info)
	{
		global $errors;

		if (!$dealer_info) {
			$sql = "SELECT `T1`.`ID`, `T2`.`shc_stripe_enable`, `T2`.`shc_stripe_publishable_key`, `T2`.`shc_stripe_secret_key`, `T2`.`shc_stripe_currency` ";
			$sql .= "FROM `" . RL_DBPREFIX . "shc_orders` AS `T1` ";
			$sql .= "LEFT JOIN `" . RL_DBPREFIX . "accounts` AS `T2` ON `T1`.`Dealer_ID` = `T2`.`ID` ";
			$sql .= "WHERE `T1`.`ID` = '".$this->rlPayment->getOption('item_id')."' ";
			$sql .= "LIMIT 1";

			$dealer_info = $this->getRow($sql);
		}

		if ($dealer_info['shc_stripe_publishable_key'] && $dealer_info['shc_stripe_secret_key']) {
			$GLOBALS['config']['stripe_publishable_key'] = $dealer_info['shc_stripe_publishable_key'];
			$GLOBALS['config']['stripe_secret_key'] = $dealer_info['shc_stripe_secret_key'];
		} else {
			$errors[] = $GLOBALS['lang']['stripe_seller_payment_details_empty'];
		}
	}
	
	/**
	* check settings of the gateway
	* 
	*/
	public function isConfigured()
	{
		if ($GLOBALS['config']['stripe_publishable_key'] && $GLOBALS['config']['stripe_secret_key']) {
			return true;
		}

		return false;
	}
	
	/**
	* get plan details by service
	* 
	*/
	protected function getItemPlan()
	{
		$plan_info = array();
		$service = $this->rlPayment->getOption('service');
		
		if (in_array($service, array('listing', 'package', 'featured'))) {
			$table = 'listing_plans';
		} elseif($service == 'banner') {
			$table = 'banner_plans';
		}

		$GLOBALS['rlHook']->load('stripeGetItemPlan');

		if ($table) {
			$sql = "SELECT * FROM `".RL_DBPREFIX.$table."` WHERE `ID` = '".$this->rlPayment->getOption('plan_id')."' LIMIT 1";
			$plan_info = $this->reefless->getRow($sql);
		}
		
		return $plan_info;
	}
	
	/**
	* get callback response after payment
	* 
	*/
	public function getWebhookResponse()
	{
		$input = @file_get_contents("php://input");
		$response = json_decode($input);
		
		return $response;
	}
	
	/**
	* get subscription ID
	* 
	* @param mixed $subscription_id
	* @return array
	*/
	public function getSubscriptionByID($subscription_id = false)
	{
		if (!$subscription_id) {
			return false;
		}

		$sql = "SELECT * FROM `" . RL_DBPREFIX . "subscriptions` WHERE `Subscription_ID` = '".$subscription_id."' LIMIT 1";
		$subscription_info = $this->reefless->getRow($sql);
		
		if ($subscription_info) {
			$subscription_info['Stirpe_item_data'] = explode("|", base64_decode($subscription_info['Stirpe_item_data']));
		}

		return $subscription_info;
	}
	
	/**
	* get errors
	* 
	* @return array;
	* 
	*/
	public function getErrors()
	{
		if ($this->errors) {
			return $this->errors;
		}

		return array();
	}
	
	/**
	* validate credit card details
	* 
	*/
	public function validate()
	{ 
		$data = $_POST['f'];

		if($_POST['use_account_info'] && empty($this->account_info['Mail'])) {
			$this->errors[] = $GLOBALS['lang']['account_email_not_exists'];
		} 
		if(!$data['email'] && !$_POST['use_account_info']) {
			$this->errors[] = str_replace('{field}', "<b>\"{$GLOBALS['lang']['mail']}\"</b>", $GLOBALS['lang']['notice_field_empty']);
		}
		if (!$data['card_number']) {
			$this->errors[] = str_replace('{field}', "<b>\"{$GLOBALS['lang']['stripe_card_number']}\"</b>", $GLOBALS['lang']['notice_field_empty']);
		}
		if (!$data['exp_month']) {
			$this->errors[] = str_replace('{field}', "<b>\"{$GLOBALS['lang']['stripe_card_expiry_date']}\"</b>", $GLOBALS['lang']['notice_field_empty']);
		}
		if (!$data['exp_year']) {
			$this->errors[] = str_replace('{field}', "<b>\"{$GLOBALS['lang']['stripe_card_expiry_year']}\"</b>", $GLOBALS['lang']['notice_field_empty']);
		}
	}
}