Почему плагины nopCommerce важны
На nopCommerce работает более 60 000 интернет-магазинов по всему миру. Это ведущая e-commerce-платформа с открытым исходным кодом на .NET, и её архитектура плагинов — движок, стоящий за всей этой экосистемой. Каждая интеграция платёжного шлюза, каждый перевозчик, каждый виджет и каждая пользовательская функция существуют в виде плагина.
Если вы понимаете, как создавать плагины для nopCommerce, вы можете расширять одну из самых мощных e-commerce-платформ на рынке — и построить на этом бизнес. Это руководство охватывает всё: от вашего первого каркаса плагина до промышленных паттернов развёртывания.
Мы создаём плагины для nopCommerce с 2009 года, и в нашем каталоге более 38 плагинов — включая 12 интеграций бразильских платёжных шлюзов и единственное на платформе полноценное решение для платежей PIX. Это руководство отражает всё, что мы усвоили, создавая плагины, обрабатывающие миллионы транзакций.
Архитектура плагина: фундамент
Иерархия интерфейсов плагина
Каждый плагин nopCommerce начинается с интерфейса IPlugin в Nop.Services.Plugins. Вместо того чтобы заставлять вас реализовывать всё с нуля, nopCommerce предоставляет BasePlugin — абстрактный класс, который берёт на себя шаблонный код, — и набор специализированных интерфейсов для распространённых типов плагинов:
| Интерфейс | Назначение | Пример |
|---|---|---|
| IPaymentMethod | Обработка платежей (авторизация, списание, возврат, отмена) | PayPal, Stripe, PIX, MercadoPago |
| IShippingRateComputationMethod | Расчёт стоимости доставки от перевозчиков | UPS, FedEx, Correios (Бразилия) |
| ITaxProvider | Расчёт налоговых ставок по юрисдикциям | Avalara, TaxJar |
| IWidgetPlugin | Отрисовка UI-виджетов в определённых зонах | Онлайн-чат, всплывающее окно подписки, карточки Trello |
| IExchangeRateProvider | Получение курсов валют | ЕЦБ, Центральный банк Бразилии |
| IDiscountRequirementRule | Пользовательская логика скидок | «Клиент из Бразилии получает скидку 10%» |
| IExternalAuthenticationMethod | Вход через соцсети и SSO | Google, Facebook, Azure AD |
| IMultiFactorAuthenticationMethod | Плагины MFA (начиная с 4.40) | Google Authenticator, SMS OTP |
| IPickupPointProvider | Пункты самовывоза в магазинах | Сеть локальных магазинов, системы постаматов |
| IMiscPlugin | Расширения общего назначения | Управление DNS, аналитика, интеграции |
Выбирайте наиболее конкретный интерфейс под ваш сценарий. IPaymentMethod даёт вам полный жизненный цикл платежа — ProcessPaymentAsync, PostProcessPaymentAsync, RefundAsync, VoidAsync, CaptureAsync — тогда как IMiscPlugin служит запасным вариантом для всего, что не вписывается в стандартную категорию.
Структура проекта: шаг за шагом
1. Создайте проект библиотеки классов
Создайте новый проект Class Library, нацеленный на .NET 9. Рекомендуемое соглашение об именовании — Nop.Plugin.{Group}.{Name}:
Nop.Plugin.Payments.PayPalCommerce
Nop.Plugin.Shipping.FedEx
Nop.Plugin.Widgets.WhatsApp
Nop.Plugin.Misc.GoDaddy
Разместите проект в каталоге \Plugins в корне решения (а не внутри \Nop.Web\Plugins, который является целевым каталогом развёртывания). Задайте в .csproj путь вывода $(SolutionDir)\Presentation\Nop.Web\Plugins\{PluginOutputDirectory} и включите CopyLocalLockFileAssemblies, чтобы зависимости NuGet копировались в выходной каталог.
2. Создайте plugin.json
Каждому плагину требуется файл plugin.json с метаданными:
{
"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"
}
Значение SystemName должно совпадать с именем вашей сборки. Поле SupportedVersions определяет, в каких версиях nopCommerce можно установить плагин. Если вы обновляете nopCommerce и плагин перестаёт работать, проверьте это поле в первую очередь — многим плагинам достаточно лишь обновить список поддерживаемых версий.
3. Реализуйте класс плагина
Создайте класс, который реализует подходящий интерфейс плагина и наследуется от 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);
}
}
Переопределения InstallAsync, UninstallAsync и UpdateAsync — это ваши хуки жизненного цикла. Всегда вызывайте базовую реализацию — base.InstallAsync() отвечает за регистрацию в системе плагинов.
4. Добавьте конфигурацию (админ-интерфейс)
Для плагинов с настройками создайте MVC-контроллер, модель и представление Razor:
- Controllers/{Name}Controller.cs — снабжённый атрибутами
[AuthorizeAdmin]и[Area(AreaNames.ADMIN)]. Наследуйте отBasePluginController. - Models/ConfigurationModel.cs — обычный класс со свойствами ваших настроек и атрибутами
[NopResourceDisplayName]для локализации. - Views/Configure.cshtml — использует макет
_ConfigurePlugin. Также включите_ViewImports.cshtml(скопируйте из существующего плагина).
Зарегистрируйте маршрут конфигурации в RouteProvider.cs, реализующем 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;
}
Создание платёжного плагина: паттерн из реальной практики
Платёжные плагины — самый распространённый и самый сложный тип плагинов. Вот промышленный паттерн, который мы используем в SplatDev:
Основные компоненты
- Класс настроек: класс, реализующий
ISettings, со свойствами для API-ключей, URL, режимов (песочница/боевой) и переключателей функций. Храните секреты вISettingService— никогда не зашивайте учётные данные в код. - Класс Defaults: статический класс с константами — именами маршрутов, системным именем, URL конфигурации, эндпоинтами API. Убирает «магические строки» из вашей логики.
- Класс сервиса: собственно логика интеграции — HTTP-вызовы к платёжному шлюзу, разбор ответов, обработка вебхуков. Внедряйте через DI и делайте тестируемым (интерфейс + реализация).
- Потребители событий: реализуйте
IConsumer<OrderPlacedEvent>и аналогичные интерфейсы, чтобы реагировать на события магазина — отправлять подтверждения транзакций, запускать процессы после оплаты.
Поток платежа: методы, которые вы обязаны реализовать
| Метод | Когда вызывается | Что должен делать |
|---|---|---|
ProcessPaymentAsync |
Клиент нажимает «Оплатить» | Авторизовать или списать платёж. Вернуть успех/неудачу и идентификатор транзакции. |
PostProcessPaymentAsync |
После завершения обработки платежа | Перенаправить на внешний шлюз (PayPal, PagSeguro) или показать страницу подтверждения. |
RefundAsync |
Администратор инициирует возврат | Провести возврат через шлюз. Вернуть успех/неудачу. |
VoidAsync |
Администратор отменяет авторизацию | Отменить ожидающую авторизацию. Применимо, только если платёж ещё не был списан. |
CaptureAsync |
Администратор списывает авторизованный платёж | Списать ранее авторизованную сумму. Обычно применяется в схемах «авторизация, затем списание». |
GetPaymentMethodDescriptionAsync |
Отрисовка страницы оформления заказа | Вернуть отображаемое имя, описание и логотип метода оплаты. |
GetAdditionalHandlingFeeAsync |
Расчёт итоговой суммы заказа | Вернуть любую дополнительную комиссию метода оплаты либо ноль. |
Пример бразильского платёжного плагина: PIX
Бразильская система мгновенных платежей PIX требует особого потока: сгенерировать QR-код с полезной нагрузкой (строкой EMV), показать его клиенту и ожидать подтверждения через вебхук при получении платежа. Вот паттерн:
- ProcessPaymentAsync: вызовите PSP (PagSeguro, MercadoPago и т. д.), чтобы создать платёж PIX. Сохраните идентификатор транзакции (
txid) и полезную нагрузку EMV. - PostProcessPaymentAsync: отрисуйте QR-код (сгенерированный из полезной нагрузки EMV) и код для копирования-вставки. Установите статус платежа
Pending. - Обработчик вебхука: PSP отправляет вебхук, когда PIX подтверждает платёж. Обновите статус заказа и запустите
OrderPaidEvent.
Именно этот паттерн лежит в основе всех 12 бразильских платёжных плагинов SplatDev — обрабатывающих PIX, boleto и платежи по кредитным картам в рассрочку через PagSeguro, MercadoPago, Cielo, Banco Inter, Pagar.me, Rede, GetNet, PicPay, NuPay, Braspag и InfinityPay.
Виджеты: добавление UI без вмешательства в темы
Плагины-виджеты реализуют IWidgetPlugin и должны указывать, в каких зонах виджетов они отрисовываются:
public Task<IList<string>> GetWidgetZonesAsync()
{
return Task.FromResult<IList<string>>(new List<string>
{
PublicWidgetZones.HomepageBeforeBestSellers,
PublicWidgetZones.ProductDetailsAfterPictures
});
}
Затем реализуйте GetPublicViewComponentAsync, чтобы вернуть HTML виджета. Система виджетов вызывает этот метод для каждой зарегистрированной вами зоны.
Распространённые паттерны виджетов: всплывающие окна подписки на рассылку, кнопки онлайн-чата, значки доверия, баннеры согласия на использование cookie, плавающие кнопки WhatsApp, недавно просмотренные товары и уведомления социального доказательства.
Доступ к базе данных: IRepository<T> и миграции
nopCommerce использует паттерн репозитория через IRepository<T> для доступа к данным. Для плагинов, которым нужны собственные таблицы:
- Определите класс сущности (у него должно быть свойство
Id). - Создайте
ObjectContext, который регистрирует вашу сущность в Entity Framework Core. - В
InstallAsyncиспользуйте_dbContext.InstallAsync(), чтобы создать таблицы. - В
UninstallAsyncиспользуйте_dbContext.UninstallAsync(), чтобы удалить их.
Для миграций схемы между версиями плагина рассмотрите добавление MigrationManager в переопределение UpdateAsync, который проверяет текущую версию схемы и применяет необходимые операторы ALTER TABLE. Это проще, чем FluentMigrator для плагинов, и держит логику миграций в одном месте.
Тестирование: относитесь к плагину как к продукту
В SplatDev мы относимся к каждому плагину как к продукту с собственным набором тестов:
- Модульные тесты (xUnit): тестируйте слой сервисов в изоляции. Мокайте
ISettingService,IRepository<T>и любые HTTP-клиенты. Ваша платёжная логика, расчёты налогов и вычисления стоимости доставки должны иметь 100% покрытие бизнес-логики модульными тестами. - Интеграционные тесты: поднимите тестовый экземпляр nopCommerce и убедитесь, что ваш плагин устанавливается, настраивается и проходит весь жизненный цикл. Используйте тестовые учётные данные (песочницу) для платёжных шлюзов.
- Тесты локализации: проверьте, что все ресурсы локализации существуют для каждого языка, который вы заявляете как поддерживаемый. Отсутствующие строки ресурсов — самая распространённая ошибка плагинов.
- Соответствие StyleCop: nopCommerce ожидает соответствия StyleCop. Запускайте его в конвейере CI — он ловит тонкие проблемы ещё до код-ревью.
Типичные ошибки (и как их избежать)
1. Не вызван base.InstallAsync()
Если вы переопределяете InstallAsync без вызова базовой реализации, ваш плагин не зарегистрируется в системе плагинов и не появится в админке. Всегда включайте await base.InstallAsync() в конце вашего переопределения.
2. Учётные данные, зашитые в код
Храните API-ключи, токены и секреты в ISettingService — никогда не зашивайте их в plugin.json или в константы класса. Страница настроек должна позволять администраторам задавать эти значения, и при необходимости они должны сохраняться в зашифрованном виде.
3. Игнорирование совместимости версий
Версии nopCommerce ломают плагины. Поле SupportedVersions в plugin.json — не декорация: nopCommerce проверяет его перед загрузкой вашего плагина. При обновлении nopCommerce протестируйте плагин против новой версии и обновите это поле. Не увеличивайте номер просто так, без тестирования.
4. Блокировка потока запроса
Все методы плагина асинхронны неспроста. Если ваш платёжный процессор вызывает внешний API, этот вызов должен быть асинхронным. Блокировка потока через .Result или .Wait() снизит производительность под нагрузкой и может привести к взаимоблокировкам.
5. Отсутствие потребителей событий
Плагины, которые предоставляют только страницу конфигурации, упускают суть. Настоящая сила плагинов nopCommerce — в потребителях событий, реагирующих на события магазина, такие как OrderPlacedEvent, CustomerRegisteredEvent или ShipmentDeliveredEvent. Встраивайте плагин в бизнес-события магазина, а не только в админ-интерфейс.
nopCommerce 4.90: что нового для разработчиков плагинов
nopCommerce 4.90 нацелен на .NET 9 и приносит несколько улучшений для разработчиков плагинов:
- Среда выполнения .NET 9: ваши плагины работают на самой быстрой на сегодня версии .NET — автоматически выигрывая от улучшений JIT, динамической адаптации GC и оптимизаций циклов.
- Поддержка C# 13: используйте коллекции
params, интерфейсы дляref structи частичные свойства в коде своих плагинов. - Обновлённые зависимости NuGet: базовые пакеты (Autofac, FluentValidation и др.) были обновлены. Протестируйте дерево зависимостей вашего плагина.
- IMultiFactorAuthenticationMethod: плагины MFA теперь являются полноценной концепцией с собственным интерфейсом.
- Улучшенный шаблон плагина: официальный шаблон плагина nopCommerce для Visual Studio обновлён под 4.90 — используйте его как отправную точку.
Куда двигаться дальше
Разработка плагинов nopCommerce — это навык, строящий карьеру. Маркетплейс nopCommerce активен и растёт, а качественно сделанные плагины приносят регулярный доход за счёт обновлений и поддержки. В SplatDev плагины — наш основной бизнес: наш магазин на store.splatdev.com насчитывает более 38 плагинов, и мы уже много лет являемся Gold Solutions Partner.
Если вы создаёте e-commerce-проект на nopCommerce, вам не нужно строить всё с нуля. Наш каталог охватывает бразильские платежи, доставку (Correios, JadLog, Braspress), интеграции с ERP и пользовательскую функциональность. Если вам нужно что-то, чего у нас нет, мы создаём и заказные плагины.
Готовы создать или расширить свой магазин на nopCommerce? Наша команда занимается этим с 2009 года — дольше почти кого-либо в экосистеме.
Работать с нашей командой nopCommerce
Или посмотрите наш каталог плагинов: store.splatdev.com