<?php
// Conexão BD
include('../fncr-geral/coneccao-bd.php');
// Formatação de Valores
require_once('../fncr-geral/formatacao_valores.php');

// REGISTRAR RETORNO DO WEBHOOK
$headers = getallheaders();
$headers_json = json_encode(getallheaders());
$body = file_get_contents("php://input");

$sql = $bd->getConexao()->prepare('INSERT INTO webhooks (header, body, origem, data_hora) VALUES (:headers, :body, "asaas", NOW())');
$sql->bindValue(':headers', $headers_json, PDO::PARAM_STR);
$sql->bindValue(':body', $body, PDO::PARAM_STR);
if($sql->execute());

// DIRECIONAMENTO PRINCIPAL (INIT)
// *******************************************
try{
  if(
    isset($headers['asaas-access-token']) && $headers['asaas-access-token']==GLOBAL_ASAAS_HOOK_TK ||
    isset($headers['Asaas-Access-Token']) && $headers['Asaas-Access-Token']==GLOBAL_ASAAS_HOOK_TK
  ){
    $data = json_decode($body, true);
    if($data){

      $evento = isset($data['event']) ? $data['event'] : false;

      // PAGAMENTO RECEBIDO
      if($evento=="PAYMENT_RECEIVED" && isset($data['payment']['billingType']) && $data['payment']['billingType']=="PIX") pixReceived($data);

      // TRANSFERENCIA
      if(isset($data['transfer'])){
        // Autorizar
        if(isset($data['type']) && $data['type']=="TRANSFER" && $data['transfer']['status']=="PENDING") transf_autorizar($data);
        // Realizada
        if($evento=="TRANSFER_DONE" && $data['transfer']['status']=="DONE") transf_realizado($data);
        // Falha
        if(in_array($evento, ["TRANSFER_FAILED", "TRANSFER_CANCELLED"]) && in_array($data['transfer']['status'], ["FAILED", "CANCELLED"])) transf_falha($data);
      }

      // ATUALIZAÇÃO DE STATUS (CONTA E DOCUMENTOS)
      if($evento && substr($evento, 0, 15) === 'ACCOUNT_STATUS_') statusAccountDocs($data);

    }
  }
}catch(Exception $e){}


// PAGAMENTO RECEBIDO
// *******************************************

// PIX, futuramente pode alterar para geral, não somente pix
function pixReceived($data){
  // Verifica dados do pagamento
  $EXT_registro_id = $data['payment']['id'];
  // Retorna o pagamento já com validação de "pendente"
  $pgtoBD = paymentBD($EXT_registro_id);
  if(!$pgtoBD) exit;
  // Se é recebimento do fncr
  $fncr = (isset($pgtoBD['ORIGEM']) && $pgtoBD['ORIGEM']=="fncr");
  $clube = $fncr ? false : subConta_dds(['id_subconta' => $pgtoBD['FNCR_pw_subconta_id']]);

  include_once('../libraries/outros/Asaas.php');
  $asaas = new Asaas();
  $asaas->account_dds($fncr ? ['EXT_api_key'=>GLOBAL_ASAAS_PW_API_KEY] : $clube);

  $payment = $asaas->paymentData($pgtoBD['EXT_registro_id']);
  if($payment && $payment['status']=="RECEIVED"){

    // Marca o registro do pagamento como concluído
    $dados_valores = paymentReceived($pgtoBD['id'], $pgtoBD, $payment, $fncr);

    // FNCR (pagamentos de faturas)
    if($fncr){
      fncrActions('paymentReceived', [
        'pgtoBD' => $pgtoBD,
        'dados_valores' => $dados_valores,
      ]);
    }

    // NOVO FORMATO
    // As verificações possuem redundancias devido a migração da informação CLUBE_ para ORIGEM_
    // Falta migrar sistema de eventos
    elseif(isset($pgtoBD['ORIGEM']) && $pgtoBD['ORIGEM']!=""){

      // GAMEID (pagamento de jogadores)
      if($pgtoBD['ORIGEM']=="gameid" && $pgtoBD['ORIGEM_modulo']=="jogador"){
        gameidActions($pgtoBD, $dados_valores);
      }

      // CLUBES (pagamento de jogadores)
      if($pgtoBD['ORIGEM']=="clube"){
        clubeActions($clube, $pgtoBD, $dados_valores);
      }

    }

    // EVENTO (Aciona requisição ao sistema do evento)
    elseif(isset($pgtoBD['CLUBE_modulo']) && $pgtoBD['CLUBE_modulo']=="cobranca_evento"){
      eventSystemActions($pgtoBD, $dados_valores);
    }

  }
}

