定制 montu/module-affiliate 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

montu/module-affiliate

Composer 安装命令:

composer require montu/module-affiliate

包简介

Montu Affiliate Tracking Extension for Magento 2 - Captures affiliate referral codes, attributes orders, sends signed order webhooks, and renders a white-label affiliate storefront.

README 文档

README

Paquete Composer del módulo Montu_Affiliate: captura códigos de afiliados en el storefront y envía webhooks firmados con la información de las órdenes a la plataforma Montu.

Este directorio es el paquete Composer (raíz = raíz del módulo). No contiene una instalación de Magento ni entorno Docker — solo el código del módulo, instalable vía Composer en cualquier proyecto Magento 2.

✨ Características

  • No Invasivo — no modifica tablas core de Magento (crea las suyas)
  • Asíncrono — no bloquea el checkout; los webhooks se entregan por cron
  • Fail-safe — los observers nunca dejan escapar excepciones
  • Reintentos automáticos — 5 intentos con backoff exponencial (1/5/15/30/60 min)
  • White-label — el storefront del afiliado adopta los colores y la tipografía de cualquier tema de la tienda (o se configuran a mano en el admin)

📦 Instalación vía Composer

El paquete está publicado en Packagist público, así que la instalación es directa, sin configurar repositorios:

composer require montu/module-affiliate

Requisitos: Magento 2.4.x y PHP 8.1+.

Instalación para desarrollo (monorepo / repositorio path)

Este paquete vive como subcarpeta magento/ del monorepo de Montu. Para trabajar contra el código en disco (cambios en vivo), apunta Composer a la carpeta con un repo path:

// composer.json del proyecto Magento
{
  "repositories": [
    { "type": "path", "url": "../monorepo/magento", "options": { "symlink": true } }
  ]
}
composer require montu/module-affiliate:@dev

symlink: true enlaza la carpeta; usa "symlink": false para que Composer copie el paquete (recomendado en builds/deploys).

El composer.json no fija version: Composer toma la versión de los tags git del repo publicado en Packagist (git tag v1.0.0), así que puedes fijar ^1.0 si lo necesitas.

Activar el módulo (después de composer require)

bin/magento module:enable Montu_Affiliate
bin/magento setup:upgrade            # crea montu_affiliate_tracking + montu_affiliate_webhook_log
bin/magento setup:di:compile         # tras cambios de DI / constructores
bin/magento cache:clean

⚙️ Configuración

Stores → Configuration → Montu → Affiliate Tracking

Campo Descripción Default
Enable Module Activa la extensión No
URL Parameter Parámetro a capturar _m_aff
Cookie Name Nombre de la cookie _montu_aff_ref_code
Cookie Lifetime Días de duración 15
Enable Webhook Activa webhooks No
Webhook URL URL de tu endpoint -
API Key Tu API key (almacenada encriptada) -

Storefront del afiliado (sección Affiliate Storefront)

Campo Descripción Default
Enable Storefront Page Activa la ruta /storefront/{code} No
Route Path Prefix Prefijo de la URL pública storefront
Page Heading Título de la página Recommended products
Recommendations Endpoint URL Endpoint Montu de productos recomendados -
Storefront Language Idioma de la página: en_US, es_ES o es_CL (Chile) en_US
Max Products Máximo de productos a mostrar 12

Idioma: Magento no hace fallback de es_CLes_ES, por eso el módulo incluye traducciones propias para Chile (i18n/es_CL.csv). Para una tienda chilena, selecciona Spanish (Chile).

Apariencia / White-label (sección Appearance)

El storefront es white-label: adopta los colores y la tipografía de la tienda automáticamente. Todos los colores, bordes, radios de tarjeta y la fuente se controlan por variables CSS.

Campo Descripción Default
Theme Mode Auto (muestrea el tema de la tienda en runtime), Manual (usa los colores de abajo) u Off (estilo neutro) Auto
Accent / Primary Color Color principal (botones, lista activa, resaltados). Acepta #hex, rgb()/rgba() o nombre CSS (muestreado)
Accent Text Color Color de texto legible sobre el acento #ffffff
Body Text Color Color de texto del storefront (vacío → hereda el tema) (heredado)
Muted Text Color Color de texto secundario (conteos, subtítulos) #6d6d6d
Border Color Color de bordes/divisores #e3e3e3
Card Background Color Fondo de las tarjetas de producto #ffffff
Card Corner Radius Radio de esquina de las tarjetas (10px, 0, 0.5rem) 10px
Font Family Stack de fuentes del storefront (vacío → hereda la fuente del tema) (heredado)
  • Auto: sin configurar nada, el storefront muestrea el color del botón primario, el color de texto y la fuente del tema vivo de la tienda (Luma, custom o re-skin) y se adapta. Los valores de arriba sirven como semilla/fallback.
  • Manual: fija exactamente los colores configurados, sin muestreo runtime. Los campos vacíos usan el default neutro.
  • Off: estilo neutro por defecto (sin muestreo, ignora los colores).

🛍️ Tienda del Afiliado (/storefront/{code})

Un visitante puede entrar con un código de afiliado de dos formas, y en ambas se guarda la cookie con el código:

  1. Query paramhttps://tienda.com/?_m_aff=ABC123 (capturado por JS).
  2. Ruta storefronthttps://tienda.com/storefront/ABC123, que además renderiza una página con los productos que ese afiliado recomienda.

La ruta la resuelve un router personalizado (Controller/Router.php) que toma el código del path y reenvía a Controller/Storefront/Index.php. El controlador valida el código (^[a-zA-Z0-9_\-]{1,100}$), escribe la cookie en el servidor (mismo nombre/duración que la captura por JS) y renderiza la página, declarada cacheable="false" para que el Full Page Cache / Fastly nunca la sirva cacheada.

