Home / Blog

La guía completa del desarrollo de plugins para nopCommerce

Carlos Casalicchio · June 23, 2026 ·7 min de lectura

Por qué importan los plugins de nopCommerce

nopCommerce da soporte a más de 60.000 tiendas online en todo el mundo. Es la plataforma de comercio electrónico de código abierto líder sobre .NET, y su arquitectura de plugins es el motor que hay detrás de ese ecosistema. Cada integración de pasarela de pago, cada transportista de envíos, cada widget y cada funcionalidad personalizada existe como un plugin.

Si comprendes cómo crear plugins de nopCommerce, puedes ampliar una de las plataformas de comercio electrónico más potentes del mercado, y construir un negocio haciéndolo. Esta guía cubre todo, desde el andamiaje de tu primer plugin hasta los patrones de despliegue en producción.

Llevamos creando plugins de nopCommerce desde 2009, con más de 38 plugins en nuestro catálogo, incluidas 12 integraciones de pasarelas de pago brasileñas y la única solución de pago PIX completa de la plataforma. Esta guía refleja lo que hemos aprendido creando plugins que procesan millones de transacciones.

Arquitectura de plugins: los cimientos

La jerarquía de interfaces de los plugins

Todo plugin de nopCommerce comienza con la interfaz IPlugin en Nop.Services.Plugins. En lugar de obligarte a implementarlo todo desde cero, nopCommerce proporciona BasePlugin, una clase abstracta que se encarga del código repetitivo, y un conjunto de interfaces especializadas para los tipos de plugin más habituales:

Interfaz Propósito Ejemplo
IPaymentMethod Procesamiento de pagos (autorizar, capturar, reembolsar, anular) PayPal, Stripe, PIX, MercadoPago
IShippingRateComputationMethod Calcular tarifas de envío de los transportistas UPS, FedEx, Correios (Brasil)
ITaxProvider Calcular tipos impositivos por jurisdicción Avalara, TaxJar
IWidgetPlugin Renderizar widgets de interfaz en zonas concretas Chat en vivo, ventana emergente de boletín, tarjetas de Trello
IExchangeRateProvider Obtener tipos de cambio de divisas BCE, Banco Central de Brasil
IDiscountRequirementRule Lógica de descuentos personalizada "El cliente de Brasil obtiene un 10 % de descuento"
IExternalAuthenticationMethod Inicio de sesión social y SSO Google, Facebook, Azure AD
IMultiFactorAuthenticationMethod Plugins de MFA (desde la 4.40) Google Authenticator, OTP por SMS
IPickupPointProvider Puntos de recogida en tienda Red de tiendas locales, sistemas de taquillas
IMiscPlugin Extensiones de propósito general Gestión de DNS, analítica, integraciones

Elige la interfaz más específica para tu caso de uso. IPaymentMethod te ofrece el ciclo de vida completo del pago (ProcessPaymentAsync, PostProcessPaymentAsync, RefundAsync, VoidAsync, CaptureAsync), mientras que IMiscPlugin es la vía de escape para cualquier cosa que no encaje en una categoría estándar.

Estructura del proyecto: paso a paso

1. Crea el proyecto de biblioteca de clases

Crea un nuevo proyecto de tipo Class Library dirigido a .NET 9. La convención de nomenclatura recomendada es Nop.Plugin.{Group}.{Name}:

Nop.Plugin.Payments.PayPalCommerce
Nop.Plugin.Shipping.FedEx
Nop.Plugin.Widgets.WhatsApp
Nop.Plugin.Misc.GoDaddy

Coloca el proyecto en el directorio \Plugins de la raíz de la solución (no dentro de \Nop.Web\Plugins, que es el destino del despliegue). Establece la ruta de salida del .csproj en $(SolutionDir)\Presentation\Nop.Web\Plugins\{PluginOutputDirectory} y activa CopyLocalLockFileAssemblies para asegurarte de que las dependencias de NuGet se copian a la salida.

2. Crea plugin.json

Todo plugin requiere un archivo plugin.json con metadatos:

{
  "Group": "Payment methods",
  "FriendlyName": "My Payment Gateway",
  "SystemName": "Payments.MyGateway",
  "Version": "1.00",
  "SupportedVersions": [ "4.90" ],
  "Author": "SplatDev",
  "DisplayOrder": 1,
  "FileName": "Nop.Plugin.Payments.MyGateway.dll",
  "Description": "Process payments via My Gateway"
}

