<?php
class ControllerPaymentBcash extends Controller {

	public function index() {
		$this->language->load('payment/bcash');

		$data['button_confirm'] = $this->language->get('button_confirm_bcash');
		$data['text_instruction'] = $this->language->get('text_instruction');
		$data['text_loading'] = $this->language->get('text_loading');

		$order_id = $this->session->data['order_id'];

		$this->load->model('checkout/order');
		$order_info = $this->model_checkout_order->getOrder($order_id);

		$campos = array();
		$campos['email_loja'] = $this->config->get('bcash_email');
		$campos['token'] = $this->config->get('bcash_token');
		$campos['url_retorno'] = $this->url->link('payment/bcash/retorno');
		$campos['url_aviso'] = $this->url->link('payment/bcash/retorno');
		$campos['redirect'] = 'true';
		$campos['tipo_integracao'] = 'PAD';

		/*
		 * Dados do cliente
		 */

		$customer_name = trim($order_info['payment_firstname'] .' '. $order_info['payment_lastname']);
		$campos['nome'] = html_entity_decode($customer_name, ENT_QUOTES, 'UTF-8');

		$customer_email = trim($order_info['email']);
		$campos['email'] = html_entity_decode($customer_email, ENT_QUOTES, 'UTF-8');

		$customer_telefone = preg_replace('/[^0-9]/', '', $order_info['telephone']);
		if ($customer_telefone != '') {
			$campos['telefone'] = $customer_telefone;
		}

		$customer_celular = isset($order_info['custom_field']['celular']) ? $order_info['custom_field']['celular'] : '';
		$customer_celular = preg_replace ('/[^0-9]/', '', $customer_celular);
		if ($customer_celular != '') {
			$campos['celular'] = $customer_celular;
		}

		$customer_nascimento = isset($order_info['custom_field']['nascimento']) ? $order_info['custom_field']['nascimento'] : '';
		if ($customer_nascimento != '' && $customer_nascimento != '0000-00-00') {
			$campos['data_nascimento'] = date('d/m/Y', strtotime($customer_nascimento));
		}

		$customer_cpf = isset($order_info['custom_field']['cpf']) ? $order_info['custom_field']['cpf'] : '';
		if($this->validaCPF($customer_cpf)){
			$campos['cpf'] = preg_replace ('/[^0-9]/', '', $customer_cpf);
		}

		$customer_rg = isset($order_info['custom_field']['rg']) ? $order_info['custom_field']['rg'] : '';
		$customer_rg = preg_replace ('/[^0-9]/', '', $customer_rg);
		if($customer_rg != ''){
			$campos['rg'] = html_entity_decode($customer_rg, ENT_QUOTES, 'UTF-8');
		}

		$customer_cnpj = isset($order_info['custom_field']['cnpj']) ? $order_info['custom_field']['cnpj'] : '';
		if($this->validaCNPJ($customer_cnpj)){
			$campos['cliente_cnpj'] = preg_replace ('/[^0-9]/', '', $customer_cnpj);
		}

		$customer_razao = isset($order_info['custom_field']['razao']) ? $order_info['custom_field']['razao'] : '';
		$customer_razao = preg_replace ('/[^0-9]/', '', $customer_razao);
		if($customer_razao != ''){
			$campos['cliente_razao_social'] = html_entity_decode($customer_razao, ENT_QUOTES, 'UTF-8');
		}

		/*
		 * Frete
		 */

		$field = $this->cart->hasShipping() ? 'shipping' : 'payment';

		$this->load->model('localisation/zone');
		$zone = $this->model_localisation_zone->getZone($order_info["{$field}_zone_id"]);

		$customer_cep = preg_replace ('/[^0-9]/', '', $order_info["{$field}_postcode"]);
		if ($customer_cep != '') {
			$campos['cep'] = $customer_cep;
		}

		$customer_endereco = $order_info["{$field}_address_1"];
		$customer_number = isset($order_info["{$field}_custom_field"]['numero']) ? $order_info["{$field}_custom_field"]['numero'] : '';
		if ($customer_endereco != '') {
			if ($customer_number != '') {
				$customer_endereco .= ', ' . $customer_number;
			}
			$campos['endereco'] = html_entity_decode($customer_endereco, ENT_QUOTES, 'UTF-8');
		}

		$customer_complemento = isset($order_info["{$field}_custom_field"]['complemento']) ? $order_info["{$field}_custom_field"]['complemento'] : '';
		if ($customer_complemento != '') {
			$campos['complemento'] = html_entity_decode($customer_complemento, ENT_QUOTES, 'UTF-8');
		}

		$customer_bairro = $order_info["{$field}_address_2"];
		if ($customer_bairro != '') {
			$campos['bairro'] = html_entity_decode($customer_bairro, ENT_QUOTES, 'UTF-8');
		}

		$customer_cidade = $order_info["{$field}_city"];
		if ($customer_cidade != '') {
			$campos['cidade'] = html_entity_decode($customer_cidade, ENT_QUOTES, 'UTF-8');
		}

		$customer_estado = isset($zone['code']) ? $zone['code'] : '';
		if ($customer_estado != '') {
			$campos['estado'] = html_entity_decode($customer_estado, ENT_QUOTES, 'UTF-8');
		}

		// utiliza valor de frete zero, pois este valor sera enviado como um produto extra
		$campos['frete'] = 0.00;
		$campos['tipo_frete'] = $order_info['shipping_method'];

		/*
		 * Produtos
		 */

		$count_products = 0;

		foreach ($this->cart->getProducts() as $product) {
			$count_products++;

			$options_names = array();
			foreach ($product['option'] as $option) {
				if (in_array($option['type'], array('select','radio','checkbox','image'))) {
					$options_names[] = $option['value'];
				}
			}
			$options_names = implode('/', $options_names);
			if ($options_names) { $options_names = " ({$options_names})"; }

			$value = $this->currency->convert($product['price'], $this->config->get('config_currency'), $order_info['currency_code']);

			$campos['produto_codigo_'.$count_products]    = $product['product_id'];
			$campos['produto_descricao_'.$count_products] = $product['name'].$options_names;
			$campos['produto_qtde_'.$count_products]      = $product['quantity'];
			$campos['produto_valor_'.$count_products]     = number_format($value, 2, '.', '');
		}

		// vales presentes
		$vouchers = isset($this->session->data['vouchers']) ? $this->session->data['vouchers'] : array();

		$total_voucher = 0;
		$count_vouchers = 0;

		foreach ($vouchers as $voucher_id => $voucher) {
			$count_vouchers++;
			$count_products++;

			$amount = $this->currency->convert($voucher['amount'], $this->config->get('config_currency'), $order_info['currency_code']);
			$total_voucher += $amount;

			$campos['produto_codigo_'.$count_products]    = 'voucher_'.$count_vouchers;
			$campos['produto_descricao_'.$count_products] = $voucher['description'];
			$campos['produto_qtde_'.$count_products]      = 1;
			$campos['produto_valor_'.$count_products]     = number_format($amount, 2, '.', '');
		}

		// total extra do pedido (frete, descontos e taxas) pode ser um valor positivo ou negativo
		$total_extra = $this->currency->format($order_info['total'] - $this->cart->getSubTotal() - $total_voucher, $order_info['currency_code'], false, false);

		$campos['desconto'] = 0.00;

		// se o extra for positivo adiciona como produto
		if ($total_extra > 0) {
			$count_products++;

			$campos['produto_codigo_'.$count_products]    = 'extra_amount';
			$campos['produto_descricao_'.$count_products] = $this->language->get('text_extra_amount');
			$campos['produto_qtde_'.$count_products]      = 1;
			$campos['produto_valor_'.$count_products]     = number_format($total_extra, 2, '.', '');
		}
		// se o extra for negativo envia como desconto
		elseif ($total_extra < 0) {
			$campos['desconto'] = number_format($total_extra * (-1), 2, '.', ''); // precisa ser um valor positivo
		}

		// referencia do pedido
		if ($this->config->get('bcash_posfixo') != '') {
			$campos['id_pedido'] = $order_id . '_' . $this->config->get('bcash_posfixo');
		} else {
			$campos['id_pedido'] = $order_id;
		}

		if ($this->config->get('bcash_hash') == '1') {
			$arrHash = $campos;
			ksort($arrHash);
			$hash = md5(http_build_query($arrHash).$campos['token']);
			$campos['hash'] = $hash;
		}

		$data['action'] = 'https://www.bcash.com.br/checkout/pay/';
		$data['campos'] = $campos;

		if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/bcash.tpl')) {
			return $this->load->view($this->config->get('config_template') . '/template/payment/bcash.tpl', $data);
		} else {
			return $this->load->view('default/template/payment/bcash.tpl', $data);
		}
	}

	public function confirm() {
		if ($this->session->data['payment_method']['code'] == 'bcash') {
			$this->load->model('checkout/order');

			$comment = '';

			$this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('bcash_order_aguardando'), $comment, true);
		}
	}

	public function retorno() {
		// pega o id da transacao
		if (isset($_POST['transacao_id'])) {
			$id_transacao = $_POST['transacao_id'];
		} else if (isset($_POST['id_transacao'])) {
			$id_transacao = $_POST['id_transacao'];
		}

		$id_transacao = trim($id_transacao);

		if ($id_transacao == '') {
			$this->response->redirect($this->url->link('checkout/success'));
			exit;
		}

		// por questão de segurança é recomendado não utilizar apenas os dados recebidos no primeiro post
		// por isto vamos executar a consulta de dados da transação para autenticação e obter todos os dados de seu pedido
		$urlPost = "https://www.bcash.com.br/transacao/consulta/";
		$tipoRetorno = "2"; // 1=XML; 2=JSON;
		$codificacao = "1"; // 1=UTF-8; 2=ISO-8859-1;

		$chaveAcesso = $this->config->get('bcash_token');
		$emailLoja = $this->config->get('bcash_email');

		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $urlPost);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, array('id_transacao'=>$id_transacao, 'id_pedido'=>'', 'tipo_retorno'=>$tipoRetorno, 'codificacao'=>$codificacao));
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Basic '.base64_encode($emailLoja.':'.$chaveAcesso)));

		// parametros utilizados para evitar verificacao SSL caso nao disponha do protocolo de seguranca
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

		ob_start();
		curl_exec ($ch);
		$resposta = ob_get_contents();
		ob_end_clean();

		// captura o http code para tratamento dos erros na requisicao
		$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);

		if ($httpCode == "200") {

			// sucesso na consulta CURL
			$dados = json_decode($resposta, TRUE);

			$cod_status     = intval($dados['transacao']['cod_status']);
			$status         = trim($dados['transacao']['status']);
			$tipo_pagamento = trim($dados['transacao']['meio_pagamento']);
			$parcelas       = trim($dados['transacao']['parcelas']);
			$id_pedido      = trim($dados['transacao']['id_pedido']);
			$data_credito   = trim($dados['transacao']['data_credito']);

			// busca o pedido
			$id_pedido = explode('_', $id_pedido);
			$order_id = $id_pedido[0];

			$this->load->model('checkout/order');
			$order = $this->model_checkout_order->getOrder($order_id);

			if (!is_array($order)) {
				// se nao encontrar o pedido grava log de erro
				$this->log->write('Bcash: Pedido nao encontrado. ID: '.$order_id);
				$this->response->redirect($this->url->link('checkout/success'));
				exit;
			}

			// comentarios que serao adicionados no historico do pedido
			$comment = '';
			if ($status != '') { $comment .= "\nStatus da transação no Bcash: ".$status; }
			if ($tipo_pagamento != '') { $comment .= "\nTipo de pagamento escolhido: ".$tipo_pagamento; }
			if ($parcelas != '') { $comment .= "\nNúmero de parcelas: ".$parcelas; }
			$comment = trim($comment);

			// verifica se precisa notificar o cliente
			$update_status_alert = false;
			if ($this->config->get('bcash_update_status_alert')) {
				$update_status_alert = true;
			}

			if ($order['order_status_id'] == '0') {
				$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_aguardando'), '', true);
			}

			switch($cod_status){
			case 1: // 1 – Em andamento
				if (is_numeric($this->config->get('bcash_order_andamento')) && $this->config->get('bcash_order_andamento') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_andamento')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_andamento'), $comment, $update_status_alert);
					}
				}
				break;

			case 3: // 3 – Aprovada
				if (is_numeric($this->config->get('bcash_order_aprovada')) && $this->config->get('bcash_order_aprovada') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_aprovada')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_aprovada'), $comment, $update_status_alert);
					}
				}
				break;

			case 4: // 4 – Concluída
				if (is_numeric($this->config->get('bcash_order_concluida')) && $this->config->get('bcash_order_concluida') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_concluida')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_concluida'), $comment, $update_status_alert);
					}
				}
				break;

			case 5: // 5 – Disputa
				if (is_numeric($this->config->get('bcash_order_disputa')) && $this->config->get('bcash_order_disputa') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_disputa')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_disputa'), $comment, $update_status_alert);
					}
				}
				break;

			case 6: // 6 – Devolvida
				if (is_numeric($this->config->get('bcash_order_devolvida')) && $this->config->get('bcash_order_devolvida') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_devolvida')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_devolvida'), $comment, $update_status_alert);
					}
				}
				break;

			case 7: // 7 – Cancelada
				if (is_numeric($this->config->get('bcash_order_cancelada')) && $this->config->get('bcash_order_cancelada') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_cancelada')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_cancelada'), $comment, $update_status_alert);
					}
				}
				break;

			case 8: // 8 – Chargeback
				if (is_numeric($this->config->get('bcash_order_chargeback')) && $this->config->get('bcash_order_chargeback') > 0) {
					if ($order['order_status_id'] != $this->config->get('bcash_order_chargeback')) {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('bcash_order_chargeback'), $comment, $update_status_alert);
					}
				}
				break;
			}

		}else{

			// erro na consulta CURL
			$dados = json_decode($resposta, TRUE);
			$erro_codigo = $dados['erro']['codigo'];
			$erro_descricao = $dados['erro']['descricao'];

			if ($erro_codigo == '2015005') {
				$erro_descricao .= ' (email e/ou token inválidos)';
			}

			// grava log de erro para facil depuracao
			$this->log->write("Bcash: Erro no retorno automático de dados.\nHTTP CODE: {$httpCode}\nCódigo: {$erro_codigo}\nDescrição: {$erro_descricao}");
		}

		$this->response->redirect($this->url->link('checkout/success'));
	}

	private function validaCPF($strCPF){
		// validacao: apenas numeros ou no formato 000.000.000-00
		if (!preg_match('/^[0-9]{11}$/', $strCPF) && !preg_match('/^[0-9]{3}\.[0-9]{3}\.[0-9]{3}-[0-9]{2}$/', $strCPF)) { return false; }

		// remove caracteres nao numericos (pontuacao)
		$strCPF = preg_replace('/[^0-9]/', '', $strCPF);

		// nao aceita sequencias de numeros iguais (00000000000, 11111111111, etc)
		for ($a = 0; $a < 10; $a++) {
			if (str_repeat($a, 11) == $strCPF) { return false; }
		}

		// digito verificador informado
		$strCPF_dv = substr($strCPF, 9, 2);

		// separa os digitos
		$digito = str_split($strCPF);

		// calcula o digito verificador
		$mult = 10; $soma = 0;
		for ($a = 0; $a < 9; $a++) { $soma += $digito[$a] * $mult--; }
		$soma = $soma % 11;
		$digito[9] = ($soma < 2) ? 0 : 11 - $soma;

		$mult = 11; $soma = 0;
		for ($a = 0; $a < 10; $a++){ $soma += $digito[$a] * $mult--; }
		$soma = $soma % 11;
		$digito[10] = ($soma < 2) ? 0 : 11 - $soma;

		// verifica se o digito verificador informado e igual ao calculado
		$digitoVerificador = $digito[9] .''. $digito[10];
		if ($digitoVerificador != $strCPF_dv) { return false; }

		return true;
	}

	private function validaCNPJ($strCNPJ){
		// validacao: apenas numeros ou no formato 00.000.000/0000-00
		if (!preg_match('/^[0-9]{14,15}$/', $strCNPJ) && !preg_match('/^[0-9]{2,3}\.[0-9]{3}\.[0-9]{3}\/[0-9]{4}-[0-9]{2}$/', $strCNPJ)) { return false; }

		// remove caracteres nao numericos (pontuacao)
		$strCNPJ = preg_replace('/[^0-9]/', '', $strCNPJ);

		if (strlen($strCNPJ) == 15) {
			if (substr($strCNPJ,0,1) != 0) { return false; }
			$strCNPJ = substr($strCNPJ, 1, 14);
		}

		// nao aceita sequencias de numeros iguais (00000000000000, 11111111111111, etc)
		for ($a = 0; $a < 10; $a++) {
			if (str_repeat($a, 14) == $strCNPJ) { return false; }
		}

		// digito verificador informado
		$strCNPJ_dv = substr($strCNPJ, 12, 2);

		// separa os digitos
		$digito = str_split($strCNPJ);

		// calcula o digito verificador
		$mult = 5; $soma = 0;
		for ($a = 0; $a < 12; $a++) { $soma += $digito[$a] * $mult--; if ($mult < 2) { $mult = 9; }}
		$soma = $soma % 11;
		$digito[12] = ($soma < 2) ? 0 : 11 - $soma;

		$mult = 6; $soma = 0;
		for ($a = 0; $a < 13; $a++){ $soma += $digito[$a] * $mult--; if ($mult < 2) { $mult = 9; }}
		$soma = $soma % 11;
		$digito[13] = ($soma < 2) ? 0 : 11 - $soma;

		// verifica se o digito verificador informado e igual ao calculado
		$digitoVerificador = $digito[12] .''. $digito[13];
		if ($digitoVerificador != $strCNPJ_dv) { return false; }

		return true;
	}
}