Los productos se obtienen vía Service/RecommendationClient.php desde el endpoint de recomendaciones de Montu (GET /montu/api/v1/ecommerce/magento/recommendations/{store_id}/{code}), firmado con HMAC-SHA256 (igual que el webhook). Configura Recommendations Endpoint URL en admin con la URL terminada en el id de tienda. La forma esperada del JSON está documentada en RecommendationClient::parseResponse(). Si el endpoint falla o no responde, la página degrada con elegancia (datos de ejemplo) en vez de romperse.

Full Page Cache / Fastly: la ruta /storefront/{code} está declarada cacheable="false", así que el FPC/Fastly nunca la cachea (es por-afiliado y escribe la cookie). El JS de captura (tracking.js) lee el parámetro ?_m_aff= en el cliente, así que funciona aunque el resto de las páginas estén cacheadas.

Queue-it / Klevu / reglas de path: si la tienda tiene una sala de espera virtual o un proxy de búsqueda delante del storefront, agrega el prefijo de la ruta (/storefront/...) a la lista de paths permitidos para que no sea interceptado.

🔄 Cómo Funciona

?_m_aff=ABC123 → JS guarda cookie
   → (compra) → Observer encola fila pending en montu_affiliate_webhook_log
   → Cron/ProcessWebhooks (cada 5 min) → POST firmado (HMAC-SHA256) a tu endpoint
  1. Capturaview/frontend/web/js/tracking.js guarda ?_m_aff= en cookie.
  2. Persistir al carritoObserver/SaveAffiliateToQuote (checkout_cart_save_after).
  3. Vincular a ordenObserver/CopyAffiliateToOrder (sales_model_service_quote_submit_success).
  4. Encolar webhookObserver/SendOrderWebhook (checkout_submit_all_after) si la orden tiene código de afiliado o cupón.
  5. Entregar asyncCron/ProcessWebhooksService/WebhookService (Curl + HMAC + reintentos).

📊 Sistema de Reintentos

Intento
Espera 1 min 5 min 15 min 30 min 1 hora

Tras el 5º intento el webhook se marca como max_retries.

📨 Formato del Webhook

Headers

Content-Type: application/json
X-Montu-Api-Key: <tu_api_key>
X-Montu-Store-Domain: <url_tienda>
X-Montu-Store-Code: <codigo_tienda>
X-Montu-Timestamp: <unix_timestamp>
X-Montu-Signature: <hmac_sha256 del body crudo>

Body (JSON)

{
    "webhook_version": "1.0",
    "event": "order.placed",
    "timestamp": "2024-01-15T10:30:00+00:00",
    "store": { "code": "default", "name": "Mi Tienda", "base_url": "https://tutienda.com/" },
    "order": { "increment_id": "000000123", "grand_total": 150.00, "currency_code": "USD" },
    "affiliate": { "code": "ABC123" },
    "customer": { "email": "customer@example.com" },
    "items": [],
    "billing_address": {},
    "shipping_address": {}
}

El backend valida la firma y rechaza timestamps de más de 5 minutos (anti-replay). El receptor vive en el backend Django: back/montu/rest_api/v1/views/ecommerce/magento/. Cualquier cambio al payload aquí requiere el cambio correspondiente allá, en sincronía.

🧪 Testing Local

  1. URL de prueba en webhook.site.
  2. En admin → Webhook URL: https://webhook.site/tu-uuid, API Key: test-key-123.
  3. Visitar https://tu-tienda.test/?_m_aff=TEST123, verificar cookie, crear una orden, y:
bin/magento cron:run                  # fuerza Cron/ProcessWebhooks
tail -f var/log/montu_affiliate.log   # logs del módulo
# SELECT * FROM montu_affiliate_webhook_log;

📁 Estructura del paquete

magento/                       ← raíz del paquete Composer (montu/module-affiliate)
├── composer.json              # name + type magento2-module + autoload PSR-4
├── registration.php           # ComponentRegistrar::register(MODULE, 'Montu_Affiliate', __DIR__)
├── etc/                       # module.xml, di.xml, events.xml, crontab.xml, db_schema.xml, adminhtml/system.xml …
├── Model/                     # Config, AffiliateTracking, WebhookLog, repositories, ResourceModels
├── Api/                       # interfaces de repositorios
├── Observer/                  # SaveAffiliateToQuote, CopyAffiliateToOrder, SendOrderWebhook
├── Service/                   # WebhookService (Curl + HMAC + reintentos), RecommendationClient
├── Cron/                      # ProcessWebhooks
├── Controller/               # Router + Storefront/Index (ruta /storefront/{code})
├── Block/ + ViewModel/        # adminhtml order view, storefront config
└── view/                      # frontend (tracking.js/.phtml, storefront) + adminhtml

Tablas propias (nunca toca core)

  • montu_affiliate_tracking — código de afiliado por quote/orden
  • montu_affiliate_webhook_log — cola de webhooks con status + retry count

🗑️ Desinstalación

bin/magento module:disable Montu_Affiliate
composer remove montu/module-affiliate
bin/magento setup:upgrade

Requisitos

  • Magento 2.4.x, PHP 8.1+ (ver composer.json para los módulos Magento requeridos)
  • Cron de Magento funcionando (* * * * * php bin/magento cron:run)

Licencia

Open Software License 3.0 (OSL-3.0) — ver LICENSE.txt.

Soporte

dev@montu.io

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: OSL-3.0
  • 更新时间: 2026-06-23