# Instalador/configurador do Trivio PDV+ via API direta (sem UI Automation). # Servido via "irm https://triviocli.grupobona.com.br | iex" - roda 100% em # memoria, nenhum arquivo .ps1/.cmd/.bat fica na maquina. Este script NAO tem # nenhuma credencial: a assinatura Hubee (HMAC) e calculada no proprio # servidor (triviocli.grupobona.com.br/merchants/{cnpj}, ver # trivio-signer-server.js), que repassa a chamada assinada pra api.triv.io e # devolve so o resultado. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $script:SignerBaseUrl = 'https://triviocli.grupobona.com.br' $script:InstallerUrl = 'https://trivio-arquivos.s3.amazonaws.com/pdvreader/Instalador%20PDV%2B.exe' $script:InstallDir = 'C:\TrivioCRM\PDV+' $script:IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) function Test-Cnpj { param([string]$Value) $digits = ($Value -replace '\D', '') if ($digits.Length -ne 14) { return $false } if ($digits -match '^(\d)\1{13}$') { return $false } $calc = { param($nums, $weights) $sum = 0 for ($i = 0; $i -lt $nums.Length; $i++) { $sum += [int]::Parse($nums[$i]) * $weights[$i] } $rest = $sum % 11 if ($rest -lt 2) { return 0 } else { return 11 - $rest } } $d1 = & $calc $digits[0..11] @(5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2) $d2 = & $calc $digits[0..12] @(6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2) return ($digits[12] -eq [string]$d1) -and ($digits[13] -eq [string]$d2) } # A assinatura Hubee acontece no servidor (triviocli.grupobona.com.br/merchants/{cnpj} # -> trivio-signer-server.js -> api.triv.io). Este script so fala com o nosso # proprio dominio, nunca tem o ClientSecret em maos. function Get-TrivioMerchant { param([string]$CnpjDigits) $fullUrl = "$script:SignerBaseUrl/merchants/$CnpjDigits" try { return Invoke-RestMethod -Uri $fullUrl -Method Get -ErrorAction Stop } catch { $resp = $_.Exception.Response if ($resp -and [int]$resp.StatusCode -eq 404) { return $null } throw } } function Get-ErpOrdinal { param([string]$NameErp) $key = '' if ($NameErp) { $key = $NameErp.Trim().ToLowerInvariant() } switch ($key) { 'sistemabig' { return 0 } 'alpha7' { return 1 } 'pontosys' { return 2 } 'automatiza' { return 3 } 'softpharma' { return 4 } 'vetor' { return 5 } default { return 0 } } } function Stop-TrivioProcess { Get-Process -Name 'TrivioPDV+' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue $deadline = (Get-Date).AddSeconds(10) while ((Get-Date) -lt $deadline) { if (-not (Get-Process -Name 'TrivioPDV+' -ErrorAction SilentlyContinue)) { break } Start-Sleep -Milliseconds 200 } Start-Sleep -Seconds 2 } # TrivioPdvPlusStarter nao e so "abre uma vez": e um servico supervisor que # reabre o TrivioPDV+.exe sempre que detecta que ele nao esta rodando. Matar # so o processo nao e confiavel - precisa pausar o servico antes de mexer em # qualquer coisa, senao ele briga pelo mutex global do app com a instancia # que a gente (ou o proprio instalador) tenta subir, e aparece o aviso # "PDV+ ja esta em execucao". Precisa rodar como Administrador pra isso # funcionar (ver $script:IsAdmin). # # Stop-Service do PowerShell fica esperando (sem timeout) o servico chegar # em "Parado" - se ele nunca chegar, trava o script inteiro. sc.exe stop so # manda o sinal e volta na hora; Set-Service -StartupType Disabled impede o # servico de subir de novo sozinho. Mas so mandar o sinal e sair correndo # tambem e arriscado: se matarmos o processo filho antes do servico # processar o stop, ele relança na hora (o servico e o supervisor, essa e # a funcao dele). Por isso espera a confirmacao real via Get-Service (que # so consulta o estado, nao trava) com um limite de tempo - nem trava pra # sempre, nem sai sem confirmar. function Stop-TrivioWatchdogService { try { Set-Service -Name 'TrivioPdvPlusStarter' -StartupType Disabled -ErrorAction Stop } catch {} try { sc.exe stop TrivioPdvPlusStarter | Out-Null } catch {} $deadline = (Get-Date).AddSeconds(10) while ((Get-Date) -lt $deadline) { $svc = Get-Service -Name 'TrivioPdvPlusStarter' -ErrorAction SilentlyContinue if (-not $svc -or $svc.Status -eq 'Stopped') { break } Start-Sleep -Milliseconds 300 } } function Start-TrivioWatchdogService { try { Set-Service -Name 'TrivioPdvPlusStarter' -StartupType Automatic -ErrorAction Stop sc.exe start TrivioPdvPlusStarter | Out-Null return $true } catch { return $false } } function Install-TrivioExe { $exePath = Join-Path $script:InstallDir 'TrivioPDV+.exe' if (Test-Path $exePath) { return $exePath } $installerPath = Join-Path $env:TEMP 'InstaladorPDV+.exe' Write-Host 'Baixando instalador oficial...' -ForegroundColor Cyan Invoke-WebRequest -Uri $script:InstallerUrl -OutFile $installerPath -UseBasicParsing Write-Host 'Instalando (silencioso)...' -ForegroundColor Cyan $proc = Start-Process -FilePath $installerPath -ArgumentList '/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', '/SP-' -PassThru # O instalador (secao [Run] do Inno Setup) abre o TrivioPDV+.exe sozinho # ao terminar com a flag WaitUntilTerminated - ou seja, o PROPRIO # instalador fica esperando esse app fechar antes de se considerar # terminado. Esse app abre parado numa tela de configuracao vazia, # esperando alguem digitar o CNPJ. Sem ninguem ali, vira deadlock: o # instalador espera o app fechar, a gente espera o instalador terminar # pra so entao fechar o app. Por isso NAO da pra usar -Wait aqui - mata # qualquer TrivioPDV+.exe que aparecer enquanto ainda espera o # instalador, pra nunca deixar a tela ficar parada esperando alguem. $deadline = (Get-Date).AddSeconds(120) while (-not $proc.HasExited -and (Get-Date) -lt $deadline) { Get-Process -Name 'TrivioPDV+' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Milliseconds 500 } if (-not $proc.HasExited) { throw 'Instalador nao terminou em 120s.' } if ($proc.ExitCode -ne 0) { throw "Instalador retornou codigo $($proc.ExitCode)." } if (-not (Test-Path $exePath)) { throw "Instalacao concluida mas '$exePath' nao foi encontrado." } Remove-Item $installerPath -Force -ErrorAction SilentlyContinue return $exePath } function Set-TrivioConfig { param($Merchant, [string]$CnpjDigits) New-Item -ItemType Directory -Force -Path $script:InstallDir | Out-Null # Mesmos nomes de propriedade de trivio_PdvReader_App.Core.Shared.ValueObjects.Merchant $merchantOut = [ordered]@{ LegalName = $Merchant.legalName CompanyName = $Merchant.companyName Alias = $Merchant.alias Cnpj = $Merchant.cnpj Address = $Merchant.address Number = $Merchant.number Neighborhood = $Merchant.neighborhood City = $Merchant.city Uf = $Merchant.uf EconomicGroupId = $Merchant.economicGroupId MerchantId = $Merchant.merchantId NameErp = $Merchant.nameErp TimeZone = $Merchant.timeZone } ($merchantOut | ConvertTo-Json) | Set-Content -Path (Join-Path $script:InstallDir 'MerchantConfig.json') -Encoding UTF8 # So os campos que afetam o boot (ver FormConfig.btnSave_Click); o resto # fica nos defaults de ConfigValueObject e pode ser revisto depois no # proprio menu "Configuracoes" do PDV+. $configOut = [ordered]@{ Cnpj = $CnpjDigits Erp = Get-ErpOrdinal -NameErp $Merchant.nameErp } ($configOut | ConvertTo-Json) | Set-Content -Path (Join-Path $script:InstallDir 'PdvReaderConfig.json') -Encoding UTF8 } function Invoke-TrivioInstallAndConfigure { param([string]$CnpjDigits) if (-not $script:IsAdmin) { Write-Host 'Aviso: nao esta rodando como Administrador. O PDV+ usa um servico (TrivioPdvPlusStarter) que so da pra pausar durante a configuracao com privilegios de administrador - sem isso ele pode reabrir o app por conta propria no meio do processo. Recomendado fechar e abrir o PowerShell como Administrador.' -ForegroundColor Yellow } Write-Host 'Consultando CNPJ na API da Trivio...' -ForegroundColor Cyan $merchant = $null try { $merchant = Get-TrivioMerchant -CnpjDigits $CnpjDigits } catch { Write-Host "Erro ao consultar a API da Trivio: $($_.Exception.Message)" -ForegroundColor Red; return } if (-not $merchant) { Write-Host 'CNPJ nao cadastrado na Trivio. Entre em contato com o suporte.' -ForegroundColor Red; return } Stop-TrivioWatchdogService Stop-TrivioProcess $exePath = $null try { $exePath = Install-TrivioExe } catch { Write-Host "Erro ao instalar o PDV+: $($_.Exception.Message)" -ForegroundColor Red; return } # O instalador registra/inicia o servico TrivioPdvPlusStarter e tambem # abre o app sozinho (secao [Run] do Inno Setup) - os dois competem pelo # mutex global do app. Pausa o servico de novo (agora que ele existe) e # mata em loop por uma janela maior, ate ter certeza que ninguem mais vai # reabrir sozinho antes da gente escrever a config. Stop-TrivioWatchdogService $deadline = (Get-Date).AddSeconds(15) while ((Get-Date) -lt $deadline) { Get-Process -Name 'TrivioPDV+' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Milliseconds 500 } Stop-TrivioProcess Set-TrivioConfig -Merchant $merchant -CnpjDigits $CnpjDigits Write-Host 'PDV+ configurado com sucesso.' -ForegroundColor Green Write-Host " Loja: $($merchant.companyName)" Write-Host " Razao social: $($merchant.legalName)" Write-Host " MerchantId: $($merchant.merchantId)" Write-Host " EconomicGroupId: $($merchant.economicGroupId)" Write-Host " ERP integrado: $($merchant.nameErp)" Write-Host 'Iniciando TrivioPDV+...' -ForegroundColor Cyan if (-not (Start-TrivioWatchdogService)) { Start-Process -FilePath $exePath -WorkingDirectory (Split-Path $exePath) } # Mesmo com o kill-loop, pode sobrar uma instancia "perdedora" da corrida # do mutex parada num MessageBox "PDV+ ja esta em execucao" (a instancia # de verdade roda sem janela, na bandeja - so essa tem titulo "Aviso"). # Espera o dialogo ter chance de aparecer e fecha so esse, sem mexer na # instancia real. Start-Sleep -Seconds 3 Get-Process -Name 'TrivioPDV+' -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowTitle -eq 'Aviso' } | Stop-Process -Force -ErrorAction SilentlyContinue } function Invoke-TrivioLookup { param([string]$CnpjDigits) try { $merchant = Get-TrivioMerchant -CnpjDigits $CnpjDigits } catch { Write-Host "Erro ao consultar a API da Trivio: $($_.Exception.Message)" -ForegroundColor Red; return } if (-not $merchant) { Write-Host 'CNPJ nao encontrado na Trivio.' -ForegroundColor Red; return } Write-Host "Loja: $($merchant.companyName)" Write-Host "Razao social: $($merchant.legalName)" Write-Host "MerchantId: $($merchant.merchantId)" Write-Host "EconomicGroupId: $($merchant.economicGroupId)" Write-Host "ERP integrado: $($merchant.nameErp)" } function Invoke-TrivioUninstall { Stop-TrivioWatchdogService Stop-TrivioProcess $uninstaller = Join-Path $script:InstallDir 'unins000.exe' if (Test-Path $uninstaller) { Write-Host 'Rodando desinstalador oficial...' -ForegroundColor Cyan Start-Process -FilePath $uninstaller -ArgumentList '/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', '/SP-' -Wait } if (Test-Path $script:InstallDir) { Remove-Item $script:InstallDir -Recurse -Force -ErrorAction SilentlyContinue } $identityDir = Join-Path $env:ProgramData 'Trivio' if (Test-Path $identityDir) { Remove-Item $identityDir -Recurse -Force -ErrorAction SilentlyContinue } try { Unregister-ScheduledTask -TaskName 'TrivioPDV+' -Confirm:$false -ErrorAction Stop } catch {} try { sc.exe delete TrivioPdvPlusStarter | Out-Null } catch {} Write-Host 'Limpeza concluida (alguns itens podem exigir execucao como Administrador).' -ForegroundColor Yellow } function Read-CnpjFromUser { while ($true) { $value = Read-Host 'CNPJ (com ou sem pontuacao)' if (Test-Cnpj $value) { return ($value -replace '\D', '') } Write-Host 'CNPJ invalido (digitos verificadores nao conferem).' -ForegroundColor Red } } function Show-TrivioMenu { Write-Host '' Write-Host '======================================' -ForegroundColor Cyan Write-Host ' Trivio PDV+ - instalador direto' -ForegroundColor Cyan Write-Host '======================================' -ForegroundColor Cyan Write-Host ' 1) Instalar / configurar (CNPJ)' Write-Host ' 2) Consultar CNPJ (somente leitura)' Write-Host ' 3) Desinstalar tudo' Write-Host ' 0) Sair' Write-Host '======================================' -ForegroundColor Cyan } while ($true) { Show-TrivioMenu $opt = Read-Host 'Escolha uma opcao' switch ($opt) { '1' { Invoke-TrivioInstallAndConfigure -CnpjDigits (Read-CnpjFromUser) } '2' { Invoke-TrivioLookup -CnpjDigits (Read-CnpjFromUser) } '3' { Invoke-TrivioUninstall } '0' { return } default { Write-Host 'Opcao invalida.' -ForegroundColor Yellow } } }