El mayor portal de MU Online de Brasil — desde 2003
Tutorial Intermedio Web

Cómo crear un sistema de referidos (referral) en MU Online

Implementa un sistema de referidos en el sitio de tu servidor de MU Online, con enlaces únicos, recompensas en Cash y protección contra fraudes de auto-referido.

GA Gabriel · Actualizado el 14 sep 2025 · ⏱ 17 min de lectura
Respuesta rápida

Un sistema de referidos —o referral— convierte a tus propios jugadores en el mejor canal de adquisición del servidor. La lógica es simple y poderosa: cada jugador recibe un enlace único; cuando un amigo se registra por ese enlace y realmente empieza a jugar, ambos ganan una recompensa. El resultado

Un sistema de referidos —o referral— convierte a tus propios jugadores en el mejor canal de adquisición del servidor. La lógica es simple y poderosa: cada jugador recibe un enlace único; cuando un amigo se registra por ese enlace y realmente empieza a jugar, ambos ganan una recompensa. El resultado es un crecimiento orgánico y barato, impulsado por quien ya confía en el servidor. Pero hay un abismo entre la idea y una implementación que no sea inmediatamente explotada por quien quiere farmear recompensas con cuentas falsas. Este tutorial muestra cómo construir un sistema de referral en el sitio de tu servidor de MU Online que sea a la vez atractivo para el jugador honesto y resistente al fraude, con enlaces rastreables, liberación condicionada a engagement real y crédito automático de Cash. Usaremos PHP y SQL Server como ejemplo por ser el estándar de la mayoría de los servidores privados, pero la lógica se aplica a cualquier stack. Los nombres de tablas y columnas varían por versión y emulador, así que trata cada query como un esqueleto a adaptar.

Requisitos previos

El sistema de referidos vive en el sitio, así que necesitas un sitio funcional integrado a la base de datos del servidor. Si aún no integraste sitio y juego, empieza por la guía de cómo crear servidor de MU Online antes de seguir.

  • Sitio del servidor corriendo en PHP 7.4+ con acceso a la base de datos.
  • SQL Server con la tabla de cuentas de MU (frecuentemente MEMB_INFO) accesible.
  • Sistema de cuentas/login ya funcionando en el sitio.
  • Una columna o tabla donde se almacena el Cash (moneda del cash shop) del jugador — el nombre varía por versión (ej.: CashShopData, WCoinC, Credits).
  • Conocimiento básico de PHP, SQL y sesiones de login.

Cómo funciona el flujo de referidos

Antes del código, fija el flujo. Cada etapa existe para cerrar una brecha de fraude:

  1. El jugador logueado accede a la página "Refiere a un amigo" y ve su código de referido único y el enlace listo para copiar.
  2. Un nuevo visitante hace clic en el enlace; el código queda grabado en su sesión/cookie.
  3. Al registrarse, la nueva cuenta se vincula al referidor, con estado pendiente.
  4. El sistema monitorea el progreso del referido. Cuando alcanza una meta real (ej.: nivel 150 o 3 días jugados), el estado pasa a liberado.
  5. Solo entonces se acreditan las recompensas para ambos lados, y el vínculo se marca como pagado para nunca pagar dos veces.

El punto crítico es el paso 4: recompensa liberada en el registro es una invitación al fraude. Recompensa liberada por engagement real filtra el 90% de los abusos.

Paso 1 — Estructura de datos

Crea una tabla dedicada para los referidos. Mantiene el historial auditable y separa la lógica de referidos de las tablas del juego:

CREATE TABLE Referrals (
    Id            INT IDENTITY(1,1) PRIMARY KEY,
    ReferrerAcc   VARCHAR(20) NOT NULL,   -- cuenta que refirio
    ReferredAcc   VARCHAR(20) NOT NULL,   -- cuenta referida
    ReferredIP    VARCHAR(45) NULL,
    Status        VARCHAR(10) NOT NULL DEFAULT 'pendente', -- pendente/liberado/pago
    CreatedAt     DATETIME NOT NULL DEFAULT GETDATE(),
    RewardedAt    DATETIME NULL,
    CONSTRAINT UQ_Referred UNIQUE (ReferredAcc) -- cada cuenta solo es referida una vez
);

Genera el código de referido a partir del propio nombre de la cuenta (con un hash corto) o almacena un código aleatorio por cuenta. Para simplificar, muchos servidores usan el propio nombre de usuario como código.