// Registro do pagamento no BD
function paymentBD($EXT_registro_id){
  global $bd;
  $sql = $bd->getConexao()->prepare('
    SELECT
      p.*,
      CASE WHEN tx_clube.id is not null THEN tx_clube.valor_fixo ELSE tx_geral.valor_fixo END as taxa_valor_fixo,
      CASE WHEN tx_clube.id is not null THEN tx_clube.valor_percent ELSE tx_geral.valor_percent END as taxa_valor_percent
    FROM pgtos_ext_pagamentos p
      LEFT JOIN pwbank_taxas tx_geral ON tx_geral.id_pwbank_subconta = 0 AND tx_geral.ext_forma_pgto_id = p.FNCR_ext_forma_pgto
      LEFT JOIN pwbank_taxas tx_clube ON tx_clube.id_pwbank_subconta = p.FNCR_pw_subconta_id AND tx_clube.ext_forma_pgto_id = p.FNCR_ext_forma_pgto
    WHERE p.EXT_registro_id = :EXT_registro_id');
  $sql->bindValue(':EXT_registro_id', $EXT_registro_id, PDO::PARAM_STR);
  if($sql->execute()){$pgto = $sql->fetch(PDO::FETCH_ASSOC);}

  // Se ainda está aberto
  if($pgto && !$pgto['finalizado'] && !$pgto['cancelado'] && !$pgto['excluido']){ return $pgto; }
  exit;
}

// Marca o pagamento como concluído
function paymentReceived($id, $pgtoBD, $payment, $fncr){
  global $bd;

  date_default_timezone_set("America/Sao_paulo");
  $bd->getConexao()->exec("set names utf8");
  $bd->getConexao()->exec('set time_zone = "'.date('P').'"');

  // Marca o pagamento como concluído
  $sql = $bd->getConexao()->prepare('UPDATE pgtos_ext_pagamentos SET finalizado = 1, finalizado_data_hora = NOW() WHERE id = :id');
  $sql->bindValue(':id', $id, PDO::PARAM_STR);
  if($sql->execute());

  $split_value = isset($payment['split'][0]->totalValue) ? $payment['split'][0]->totalValue : 0;

  // Calculos de valores (para registros)
  $servico_valor_bruto = $pgtoBD['valor']; // valor total do pagamento (sem qualquer desconto de taxas)
  $servico_valor_liquido = $payment['netValue']; // valor do pagamento (já descontado a taxa do serviço)
  $clube_valor_liquido = $servico_valor_liquido - $split_value; // valor disponivel ao clube (sem taxa de serviço e taxa do gameid)
  $servico_valor_taxa = $servico_valor_bruto - $servico_valor_liquido; // valor da taxa cobrada pelo serviço
  $clube_valor_taxa = $servico_valor_bruto - $clube_valor_liquido; // valor total descontado do clube

  if(!$fncr){
    // Registra o valor no extrato para o clube
    $sql = $bd->getConexao()->prepare('INSERT INTO pgtos_ext_extrato
    (uuid, FNCR_clube_id, FNCR_pw_conta_id, FNCR_pw_subconta_id, FNCR_ext_pgto_id, servico_valor_bruto, servico_valor_taxa, servico_valor_liquido, clube_valor_taxa, clube_valor_liquido, data_hora) VALUES
    (:uuid, :FNCR_clube_id, :FNCR_pw_conta_id, :FNCR_pw_subconta_id, :FNCR_ext_pgto_id, :servico_valor_bruto, :servico_valor_taxa, :servico_valor_liquido, :clube_valor_taxa, :clube_valor_liquido, NOW())');
    $sql->bindValue(':uuid', uuid(), PDO::PARAM_STR);
    $sql->bindValue(':FNCR_clube_id', $pgtoBD['FNCR_clube_id'], PDO::PARAM_STR);
    $sql->bindValue(':FNCR_pw_conta_id', $pgtoBD['FNCR_pw_conta_id'], PDO::PARAM_STR);
    $sql->bindValue(':FNCR_pw_subconta_id', $pgtoBD['FNCR_pw_subconta_id'], PDO::PARAM_STR);
    $sql->bindValue(':FNCR_ext_pgto_id', $pgtoBD['id'], PDO::PARAM_STR);
    $sql->bindValue(':servico_valor_bruto', $servico_valor_bruto, PDO::PARAM_STR);
    $sql->bindValue(':servico_valor_taxa', $servico_valor_taxa, PDO::PARAM_STR);
    $sql->bindValue(':servico_valor_liquido', $servico_valor_liquido, PDO::PARAM_STR);
    $sql->bindValue(':clube_valor_taxa', $clube_valor_taxa, PDO::PARAM_STR);
    $sql->bindValue(':clube_valor_liquido', $clube_valor_liquido, PDO::PARAM_STR);
    if($sql->execute());
  }

  return [
    'servico_valor_bruto' => $servico_valor_bruto,
    'servico_valor_liquido' => $servico_valor_liquido,
    'clube_valor_liquido' => $clube_valor_liquido,
    'servico_valor_taxa' => $servico_valor_taxa,
    'clube_valor_taxa' => $clube_valor_taxa,
    'gid_liquido' => $split_value,
  ];
}


// TRANSFERENCIAS
// *******************************************

// AUTORIZAR TRANSFERENCIA
// Asaas consulta esse endpoint 5 segundos depois da transferencia criada.
function transf_autorizar($data){
  //echo json_encode(['status'=>"APPROVED"]); exit;
  //echo json_encode(['status'=>'REFUSED', 'refuseReason'=>'Erro F']); exit;

  //$rs = ['status'=>'REFUSED', 'refuseReason'=>'Erro não identificado'];
  //returnContinue($rs);
  //exit;
  global $bd;

  $trasnfBD = transfBD($data['transfer']['externalReference']);
  // SE EXISTE TRANSFERENCIA
  if($trasnfBD){
    // VALIDAR HASH DE AUTENTICAÇÃO
    if(hashAutenticacao($trasnfBD)){

      // SE FOR REGISTRO DE TAXA
      if($trasnfBD['ORIGEM']=='pw_taxa') transf_set_aprovado($trasnfBD);

      // SE TRANSFERENCIA CONTINUA ABERTA
      if(!$trasnfBD['autorizado'] && !$trasnfBD['concluido'] && !$trasnfBD['cancelado']){
        transf_set_aprovado($trasnfBD);
      }else{$rs = ['status'=>'REFUSED', 'refuseReason'=>'Repasse já autorizado/concluído/cancelado'];}

    }else{$rs = ['status'=>'REFUSED', 'refuseReason'=>'Hash de autenticação inválida'];}
  }else{$rs = ['status'=>'REFUSED', 'refuseReason'=>'Repasse não encontrado (bd)'];}

  if(!isset($rs)){$rs = ['status'=>'REFUSED', 'refuseReason'=>'Erro não identificado'];}

  // Só chega aqui se houve erro
  returnContinue($rs);

  // ERRO JÁ RETORNADO
  // continua script ...

  if(!$trasnfBD) exit;

  // Cancela a transferencia
  transf_set_cancelado($trasnfBD);

  // Envia ao clube, aviso de transferencia atualizada
  if($trasnfBD) transfUpdateRequest($trasnfBD);
}

// Marca transferencia como aprovada
function transf_set_aprovado($trasnfBD){
  global $bd;

  $sql = $bd->getConexao()->prepare('UPDATE pgtos_ext_transferencias SET autorizado = 1, autorizado_data_hora = NOW() WHERE id = :id');
  $sql->bindValue(':id', $trasnfBD['id'], PDO::PARAM_STR);
  if($sql->execute());

  // Retorna aviso ao serviço
  echo json_encode(['status'=>"APPROVED"]); exit;
}

// Marca transferencia como cancelada
function transf_set_cancelado($trasnfBD){
  global $bd;
  if($trasnfBD['cancelado']==0){
    $sql = $bd->getConexao()->prepare('UPDATE pgtos_ext_transferencias SET cancelado = 1, cancelado_data_hora = NOW() WHERE id = :id');
    $sql->bindValue(':id', $trasnfBD['id'], PDO::PARAM_STR);
    if($sql->execute());
  }
}

// Transferência realizado
function transf_realizado($data){
  global $bd;
  $trasnfBD = transfBD($data['transfer']['externalReference']);
  if($trasnfBD && $trasnfBD['autorizado'] && !$trasnfBD['concluido'] && !$trasnfBD['cancelado']){

    // Dados subconta
    $subconta = subConta_dds(['id_subconta' => $trasnfBD['FNCR_pw_subconta_id']]);

    // Valida informações pela api do serviço
    include_once('../libraries/outros/Asaas.php');
    $asaas = new Asaas();
    $asaas->account_dds($subconta);
    $transfer = $asaas->transferData($trasnfBD['EXT_registro_id']);

    // Se existe a transferencia e está concluída
    if($transfer && $transfer['status']=="DONE"){

      $EXT_infs_extras = $trasnfBD['EXT_infs_extras'];

      // Inclui ID de transação do pix nas informações extras
      if(isset($transfer['endToEndIdentifier']) && $EXT_infs_extras!=""){
        $infs_extras = json_decode($trasnfBD['EXT_infs_extras'], true);
        if($infs_extras){
          $infs_extras['endToEndIdentifier'] = $transfer['endToEndIdentifier'];
          $EXT_infs_extras = json_encode($infs_extras);
        }
      }

      // Marca a transferencia como concluída (e inclui dados da extras da transação)
      $sql = $bd->getConexao()->prepare('UPDATE pgtos_ext_transferencias SET
        concluido = 1,
        concluido_data_hora = NOW(),
        EXT_infs_extras = :EXT_infs_extras
      WHERE id = :id');
      $sql->bindValue(':id', $trasnfBD['id'], PDO::PARAM_STR);
      $sql->bindValue(':EXT_infs_extras',$EXT_infs_extras, PDO::PARAM_STR);
      if($sql->execute());

      // TRANSFERÊNCIA DE TAXA DA PW
      if($trasnfBD['ORIGEM']=='pw_taxa'){
        // Registro no FNCR
        fncrInsertCaixa([
          "id_categoria"=>  146, // Pokerweb -> PWpay -> Pix Transferências
          "id_conta"=>      6, // GameID - Asaas
          "id_clube"=>      $trasnfBD['FNCR_clube_id'],
          "descricao"=>     null,
          "documento"=>     $trasnfBD['uuid'],
          "valor"=>         $trasnfBD['valor'],
          "taxa_servico"=>  0,
          "observacao"=>
            'Transferência: '.echomoeda($trasnfBD['ORIGEM_valor'])."\n"
        ]);
      }

      // TRANSFERÊNCIA DO CLUBE
      if($trasnfBD['ORIGEM']=='clube'){

        // Calculos de valores (para registro no extrato)
        $valor_transferido = $transfer['value'];
        $servico_valor_taxa = $transfer['transferFee']; // valor da taxa cobrada pelo serviço
        $clube_valor_taxa = $trasnfBD['valor_taxa']; // valor total descontado do clube
        $clube_valor_total = $valor_transferido + $clube_valor_taxa; // Transferido + Taxa

        // Registra o valor no extrato para o clube
        $sql = $bd->getConexao()->prepare('INSERT INTO pgtos_ext_extrato
        (uuid, FNCR_clube_id, FNCR_pw_conta_id, FNCR_pw_subconta_id, FNCR_ext_transferencia_id, servico_valor_bruto, servico_valor_taxa, servico_valor_liquido, clube_valor_taxa, clube_valor_liquido, data_hora) VALUES
        (:uuid, :FNCR_clube_id, :FNCR_pw_conta_id, :FNCR_pw_subconta_id, :FNCR_ext_transferencia_id, :servico_valor_bruto, :servico_valor_taxa, :servico_valor_liquido, :clube_valor_taxa, :clube_valor_liquido, NOW())');
        $sql->bindValue(':uuid', uuid(), PDO::PARAM_STR);
        $sql->bindValue(':FNCR_clube_id', $trasnfBD['FNCR_clube_id'], PDO::PARAM_STR);
        $sql->bindValue(':FNCR_pw_conta_id', $trasnfBD['FNCR_pw_conta_id'], PDO::PARAM_STR);
        $sql->bindValue(':FNCR_pw_subconta_id', $trasnfBD['FNCR_pw_subconta_id'], PDO::PARAM_STR);
        $sql->bindValue(':FNCR_ext_transferencia_id', $trasnfBD['id'], PDO::PARAM_STR);
        $sql->bindValue(':servico_valor_bruto', $valor_transferido, PDO::PARAM_STR);
        $sql->bindValue(':servico_valor_taxa', $servico_valor_taxa, PDO::PARAM_STR);
        $sql->bindValue(':servico_valor_liquido', $valor_transferido, PDO::PARAM_STR);
        $sql->bindValue(':clube_valor_taxa', $clube_valor_taxa, PDO::PARAM_STR);
        $sql->bindValue(':clube_valor_liquido', $clube_valor_total, PDO::PARAM_STR);
        if($sql->execute());

        // Envia ao clube, aviso de transferencia atualizada
        transfUpdateRequest($trasnfBD);
      }

      // TRANSFERÊNCIAS ENTRE CAIXAS (FNCR)
      if($trasnfBD['ORIGEM']=='fncr' && $trasnfBD['ORIGEM_modulo']=='fingeral_registro'){
        fncrActions('transferDone', [
          'trasnfBD' => $trasnfBD,
        ]);
      }

    }
  }
}

// Transferência com falha
function transf_falha($data){
  global $bd;
  $trasnfBD = transfBD($data['transfer']['externalReference']);
  if($trasnfBD){
    transf_set_cancelado($trasnfBD);
    transfUpdateRequest($trasnfBD);
  }
}

// Dados do repasse no BD
function transfBD($uuid){
  global $bd;

  $sql = $bd->getConexao()->prepare('SELECT t.* FROM pgtos_ext_transferencias t WHERE t.uuid = :uuid AND EXT_registro_id is not null');
  $sql->bindValue(':uuid', $uuid, PDO::PARAM_STR);
  if($sql->execute()){$repasse = $sql->fetch(PDO::FETCH_ASSOC);}

  // Se ainda está aberto
  if($repasse){ return $repasse; }
  return false;
}

// Envia ao clube, aviso de transferencia atualizada
function transfUpdateRequest($trasnfBD){
  $clube = subConta_dds([
    'tipo' => "clube",
    'tipo_id' => $trasnfBD['FNCR_clube_id']
  ]);
  clubSystemRequest($clube['link_sistema'], 'transfer/updated/'.$trasnfBD['uuid']);
}


// ATUALIZAÇÃO DE STATUS DE SUBCONTA (PWBANK)
// *******************************************

// Atualizar status de conta ou documentos
function statusAccountDocs($data){
  global $bd;
  if(!isset($data['accountStatus']['id'])) exit;

  $EXT_registro_id = $data['accountStatus']['id'];
  unset($data['accountStatus']['id']);

  // Dados da conta
  $sql = $bd->getConexao()->prepare('
  SELECT
    sc.id,
    sc.EXT_api_key,
    c.nome as clube
  FROM pwbank_subcontas sc
    LEFT JOIN pwbank_contas bc ON bc.id = sc.id_conta
    LEFT JOIN clubes c ON c.id = sc.tipo_id
  WHERE sc.EXT_registro_id = :EXT_registro_id AND sc.ext_servico_id = 2');
  $sql->bindValue(':EXT_registro_id', $EXT_registro_id, PDO::PARAM_STR);
  if($sql->execute()){$subconta = $sql->fetch(PDO::FETCH_ASSOC);}

  $id_subconta = $subconta['id'];

  // Se subconta existe
  if($subconta){

    // Atualiza o status da conta
    $EXT_status = json_encode($data['accountStatus']);
    $aprovado = (isset($data['accountStatus']['general']) && $data['accountStatus']['general']=="APPROVED") ? 1 : 0;

    $sql = $bd->getConexao()->prepare('
    UPDATE pwbank_subcontas SET
      EXT_status = :EXT_status,
      aprovado = :aprovado,
      data_hora_updated = now()
    WHERE id = :id');
    $sql->bindValue(':EXT_status', $EXT_status, PDO::PARAM_STR);
    $sql->bindValue(':aprovado', $aprovado, PDO::PARAM_STR);
    $sql->bindValue(':id', $id_subconta, PDO::PARAM_STR);
    $sql->execute();

    // Se documentos foi atualizado, realiza uma consulta
    if(substr($data['event'], 0, 24)==='ACCOUNT_STATUS_DOCUMENT_'){
      include_once('../libraries/outros/Asaas.php');
      $asaas = new Asaas();
      $asaas->account_dds($subconta);
      $docs = $asaas->account_docs();

      if($docs && isset($docs->data)){
        // Docs atuais
        $sql = $bd->getConexao()->prepare('
        SELECT 
          sd.id,
          sd.ext_doc_id,
          sd.ext_doc_type
        FROM pwbank_subcontas_documentos sd
        WHERE sd.id_subconta = :id_subconta');
        $sql->bindValue(':id_subconta', $id_subconta, PDO::PARAM_STR);
        if($sql->execute()){$docs_bd = $sql->fetchall(PDO::FETCH_ASSOC);}

        $docs_atuais = [];
        foreach($docs_bd as $l){ $docs_atuais[$l['ext_doc_id'].'.'.$l['ext_doc_type']] = $l; }

        // Analisar se há motivo para recusa
        $recusa_motivo = (isset($docs->rejectReasons) && $docs->rejectReasons!="") ? $docs->rejectReasons : null;

        // Roda cada documento, para inserir ou atualizar as informações locais
        foreach($docs->data as $l){
          $ext_reprovado_motivo = $l->status=="REJECTED" ? $recusa_motivo : null;
          // Atualizar Informações
          if(isset($docs_atuais[$l->id.'.'.$l->type])){
            $sql = $bd->getConexao()->prepare('UPDATE pwbank_subcontas_documentos SET
              ext_doc_status = :ext_doc_status,
              ext_reprovado_motivo = :ext_reprovado_motivo,
              data_hora_updated = now()
            WHERE id = :id');
            $sql->bindValue(':id', $docs_atuais[$l->id.'.'.$l->type]['id'], PDO::PARAM_STR);
            $sql->bindValue(':ext_doc_status', $l->status, PDO::PARAM_STR);
            $sql->bindValue(':ext_reprovado_motivo', $ext_reprovado_motivo, PDO::PARAM_STR);
            $sql->execute();
          }
        }
      }
    }

    // Envio de e-mail interno
    $status_conteudo_email = json_encode($data['accountStatus'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

    require_once('../libraries/outros/Email.php');
    $email = new Email();
    $email->emails(['leandro@pokerweb.com.br']);
    $email->conteudo('PokerWeb - GameID - Status de conta',
      "MENSAGEM AUTOMÁTICA<br><br>".
      "A subconta do clube <strong>{$subconta['clube']}</strong>, teve status atualizado para:<br>".
      "<pre>".htmlentities($status_conteudo_email)."</pre>"
    );
    $email->send();

  }
}


// FNCR
// *******************************************

// Realiza ações para o FNCR
function fncrActions($tipo, $dds){
  // Pagamento de fatura de clube confirmado
  if($tipo=="paymentReceived" && $dds['pgtoBD']['ORIGEM_modulo']=="clube_fatura"){ fncrClubePayment($dds['pgtoBD'], $dds['dados_valores']); }
  // Repasse confirmado
  if($tipo=="transferDone"){ fncrTransferenciaConfirmada($dds['trasnfBD']); }
}

// Pagamento de fatura de clube confirmado
function fncrClubePayment($pgtoBD, $dados_valores){
  global $bd;

  $id_conta = 7;

  // Dados do registro PIX
  $sql = $bd->getConexao()->prepare('SELECT * FROM clubes_financeiro WHERE id = :id');
  $sql->bindValue(':id', $pgtoBD['ORIGEM_modulo_id'], PDO::PARAM_STR);
  if($sql->execute()){$resul_registro = $sql->fetch(PDO::FETCH_ASSOC);}

  // Se fatura continua aberta
  if($resul_registro['id']!="" && ($resul_registro['status']=="2" or $resul_registro['status']=="3" or $resul_registro['status']=="7")){

    $valor = $pgtoBD['valor'];

    // Atualize registro financeiro da fatura
    $sql = $bd->getConexao()->prepare('UPDATE clubes_financeiro SET
      data_pgto = NOW(),
      data_notificacao = NOW(),
      data_liberacao = NOW(),
      valor_pago = :valor,
      valor_liberado = :valor,
      valor_pendente = 0,
      valor_desc_pag = 0,
      status = 4
      WHERE id = :id AND status > 0');
    $sql->bindValue(':valor', $valor, PDO::PARAM_STR);
    $sql->bindValue(':id', $resul_registro['id'], PDO::PARAM_STR);
    if($sql->execute());

    // Atualiza registro pix do clube (da fatura)
    $sql = $bd->getConexao()->prepare('UPDATE clubes_pix SET pago = 1, data_hora_pagamento = NOW(), id_transacao = :id_transacao WHERE id = :id');
    $sql->bindValue(':id', $resul_registro['id_pix'], PDO::PARAM_STR);
    $sql->bindValue(':id_transacao', $pgtoBD['EXT_registro_id'], PDO::PARAM_STR);
    if($sql->execute());

    // Inserindo Registros no Financeiro Geral
    $id_categoria_boleto_pago = 63; // Categoria "PokerWeb - Mensalidades"

    if($resul_registro['periodo_mes']!=date("m")){
      $data_vencimento = "20".$resul_registro['periodo_ano'].'-'.$resul_registro['periodo_mes'].'-'.'01';
    }else{
      $data_vencimento = date("Y-m-d");
    }

    // PW ADS
    $sql = $bd->getConexao()->prepare('
      SELECT
        sum(ifnull(valor,0)) as total
      FROM clubes_compras
      WHERE id_clube = :id_clube AND id_fatura = :id_fatura AND id_produto = :id_produto_ads');
    $sql->bindValue(':id_clube', $resul_registro['id_clube'], PDO::PARAM_STR);
    $sql->bindValue(':id_fatura', $resul_registro['id'], PDO::PARAM_STR);
    $sql->bindValue(':id_produto_ads', 20, PDO::PARAM_STR);
    if($sql->execute()){ $valor_ads = $sql->fetch(PDO::FETCH_ASSOC);}

    $valor_ads = $valor_ads['total']*-1;
    $valor_sem_ads = $resul_registro['valor'] + $valor_ads;
    if($valor_ads>0){$valor+=$valor_ads;}

    // INSERIR VALOR NO CAIXA
    $sql = $bd->getConexao()->prepare('INSERT INTO fingeral_registros
      (id_categoria, id_conta, id_clube, id_clube_financeiro, valor, periodo_mes, periodo_ano, data_lancamento, data_vencimento, data_pagamento, pagar_automatico, status_pago, status) VALUES
      (:id_categoria, :id_conta, "'.$resul_registro['id_clube'].'", "'.$resul_registro['id'].'", :valor, "'.$resul_registro['periodo_mes'].'", "'.$resul_registro['periodo_ano'].'", NOW(), "'.$data_vencimento.'", NOW(), 1, 1, 0)');
    $sql->bindValue(':id_categoria', $id_categoria_boleto_pago, PDO::PARAM_STR);
    $sql->bindValue(':id_conta', $id_conta, PDO::PARAM_STR);
    $sql->bindValue(':valor', $valor, PDO::PARAM_STR);
    if($sql->execute());

    $id_fingeral_registro = $bd->lastId();

    // Registro do ads no caixa
    if($valor_ads>0){
      $sql = $bd->getConexao()->prepare('INSERT INTO fingeral_registros
        (id_categoria, id_conta, id_clube, id_clube_financeiro, valor, periodo_mes, periodo_ano, data_lancamento, data_vencimento, data_pagamento, pagar_automatico, status_pago, status) VALUES
        (:id_categoria, :id_conta, "'.$resul_registro['id_clube'].'", "'.$resul_registro['id'].'", :valor, "'.$resul_registro['periodo_mes'].'", "'.$resul_registro['periodo_ano'].'", NOW(), "'.$data_vencimento.'", NOW(), 1, 1, 0)');
      $sql->bindValue(':id_categoria', 141, PDO::PARAM_STR);
      $sql->bindValue(':id_conta', $id_conta, PDO::PARAM_STR);
      $sql->bindValue(':valor', $valor_ads*-1, PDO::PARAM_STR);
      if($sql->execute());
    }

    // Taxa Asaas
    if($dados_valores['servico_valor_taxa']>0){
      $sql = $bd->getConexao()->prepare('INSERT INTO fingeral_registros
      (id_categoria, id_conta, id_clube, id_clube_financeiro, valor, periodo_mes, periodo_ano, data_lancamento, data_vencimento, data_pagamento, pagar_automatico, status_pago, status) VALUES
      (:id_categoria, :id_conta, "'.$resul_registro['id_clube'].'", "'.$resul_registro['id'].'", :valor, "'.$resul_registro['periodo_mes'].'", "'.$resul_registro['periodo_ano'].'", NOW(), "'.$data_vencimento.'", NOW(), 1, 1, 0)');
      $sql->bindValue(':id_categoria', 143, PDO::PARAM_STR);
      $sql->bindValue(':id_conta', $id_conta, PDO::PARAM_STR);
      $sql->bindValue(':valor', $dados_valores['servico_valor_taxa']*-1, PDO::PARAM_STR);
      if($sql->execute());
    }

    // Liberar Clube se bloqueado
    if($resul_registro['bloq_status_clube']==0){
      // Liberar Clube se bloqueado
      $sql = $bd->getConexao()->prepare('UPDATE clubes SET bloqueio = 0, visualizacao = 0 WHERE id = :id_clube');
      $sql->bindValue(':id_clube', $resul_registro['id_clube'], PDO::PARAM_STR);
      if($sql->execute());

      // Inserir Registro de Status
      $sql = $bd->getConexao()->prepare('INSERT INTO clubes_financeiro_datas
      (id_financeiro, data, hora, status, origem) VALUES
      ("'.$resul_registro['id'].'", NOW(), NOW(), "4", "1")');
      if( $sql->execute() );
    }

    include_once('../libraries/outros/NFs/NFs.php');
    $nf = new NFs();
    $nf->fingeralRegistro($id_fingeral_registro);
    $nf->cadastrar();

  }

}

// Realiza ações de repasse entre contas internas
function fncrTransferenciaConfirmada($trasnfBD){
  global $bd;

  $pw = $trasnfBD['pix_documento']=="25131762000158";
  $gid = $trasnfBD['pix_documento']=="44249060000118";

  $valor = $trasnfBD['ORIGEM_valor'];

  $periodo_mes = date('m');
  $periodo_ano = date('y');

  // TRANSFERENCIA ENTRE CONTAS

  $id_conta = $pw ? 1 : 2;
  $descricao = ($gid ? "GameID" : "PokerWeb") . " << ".($gid ? "GameID" : "PokerWeb")." Asaas";
  $sql = $bd->getConexao()->prepare('INSERT INTO fingeral_registros
    (id_categoria, id_conta, valor, descricao, id_ref, periodo_mes, periodo_ano, data_lancamento, data_vencimento, data_pagamento, status_pago, status) VALUES
    (125, :id_conta, :valor, :descricao, :id_ref, :periodo_mes, :periodo_ano, NOW(), NOW(), NOW(), 1, 0)');
  $sql->bindValue(':valor', $valor, PDO::PARAM_STR);
  $sql->bindValue(':id_conta', $id_conta, PDO::PARAM_STR);
  $sql->bindValue(':descricao', $descricao, PDO::PARAM_STR);
  $sql->bindValue(':id_ref', $trasnfBD['ORIGEM_modulo_id'], PDO::PARAM_STR);
  $sql->bindValue(':periodo_mes', date('m'), PDO::PARAM_STR);
  $sql->bindValue(':periodo_ano', date('y'), PDO::PARAM_STR);
  if($sql->execute());

  $id_lancamento = $bd->lastId();

  $sql = $bd->getConexao()->prepare('UPDATE fingeral_registros SET id_ref = :id_ref WHERE id = :id');
  $sql->bindValue(':id', $trasnfBD['ORIGEM_modulo_id'], PDO::PARAM_STR);
  $sql->bindValue(':id_ref', $id_lancamento, PDO::PARAM_STR);
  if($sql->execute());
}


// GAMEID
// *******************************************

// Realiza ações para o GameID, de pagamento confirmado
function gameidActions($pgtoBD, $dados_valores){
  global $bd;

  // Dados do jogador no GameID
  $sql = $bd->getConexao()->prepare('SELECT gameid, nome_completo FROM api_gameid.jogadores j WHERE j.id = :id');
  $sql->bindValue(':id', $pgtoBD['ORIGEM_modulo_id'], PDO::PARAM_STR);
  if($sql->execute()){$jogador_gid = $sql->fetch(PDO::FETCH_ASSOC);}

  // Registro no FNCR
  fncrInsertCaixa([
    "id_categoria"=>  120, // GameID - Taxas de Conveniência
    "id_conta"=>      6, // GameID - Asaas
    "id_clube"=>      $pgtoBD['FNCR_clube_id'],
    "descricao"=>     'GameID: '.$jogador_gid['gameid'].' - '.$jogador_gid['nome_completo'],
    "documento"=>     $pgtoBD['uuid'],
    "valor"=>         $dados_valores['gid_liquido'],
    "taxa_servico"=>  $dados_valores['servico_valor_taxa'],
    "observacao"=>
      'Jogador: '.echomoeda($dados_valores['servico_valor_bruto'])."\n".
      'Asaas: '.echomoeda($dados_valores['servico_valor_taxa'])."\n".
      'Clube: '.echomoeda($dados_valores['clube_valor_liquido']),
  ]);

  // Aciona api do GameID
  gameidRequest('received/'.$pgtoBD['uuid']);
}


// CLUBES
// *******************************************

// Realiza ações para o clube, de pagamento confirmado
function clubeActions($clube, $pgtoBD, $dados_valores){
  // Registro no FNCR
  fncrInsertCaixa([
    "id_categoria"=>  145, // Pokerweb -> PWpay -> Pix Recebimentos
    "id_conta"=>      6, // GameID - Asaas
    "id_clube"=>      $pgtoBD['FNCR_clube_id'],
    "descricao"=>     null,
    "documento"=>     $pgtoBD['uuid'],
    "valor"=>         $dados_valores['gid_liquido'],
    "taxa_servico"=>  $dados_valores['servico_valor_taxa'],
    "observacao"=>
      'Jogador: '.echomoeda($dados_valores['servico_valor_bruto'])."\n".
      'Asaas: '.echomoeda($dados_valores['servico_valor_taxa'])."\n".
      'Clube: '.echomoeda($dados_valores['clube_valor_liquido']),
  ]);

  // Aciona requisição ao sistema do clube
  clubSystemRequest($clube['link_sistema'], 'payment/received/'.$pgtoBD['uuid']);
}


// REALIZA AÇÕES EM SISTEMAS/APIS
// *******************************************
// *******************************************

// GAMEID - REQUEST (API)
function gameidRequest($url_ext){
  $access_token_pw = accessTkPw();

  $url = DEVELOPER ? 'http://192.168.100.44/_apis/gameid/api/pgto_ext/' : 'https://pw.pokerweb.com.br/_apis/gameid/v2/api/pgto_ext/';

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url.$url_ext);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Access_token_PW: ".$access_token_pw,
    "accept: application/json",
    "content-type: application/json",
  ]);
  $response = curl_exec($ch);
  // echoPre($response);
  $err = curl_error($ch);
  curl_close($ch);
}

// CLUBE - REQUISIÇÃO AO SISTEMA
function clubSystemRequest($url_link_sistema, $url_ext){
  $access_token_pw = accessTkPw();

  //$url = DEVELOPER ? 'http://192.168.100.44/st_code/' : $url_link_sistema.'.pokerweb.com.br/';

  //curl_setopt($ch, CURLOPT_URL, 'http://192.168.100.44/st_code/api/pgto_ext/'.$url_ext); // LOCAL IP
  //curl_setopt($ch, CURLOPT_URL, $url_link_sistema.'.pokerweb.com.br/api/pgto_ext/'.$url_ext); // PRODUÇÃO
  //curl_setopt($ch, CURLOPT_URL, 'http://'.$url_link_sistema.'.localhost/api/pgto_ext/'.$url_ext); // LOCAL URL

  // REQUISIÇÃO
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url_link_sistema.'.pokerweb.com.br/api/pgto_ext/'.$url_ext); // PRODUÇÃO
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, '{}');
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Access_token_PW: ".$access_token_pw,
    "accept: application/json",
    "content-type: application/json",
  ]);
  $response = curl_exec($ch);
  //echo $response;
  $err = curl_error($ch);
  curl_close($ch);
}

// EVENTOS - AÇÕES TEMPORÁRIAS PARA EVENTO
function eventSystemActions($pgtoBD, $dados_valores){
  global $bd;

  // Registro no FNCR
  fncrInsertCaixa([
    "id_categoria"=>  145, // Pokerweb -> PWpay -> Pix Recebimentos
    "id_conta"=>      6, // GameID - Asaas
    "id_clube"=>      $pgtoBD['FNCR_clube_id'],
    "descricao"=>     null,
    "documento"=>     $pgtoBD['uuid'],
    "valor"=>         $dados_valores['gid_liquido'],
    "taxa_servico"=>  $dados_valores['servico_valor_taxa'],
    "observacao"=>
      'Jogador: '.echomoeda($dados_valores['servico_valor_bruto'])."\n".
      'Asaas: '.echomoeda($dados_valores['servico_valor_taxa'])."\n".
      'Clube: '.echomoeda($dados_valores['clube_valor_liquido']),
  ]);

  // BD e Link do clube
  $sql = $bd->getConexao()->prepare('SELECT * FROM clubes_configuracao WHERE id_clube = :id_clube');
  $sql->bindValue(':id_clube', $pgtoBD['FNCR_clube_id'], PDO::PARAM_STR);
  if($sql->execute()){$resul_config = $sql->fetch(PDO::FETCH_ASSOC);}

  if($resul_config['link_sistema']!="" && $resul_config['bd']!=""){
    // Atualiza cobrança no clube
    $bdclube = new ConeccaoClube($resul_config['bd']);
    $sql = $bdclube->getConexao()->prepare('UPDATE fingeral_cobrancas SET
      prevenda = 0,
      pago = 1,
      pago_data_hora = NOW(),
      prevenda_finalizado = 1,
      prevenda_finalizado_data_hora = NOW(),
      valor = prevenda_valor
    WHERE id = :id');
    $sql->bindValue(':id', $pgtoBD['CLUBE_pre_venda_id'], PDO::PARAM_STR);
    $sql->execute();

    include_once('../libraries/outros/Firebase.php');
    $RT = new Firebase();
    $RT->init(GLOBAL_FBS_ACCOUNT)->setNoPrincipal($resul_config['link_sistema'])->defChild('evento')->defChild('acoes');
    $RT->run('acao_evento', [
      "acao"=> "pix_pagamento_confirmado",
      "opts"=> [
        'id'=>$pgtoBD['id'],
        'uuid'=>$pgtoBD['uuid'],
      ],
    ], true);
  }
}


// FUNÇÕES AUXILIARES
// *******************************************

// FNCR - Lançamento no caixa
function fncrInsertCaixa($dds){
  global $bd;
  // Registro do Valor
  $sql = $bd->getConexao()->prepare('INSERT INTO fingeral_registros
  (id_conta, id_categoria, id_clube, descricao, observacao, documento, valor, taxa_servico, periodo_mes, periodo_ano, data_lancamento, data_vencimento, data_pagamento, status, status_pago) VALUES
  (:id_conta, :id_categoria, :id_clube, :descricao, :observacao, :documento, :valor, :taxa_servico, :periodo_mes, :periodo_ano, NOW(), NOW(), NOW(), 0, 1)');
  $sql->bindValue(':id_conta', $dds['id_conta'], PDO::PARAM_STR);
  $sql->bindValue(':id_categoria', $dds['id_categoria'], PDO::PARAM_STR);
  $sql->bindValue(':id_clube', $dds['id_clube'], PDO::PARAM_STR);
  $sql->bindValue(':descricao', $dds['descricao'], PDO::PARAM_STR);
  $sql->bindValue(':observacao', $dds['observacao'], PDO::PARAM_STR);
  $sql->bindValue(':documento', $dds['documento'], PDO::PARAM_STR);
  $sql->bindValue(':valor', $dds['valor'], PDO::PARAM_STR);
  $sql->bindValue(':taxa_servico', $dds['taxa_servico'], PDO::PARAM_STR);
  $sql->bindValue(':periodo_mes', date("m"), PDO::PARAM_STR);
  $sql->bindValue(':periodo_ano', date("y"), PDO::PARAM_STR);
  if($sql->execute());
}

// SUBCONTA do clube
function subConta_dds($opts){
  global $bd;

  if(isset($opts['id_subconta'])){
    $sql = $bd->getConexao()->prepare('
    SELECT
      sc.*,
      cc.link_sistema
    FROM pwbank_subcontas sc
      LEFT JOIN pwbank_contas bc ON bc.id = sc.id_conta
      LEFT JOIN clubes_configuracao cc ON cc.id_clube = sc.tipo_id
    WHERE sc.id = :id');
    $sql->bindValue(':id', $opts['id_subconta'], PDO::PARAM_STR);
    if($sql->execute()){$subconta = $sql->fetch(PDO::FETCH_ASSOC);}
  }

  elseif(isset($opts['tipo']) && isset($opts['tipo_id']) && $opts['tipo_id']>0){
    // Dados da subconta
    $sql = $bd->getConexao()->prepare('
    SELECT
      sc.*,
      cc.link_sistema
    FROM pwbank_subcontas sc
      LEFT JOIN pwbank_contas bc ON bc.id = sc.id_conta
      LEFT JOIN clubes_configuracao cc ON cc.id_clube = sc.tipo_id
    WHERE sc.ext_servico_id = 2 AND sc.tipo = :tipo AND sc.tipo_id = :tipo_id');
    $sql->bindValue(':tipo', $opts['tipo'], PDO::PARAM_STR);
    $sql->bindValue(':tipo_id', $opts['tipo_id'], PDO::PARAM_STR);
    if($sql->execute()){$subconta = $sql->fetch(PDO::FETCH_ASSOC);}
  }

  return $subconta;
}

// TK FNCR (para acesso às apis internas)
function accessTkPw(){
  // ACCESS TOKEN PW
  include_once dirname(__FILE__).'/../../_vendors/google-authenticator/FixedBitNotation.php';
  include_once dirname(__FILE__).'/../../_vendors/google-authenticator/GoogleAuthenticatorInterface.php';
  include_once dirname(__FILE__).'/../../_vendors/google-authenticator/GoogleAuthenticator.php';
  include_once dirname(__FILE__).'/../../_vendors/google-authenticator/GoogleQrUrl.php';
  $auth = new \Google\Authenticator\GoogleAuthenticator();

  $timeSlice = floor(time()/30); // Período atual de 30 segundos
  $code = $auth->getCode(strtoupper(GLOBAL_KEY_CRYPTO), $timeSlice);

  require_once('../libraries/outros/Crypto.php');
  $crypto = new Crypto();
  return $crypto->encode(json_encode(array("code_auth" => $code, "system" => 'fncr')));
}

// VERIFICAR HASH DE AUTENTICAÇÃO
function hashAutenticacao($dds){
  if(empty($dds['hash_autenticacao'])) return false;

  require_once('../libraries/outros/Crypto.php');
  $crypto = new Crypto();
  $infs = json_decode($crypto->decode($dds['hash_autenticacao']), true);
  if(!$infs) return false;
  $infs = (object) $infs;
  if(
    empty($infs->uuid)
    || empty($infs->ORIGEM_modulo)
    || empty($infs->pix_chave)
    || empty($infs->pix_documento)
    || empty($infs->expire)
  ){ return false; }

  // Verifica expiração
  if(time()>$infs->expire) return false;
  // Temporário - Verifica ORIGEM_modulo que estão disponíveis (pix_subconta e taxa)
  if(!in_array($infs->ORIGEM_modulo, ['pix_subconta', 'ext_transferencia'])) return false;
  // Confronta informações primárias
  if($infs->uuid!=$dds['uuid']){ return false; }

  // Confronta informações secundárias se for diferente de 'ext_transferencia'
  if(
    $infs->ORIGEM_modulo!="ext_transferencia"
    && (
      $infs->ORIGEM_modulo!=$dds['ORIGEM_modulo']
      || $infs->pix_chave!=$dds['pix_chave']
      || $infs->pix_documento!=$dds['pix_documento']
    )
  ){ return false; }

  /*
  if($infs->uuid!=$dds['uuid']
    || $infs->ORIGEM_modulo!=$dds['ORIGEM_modulo']
    || $infs->pix_chave!=$dds['pix_chave']
    || $infs->pix_documento!=$dds['pix_documento']
  ){ return false; }
  */

  return true;
}

// Retorna OK e continua ações
function returnContinue($dds=['status'=>'ok']){
  ignore_user_abort(true);
  set_time_limit(0);
  while(ob_get_level()>0)@ob_end_clean();
  // Monta saída
  ob_start();
  $body = json_encode($dds,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
  header('Connection: close');
  header('Content-Length: '.strlen($body));
  echo $body;
  // envia e fecha buffer atual
  ob_end_flush();
  flush();
  // a partir daqui, qualquer echo é descartado
  ob_start(function($buf){return '';});
}

?>