--- name: Bling - Fix fingerprint falso positivo (2026-04-22) description: Correcao do bug que fazia contas Bling com multiplas lojas cairem em loop de reautorizacao + limpeza de dados contaminados type: project originSessionId: 900f26b9-8e66-41bd-9ba3-3e12fe12867b --- # Bling — Fix fingerprint "token mudou de loja" (2026-04-22) ## Sintoma Usuario reclamou que "Bling esta caindo direto, tendo que conectar as contas". Contas marcadas com `status = erro` e mensagem `"token mudou de loja (era X, agora Y) - reautorize"`. ## Causa raiz `BlingApi::getLojaFingerprint()` usava `loja.id` do pedido mais recente como identificador unico do tenant Bling. Mas uma conta Bling legitima pode ter varios canais (Shopee, Mercado Livre, Amazon, loja fisica), cada um com `loja_id` proprio. Cada novo pedido de canal diferente mudava o fingerprint → cron marcava `status = erro` → reconexao → outra loja virava a mais recente → erro de novo. Ciclo infinito. **Caso G Closet**: 15 `loja_id` distintas na mesma conta Bling. ## Fix aplicado ### `app/Libraries/BlingApi.php` — novo metodo ```php public function getLojaIdsRecentes(int $paginas = 3): array { $lojaIds = []; for ($p = 1; $p <= $paginas; $p++) { $r = $this->get('pedidos/vendas', ['limite' => 100, 'pagina' => $p]); if (($r['http_code'] ?? 0) !== 200) break; $pedidos = $r['dados']['data'] ?? []; if (empty($pedidos)) break; foreach ($pedidos as $ped) { $lid = $ped['loja']['id'] ?? null; if ($lid) $lojaIds[(int)$lid] = true; } if (count($pedidos) < 100) break; usleep(400000); } return array_keys($lojaIds); } ``` ### `app/Controllers/Bling.php` - `callback()` (OAuth): usa `getLojaIdsRecentes(2)` + valida contra `bling_pedidos` historicos de outras contas (nao so `bling_contas.bling_loja_id`). - `sincronizar()`: REMOVIDA checagem "token mudou de loja" (era falso positivo). Mantida apenas checagem "loja pertence a outra conta" baseada em `bling_pedidos`. ### Tentativas que nao deram certo - `GET /empresas/me/dados-basicos` → HTTP 403 `insufficient_scope` (app Bling nao tem escopo). - `GET /lojas` → HTTP 404 (endpoint inacessivel). Por isso a solucao usa o SET de `loja_id` observados em vez do CNPJ da empresa. ## Contaminacao descoberta e corrigida Ao rodar o sync com fix novo, detectou colisao entre: - G Closet (conta 2, CNPJ `55.157.703/0001-10`) - GotechBr (conta 5, CNPJ `28.347.294/0001-41`) **10 loja_ids sobrepostos** — ambas contas tinham os mesmos pedidos importados. ### Como aconteceu - 30/03/2026: G Closet conectada com OAuth feito enquanto Bling estava logado como GotechBr → baixou 1000 pedidos da GotechBr erradamente. - 10/04/2026: GotechBr conectada corretamente → re-importou os mesmos 1000 pedidos (legitimamente dela). - 17/04/2026: validacao de fingerprint adicionada, mas dados antigos ja contaminados. ### Limpeza ```sql CREATE TABLE bling_pedidos_backup_contaminacao_2026_04_22 AS SELECT * FROM bling_pedidos WHERE bling_conta_id = 2 AND loja_id IN ( 0, 203462744, 203464230, 203467917, 203531556, 203547711, 203614804, 205071536, 205081436, 205094656 ); DELETE FROM bling_pedidos WHERE bling_conta_id = 2 AND loja_id IN ( 0, 203462744, 203464230, 203467917, 203531556, 203547711, 203614804, 205071536, 205081436, 205094656 ); ``` Removeu 1000 linhas. Backup em `bling_pedidos_backup_contaminacao_2026_04_22`. ## Estado final (2026-04-22 12:39) | Conta | Status | Pedidos | Lojas | Token expira | |------------------|--------|---------|-------|--------------| | G Closet (2) | ativa | 687 | 5 | 15:16 | | VALOR MOVEIS (3) | ativa | 2 | 1 | 18:00 | | GotechBr (5) | ativa | 1001 | 10 | 15:03 | Sync pos-fix: **1689 pedidos sincronizados, 0 erros**. Zero sobreposicao de loja_id entre contas. ## Crons ativos ```cron */10 8-21 * * * wget -q -O /dev/null https://sistema.gotechbr.com.br/cron/catalogo-bling?token=... 0 */2 * * * wget -q -O /dev/null https://sistema.gotechbr.com.br/bling/cron-renovar-tokens?token=... */5 * * * * wget -q -O /dev/null https://sistema.gotechbr.com.br/bling/cron-sincronizar?token=... ``` ## Como debugar se acontecer de novo 1. `SELECT status, ultimo_erro FROM bling_contas WHERE id = X` — ver erro atual. 2. Se erro contem `"loja X ja pertence a conta Y"`: OAuth real errado. Usuario precisa deslogar em bling.com.br e entrar com a conta certa antes de reautorizar. 3. Checar contaminacao: ```sql SELECT loja_id, COUNT(DISTINCT bling_conta_id) FROM bling_pedidos GROUP BY loja_id HAVING COUNT(DISTINCT bling_conta_id) > 1; ``` ## Relacionados - [[bling_integracao]] - [[bling_modulo_2026_03_31]]