Cómo enviar SMS a través de la API SMPP usando Java

La API de Mensajería Peer-to-Peer (SMPP) es un protocolo de telecomunicaciones potente diseñado para intercambiar mensajes SMS entre Centros de Servicio de Mensajes Cortos (SMSCs) y Entidades Externas de Mensajería Corta (ESMEs). Al aprovechar Java y la API SMPP, los desarrolladores pueden construir aplicaciones robustas para enviar y recibir mensajes SMS de manera eficiente. Esta guía completa te guía a través del proceso de implementación de la API SMPP en Java para conectarte con la Pasarela SMS Ozeki, incluyendo ejemplos prácticos de código para la gestión de conexiones, el envío de mensajes y el manejo de informes de entrega.

¿Por qué usar Java y la API SMPP para la mensajería SMS?

Java es un lenguaje de programación versátil e independiente de la plataforma ampliamente utilizado para construir aplicaciones empresariales. Cuando se combina con la API SMPP, Java permite a los desarrolladores crear soluciones SMS escalables que se integran perfectamente con pasarelas SMS como Ozeki. El protocolo SMPP es ideal para aplicaciones SMS de alto rendimiento debido a su fiabilidad, soporte para mensajería masiva y capacidades de seguimiento de entregas. Esta guía utiliza la biblioteca jSMPP, una implementación pura de Java del protocolo SMPP, para simplificar el desarrollo.

Configuración del cliente de la API SMPP en Java para enviar mensajes SMS

Para comenzar a enviar mensajes SMS usando la API SMPP en Java, necesitas configurar una cuenta de usuario SMPP en el servidor SMPP de la Pasarela SMS Ozeki y configurar tu aplicación Java para conectarse a su servidor SMPP. La biblioteca jSMPP es una opción popular para los desarrolladores Java debido a su soporte integral para las características del protocolo SMPP. A continuación, describimos los pasos para configurar tu proyecto Java.

Paso 1: Añadir la dependencia de jSMPP

Para usar la biblioteca jSMPP en tu proyecto Java, incluye la siguiente dependencia de Maven en tu archivo pom.xml:

<dependency>
    <groupId>org.jsmpp</groupId>
    <artifactId>jsmpp</artifactId>
    <version>2.3.10</version>
</dependency>

Esta dependencia proporciona todas las clases necesarias para implementar la API SMPP en Java, incluyendo gestión de sesiones, codificación de mensajes y manejo de recibos de entrega.

Paso 2: Ejemplo básico de conexión SMPP

Conectarse a un servidor SMPP requiere establecer una sesión y vincularla a la Pasarela SMS Ozeki. El siguiente código Java demuestra cómo crear un cliente SMPP simple usando la biblioteca jSMPP:

import org.jsmpp.*;
import org.jsmpp.bean.*;
import org.jsmpp.session.*;

public class SimpleSMPPClient {
    public static void main(String[] args) {
        SMPPSession session = new SMPPSession();
        try {
            // Conectar y vincular a la Pasarela SMS Ozeki
            session.connectAndBind(
                "tu.servidor.ozeki", 
                2775, 
                new BindParameter(
                    BindType.BIND_TX, 
                    "tu_usuario", 
                    "tu_contraseña", 
                    "cp", 
                    TypeOfNumber.ALPHANUMERIC, 
                    NumberingPlanIndicator.UNKNOWN, 
                    null)
            );
            
            System.out.println("Conectado exitosamente al servidor SMPP");
            
            // Añadir código de envío de mensajes aquí
            
        } catch (Exception e) {
            System.err.println("Error al conectar y vincular al servidor SMPP: " + e.getMessage());
        } finally {
            session.unbindAndClose();
        }
    }
}

En este ejemplo, reemplaza tu.servidor.ozeki, tu_usuario, y tu_contraseña con las credenciales reales proporcionadas por tu administrador de la Pasarela SMS Ozeki. El BindType.BIND_TX indica un vínculo de transmisor, adecuado para enviar mensajes SMS.

Gestión de conexiones de la API SMPP en Java para entrega confiable de SMS

La entrega confiable de SMS requiere mantener una conexión SMPP activa. El protocolo SMPP utiliza mensajes de keep-alive (PDUs enquire_link) para asegurar que la conexión permanezca activa. A continuación se muestra un ejemplo de cómo configurar los ajustes de keep-alive y monitorear cambios de estado de sesión en Java:

session.setEnquireLinkTimer(30000); // Enviar keep-alive cada 30 segundos
session.setTransactionTimer(10000); // Establecer tiempo de espera de transacción a 10 segundos

// Añadir listener de estado de sesión para monitoreo
session.addSessionStateListener(new SessionStateListener() {
    @Override
    public void onStateChange(SessionState newState, SessionState oldState, Session source) {
        System.out.println("El estado de la sesión SMPP cambió de " + oldState + " a " + newState);
    }
});

Estos ajustes aseguran que la conexión permanezca estable, y el listener de estado de sesión te ayuda a monitorear cambios, como desconexiones, para un manejo robusto de errores.

