<?php
//---------------------------------------------------------------------------------------------------------
// 08/Noviembre/2018 ==> Módulo encargado de los pagos a redsys
//---------------------------------------------------------------------------------------------------------
//Los módulos heredan los atributos de la clase Module:
/*	$templateFile = '';
	$loadedModules = array();
	$modulesList = array();
	$options = NULL;
	$data_update = '';
*/

//Necesitamos poder usar las librerías de PayPal
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Core\ProductionEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalCheckoutSdk\Orders\OrdersGetRequest;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
//use PayPalCheckoutSdk\Orders\OrdersAuthorizeRequest;
//use PayPalCheckoutSdk\Payments\AuthorizationsCaptureRequest;

class Paypal extends Module{
	//Definimos la lista de acciones que ejecutará este módulo
	protected static $actionList = array('');

	//Valores del módulo:
	private static $id = 'AQeTfVZzzZZXYKWVercgPMMvqCtFFwfcCb8naGMVaT91xzLlxmU7oEGzraXlJp2N2HqDpO7YwpNjGgXL';	//Real
	//private static $id = 'AXhikvfLnoFIMB7yCHz5t9hAwSC2I1kO6ppDsZJ93y2-jgyaauwnBy9FDzDutrth-r4Bjz_oHq6zPUV3';	//sandbox
	private static $secret_key = 'EAAIOPNkt6OsFDpFQB6I9kQy5zUfH-Ddkn7yCE7015XtYPXGFA01DUDJDxp3MoI2f1mTlxGwqp8p-rvz';	//Real
	//private static $secret_key = 'EA2MnADcAEUfrwp4qlrTZGDe68bwCxqxRhjX6nJyYg7QdKLbKPkpIyLxYRD8tuo6TBXq2RX3rr5YkK7q';	//Sandbox
	
	private static $sandbox = true;	//Poner a false para modo "live"
	
	//Función que instala el módulo
	public function install(){
		
	}
	
	//Función que desinstala el módulo
	public function uninstall(){
		
	}
	
	
	//constructor:
	public function __construct() {
		//Vamos a inicializar algunas variables
		$this->notify_url = Shop::$configuracion->url . 'resultado_paypal';
	}
	
	//Aquí vienen ahora las funciones que se encargan de añadir funciones a los eventos de webStore
	
	//Esta función es la encargada de ejecutar del módulo lo que sea necesario:
	public function execute(){
		//El objto opciones será el que se le pasa a la vista
		$options = new stdClass();
		//Vamos a ver qué opciones hemos recibido
		$opciones_recibidas = new ObOptions($this->getModuleOptions());
		//Vamos a ver si estamos creando el pago:
		$createOrder = $opciones_recibidas->getDefaultValue('createOrder', true);	//Por defecto vamos a crear una "orden" para paypal
		if ($createOrder){
			//Vamos a tirar de la sdk de paypal:
			require _WS_MODULES_DIR_ . strtolower(get_class($this)) . '/lib/vendor/autoload.php';

			//1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.			
			//Empezamos creando el "ambiente"
			
			$httpClient = self::getPayPalHttpClient();
			
			if ($httpClient != NULL){
				//Para componer ahora la petición, empezamos creando un pedido:
				$request = new OrdersCreateRequest();
				$request->prefer('return=representation');
				$request->body = self::componer_pago();
				//Teniendo la petición, vamos a ejecutarla sobre el cliente http que hemos configurado
				$response = $httpClient->execute($request);
				if (false)
				{
				  print "Status Code: {$response->statusCode}\n";
				  print "Status: {$response->result->status}\n";
				  print "Order ID: {$response->result->id}\n";
				  print "Intent: {$response->result->intent}\n";
				  print "Links:\n";
				  foreach($response->result->links as $link)
				  {
					print "\t{$link->rel}: {$link->href}\tCall Type: {$link->method}\n";
				  }

				  // To print the whole response body, uncomment the following line
				  // echo json_encode($response->result, JSON_PRETTY_PRINT);
				}

				// 4. Return a successful response to the client.
				$options->response = $response;
			}
		}else{
			$options->id = self::$id;
		}
				
		$this->setViewOptions($options);
		//var_dump($this->viewOptions);
		//Dejamos que se cargue la vista correspondiente
		
		//TODO ==> En el futuro aquí comprobaremos otras cosas
		/*
		$opciones_recibidas = new ObOptions($this->getModuleOptions());	//Recogemos las opciones que nos puedan haber mandado
		//$variable = $opciones_recibidas->getDefaultValue('nombre', false);
		
		
		//El objto opciones será el que se le pasa a la vista
		$options = new stdClass();
				
		$chequear_pago = $opciones_recibidas->getDefaultValue('chequear_pago', false);
		if ($chequear_pago){
			$options = $this->checkPago($opciones_recibidas);
		}else{
			//Cuando se muestra el formulario de PayPal es cuando incrementamos el número de pedido
			$cart = CabeceraCesta::getCart();
			$cart->incrementarNumeroPedido();
			$options->id = self::$id;
			
		}

			
		//Lo último es asignar las opciones a la vista
		$this->setViewOptions($options);
		*/
	}

