<?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 = '';
*/

class Redsys_pasarela extends Module{
	//Definimos la lista de acciones que ejecutará este módulo
	protected static $actionList = array('');
// para las pruebas de cajamar los datos de prueba son:
	private $Ds_Merchant_MerchantCode = '';
	private $claveComercio256 = '';
	private $url_pago = 'https://sis-t.redsys.es:25443/sis/realizarPago';

// PARA EL ENTORNO REAL AHI QUE COMENTAR LOS DATOS DE ARRIBA Y CAMBIARLOS POR LOS REALES.
	/*private $Ds_Merchant_MerchantCode = '';
	private $claveComercio = '';
	private $claveComercio256 = '';
	private $url_pago = 'https://sis.redsys.es/sis/realizarPago';*/
	
	private $Ds_Merchant_Terminal = '001';
	private $Ds_Merchant_Currency = '978';
	private $Ds_Merchant_TransactionType = '0';
	private $Ds_Merchant_ConsumerLanguage = '001';
	private $Ds_Merchant_MerchantURL = '';
	private $Ds_Merchant_UrlOK = '/';
	private $Ds_Merchant_UrlKO = '/';
	private $Ds_Merchant_Amount = '000';
	private $Ds_Merchant_Order = '000000000000';

	public $Ds_SignatureVersion = 'HMAC_SHA256_V1';
	public $Ds_MerchantParameters = '';
	public $Ds_Signature = '';