El SystemName debe coincidir con el nombre de tu ensamblado. SupportedVersions determina qué versiones de nopCommerce pueden instalar el plugin. Si actualizas nopCommerce y un plugin deja de funcionar, revisa este campo primero: muchos plugins solo necesitan que se actualicen sus versiones compatibles.

3. Implementa la clase del plugin

Crea una clase que implemente la interfaz de plugin adecuada y que derive de BasePlugin:

public class MyPaymentProcessor : BasePlugin, IPaymentMethod
{
    public override Task InstallAsync()
    {
        // Insert settings, locale resources, or database tables
        return base.InstallAsync();
    }

    public override Task UninstallAsync()
    {
        // Clean up settings, locale resources, or database tables
        return base.UninstallAsync();
    }

    public override Task UpdateAsync(string currentVersion, string targetVersion)
    {
        // Handle version migrations
        return base.UpdateAsync(currentVersion, targetVersion);
    }

    public Task<ProcessPaymentResult> ProcessPaymentAsync(ProcessPaymentRequest request)
    {
        // Your payment logic here
    }

    public override string GetConfigurationPageUrl()
    {
        return _nopUrlHelper.RouteUrl(MyDefaults.Route.Configuration);
    }
}

Las sobrescrituras de InstallAsync, UninstallAsync y UpdateAsync son tus enganches del ciclo de vida. Llama siempre a la implementación base: base.InstallAsync() se encarga del registro en el sistema de plugins.

4. Añade la configuración (interfaz de administración)

Para los plugins con ajustes, crea un controlador MVC, un modelo y una vista de Razor:

  1. Controllers/{Name}Controller.cs: decorado con [AuthorizeAdmin] y [Area(AreaNames.ADMIN)]. Hereda de BasePluginController.
  2. Models/ConfigurationModel.cs: una clase simple con las propiedades de tus ajustes y atributos [NopResourceDisplayName] para la localización.
  3. Views/Configure.cshtml: utiliza el diseño _ConfigurePlugin. Incluye también _ViewImports.cshtml (cópialo de un plugin existente).

Registra la ruta de configuración en un RouteProvider.cs que implemente IRouteProvider:

public class RouteProvider : IRouteProvider
{
    public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder)
    {
        endpointRouteBuilder.MapControllerRoute(
            name: MyDefaults.Route.Configuration,
            pattern: "Admin/MyGateway/Configure",
            defaults: new { controller = "MyGateway", action = "Configure", area = AreaNames.ADMIN });
    }

    public int Priority => 0;
}

Crear un plugin de pago: el patrón del mundo real

Los plugins de pago son el tipo de plugin más común, y también el más complejo. Este es el patrón de producción que utilizamos en SplatDev:

Componentes principales

  1. Clase de ajustes: una clase que implementa ISettings con propiedades para las claves de API, las URL, los modos (sandbox/producción) y los interruptores de funcionalidades. Guarda los secretos en ISettingService: nunca escribas las credenciales directamente en el código.
  2. Clase de valores predeterminados: una clase estática con constantes: nombres de rutas, nombre de sistema, URL de configuración, puntos de conexión de API. Mantiene las cadenas mágicas fuera de tu lógica.
  3. Clase de servicio: tu lógica de integración real: llamadas HTTP a la pasarela de pago, análisis de respuestas, gestión de webhooks. Inyéctala mediante DI y mantenla comprobable (interfaz + implementación).
  4. Consumidores de eventos: implementa IConsumer<OrderPlacedEvent> e interfaces similares para reaccionar a los eventos de la tienda: enviar confirmaciones de transacciones, activar flujos de trabajo posteriores al pago.

Flujo de pago: los métodos que debes implementar