Paso 2 — Capturar el código en la llegada

Cuando alguien accede al sitio con ?ref=CODIGO, graba ese código antes de que se pierda. Una cookie de larga duración cubre a los visitantes que no se registran en la misma sesión:

<?php
// incluir en la parte superior del index.php del sitio
if (isset($_GET['ref']) && !isset($_COOKIE['ref_code'])) {
    $ref = preg_replace('/[^a-zA-Z0-9_]/', '', $_GET['ref']);
    if ($ref !== '') {
        // 30 dias de ventana de atribucion
        setcookie('ref_code', $ref, time() + 60*60*24*30, '/');
    }
}

Nota la sanitización: aceptamos solo caracteres válidos de cuenta, lo que ya elimina intentos de inyección por la URL.

Paso 3 — Vincular en el registro

En el procesamiento del registro, después de crear la cuenta con éxito, registra el vínculo, pero solo tras las verificaciones antifraude:

<?php
function registrarReferral(PDO $db, string $novaConta, string $novoIP): void {
    if (empty($_COOKIE['ref_code'])) return;

    $ref = preg_replace('/[^a-zA-Z0-9_]/', '', $_COOKIE['ref_code']);
    if ($ref === '' || strcasecmp($ref, $novaConta) === 0) return; // auto-referido

    // El referidor tiene que existir de verdad
    $stmt = $db->prepare("SELECT memb___id FROM MEMB_INFO WHERE memb___id = ?");
    $stmt->execute([$ref]);
    if (!$stmt->fetch()) return;

    // Bloquea el mismo IP entre referidor y referido
    $ipInd = $db->prepare("
        SELECT r.ReferredIP FROM Referrals r
        WHERE r.ReferrerAcc = ? AND r.ReferredIP = ?");
    $ipInd->execute([$ref, $novoIP]);
    if ($ipInd->fetch()) return; // ya refirio a alguien de este mismo IP

    $ins = $db->prepare("
        INSERT INTO Referrals (ReferrerAcc, ReferredAcc, ReferredIP)
        VALUES (?, ?, ?)");
    $ins->execute([$ref, $novaConta, $novoIP]);
}

Paso 4 — Liberar la recompensa por engagement

Este es el corazón antifraude. Un script agendado (cron o Programador de Tareas de Windows) corre periódicamente, verifica cuáles referidos alcanzaron la meta y libera las recompensas. La meta de ejemplo es nivel 150 en algún personaje de la cuenta — ajusta el nombre de la tabla Character y la columna de nivel a tu versión:

<?php
// cron/liberar_referrals.php — correr cada 10 min
require 'db.php';

$pendentes = $db->query("
    SELECT Id, ReferrerAcc, ReferredAcc
    FROM Referrals WHERE Status = 'pendente'")->fetchAll(PDO::FETCH_ASSOC);

foreach ($pendentes as $r) {
    // El referido alcanzo la meta?
    $chk = $db->prepare("
        SELECT TOP 1 cLevel FROM Character
        WHERE AccountID = ? AND cLevel >= 150");
    $chk->execute([$r['ReferredAcc']]);

    if ($chk->fetch()) {
        creditarCash($db, $r['ReferrerAcc'], 200); // referidor
        creditarCash($db, $r['ReferredAcc'], 100);  // referido
        $up = $db->prepare("
            UPDATE Referrals SET Status = 'pago', RewardedAt = GETDATE()
            WHERE Id = ?");
        $up->execute([$r['Id']]);
    }
}

function creditarCash(PDO $db, string $conta, int $valor): void {
    // El nombre de la columna/tabla de Cash VARIA por version
    $up = $db->prepare("
        UPDATE MEMB_INFO SET Credits = Credits + ? WHERE memb___id = ?");
    $up->execute([$valor, $conta]);
}

Fíjate en que la recompensa solo se acredita una vez, porque el estado pasa a pago en la misma transacción lógica.

Paso 5 — Página del jugador

Dale al jugador logueado una página que muestre el enlace y el historial. Es lo que genera el compartir:

<?php
$conta = $_SESSION['username'];
$link  = "https://tusitio.com/?ref=" . urlencode($conta);

$stats = $db->prepare("
    SELECT
      SUM(CASE WHEN Status = 'pago' THEN 1 ELSE 0 END) AS pagos,
      COUNT(*) AS total
    FROM Referrals WHERE ReferrerAcc = ?");
$stats->execute([$conta]);
$row = $stats->fetch(PDO::FETCH_ASSOC);
?>
<h2>Refiere y gana</h2>
<input type="text" value="<?= htmlspecialchars($link) ?>" readonly onclick="this.select()">
<p>Amigos que ya jugaron: <?= (int)$row['pagos'] ?> de <?= (int)$row['total'] ?> referidos</p>

Capas de protección antifraude

Ninguna verificación aislada resuelve. Combina varias y el costo de defraudar supera la recompensa:

CapaQué verificaLímite
Meta de engagementNivel/tiempo mínimo del referidoFiltra cuentas descartables
Bloqueo de auto-referidoNombre de cuenta igualImpide el caso más obvio
Comparación de IPMismo IP entre las cuentasIP dinámico y VPN lo esquivan
HWID/hardwareMisma máquina (cuando está disponible)Depende del soporte del cliente
Correo únicoMismo correo en ambas cuentasSolo si el correo es obligatorio
Límite por referidorMáximo de referidos por díaReduce el farmeo en masa

Errores comunes y soluciones

SíntomaCausa probableSolución
Recompensa dada en masa a cuentas fantasmaLiberación en el registroCondiciónala a la meta de engagement en el cron
El mismo jugador gana varias veces por el mismo referidoFalta de estado "pagado"Usa la constraint única y marca como pagado al acreditar
El Cash no se acreditaNombre de la columna equivocadoVerifica el schema; la columna de Cash varía por versión
El código ?ref= desaparece antes del registroSin cookie de atribuciónGraba el código en una cookie de 30 días
El auto-referido pasaSolo compara el nombreCombina IP, HWID y correo además del nombre
El cron no corre en WindowsSin tarea agendadaCrea una tarea en el Programador para llamar al PHP vía CLI

Buenas prácticas

Usa siempre prepared statements: el ejemplo de arriba nunca concatena entrada del usuario en SQL. Registra logs de cada liberación de recompensa para auditar disputas. Define recompensas modestas lo suficiente para no romper la economía del servidor, pero atractivas lo bastante para motivar el compartir; el Cash es preferible a los ítems porque es trivial de acreditar y revertir. Y comunica las reglas claramente en la página de referidos: metas, plazos y qué constituye fraude sancionable con baneo.

Lista de verificación de lanzamiento

  • Tabla Referrals creada con constraint de referido único
  • Captura del código ?ref= vía cookie de 30 días
  • Vínculo creado en el registro solo tras las verificaciones antifraude
  • Bloqueo de auto-referido por nombre, IP y correo
  • Cron/tarea liberando recompensas por meta de engagement
  • Crédito de Cash probado con el schema real del servidor
  • Página del jugador con enlace e historial funcionando
  • Todas las queries usando prepared statements
  • Reglas publicadas y recompensas balanceadas con la economía
  • Logs de liberación activos para auditoría

Preguntas frecuentes

¿Cuándo debo liberar la recompensa del referido?

Nunca en el registro. Libérala solo cuando el referido alcance una meta real de engagement, como un nivel mínimo o un tiempo mínimo jugado, para evitar cuentas falsas creadas solo por la recompensa.

¿Cómo impido que la persona se auto-refiera?

Compara IP, hardware/HWID cuando esté disponible y correo electrónico entre el referidor y el referido, y bloquea las recompensas cuando coincidan. Ninguna verificación aislada es perfecta; combina varias.

¿Dónde guardo el código de referido?

En una columna de la tabla de cuentas o en una tabla propia de referidos. Lo ideal es una tabla dedicada que registra referidor, referido, estado y fecha, manteniendo el historial auditable.

¿Puedo dar recompensa en ítems en lugar de Cash?

Sí, pero el Cash (moneda del cash shop) es más simple y seguro de acreditar vía sitio. Entregar ítems exige manipular el inventario en la base de datos, lo que es más arriesgado y varía mucho por versión.

¿El sistema de referral funciona en cualquier versión de MU?

La lógica del sitio es independiente de la versión. Lo que cambia es el nombre de las tablas de cuenta y la forma de acreditar Cash, que varían por emulador; adapta las queries a tu schema.

GA
Editor de guías y builds

Gabriel cubre gameplay, builds de clases, PvP y progresión. Prueba cada estrategia en un servidor antes de publicar.

Sigue leyendo

Artículos relacionados