	//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->Ds_Merchant_MerchantURL = Shop::$configuracion->url . 'resultado_redsys';
		$this->Ds_Merchant_UrlKO = Shop::$configuracion->url . 'cesta/';
	}
	
	//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(){
		$opciones_recibidas = new ObOptions($this->getModuleOptions());	//Recogemos las opciones que nos puedan haber mandado
		//Utilizamos la Api de RedSys:
		//Necesitamos la librería de redsys
		//vamos a tener en cuenta la versión de php:
		$version = phpversion();
		$version = explode('.', $version);
		$version = intval($version[0]);

		switch($version){
			case 4:
				require_once(_WS_MODULES_DIR_ . strtolower(get_class($this)) . '/lib/redsysHMAC256_API_PHP_4.0.2/apiRedsys.php');
			break;
			case 7:
				require_once(_WS_MODULES_DIR_ . strtolower(get_class($this)) . '/lib/redsysHMAC256_API_PHP_7.0.0/apiRedsys.php');
			break;
			case 5:
			default:	//La versión 5 es la que vamos a poner por defecto
				require_once(_WS_MODULES_DIR_ . strtolower(get_class($this)) . '/lib/redsysHMAC256_API_PHP_5.2.0/apiRedsys.php');
			break;
		}
		//Vamos a controlar de las opciones recibidas en qué estamos:
		$chequear_pago = $opciones_recibidas->getDefaultValue('chequear_pago', false);
		if ($chequear_pago){
			$options = $this->checkPago($opciones_recibidas);
		}else{
			$options = $this->generarFormularioPasarela();
		}
		//Lo último es asignar las opciones a la vista
		$this->setViewOptions($options);
	}

	private function generarFormularioPasarela(){
		//Ojo, el número de pedido NO es el código si no un contador:
		$cart = CabeceraCesta::getCart();
		
		$cart->incrementarNumeroPedido();
		$this->init($cart);
		$options = new stdClass();
		//Como es para las pruebas no voy a comprobar nada
		$pasarela = $cart->pasarela(1);
		$options->pasarela = $pasarela;	//El tipo de la pasarela de redsys, por ahora, es 1
		//Si no hay pasarela no seguimos:
		if ($pasarela){
			$conector = new RedsysAPI;
			//Parámetros fijos
			$conector->setParameter('DS_MERCHANT_MERCHANTCODE', $this->Ds_Merchant_MerchantCode);
			$conector->setParameter('DS_MERCHANT_TERMINAL', $this->Ds_Merchant_Terminal);
			$conector->setParameter('DS_MERCHANT_TRANSACTIONTYPE', $this->Ds_Merchant_TransactionType);
			$conector->setParameter('DS_MERCHANT_CURRENCY', $this->Ds_Merchant_Currency);
			$conector->setParameter('DS_MERCHANT_MERCHANTURL', $this->Ds_Merchant_MerchantURL);
			$conector->setParameter('DS_MERCHANT_CONSUMERLANGUAGE', $this->Ds_Merchant_ConsumerLanguage);
			$conector->setParameter('DS_MERCHANT_URLOK', $this->Ds_Merchant_UrlOK);
			$conector->setParameter('DS_MERCHANT_URLKO', $this->Ds_Merchant_UrlKO);
			//Parámetros variables
			$conector->setParameter('DS_MERCHANT_AMOUNT', $this->Ds_Merchant_Amount);
			$conector->setParameter('DS_MERCHANT_ORDER', $this->Ds_Merchant_Order);
			$conector->setParameter('DS_MERCHANT_PRODUCTDESCRIPTION', 'Pedido a ' . Shop::$empresa->nombre);
			//$conector->setParameter('DS_MERCHANT_TITULAR', quitar_tildes($Ds_Merchant_Titular));
			$conector->setParameter('DS_MERCHANT_MERCHANTNAME', Shop::$empresa->nombre_legal);

			$this->Ds_MerchantParameters = $conector->createMerchantParameters();
			$this->Ds_Signature = $conector->createMerchantSignature($this->claveComercio256);
			//Vamos a componer las opciones:
			$options->Ds_SignatureVersion = $this->Ds_SignatureVersion;
			$options->Ds_MerchantParameters = $this->Ds_MerchantParameters;
			$options->Ds_Signature = $this->Ds_Signature;
			$options->url_pago = $this->url_pago;
		}
		return($options);
	}
	
	private function checkPago($opciones_recibidas){
		$templateFile = 'resultado_compra_incorrecta.php';
		$options = new stdClass();
		$opciones_recibidas = new ObOptions($opciones_recibidas);
		$Ds_SignatureVersionOriginal = 'HMAC_SHA256_V1';
		$Ds_SignatureVersion = $opciones_recibidas->getDefaultValue('Ds_SignatureVersion', '');
		$Ds_MerchantParameters = $opciones_recibidas->getDefaultValue('Ds_MerchantParameters', '');
		$Ds_Signature = $opciones_recibidas->getDefaultValue('Ds_Signature', '');
		//Vamos a capturar la salida:
		ob_start();
		if ( 
			(trim($Ds_SignatureVersion) != '') && 
			(trim($Ds_MerchantParameters) != '') && 
			(trim($Ds_Signature) != '') && 
			($Ds_SignatureVersionOriginal == $Ds_SignatureVersion) 
		){
			//Vamos a cargar los datos recibidos por la pasarela
			$conector = new RedsysAPI;
			$version = $conector->ver();
			$decoded = $conector->decodeMerchantParameters($Ds_MerchantParameters);
			$Ds_Date = $conector->getParameter("Ds_Date");
			$Ds_Hour = $conector->getParameter("Ds_Hour");
			$Ds_Amount = $conector->getParameter("Ds_Amount");
			$Ds_Currency = $conector->getParameter("Ds_Currency");
			$Ds_Order = $conector->getParameter("Ds_Order");
			$Ds_MerchantCode = $conector->getParameter("Ds_MerchantCode");
			$Ds_Terminal = $conector->getParameter("Ds_Terminal");
			$Ds_Response = $conector->getParameter("Ds_Response");
			$Ds_MerchantData = $conector->getParameter("Ds_MerchantData");
			$Ds_SecurePayment = $conector->getParameter("Ds_SecurePayment");
			$Ds_TransactionType = $conector->getParameter("Ds_TransactionType");
			$Ds_Card_Country = $conector->getParameter("Ds_Card_Country");
			$Ds_AuthorisationCode = $conector->getParameter("Ds_AuthorisationCode");
			$Ds_ConsumerLanguage = $conector->getParameter("Ds_ConsumerLanguage");
			$Ds_Card_Number = $conector->getParameter("Ds_Card_Number");	//==> Quitado porque no nos van a pasar el número de tarjeta ni lo necesitamos
			//Teniendo los datos vamos a cargar la cesta con el código recibido:
			$cesta = new CabeceraCesta(array(
				'numero_pedido' => intval($Ds_Order),
				'fusionarCesta' => false	//EXTREMADAMENTE IMPORTANTE, ESTE PROCESO SE EJECUTA SIN USUARIO Y LA CESTA TIENE USUARIO. HAY QUE EVITAR QUE INTENTE FUSIONAR
			));
			$this->init($cesta);	//Ahora inicializamos las variables de este módulo, una vez que tengo una cesta
			//Teniendo toda esta información, vamos a calcular la firma recibida
			$firma = $conector->createMerchantSignatureNotif($this->claveComercio256, $Ds_MerchantParameters);	
			if ( $firma === $Ds_Signature ){
			?>
Versión final de la librería: <?=$version;?>
Hemos recibido esta informacion de la pasarela:
Fecha: <?=$Ds_Date;?>---------------
Hora: <?=$Ds_Hour;?>---------------
Importe: <?=$Ds_Amount;?>---------------
Moneda: <?=$Ds_Currency;?>---------------
Orden: <?=$Ds_Order;?>---------------
Cod. comercio: <?=$Ds_MerchantCode;?>---------------
Terminal: <?=$Ds_Terminal;?>---------------
Firma: <?=$Ds_Signature;?>---------------
Respuesta: <?=$Ds_Response;?>---------------
Datos: <?=$Ds_MerchantData ;?>---------------
Tipo de pago: <?=$Ds_SecurePayment;?>---------------
Tipo de transacción: <?=$Ds_TransactionType;?>---------------
País de la tarjeta: <?=$Ds_Card_Country;?>---------------
Código de autorización: <?=$Ds_AuthorisationCode;?>---------------
Lenguaje del comercio: <?=$Ds_ConsumerLanguage;?>---------------
Número de tarjeta: <?=$Ds_Card_Number;?>---------------
				<?php
				//Finalizamos la compra:
				if ($Ds_Order > 0){
					if ($Ds_Response > 100){
						echo($this->getError($Ds_Response));
					}else if ($cesta->codigo > 0){
						//Vamos a asegurarnos de que todo es correcto:
						$ready = $cesta->readyToFinish();
						echo("Ready es : {$ready}<br/>");
						if ($ready >= 200){
							$pedido = $cesta->finish();
							//Vamos a dar el pedido por pagado:
							if ($pedido != NULL){
								$pedido->pagado();
								$templateFile = 'resultado_compra_correcta.php';
								?>
								----------------------------------------------------------------------------------------------------------------------------------------
								----------------------------------------------------------------------------------------------------------------------------------------
																		CORRECTO, PEDIDO FINALIZADO CON CÓDIGO <?=$pedido->codigo;?>
								----------------------------------------------------------------------------------------------------------------------------------------
								----------------------------------------------------------------------------------------------------------------------------------------
								<?php
							}else{
								?>
								----------------------------------------------------------------------------------------------------------------------------------------
								----------------------------------------------------------------------------------------------------------------------------------------
																	INCORRECTO, Error al crear el pedido
								----------------------------------------------------------------------------------------------------------------------------------------
								----------------------------------------------------------------------------------------------------------------------------------------
								<?php
							}
						}else{
							?>
							----------------------------------------------------------------------------------------------------------------------------------------
							----------------------------------------------------------------------------------------------------------------------------------------
																INCORRECTO, PEDIDO NO FINALIZADO CON ERROR <?=$ready;?>
							----------------------------------------------------------------------------------------------------------------------------------------
							----------------------------------------------------------------------------------------------------------------------------------------
							<?php
						}
					}else{
						var_dump($cesta);
						?>
						----------------------------------------------------------------------------------------------------------------------------------------
						----------------------------------------------------------------------------------------------------------------------------------------
						    EL PEDIDO NO SE HA PODIDO FINALIZAR PORQUE EL CÓDIGO DE PEDIDO RECIBIDO NO COINCIDE CON NINGUNA CESTA EXISTENTE EN LA BASE DE DATOS
						----------------------------------------------------------------------------------------------------------------------------------------
						----------------------------------------------------------------------------------------------------------------------------------------
						<?php
					}
				}else{
					?>
					----------------------------------------------------------------------------------------------------------------------------------------
					----------------------------------------------------------------------------------------------------------------------------------------
					                      EL PEDIDO NO SE HA PODIDO FINALIZAR PORQUE EL CÓDIGO DE PEDIDO RECIBIDO ES 0
					----------------------------------------------------------------------------------------------------------------------------------------
					----------------------------------------------------------------------------------------------------------------------------------------
					<?php
				}
			}else{
				//Ha ocurrido un error, vamos a enviar un email a la empresa informando:
				?>
				----------------------------------------------------------------------------------------------------------------------------------------
				----------------------------------------------------------------------------------------------------------------------------------------
				                            EL PEDIDO NO SE HA PODIDO FINALIZAR PORQUE LAS FIRMAS NO COINCIDEN
				----------------------------------------------------------------------------------------------------------------------------------------
				----------------------------------------------------------------------------------------------------------------------------------------
				<?php
			}
		}
		//Enviamos un email a la empresa con los datos técnicos de la pasarela
		$texto = ob_get_clean();
		echo($texto);
		//Pedro 10/Octubre/2019 ==> Quito este email porque ya se envía uno desde la pasarela
		/*Email::sendMail(array(
			'destinatario' => Shop::$empresa->direccion_email . ',' . Shop::$empresa->nombre_legal,
			'asunto' => 'Resultado intento pago pasarela ',
			'contenido' => 'Hemos recibido un intento de pago. Estos son los datos técnicos:<br/>
			Ds_SignatureVersion = ' . $Ds_SignatureVersion . "\r\n" . '
			Ds_MerchantParameters = ' . $Ds_MerchantParameters . "\r\n" . '
			Ds_Signature = ' . $Ds_Signature . "\r\n" . '
			Parametros decodificados: ' . $decoded . "\r\n" . '
			Firma calculada: ' . $firma . "\r\n" . '
			Texto:' . "\r\n" . '
			'. $texto
		));*/
		$this->setTemplateFile($templateFile);
		return($options);
	}
	
	private function init($cart){
		//Estas variables se asignan en función de la cesta
		$this->Ds_Merchant_Amount = number_format($cart->importe + $cart->g_envio, 2, '', '');
		$this->Ds_Merchant_Order = str_pad($cart->numero_pedido, 12, '0', STR_PAD_LEFT);
		$this->Ds_Merchant_UrlOK = Shop::$configuracion->url . 'finalizar_compra/' . $this->Ds_Merchant_Order;
	}
	
	private function getError($codigoError){
		$retorno = 'Error sin identificar';
		switch($codigoError){
			case 101:
				$retorno = 'Tarjeta caducada';
			break;
			case 102:
				$retorno = 'Tarjeta en excepción transitoria o bajo sospecha de fraude';
			break;
			case 106:
				$retorno = 'Intentos de PIN excedidos';
			break;
			case 125:
				$retorno = 'Tarjeta no efectiva';
			break;
			case 129:
				$retorno = 'Código de seguridad (CVV2/CVC2) incorrecto';
			break;
			case 180:
				$retorno = 'Tarjeta ajena al servicio';
			break;
			case 184:
				$retorno = 'Error en la autenticación del titular';
			break;
			case 190:
				$retorno = 'Denegación sin especificar Motivo';
			break;
			case 191:
				$retorno = 'Fecha de caducidad errónea';
			break;
			case 202:
				$retorno = 'Tarjeta en excepción transitoria o bajo sospecha de fraude con retirada de tarjetaa';
			break;
			case 904:
				$retorno = 'Comercio no registrado en FUC';
			break;
			case 909:
			case 9912:
				$retorno = 'Error de sistema';
			break;
			case 912:
				$retorno = 'Emisor no disponible';
			break;
			case 950:
				$retorno = 'Operación de devolución no permitida';
			break;
			case 9064:
				$retorno = 'Número de posiciones de la tarjeta incorrecto';
			break;
			case 9078:
				$retorno = 'No existe método de pago válido para esa tarjeta';
			break;
			case 9093:
				$retorno = 'Tarjeta no existente';
			break;
			case 9218:
				$retorno = 'El comercio no permite op. seguras por entrada /operaciones';
			break;
			case 9253:
				$retorno = 'Tarjeta no cumple el check-digit';
			break;
			case 9256:
				$retorno = 'El comercio no puede realizar preautorizaciones';
			break;
			case 9257:
				$retorno = 'Esta tarjeta no permite operativa de preautorizaciones';
			break;
			case 9261:
				$retorno = 'Operación detenida por superar el control de restricciones en la entrada al SIS';
			break;
			case 9913:
				$retorno = 'Error en la confirmación que el comercio envía al TPV Virtual (solo aplicable en la opción de sincronización SOAP)';
			break;
			case 9914:
				$retorno = 'Confirmación “KO” del comercio (solo aplicable en la opción de sincronización SOAP)';
			break;
			case 9928:
				$retorno = 'Anulación de autorización en diferido realizada por el SIS (proceso batch)';
			break;
			case 9929:
				$retorno = 'Anulación de autorización en diferido realizada por el comercio';
			break;
			case 9104:
				$retorno = 'Comercio con “titular seguro” y titular sin clave de compra segura';
			break;
			case 9915:
				$retorno = 'A petición del usuario se ha cancelado el pago';
			break;
			case 9094:
				$retorno = 'Rechazo servidores internacionales';
			break;
			case 944:
				$retorno = 'Sesión Incorrecta';
			break;
			case 913:
				$retorno = 'Pedido repetido';
			break;
		}
		return($retorno);
	}
}