Warum nopCommerce-Plugins wichtig sind
nopCommerce betreibt weltweit über 60,000 Online-Shops. Es ist die führende Open-Source-E-Commerce-Plattform auf .NET — und seine Plugin-Architektur ist der Motor hinter diesem Ökosystem. Jede Zahlungs-Gateway-Integration, jeder Versanddienstleister, jedes Widget und jede individuelle Funktion existiert als Plugin.
Wenn Sie verstehen, wie man nopCommerce-Plugins erstellt, können Sie eine der leistungsfähigsten E-Commerce-Plattformen auf dem Markt erweitern — und daraus ein Geschäft machen. Dieser Leitfaden deckt alles ab, vom ersten Plugin-Grundgerüst bis zu Mustern für das Produktiv-Deployment.
Wir entwickeln nopCommerce-Plugins seit 2009 und haben über 38 Plugins in unserem Katalog — darunter 12 brasilianische Zahlungs-Gateway-Integrationen und die einzige vollständige PIX-Zahlungslösung auf der Plattform. Dieser Leitfaden spiegelt wider, was wir beim Entwickeln von Plugins gelernt haben, die Millionen von Transaktionen verarbeiten.
Plugin-Architektur: Das Fundament
Die Hierarchie der Plugin-Interfaces
Jedes nopCommerce-Plugin beginnt mit dem IPlugin-Interface in Nop.Services.Plugins. Anstatt alles von Grund auf selbst implementieren zu müssen, stellt nopCommerce BasePlugin bereit — eine abstrakte Klasse, die den Boilerplate-Code übernimmt — sowie eine Reihe spezialisierter Interfaces für gängige Plugin-Typen:
| Interface | Zweck | Beispiel |
|---|---|---|
| IPaymentMethod | Zahlungsabwicklung (Autorisierung, Erfassung, Rückerstattung, Stornierung) | PayPal, Stripe, PIX, MercadoPago |
| IShippingRateComputationMethod | Versandkosten von Zustellern berechnen | UPS, FedEx, Correios (Brasilien) |
| ITaxProvider | Steuersätze nach Rechtsraum berechnen | Avalara, TaxJar |
| IWidgetPlugin | UI-Widgets in bestimmten Zonen rendern | Live-Chat, Newsletter-Popup, Trello-Karten |
| IExchangeRateProvider | Währungswechselkurse abrufen | EZB, Zentralbank von Brasilien |
| IDiscountRequirementRule | Individuelle Rabattlogik | «Kunde aus Brasilien erhält 10% Rabatt» |
| IExternalAuthenticationMethod | Social Login und SSO | Google, Facebook, Azure AD |
| IMultiFactorAuthenticationMethod | MFA-Plugins (seit 4.40) | Google Authenticator, SMS OTP |
| IPickupPointProvider | Abholstandorte im Geschäft | Lokales Filialnetz, Schliessfachsysteme |
| IMiscPlugin | Universelle Erweiterungen | DNS-Verwaltung, Analytics, Integrationen |
Wählen Sie das spezifischste Interface für Ihren Anwendungsfall. IPaymentMethod gibt Ihnen den vollständigen Zahlungs-Lebenszyklus — ProcessPaymentAsync, PostProcessPaymentAsync, RefundAsync, VoidAsync, CaptureAsync — während IMiscPlugin die Notlösung für alles ist, was nicht in eine Standardkategorie passt.
Projektstruktur: Schritt für Schritt
1. Das Klassenbibliothek-Projekt erstellen
Erstellen Sie ein neues Class Library-Projekt für .NET 9. Die empfohlene Namenskonvention lautet Nop.Plugin.{Group}.{Name}:
Nop.Plugin.Payments.PayPalCommerce
Nop.Plugin.Shipping.FedEx
Nop.Plugin.Widgets.WhatsApp
Nop.Plugin.Misc.GoDaddy
Platzieren Sie das Projekt im Verzeichnis \Plugins im Solution-Root (nicht in \Nop.Web\Plugins, das das Deployment-Ziel ist). Setzen Sie den Ausgabepfad der .csproj auf $(SolutionDir)\Presentation\Nop.Web\Plugins\{PluginOutputDirectory} und aktivieren Sie CopyLocalLockFileAssemblies, damit die NuGet-Abhängigkeiten in die Ausgabe kopiert werden.
2. plugin.json erstellen
Jedes Plugin benötigt eine plugin.json-Datei mit Metadaten:
{
"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"
}
Der SystemName muss mit Ihrem Assembly-Namen übereinstimmen. SupportedVersions bestimmt, welche nopCommerce-Versionen das Plugin installieren können. Wenn Sie nopCommerce aktualisieren und ein Plugin nicht mehr funktioniert, prüfen Sie zuerst dieses Feld — bei vielen Plugins müssen lediglich die unterstützten Versionen aktualisiert werden.
3. Die Plugin-Klasse implementieren
Erstellen Sie eine Klasse, die das passende Plugin-Interface implementiert und von BasePlugin ableitet:
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);
}
}
Die Overrides InstallAsync, UninstallAsync und UpdateAsync sind Ihre Lifecycle-Hooks. Rufen Sie immer die Basis-Implementierung auf — base.InstallAsync() übernimmt die Registrierung im Plugin-System.
4. Konfiguration hinzufügen (Admin-UI)
Erstellen Sie für Plugins mit Einstellungen einen MVC-Controller, ein Model und eine Razor-View:
- Controllers/{Name}Controller.cs — dekoriert mit
[AuthorizeAdmin]und[Area(AreaNames.ADMIN)]. VonBasePluginControllerableiten. - Models/ConfigurationModel.cs — eine einfache Klasse mit Ihren Einstellungs-Properties und
[NopResourceDisplayName]-Attributen für die Lokalisierung. - Views/Configure.cshtml — verwendet das Layout
_ConfigurePlugin. Fügen Sie ausserdem_ViewImports.cshtmlhinzu (von einem bestehenden Plugin kopieren).
Registrieren Sie die Konfigurations-Route in einer RouteProvider.cs, die IRouteProvider implementiert:
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;
}
Ein Zahlungs-Plugin erstellen: Das Praxismuster
Zahlungs-Plugins sind der häufigste — und komplexeste — Plugin-Typ. Hier ist das Produktivmuster, das wir bei SplatDev verwenden:
Kernkomponenten
- Settings-Klasse: Eine Klasse, die
ISettingsimplementiert, mit Properties für API-Schlüssel, URLs, Modi (Sandbox/Produktion) und Feature-Toggles. Speichern Sie Geheimnisse inISettingService— codieren Sie Zugangsdaten niemals fest ein. - Defaults-Klasse: Eine statische Klasse mit Konstanten — Routennamen, Systemname, Konfigurations-URLs, API-Endpunkte. Hält Magic Strings aus Ihrer Logik heraus.
- Service-Klasse: Ihre eigentliche Integrationslogik — HTTP-Aufrufe an das Payment-Gateway, Parsen von Antworten, Webhook-Verarbeitung. Per DI injizieren und testbar halten (Interface + Implementierung).
- Event-Consumer: Implementieren Sie
IConsumer<OrderPlacedEvent>und ähnliche Interfaces, um auf Shop-Ereignisse zu reagieren — Transaktionsbestätigungen versenden, Workflows nach der Zahlung auslösen.
Zahlungsablauf: Die Methoden, die Sie implementieren müssen
| Methode | Wann aufgerufen | Was sie tun soll |
|---|---|---|
ProcessPaymentAsync |
Kunde klickt auf «Bezahlen» | Zahlung autorisieren oder erfassen. Erfolg/Fehler und Transaktions-ID zurückgeben. |
PostProcessPaymentAsync |
Nach Abschluss der Zahlungsabwicklung | Zum externen Gateway (PayPal, PagSeguro) weiterleiten oder eine Bestätigungsseite anzeigen. |
RefundAsync |
Admin leitet Rückerstattung ein | Die Rückerstattung über das Gateway abwickeln. Erfolg/Fehler zurückgeben. |
VoidAsync |
Admin storniert eine Autorisierung | Die ausstehende Autorisierung stornieren. Nur zutreffend, wenn die Zahlung noch nicht erfasst wurde. |
CaptureAsync |
Admin erfasst eine autorisierte Zahlung | Einen zuvor autorisierten Betrag erfassen. Üblich bei Abläufen mit Autorisierung und anschliessender Erfassung. |
GetPaymentMethodDescriptionAsync |
Checkout-Seite wird gerendert | Anzeigenamen, Beschreibung und Logo für die Zahlungsmethode zurückgeben. |
GetAdditionalHandlingFeeAsync |
Berechnung der Bestellsumme | Eine allfällige zusätzliche Gebühr der Zahlungsmethode zurückgeben oder null. |
Beispiel für ein brasilianisches Zahlungs-Plugin: PIX
Das brasilianische PIX-Echtzeitzahlungssystem erfordert einen bestimmten Ablauf: einen QR-Code mit einem Payload (EMV-String) generieren, ihn dem Kunden anzeigen und auf eine Webhook-Bestätigung warten, wenn die Zahlung eingegangen ist. Hier ist das Muster:
- ProcessPaymentAsync: Rufen Sie den PSP (PagSeguro, MercadoPago usw.) auf, um eine PIX-Zahlung zu erstellen. Speichern Sie die Transaktions-ID (
txid) und den EMV-Payload. - PostProcessPaymentAsync: Rendern Sie den QR-Code (aus dem EMV-Payload generiert) und den «Copy-Paste»-Code. Setzen Sie den Zahlungsstatus auf
Pending. - Webhook-Handler: Der PSP sendet einen Webhook, wenn PIX die Zahlung bestätigt. Aktualisieren Sie den Bestellstatus und lösen Sie
OrderPaidEventaus.
Das ist das Muster hinter allen 12 brasilianischen Zahlungs-Plugins von SplatDev — sie verarbeiten PIX, boleto und Kreditkartenzahlungen in Raten über PagSeguro, MercadoPago, Cielo, Banco Inter, Pagar.me, Rede, GetNet, PicPay, NuPay, Braspag und InfinityPay.
Widgets: UI hinzufügen, ohne Themes anzufassen
Widget-Plugins implementieren IWidgetPlugin und müssen angeben, in welchen Widget-Zonen sie gerendert werden:
public Task<IList<string>> GetWidgetZonesAsync()
{
return Task.FromResult<IList<string>>(new List<string>
{
PublicWidgetZones.HomepageBeforeBestSellers,
PublicWidgetZones.ProductDetailsAfterPictures
});
}
Implementieren Sie anschliessend GetPublicViewComponentAsync, um das HTML des Widgets zurückzugeben. Das Widget-System ruft diese Methode für jede von Ihnen registrierte Zone auf.
Gängige Widget-Muster: Newsletter-Anmelde-Popups, Live-Chat-Buttons, Trust-Badges, Cookie-Consent-Banner, schwebende WhatsApp-Buttons, zuletzt angesehene Produkte und Social-Proof-Benachrichtigungen.
Datenbankzugriff: IRepository<T> und Migrationen
nopCommerce verwendet für den Datenzugriff ein Repository-Muster über IRepository<T>. Für Plugins, die eigene Tabellen benötigen:
- Definieren Sie Ihre Entity-Klasse (muss eine
Id-Property haben). - Erstellen Sie einen
ObjectContext, der Ihre Entity bei Entity Framework Core registriert. - Verwenden Sie in
InstallAsyncdie Methode_dbContext.InstallAsync(), um die Tabellen zu erstellen. - Verwenden Sie in
UninstallAsyncdie Methode_dbContext.UninstallAsync(), um sie zu löschen.
Für Schema-Migrationen zwischen Plugin-Versionen sollten Sie in Ihrem UpdateAsync-Override einen MigrationManager hinzufügen, der die aktuelle Schema-Version prüft und die notwendigen ALTER-TABLE-Anweisungen anwendet. Das ist für Plugins einfacher als FluentMigrator und hält Ihre Migrationslogik an einem Ort.
Testing: Behandeln Sie Ihr Plugin wie ein Produkt
Bei SplatDev behandeln wir jedes Plugin als Produkt mit eigener Test-Suite:
- Unit-Tests (xUnit): Testen Sie Ihre Service-Schicht isoliert. Mocken Sie
ISettingService,IRepository<T>und sämtliche HTTP-Clients. Ihre Zahlungslogik, Steuerberechnungen und Versandkostenberechnungen sollten für die Geschäftslogik eine Unit-Test-Abdeckung von 100% haben. - Integrationstests: Starten Sie eine Test-nopCommerce-Instanz und überprüfen Sie, dass sich Ihr Plugin über den gesamten Lebenszyklus hinweg installiert, konfiguriert und verarbeitet. Verwenden Sie Sandbox-/Test-Zugangsdaten für Payment-Gateways.
- Lokalisierungstests: Überprüfen Sie, dass alle Locale-Ressourcen für jede Sprache vorhanden sind, die Sie zu unterstützen angeben. Fehlende Ressourcen-Strings sind der häufigste Plugin-Fehler.
- StyleCop-Konformität: nopCommerce erwartet StyleCop-Konformität. Führen Sie es in Ihrer CI-Pipeline aus — es findet subtile Probleme vor dem Code-Review.
Häufige Fallstricke (und wie man sie vermeidet)
1. base.InstallAsync() nicht aufrufen
Wenn Sie InstallAsync überschreiben, ohne die Basis aufzurufen, registriert sich Ihr Plugin nicht im Plugin-System und erscheint nicht im Admin-Bereich. Fügen Sie immer await base.InstallAsync() am Ende Ihres Overrides ein.
2. Zugangsdaten fest einprogrammieren
Speichern Sie API-Schlüssel, Tokens und Geheimnisse in ISettingService — codieren Sie sie niemals fest in plugin.json oder als Klassenkonstanten ein. Die Einstellungsseite sollte es Admins ermöglichen, diese Werte zu konfigurieren, und sie sollten bei Bedarf verschlüsselt gespeichert werden.
3. Versionskompatibilität ignorieren
nopCommerce-Versionen machen Plugins unbrauchbar. Das Feld SupportedVersions in plugin.json ist nicht bloss Dekoration — nopCommerce prüft es, bevor es Ihr Plugin lädt. Testen Sie Ihr Plugin beim Aktualisieren von nopCommerce gegen die neue Version und aktualisieren Sie dieses Feld. Erhöhen Sie die Nummer nicht einfach ohne Test.
4. Den Request-Thread blockieren
Alle Plugin-Methoden sind aus gutem Grund asynchron. Wenn Ihr Payment-Processor eine externe API aufruft, sollte dieser Aufruf asynchron sein. Das Blockieren des Threads mit .Result oder .Wait() verschlechtert die Performance unter Last und kann zu Deadlocks führen.
5. Keine Event-Consumer
Plugins, die nur eine Konfigurationsseite bereitstellen, verfehlen den Kern. Die eigentliche Stärke von nopCommerce-Plugins kommt von Event-Consumern — der Reaktion auf Shop-Ereignisse wie OrderPlacedEvent, CustomerRegisteredEvent oder ShipmentDeliveredEvent. Binden Sie Ihr Plugin in die Geschäftsereignisse des Shops ein, nicht nur in die Admin-UI.
nopCommerce 4.90: Was für Plugin-Entwickler neu ist
nopCommerce 4.90 zielt auf .NET 9 ab und bringt mehrere Verbesserungen für Plugin-Entwickler:
- .NET 9-Runtime: Ihre Plugins laufen auf dem bislang schnellsten .NET — und profitieren automatisch von JIT-Verbesserungen, dynamischer GC-Anpassung und Schleifenoptimierungen.
- C# 13-Unterstützung: Verwenden Sie
params-Collections,ref struct-Interfaces und partielle Properties in Ihrem Plugin-Code. - Aktualisierte NuGet-Abhängigkeiten: Die zugrunde liegenden Pakete (Autofac, FluentValidation usw.) wurden aktualisiert. Testen Sie den Abhängigkeitsbaum Ihres Plugins.
- IMultiFactorAuthenticationMethod: MFA-Plugins sind nun ein vollwertiges Konzept mit eigenem Interface.
- Verbessertes Plugin-Template: Das offizielle nopCommerce-Plugin-Template für Visual Studio wurde für 4.90 aktualisiert — verwenden Sie es als Ausgangspunkt.
Wie es weitergeht
Die Entwicklung von nopCommerce-Plugins ist eine karrierefördernde Fähigkeit. Der nopCommerce-Marktplatz ist aktiv und wächst, und gut gebaute Plugins erzeugen über Updates und Support wiederkehrende Einnahmen. Bei SplatDev sind Plugins unser Kerngeschäft — unser Store unter store.splatdev.com umfasst über 38 Plugins, und wir sind seit Jahren Gold Solutions Partner.
Wenn Sie ein E-Commerce-Projekt auf nopCommerce aufbauen, müssen Sie nicht alles von Grund auf entwickeln. Unser Katalog deckt brasilianische Zahlungen, Versand (Correios, JadLog, Braspress), ERP-Integrationen und individuelle Funktionen ab. Wenn Sie etwas benötigen, das wir nicht haben, entwickeln wir auch massgeschneiderte Plugins.
Bereit, Ihren nopCommerce-Shop aufzubauen oder zu erweitern? Unser Team macht das seit 2009 — länger als fast alle anderen im Ökosystem.
Arbeiten Sie mit unserem nopCommerce-Team
Oder durchstöbern Sie unseren Plugin-Katalog: store.splatdev.com