Por que os plugins do nopCommerce importam
O nopCommerce alimenta mais de 60.000 lojas online no mundo todo. É a principal plataforma de e-commerce open-source em .NET — e sua arquitetura de plugins é o motor por trás desse ecossistema. Toda integração de gateway de pagamento, toda transportadora, todo widget e toda funcionalidade personalizada vive como um plugin.
Se você entende como construir plugins para o nopCommerce, pode estender uma das plataformas de e-commerce mais capazes do mercado — e construir um negócio a partir disso. Este guia cobre tudo, desde o seu primeiro esqueleto de plugin até padrões de implantação em produção.
Construímos plugins para o nopCommerce desde 2009, com mais de 38 plugins em nosso catálogo — incluindo 12 integrações de gateways de pagamento brasileiros e a única solução completa de pagamento PIX na plataforma. Este guia reflete o que aprendemos construindo plugins que processam milhões de transações.
Arquitetura de plugins: a fundação
A hierarquia de interfaces de plugin
Todo plugin do nopCommerce começa com a interface IPlugin em Nop.Services.Plugins. Em vez de fazer você implementar tudo do zero, o nopCommerce fornece a BasePlugin — uma classe abstrata que cuida do código repetitivo — e um conjunto de interfaces especializadas para tipos comuns de plugin:
| Interface | Finalidade | Exemplo |
|---|---|---|
| IPaymentMethod | Processamento de pagamentos (autorizar, capturar, estornar, cancelar) | PayPal, Stripe, PIX, MercadoPago |
| IShippingRateComputationMethod | Calcular fretes a partir das transportadoras | UPS, FedEx, Correios (Brasil) |
| ITaxProvider | Calcular alíquotas de imposto por jurisdição | Avalara, TaxJar |
| IWidgetPlugin | Renderizar widgets de UI em zonas específicas | Chat ao vivo, popup de newsletter, cards do Trello |
| IExchangeRateProvider | Obter taxas de câmbio de moedas | BCE, Banco Central do Brasil |
| IDiscountRequirementRule | Lógica de desconto personalizada | "Cliente do Brasil ganha 10% de desconto" |
| IExternalAuthenticationMethod | Login social e SSO | Google, Facebook, Azure AD |
| IMultiFactorAuthenticationMethod | Plugins de MFA (desde a 4.40) | Google Authenticator, SMS OTP |
| IPickupPointProvider | Locais de retirada na loja | Rede de lojas locais, sistemas de armários |
| IMiscPlugin | Extensões de propósito geral | Gestão de DNS, analytics, integrações |
Escolha a interface mais específica para o seu caso de uso. A IPaymentMethod dá a você o ciclo de vida completo do pagamento — ProcessPaymentAsync, PostProcessPaymentAsync, RefundAsync, VoidAsync, CaptureAsync — enquanto a IMiscPlugin é a saída de emergência para qualquer coisa que não se encaixe em uma categoria padrão.
Estrutura do projeto: passo a passo
1. Crie o projeto de biblioteca de classes
Crie um novo projeto Class Library tendo como alvo o .NET 9. A convenção de nomenclatura recomendada é Nop.Plugin.{Group}.{Name}:
Nop.Plugin.Payments.PayPalCommerce
Nop.Plugin.Shipping.FedEx
Nop.Plugin.Widgets.WhatsApp
Nop.Plugin.Misc.GoDaddy
Coloque o projeto no diretório \Plugins na raiz da solução (não dentro de \Nop.Web\Plugins, que é o destino de implantação). Defina o caminho de saída do .csproj como $(SolutionDir)\Presentation\Nop.Web\Plugins\{PluginOutputDirectory} e habilite CopyLocalLockFileAssemblies para garantir que as dependências NuGet sejam copiadas para a saída.
2. Crie o plugin.json
Todo plugin requer um arquivo plugin.json com metadados:
{
"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"
}
O SystemName deve coincidir com o nome do seu assembly. SupportedVersions determina quais versões do nopCommerce podem instalar o plugin. Se você atualizar o nopCommerce e um plugin quebrar, verifique este campo primeiro — muitos plugins só precisam ter suas versões suportadas atualizadas.
3. Implemente a classe do plugin
Crie uma classe que implemente a interface de plugin apropriada e 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);
}
}
As sobrescritas de InstallAsync, UninstallAsync e UpdateAsync são seus ganchos de ciclo de vida. Sempre chame a implementação base — base.InstallAsync() cuida do registro no sistema de plugins.
4. Adicione a configuração (UI do admin)
Para plugins com configurações, crie um controller MVC, um model e uma view Razor:
- Controllers/{Name}Controller.cs — decorado com
[AuthorizeAdmin]e[Area(AreaNames.ADMIN)]. Herde deBasePluginController. - Models/ConfigurationModel.cs — uma classe simples com as propriedades das suas configurações e atributos
[NopResourceDisplayName]para localização. - Views/Configure.cshtml — usa o layout
_ConfigurePlugin. Inclua também o_ViewImports.cshtml(copie de um plugin existente).
Registre a rota de configuração em um RouteProvider.cs implementando 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;
}
Construindo um plugin de pagamento: o padrão do mundo real
Plugins de pagamento são o tipo mais comum — e mais complexo. Aqui está o padrão de produção que usamos na SplatDev:
Componentes centrais
- Classe de configurações (Settings): Uma classe implementando
ISettingscom propriedades para chaves de API, URLs, modos (sandbox/produção) e alternadores de funcionalidades. Armazene segredos noISettingService— nunca embuta credenciais no código. - Classe de defaults: Uma classe estática com constantes — nomes de rotas, system name, URLs de configuração, endpoints de API. Mantém strings mágicas fora da sua lógica.
- Classe de serviço: Sua lógica de integração propriamente dita — chamadas HTTP ao gateway de pagamento, parsing de respostas, tratamento de webhooks. Injete via DI e mantenha testável (interface + implementação).
- Consumidores de eventos (event consumers): Implemente
IConsumer<OrderPlacedEvent>e interfaces similares para reagir a eventos da loja — enviar confirmações de transação, disparar fluxos pós-pagamento.
Fluxo de pagamento: os métodos que você deve implementar
| Método | Quando é chamado | O que deve fazer |
|---|---|---|
ProcessPaymentAsync |
Cliente clica em "Pagar" | Autorizar ou capturar o pagamento. Retornar sucesso/falha e o ID da transação. |
PostProcessPaymentAsync |
Após a conclusão do processamento do pagamento | Redirecionar para o gateway externo (PayPal, PagSeguro) ou mostrar uma página de confirmação. |
RefundAsync |
Admin inicia um estorno | Processar o estorno através do gateway. Retornar sucesso/falha. |
VoidAsync |
Admin cancela uma autorização | Cancelar a autorização pendente. Aplicável apenas se o pagamento ainda não foi capturado. |
CaptureAsync |
Admin captura um pagamento autorizado | Capturar um valor previamente autorizado. Comum em fluxos de autorização-e-captura. |
GetPaymentMethodDescriptionAsync |
Renderização da página de checkout | Retornar o nome de exibição, a descrição e o logo do método de pagamento. |
GetAdditionalHandlingFeeAsync |
Cálculo do total do pedido | Retornar qualquer taxa adicional cobrada pelo método de pagamento, ou zero. |
Exemplo de plugin de pagamento brasileiro: PIX
O sistema de pagamento instantâneo PIX do Brasil requer um fluxo específico: gerar um QR code com um payload (string EMV), exibi-lo ao cliente e aguardar uma confirmação via webhook quando o pagamento for recebido. Aqui está o padrão:
- ProcessPaymentAsync: Chame o PSP (PagSeguro, MercadoPago, etc.) para criar uma cobrança PIX. Armazene o ID da transação (
txid) e o payload EMV. - PostProcessPaymentAsync: Renderize o QR code (gerado a partir do payload EMV) e o código "copia e cola". Defina o status do pagamento como
Pending. - Tratador de webhook: O PSP envia um webhook quando o PIX confirma o pagamento. Atualize o status do pedido e dispare o
OrderPaidEvent.
Este é o padrão por trás de todos os 12 plugins de pagamento brasileiros da SplatDev — processando PIX, boleto e pagamentos parcelados com cartão de crédito através de PagSeguro, MercadoPago, Cielo, Banco Inter, Pagar.me, Rede, GetNet, PicPay, NuPay, Braspag e InfinityPay.
Widgets: adicionando UI sem tocar nos temas
Plugins de widget implementam IWidgetPlugin e devem especificar em quais zonas de widget eles são renderizados:
public Task<IList<string>> GetWidgetZonesAsync()
{
return Task.FromResult<IList<string>>(new List<string>
{
PublicWidgetZones.HomepageBeforeBestSellers,
PublicWidgetZones.ProductDetailsAfterPictures
});
}
Em seguida, implemente GetPublicViewComponentAsync para retornar o HTML do widget. O sistema de widgets chama esse método para cada zona que você registrou.
Padrões comuns de widget: popups de cadastro em newsletter, botões de chat ao vivo, selos de confiança, banners de consentimento de cookies, botões flutuantes de WhatsApp, produtos vistos recentemente e notificações de prova social.
Acesso ao banco de dados: IRepository<T> e migrations
O nopCommerce usa um padrão de repositório via IRepository<T> para acesso a dados. Para plugins que precisam de tabelas personalizadas:
- Defina sua classe de entidade (deve ter uma propriedade
Id). - Crie um
ObjectContextque registre sua entidade no Entity Framework Core. - No
InstallAsync, use_dbContext.InstallAsync()para criar as tabelas. - No
UninstallAsync, use_dbContext.UninstallAsync()para removê-las.
Para migrations de schema entre versões do plugin, considere adicionar um MigrationManager à sua sobrescrita de UpdateAsync que verifica a versão atual do schema e aplica as instruções ALTER TABLE necessárias. Isso é mais simples que o FluentMigrator para plugins e mantém sua lógica de migração em um só lugar.
Testes: trate seu plugin como um produto
Na SplatDev, tratamos cada plugin como um produto com sua própria suíte de testes:
- Testes unitários (xUnit): Teste sua camada de serviço de forma isolada. Faça mock de
ISettingService,IRepository<T>e de quaisquer clientes HTTP. Sua lógica de pagamento, cálculos de impostos e cálculos de frete devem ter 100% de cobertura de testes unitários na lógica de negócio. - Testes de integração: Suba uma instância de teste do nopCommerce e verifique se o seu plugin instala, configura e processa ao longo de todo o ciclo de vida. Use credenciais de sandbox/teste para os gateways de pagamento.
- Testes de localização: Verifique se todos os recursos de idioma existem para cada idioma que você afirma suportar. Strings de recurso ausentes são o bug de plugin mais comum.
- Conformidade com StyleCop: O nopCommerce espera conformidade com o StyleCop. Execute-o no seu pipeline de CI — ele captura problemas sutis antes do code review.
Armadilhas comuns (e como evitá-las)
1. Não chamar base.InstallAsync()
Se você sobrescrever InstallAsync sem chamar a base, seu plugin não se registrará no sistema de plugins e não aparecerá no admin. Sempre inclua await base.InstallAsync() ao final da sua sobrescrita.
2. Embutir credenciais no código
Armazene chaves de API, tokens e segredos no ISettingService — nunca os embuta no plugin.json ou como constantes de classe. A página de configurações deve permitir que os administradores configurem esses valores, e eles devem ser persistidos de forma criptografada quando apropriado.
3. Ignorar a compatibilidade de versão
As versões do nopCommerce quebram plugins. O campo SupportedVersions no plugin.json não é decorativo — o nopCommerce o verifica antes de carregar seu plugin. Ao atualizar o nopCommerce, teste seu plugin contra a nova versão e atualize esse campo. Não apenas incremente o número sem testar.
4. Bloquear a thread da requisição
Todos os métodos de plugin são assíncronos por um motivo. Se o seu processador de pagamento chama uma API externa, essa chamada deve ser assíncrona. Bloquear a thread com .Result ou .Wait() vai degradar o desempenho sob carga e pode causar deadlocks.
5. Nenhum consumidor de eventos
Plugins que só fornecem uma página de configuração estão perdendo o ponto. O verdadeiro poder dos plugins do nopCommerce vem dos consumidores de eventos — reagindo a eventos da loja como OrderPlacedEvent, CustomerRegisteredEvent ou ShipmentDeliveredEvent. Conecte seu plugin aos eventos de negócio da loja, não apenas à UI do admin.
nopCommerce 4.90: o que há de novo para desenvolvedores de plugins
O nopCommerce 4.90 tem como alvo o .NET 9 e traz várias melhorias para desenvolvedores de plugins:
- Runtime do .NET 9: Seus plugins rodam no .NET mais rápido até hoje — beneficiando-se automaticamente de melhorias no JIT, adaptação dinâmica do GC e otimizações de laços.
- Suporte a C# 13: Use coleções
params, interfacesref structe propriedades parciais no código do seu plugin. - Dependências NuGet atualizadas: Pacotes subjacentes (Autofac, FluentValidation, etc.) foram atualizados. Teste a árvore de dependências do seu plugin.
- IMultiFactorAuthenticationMethod: Plugins de MFA agora são um conceito de primeira classe, com sua própria interface.
- Template de plugin aprimorado: O template oficial de plugin do nopCommerce para o Visual Studio foi atualizado para a 4.90 — use-o como seu ponto de partida.
Para onde ir a partir daqui
O desenvolvimento de plugins para o nopCommerce é uma habilidade que constrói carreira. O marketplace do nopCommerce é ativo e crescente, e plugins bem construídos geram receita recorrente através de atualizações e suporte. Na SplatDev, plugins são nosso negócio principal — nossa Loja em store.splatdev.com tem mais de 38 plugins, e somos Gold Solutions Partner há anos.
Se você está construindo um projeto de e-commerce em nopCommerce, não precisa construir tudo do zero. Nosso catálogo cobre pagamentos brasileiros, frete (Correios, JadLog, Braspress), integrações com ERP e funcionalidades personalizadas. Se você precisa de algo que não temos, também construímos plugins sob medida.
Pronto para construir ou estender sua loja nopCommerce? Nossa equipe faz isso desde 2009 — há mais tempo que quase todo mundo no ecossistema.
Trabalhe com nossa equipe nopCommerce
Ou navegue pelo nosso catálogo de plugins: store.splatdev.com