	private static function componer_pago($intent = 'CAPTURE'){
		$cart = CabeceraCesta::getCart();
		//Vamos a obtener un número de pedido
		$cart->incrementarNumeroPedido();
		$lineas_pedido = array();
		foreach($cart->lineas as $clave => $linea){
			$articulo = $linea->objeto_articulo;
			$lineas_pedido[] = array(
				'name' => $articulo->nombre,
				'description' => $articulo->nombre,
				'sku' => $articulo->ean,
				'unit_amount' => array(
					'currency_code' => 'EUR',
					'value' => number_format($linea->pvp_unitario, 2)
				),
				'quantity' => $linea->cantidad
			);
		}

		return(array(
			'intent' => $intent,
			'application_context' => array(
				'brand_name' => Shop::$empresa->nombre,
				'locale' => 'es-ES',
				'landing_page' => 'BILLING',
				'shipping_preferences' => 'SET_PROVIDED_ADDRESS',
				'user_action' => 'PAY_NOW',
			),
			'purchase_units' => array(
				0 => array(
					'reference_id' => $cart->numero_pedido,
					'description' => 'Compra en ' . Shop::$empresa->nombre_legal,
					'custom_id' => $cart->numero_pedido,
					'soft_descriptor' => Shop::$empresa->nombre_legal,
					'amount' => array(
						'currency_code' => 'EUR',
						'value' => number_format($cart->importe + $cart->g_envio, 2),
						'breakdown' => array(
							'item_total' => array(
								'currency_code' => 'EUR',
								'value' => number_format($cart->importe, 2)
							),
							'shipping' => array(
								'currency_code' => 'EUR',
								'value' => number_format($cart->g_envio, 2)
							)
						)
					),
					'items' => $lineas_pedido
				)
			)
		));
	}

	private static function getPayPalHttpClient(){
		$enviroment = NULL;			//Entoron en que el vamos a trabajar
		$httpClient = NULL;			//conexion HTTP con la que hacer peticiones

		if (self::$sandbox){
			$enviroment = new SandboxEnvironment(self::$id, self::$secret_key);
		}else{
			$enviroment = new ProductionEnvironment(self::$id, self::$secret_key);
		}

		if ($enviroment != NULL){
			$httpClient = new PayPalHttpClient($enviroment);
			//var_dump($httpClient);
		}

		return($httpClient);
	}
	/*
	private function checkPago($opciones_recibidas){
		$options = new stdClass();
		ob_start();
			//Vamos a incluir la librería que hemos descargado:
			require_once(_WS_MODULES_DIR_ . strtolower(get_class($this)) . '/lib/PaypalPN.php');
			$checker = new PaypalIPN();
			//COnfiguramos el objeto:
			$checker->useSandbox();	//Estamos indicando que usamos el sandbox
			$checker->usePHPCerts(false);	//Para que no use ficheros de certificado
			//Ejecutamos la verificación:
			if ($checker->verifyIPN()){
				echo('Pago verificado correctamente' . "\n");
				$parametros = $checker->getPayPalValues();
				$numero_pedido = $parametros['invoice'];
				if ($numero_pedido > 0){
					echo("Cargamos la cesta con el número de pedido $numero_pedido\n");
					//Vamos a finalizar la cesta:
					$cesta = new CabeceraCesta(array(
						'numero_pedido' => intval($numero_pedido),
						'fusionarCesta' => false	//EXTREMADAMENTE IMPORTANTE, ESTE PROCESO SE EJECUTA SIN USUARIO Y LA CESTA TIENE USUARIO. HAY QUE EVITAR QUE INTENTE FUSIONAR
					));
					echo("Finalizamos la compra\n");
					//Finalizamos la compra
					$pedido = $cesta->finish();
					//Vamos a dar el pedido por pagado:
					echo("Damos el pedido por pagado\n");
					$pedido->pagado();
				}else{
					echo("Hemos recibido un número de pedido erroneo\n");
				}
			}else{
				echo('Pago NO verificado' . "\n");
			}
			//Para las trazas voy a coger los parámetros:
			echo('Estos son los parámetros con los que hemos trabajado:' . "\n");
			$parametros = $checker->getPayPalValues();
			$options->parametros = $parametros;
			var_dump($parametros);
			
		//Recogemos la caché:
		$resultado = ob_get_clean();
		//Y nos enviamos un email con el resultado
		Email::sendMail(array(
			//'destinatario' => Shop::$empresa->direccion_email . ',' . Shop::$empresa->nombre_legal,
			'destinatario' => 'pedro@arminet.es,' . Shop::$empresa->nombre_legal,
			'asunto' => 'Datos técnicos pasarela ',
			'contenido' => 'Estos son los datos técnicos de la respuesta de la web a una solicitud de confirmación de PayPal:
			' . $resultado
		));
		//Indicamos cual es el fichero a mostrar
		$this->setTemplateFile('resultado_compra_correcta.php');
		return($options);
	}
	*/
	