Método Cuándo se llama Qué debe hacer
ProcessPaymentAsync El cliente hace clic en "Pagar" Autorizar o capturar el pago. Devolver éxito/fallo y el ID de la transacción.
PostProcessPaymentAsync Tras completarse el procesamiento del pago Redirigir a la pasarela externa (PayPal, PagSeguro) o mostrar una página de confirmación.
RefundAsync El administrador inicia un reembolso Procesar el reembolso a través de la pasarela. Devolver éxito/fallo.
VoidAsync El administrador anula una autorización Anular la autorización pendiente. Solo aplica si el pago aún no se había capturado.
CaptureAsync El administrador captura un pago autorizado Capturar un importe previamente autorizado. Habitual en flujos de autorización y posterior captura.
GetPaymentMethodDescriptionAsync Se renderiza la página de pago Devolver el nombre visible, la descripción y el logotipo del método de pago.
GetAdditionalHandlingFeeAsync Cálculo del total del pedido Devolver cualquier tarifa adicional que cobre el método de pago, o cero.

Ejemplo de plugin de pago brasileño: PIX

El sistema de pago instantáneo PIX de Brasil requiere un flujo específico: generar un código QR con una carga útil (cadena EMV), mostrárselo al cliente y esperar una confirmación por webhook cuando se recibe el pago. Este es el patrón:

  1. ProcessPaymentAsync: llama al PSP (PagSeguro, MercadoPago, etc.) para crear un cobro PIX. Guarda el ID de la transacción (txid) y la carga útil EMV.
  2. PostProcessPaymentAsync: renderiza el código QR (generado a partir de la carga útil EMV) y el código de "copiar y pegar". Establece el estado del pago en Pending.
  3. Gestor de webhooks: el PSP envía un webhook cuando PIX confirma el pago. Actualiza el estado del pedido y activa OrderPaidEvent.

Este es el patrón que hay detrás de los 12 plugins de pago brasileños de SplatDev, que procesan pagos con PIX, boleto y tarjeta de crédito a plazos a través de PagSeguro, MercadoPago, Cielo, Banco Inter, Pagar.me, Rede, GetNet, PicPay, NuPay, Braspag e InfinityPay.

Widgets: añadir interfaz sin tocar los temas

Los plugins de widgets implementan IWidgetPlugin y deben indicar en qué zonas de widget se renderizan:

public Task<IList<string>> GetWidgetZonesAsync()
{
    return Task.FromResult<IList<string>>(new List<string>
    {
        PublicWidgetZones.HomepageBeforeBestSellers,
        PublicWidgetZones.ProductDetailsAfterPictures
    });
}

Después implementa GetPublicViewComponentAsync para devolver el HTML del widget. El sistema de widgets llama a este método por cada zona que hayas registrado.

Patrones de widget habituales: ventanas emergentes de suscripción a boletines, botones de chat en vivo, sellos de confianza, banners de consentimiento de cookies, botones flotantes de WhatsApp, productos vistos recientemente y notificaciones de prueba social.

Acceso a la base de datos: IRepository<T> y migraciones

nopCommerce utiliza un patrón de repositorio mediante IRepository<T> para el acceso a datos. Para los plugins que necesitan tablas personalizadas:

  1. Define tu clase de entidad (debe tener una propiedad Id).
  2. Crea un ObjectContext que registre tu entidad con Entity Framework Core.
  3. En InstallAsync, utiliza _dbContext.InstallAsync() para crear las tablas.
  4. En UninstallAsync, utiliza _dbContext.UninstallAsync() para eliminarlas.

Para las migraciones de esquema entre versiones del plugin, plantéate añadir un MigrationManager a tu sobrescritura de UpdateAsync que compruebe la versión actual del esquema y aplique las sentencias ALTER TABLE necesarias. Esto es más sencillo que FluentMigrator para los plugins y mantiene tu lógica de migración en un único lugar.

Pruebas: trata tu plugin como un producto

En SplatDev tratamos cada plugin como un producto con su propio conjunto de pruebas:

  • Pruebas unitarias (xUnit): prueba tu capa de servicio de forma aislada. Simula ISettingService, IRepository<T> y cualquier cliente HTTP. Tu lógica de pago, los cálculos de impuestos y los cálculos de tarifas de envío deberían tener una cobertura de pruebas unitarias del 100 % sobre la lógica de negocio.
  • Pruebas de integración: levanta una instancia de prueba de nopCommerce y verifica que tu plugin se instala, se configura y procesa a lo largo de todo el ciclo de vida. Utiliza credenciales de sandbox/prueba para las pasarelas de pago.
  • Pruebas de localización: verifica que existen todos los recursos de idioma para cada lengua que declaras admitir. Las cadenas de recursos que faltan son el error más habitual en los plugins.
  • Cumplimiento de StyleCop: nopCommerce exige el cumplimiento de StyleCop. Ejecútalo en tu canalización de CI: detecta problemas sutiles antes de la revisión de código.