Envío de SMS con Java a través de la API SMPP

Una vez conectado, puedes enviar mensajes SMS usando el PDU submit_sm. El siguiente método Java demuestra cómo enviar un SMS usando la API SMPP en Java:

public static void sendSMS(SMPPSession session, String sender, String recipient, String message) throws Exception {
    try {
        String messageId = session.submitShortMessage(
            "CMT", // Tipo de servicio
            TypeOfNumber.ALPHANUMERIC, // TON de origen
            NumberingPlanIndicator.UNKNOWN, // NPI de origen
            sender, // Dirección del remitente
            TypeOfNumber.INTERNATIONAL, // TON de destino
            NumberingPlanIndicator.ISDN, // NPI de destino
            recipient, // Dirección del destinatario
            new ESMClass(), // Clase ESM
            (byte)0, // ID de protocolo
            (byte)1, // Bandera de prioridad
            null, // Tiempo de entrega programada
            null, // Período de validez
            new RegisteredDelivery(SMSCDeliveryReceipt.SUCCESS_FAILURE), // Recibo de entrega
            (byte)0, // Bandera de reemplazo si está presente
            new GeneralDataCoding(Alphabet.ALPHA_DEFAULT), // Codificación de datos
            (byte)0, // ID de mensaje predeterminado
            message.getBytes() // Contenido del mensaje
        );
        
        System.out.println("SMS enviado con ID de mensaje: " + messageId);
    } catch (PDUException e) {
        System.err.println("Parámetro PDU inválido: " + e.getMessage());
        throw e;
    } catch (ResponseTimeoutException e) {
        System.err.println("Tiempo de espera de respuesta: " + e.getMessage());
        throw e;
    } catch (InvalidResponseException e) {
        System.err.println("Respuesta inválida: " + e.getMessage());
        throw e;
    } catch (NegativeResponseException e) {
        System.err.println("Respuesta negativa recibida: " + e.getMessage());
        throw e;
    } catch (Exception e) {
        System.err.println("Error al enviar SMS: " + e.getMessage());
        throw e;
    }
}

Este método envía un SMS con seguimiento de recibo de entrega habilitado. El parámetro RegisteredDelivery asegura que recibas notificaciones sobre el estado de entrega del mensaje.

Manejo de informes de entrega de SMS con Java y la API SMPP

Para rastrear si un SMS fue entregado exitosamente, puedes vincular tu sesión SMPP como un transceptor (BindType.BIND_TRX) e implementar un listener de receptor de mensajes. A continuación se muestra un ejemplo de cómo manejar informes de entrega en Java:

// Vincular como transceptor para enviar y recibir mensajes
BindParameter bindParam = new BindParameter(
    BindType.BIND_TRX,
    "tu_usuario",
    "tu_contraseña",
    "cp",
    TypeOfNumber.ALPHANUMERIC,
    NumberingPlanIndicator.UNKNOWN,
    null
);

// Configurar listener de receptor de mensajes para informes de entrega
session.setMessageReceiverListener(new MessageReceiverListener() {
    @Override
    public void onAcceptDeliverSm(DeliverSm deliverSm) {
        if (MessageType.SMSC_DEL_RECEIPT.containedIn(deliverSm.getEsmClass())) {
            DeliveryReceipt delReceipt = deliverSm.getShortMessageAsDeliveryReceipt();
            System.out.println(String.format(
                "Recibido recibo de entrega para el mensaje %s: %s",
                delReceipt.getId(),
                delReceipt.getFinalStatus()
            ));
        }
        
        // Responder al informe de entrega
        try {
            byte[] messageId = new byte[]{1};
            session.deliverSmResponse(0, messageId, deliverSm);
        } catch (PDUException e) {
            System.err.println("Error al responder a deliver_sm: " + e.getMessage());
        }
    }
});

Este código procesa recibos de entrega, permitiéndote rastrear el éxito o fracaso de cada SMS enviado a través de la API SMPP en Java.

Cliente SMPP completo en Java para envío de SMS a través de la API SMPP

A continuación se muestra una clase Java completa que integra la gestión de conexiones, el envío de mensajes, y el manejo de informes de entrega. Esta implementación está lista para producción con un manejo adecuado de errores y gestión de recursos:

import org.jsmpp.*;
import org.jsmpp.bean.*;
import org.jsmpp.session.*;
import org.jsmpp.util.*;

public class SMPPClient implements AutoCloseable {
    private SMPPSession session;
    private String host;
    private int port;
    private String username;
    private String password;
    