	public static function remoteCheck($data){
		//Importante el autoload:
		require _WS_MODULES_DIR_ . strtolower(get_called_class()) . '/lib/vendor/autoload.php';
		//Vamos a componer el retorno
		$retorno = new stdClass();
		$retorno->resultado = array();
		$numero_pedido = 0;
		//Vamos a recoger los datos de entrada:
		if (is_string($data)){
			$data = json_decode($data);
		}
		
		//$data == Tiene que ser un array:
		$orderId = $orderID = '';
		if (isset($data->orderID)){
			$orderID = $data->orderID;
		}
		//Para poder usar orderID y orderId vamos a igualar los valores:
		$orderId = $orderID;
		ob_start();
		if ($orderID != ''){
			//De aquí en adelante vamos a generar el email con los datos técnicos:
			ob_start();
			echo("Datos recibidos de paypal:\n");
			echo(json_encode($data, JSON_PRETTY_PRINT));
			echo("\n-----------------------------------\n");

			$httpClient = self::getPayPalHttpClient();
			if ($httpClient != NULL){
				echo("Una vez ejecutada la consulta a paypal vamos a mostrar el resulatdo:\n");
				$response = $httpClient->execute(new OrdersGetRequest($orderID));
				//var_dump($response);
				echo(json_encode($response, JSON_PRETTY_PRINT));
				echo("\n-----------------------------------\n");


				//Según lo que hayamos recibido, vamos a aceptar el pago:
				if ( ($response->statusCode == '200') && ($response->result->status == 'APPROVED') ){
					//Capturamos y mostramos en el log el resto de info de la orden:
					$response = $httpClient->execute(new OrdersCaptureRequest($orderID));
					echo(json_encode($response, JSON_PRETTY_PRINT));
					echo("\n-----------------------------------\n");
					//Ahora vamos a analizar el status code:
					if ($response->statusCode >= 200 && $response->statusCode <= 299){
						//Vamos a comprobar que el importe coincida:
						$pagos = $response->result->purchase_units[0]->payments;
						//Vamos a ver si está correcto:
						$paymentStatus = $pagos->captures[0]->status;
						if ($paymentStatus == 'COMPLETED'){

							$numero_pedido = $response->result->purchase_units[0]->reference_id;
							echo("Número de pedido: {$numero_pedido}\n");
							echo("compra correcta, comprobamos el importe:\n");
							$cart = new CabeceraCesta(array(
								'numero_pedido' => intval($numero_pedido),
								'fusionarCesta' => false	//EXTREMADAMENTE IMPORTANTE, ESTE PROCESO SE EJECUTA SIN USUARIO Y LA CESTA TIENE USUARIO. HAY QUE EVITAR QUE INTENTE FUSIONAR
							));
							$importe_cesta = number_format($cart->importe + $cart->g_envio, 2);
							$importePayPal = $pagos->captures[0]->amount->value;
							echo("Importe cesta: $importe_cesta\n");
							echo("Importe PayPal: $importePayPal\n");
							if ($importe_cesta == $importePayPal){
								//TOMA PEDIDO PAYPAL!!!!!!
								echo("Finalizamos la compra\n");
								echo ("Listo para finalizarse: " . $cart->readyToFinish() . "\n");
								//Finalizamos la compra
								$pedido = $cart->finish();
								//Vamos a dar el pedido por pagado:
								echo("Damos el pedido por pagado\n");
								(is_object($pedido)) ? ($pedido->pagado()) : ($numero_pedido = 0);	//Si el pedido es un objeto, lo finalizamos:
							}else{
								echo("Los importes no coinciden. Por favor compruebe el pedido en PayPal\n");
							}
						}
					}
					
				}

			}
			$texto = ob_get_clean();
			Email::sendMail(array(
				//'destinatario' => Shop::$empresa->direccion_email . ',' . Shop::$empresa->nombre_legal,
				'destinatario' => 'pedro@arminet.es,' . Shop::$empresa->nombre_legal,
				'asunto' => 'Datos técnicos pasarela ',
				'contenido' => 'Estos son los datos técnicos de la respuesta de la web a una solicitud de confirmación de PayPal:
				' . $texto
			));
		}
		//Obtenemos la respuesta para mostrarla		
		$texto = ob_get_clean();
		$retorno->resultado[] = $texto;
		$retorno->numero_pedido = $numero_pedido;
		//Aquí tenemos que dar un retorno:
		$retorno = json_encode($retorno);
		return($retorno);
	}
}