Errores comunes (y cómo evitarlos)

1. No llamar a base.InstallAsync()

Si sobrescribes InstallAsync sin llamar a la base, tu plugin no se registrará en el sistema de plugins y no aparecerá en la administración. Incluye siempre await base.InstallAsync() al final de tu sobrescritura.

2. Escribir las credenciales directamente en el código

Guarda las claves de API, los tokens y los secretos en ISettingService: nunca los escribas directamente en plugin.json ni como constantes de clase. La página de ajustes debe permitir a los administradores configurar estos valores, y deben persistirse cifrados cuando corresponda.

3. Ignorar la compatibilidad de versiones

Las versiones de nopCommerce rompen los plugins. El campo SupportedVersions de plugin.json no es decorativo: nopCommerce lo comprueba antes de cargar tu plugin. Al actualizar nopCommerce, prueba tu plugin contra la nueva versión y actualiza este campo. No te limites a subir el número sin probar.

4. Bloquear el hilo de la solicitud

Todos los métodos de los plugins son asíncronos por una razón. Si tu procesador de pagos llama a una API externa, esa llamada debe ser asíncrona. Bloquear el hilo con .Result o .Wait() degradará el rendimiento bajo carga y puede provocar bloqueos mutuos (deadlocks).

5. Sin consumidores de eventos

Los plugins que solo ofrecen una página de configuración no captan lo esencial. El verdadero poder de los plugins de nopCommerce proviene de los consumidores de eventos: reaccionar a eventos de la tienda como OrderPlacedEvent, CustomerRegisteredEvent o ShipmentDeliveredEvent. Conecta tu plugin a los eventos de negocio de la tienda, no solo a la interfaz de administración.

nopCommerce 4.90: novedades para los desarrolladores de plugins

nopCommerce 4.90 está dirigido a .NET 9 y aporta varias mejoras para los desarrolladores de plugins:

  • Entorno de ejecución de .NET 9: tus plugins se ejecutan sobre el .NET más rápido hasta la fecha, beneficiándose automáticamente de las mejoras del JIT, la adaptación dinámica del GC y las optimizaciones de bucles.
  • Compatibilidad con C# 13: utiliza colecciones params, interfaces ref struct y propiedades parciales en el código de tu plugin.
  • Dependencias de NuGet actualizadas: los paquetes subyacentes (Autofac, FluentValidation, etc.) se han actualizado. Prueba el árbol de dependencias de tu plugin.
  • IMultiFactorAuthenticationMethod: los plugins de MFA son ahora un concepto de primer nivel con su propia interfaz.
  • Plantilla de plugin mejorada: la plantilla oficial de plugin de nopCommerce para Visual Studio se ha actualizado para la 4.90; utilízala como punto de partida.

Cómo seguir a partir de aquí

El desarrollo de plugins para nopCommerce es una habilidad que impulsa una carrera profesional. El marketplace de nopCommerce está activo y en crecimiento, y los plugins bien construidos generan ingresos recurrentes a través de actualizaciones y soporte. En SplatDev los plugins son nuestro negocio principal: nuestra tienda en store.splatdev.com ofrece más de 38 plugins, y llevamos años siendo Gold Solutions Partner.

Si estás creando un proyecto de comercio electrónico sobre nopCommerce, no necesitas construirlo todo desde cero. Nuestro catálogo cubre pagos brasileños, envíos (Correios, JadLog, Braspress), integraciones con ERP y funcionalidad personalizada. Si necesitas algo que no tenemos, también creamos plugins a medida.

¿Listo para crear o ampliar tu tienda de nopCommerce? Nuestro equipo lleva haciéndolo desde 2009, más tiempo que casi cualquier otro en el ecosistema.

Trabaja con nuestro equipo de nopCommerce

O explora nuestro catálogo de plugins: store.splatdev.com

Want more articles like this?

Subscribe for updates on .NET, Umbraco, nopCommerce, and software engineering.

Get in touch →