    public SMPPClient(String host, int port, String username, String password) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
        this.session = new SMPPSession();
    }
    
    public void connect() throws Exception {
        try {
            BindParameter bindParam = new BindParameter(
                BindType.BIND_TRX,
                username,
                password,
                "cp",
                TypeOfNumber.ALPHANUMERIC,
                NumberingPlanIndicator.UNKNOWN,
                null
            );
            
            session.connectAndBind(host, port, bindParam);
            
            // Configurar ajustes de sesión
            session.setEnquireLinkTimer(30000);
            session.setTransactionTimer(10000);
            
            // Configurar manejador de recibos de entrega
            session.setMessageReceiverListener(new DeliveryReceiptListener());
            
            System.out.println("Conectado exitosamente al servidor SMPP");
        } catch (Exception e) {
            System.err.println("Error al conectar al servidor SMPP: " + e.getMessage());
            throw e;
        }
    }
    
    public String sendSMS(String sender, String recipient, String message) throws Exception {
        try {
            return session.submitShortMessage(
                "CMT",
                TypeOfNumber.ALPHANUMERIC,
                NumberingPlanIndicator.UNKNOWN,
                sender,
                TypeOfNumber.INTERNATIONAL,
                NumberingPlanIndicator.ISDN,
                recipient,
                new ESMClass(),
                (byte)0,
                (byte)1,
                null,
                null,
                new RegisteredDelivery(SMSCDeliveryReceipt.SUCCESS_FAILURE),
                (byte)0,
                new GeneralDataCoding(Alphabet.ALPHA_DEFAULT),
                (byte)0,
                message.getBytes()
            );
        } catch (Exception e) {
            System.err.println("Error al enviar SMS: " + e.getMessage());
            throw e;
        }
    }
    
    @Override
    public void close() {
        if (session != null) {
            session.unbindAndClose();
        }
    }
    
    private static class DeliveryReceiptListener implements MessageReceiverListener {
        @Override
        public void onAcceptDeliverSm(DeliverSm deliverSm) {
            if (MessageType.SMSC_DEL_RECEIPT.containedIn(deliverSm.getEsmClass())) {
                DeliveryReceipt delReceipt = deliverSm.getShortMessageAsDeliveryReceipt();
                System.out.println(String.format(
                    "Recibido recibo de entrega para el mensaje %s: %s",
                    delReceipt.getId(),
                    delReceipt.getFinalStatus()
                ));
            }
        }
    }
    
    public static void main(String[] args) {
        try (SMPPClient client = new SMPPClient(
                "tu.servidor.ozeki", 
                2775, 
                "tu_usuario", 
                "tu_contraseña")) {
            
            client.connect();
            
            String messageId = client.sendSMS(
                "12345", 
                "+1234567890", 
                "¡Hola desde el cliente SMPP en Java!"
            );
            
            System.out.println("SMS enviado con ID: " + messageId);
            
            // Mantener la aplicación en ejecución para recibir informes de entrega
            System.out.println("Presiona Ctrl+C para salir...");
            Thread.sleep(Long.MAX_VALUE);
            
        } catch (Exception e) {
            System.err.println("Error en el cliente SMPP: " + e.getMessage());
        }
    }
}

Esta implementación completa encapsula la funcionalidad del cliente SMPP en una clase reutilizable, facilitando su integración en aplicaciones Java más grandes. La interfaz AutoCloseable asegura una limpieza adecuada de recursos.

Mejores prácticas para construir clientes SMPP en Java

Para asegurar que tu cliente de la API SMPP en Java sea robusto y escalable, sigue estas mejores prácticas:

  • Pool de conexiones: Usa pools de conexiones para aplicaciones SMS de alto volumen para gestionar múltiples sesiones SMPP eficientemente.
  • Manejo de excepciones: Implementa un manejo exhaustivo de excepciones para recuperarte de problemas de red o errores del servidor.
  • Pools de hilos: Usa pools de hilos para procesamiento concurrente de mensajes y mejorar el rendimiento.
  • Colas de mensajes: Implementa un mecanismo de colas para asegurar la entrega confiable de mensajes durante interrupciones de red.
  • Monitoreo de conexiones: Monitorea el estado de la sesión SMPP e implementa lógica de reconexión automática para mayor fiabilidad.
  • Codificación de caracteres: Maneja diferentes codificaciones de caracteres (ej. GSM 7-bit, UCS-2) para soportar mensajería SMS internacional.

Conclusión

Implementar la API SMPP en Java con la Pasarela SMS Ozeki proporciona una solución potente para enviar y recibir mensajes SMS en tus aplicaciones. La biblioteca jSMPP simplifica las complejidades del protocolo SMPP, permitiendo a los desarrolladores enfocarse en construir características robustas de mensajería. Esta guía ha cubierto los aspectos esenciales de configurar un cliente SMPP en Java, gestionar conexiones, enviar mensajes SMS y manejar informes de entrega. Siguiendo los ejemplos proporcionados y las mejores prácticas, puedes crear aplicaciones SMS escalables y confiables usando Java y la API SMPP.

Para entornos de producción, considera añadir características avanzadas como concatenación de mensajes para SMS largos, registro detallado y monitoreo de rendimiento. El protocolo SMPP ofrece capacidades adicionales, como entrega programada de mensajes y ajustes de prioridad, para mejorar tu aplicación a medida que evolucionan los requisitos.

More information