# Etapa 4 - Geração de link de afiliado próprio (meli.la)

## Status

- Situacao: **Concluido**
- Objetivo: para cada oferta processada, gerar um link `meli.la` próprio (tag `pechinchinhaboa`) antes de montar o texto de repost — nunca publicar link de afiliado de terceiros.

---

## Contexto

O Mercado Livre não oferece API pública para geração de links de afiliado. O portal de afiliados usa um endpoint interno (`/affiliate-program/api/v2/affiliates/createLink`) que exige:
- Cookie de sessão autenticado do portal ML
- Token CSRF obtido dinamicamente da página `/afiliados/linkbuilder`
- Body: `{"urls": ["URL_DO_PRODUTO"], "tag": "NOME_DA_TAG"}`

---

## Descobertas e problemas resolvidos

### 1. Formato do body (problema principal)
O endpoint exige `urls` (array) + `tag`, não `url` + `short` como testado inicialmente:
```json
{"urls": ["https://produto.mercadolivre.com.br/MLB-XXXXX-slug"], "tag": "pechinchinhaboa"}
```

### 2. CSRF Token separado do cookie
O header `x-csrf-token` exige um token **diferente** do cookie `_csrf`. Ele é gerado dinamicamente e extraído via GET na página `/afiliados/linkbuilder` (meta tag `csrf-token`).

### 3. URL com slug obrigatória
Enviar `https://produto.mercadolivre.com.br/MLB-XXXXX` (sem slug) retorna `error_code: 111 - URL not allowed`. A URL completa com slug (obtida do `finalUrl` já resolvido) é obrigatória.

### 4. Cookie salvo em arquivo (não no .env)
O cookie de sessão é muito longo para o parser do `.env`. Solução: salvo em `storage/app/ml_affiliate_cookie.txt`, lido pelo `config/ml.php` com prioridade sobre o `.env`.

### 5. error_code 111 — produto não elegível
Alguns produtos são bloqueados pelo próprio ML para o programa de afiliados (ex: revendas de outros afiliados, certas categorias). O sistema aborta a oferta silenciosamente nesses casos.

---

## Regra de negócio implementada

**Se não gerar link de afiliado próprio → abortar a oferta, não publicar nada.**

Nunca usar o link de entrada (de terceiros) como fallback no texto final.

---

## Arquivos alterados

| Arquivo | Alteracao |
|---|---|
| `app/Services/Affiliate/MercadoLivreAffiliateService.php` | Adicionados `generateAffiliateLink(mlb, finalUrl)` e `fetchCsrfToken()` |
| `app/Console/Commands/TelegramProcessMl.php` | Integrado `generateAffiliateLink`; aborta se sem link |
| `app/Console/Commands/TelegramProcessPending.php` | Integrado `generateAffiliateLink`; aborta se sem link |
| `app/Console/Commands/MlTestAffiliate.php` | Comando de teste isolado do endpoint de afiliado |
| `app/Console/Commands/MlSaveCookie.php` | Comando para salvar cookie interativamente |
| `config/ml.php` | Configurações do ML: cookie (arquivo), tag, endpoint, timeout |
| `.env.example` | Adicionados `ML_AFFILIATE_COOKIE=` e `ML_AFFILIATE_TAG=pechinchinhaboa` |

---

## Configuração necessária

### Cookie de sessão (renovar a cada ~30-90 dias)
```powershell
php artisan ml:save-cookie
```
Cola o cookie completo copiado do DevTools do browser logado em `mercadolivre.com.br/afiliados`.

### Tag de afiliado
Definida em `config/ml.php` como padrão `pechinchinhaboa`. Pode ser sobrescrita via `.env`:
```
ML_AFFILIATE_TAG=pechinchinhaboa
```

### Nome do perfil social (exibido no meli.la)
Configurado diretamente no portal: [mercadolivre.com.br/afiliados](https://www.mercadolivre.com.br/afiliados) → Perfil → Nome de exibição.

---

## Comandos disponíveis

| Comando | Uso |
|---|---|
| `php artisan ml:save-cookie` | Salvar/renovar cookie de sessão ML |
| `php artisan ml:test-affiliate MLB-XXXXX` | Testar geração de link para um MLB específico |
| `php artisan telegram:process-ml "URL"` | Resolver URL + scraping + gerar link + texto completo |

---

## Próxima etapa

**Etapa 5 — Publicação automática no Telegram**

- Receber o `formatted_text` gerado e publicar no(s) canal(is) de destino configurados
- Usar o bot do Telegram (MadelineProto já configurado) para enviar a mensagem
- Marcar a oferta como `PUBLISHED` no banco de dados
- Controlar frequência de postagem (evitar spam)
- Ver: `docs/TELEGRAM_ETAPA_5_PUBLICACAO.md` (a criar)
