Zum Inhalt

Print Service – Einrichtung

Vollständige Schritt-für-Schritt-Anleitung zur Einrichtung des merchantCENTRAL Print Service: vom Installieren des lokalen Druckdienstes über die Anbindung an Business Central bis zum ersten Testdruck.

Architektur in Kürze

Business Central (Cloud) kann lokale Drucker nicht direkt ansprechen. Der MC.PrintService ist eine kleine lokale Anwendung beim Kunden, die Druckaufträge entgegennimmt und an Windows- oder Zebra-Drucker weiterleitet.

┌──────────────────┐   Druckauftrag    ┌──────────────────┐   PDF / ZPL    ┌──────────────┐
│ Business Central │ ────────────────► │  MC.PrintService │ ─────────────► │   Drucker    │
│   (Cloud/SaaS)   │                   │   (beim Kunden)  │                │ Windows/Zebra│
└──────────────────┘                   └──────────────────┘                └──────────────┘

Für den Weg von BC zum MC.PrintService gibt es drei Transport-Modi:

Direkt-Push (Standard) Relay (Option C) Poll (Option D)
Funktionsweise BC ruft den Dienst direkt über die feste öffentliche IP auf BC pusht in eine Queue im kunden-eigenen Azure Die Function pollt BC; BC bleibt passiv
Eingehende Portfreigabe erforderlich nicht erforderlich nicht erforderlich
Feste öffentliche IP erforderlich nicht erforderlich nicht erforderlich
BC macht Outbound-Calls ja ja (Auftrag inkl. Label) nein (nur optionaler Wake-Ping)
Azure-Subscription des Kunden nein ja (~1–2 €/Monat) ja (~1–2 €/Monat)
Status ✅ verfügbar ✅ verfügbar ✅ verfügbar

Welchen Modus wählen?

Direkt-Push ist der Standard und für die meisten Kunden die beste Wahl: kostenfrei, sofortige Statusrückmeldung, einfach. Voraussetzung ist eine feste öffentliche IP und die Möglichkeit, einen Port freizugeben. Relay und Poll sind für Kunden ohne feste IP / ohne eingehende Portfreigabe. Der Unterschied: Bei Relay pusht BC den Auftrag aktiv ins Azure; bei Poll bleibt BC vollständig passiv (die Function holt die Aufträge ab) — ideal, wenn BC keine ausgehenden Webservice-Aufrufe konfigurieren soll.


Voraussetzungen

  • [ ] merchantCENTRAL Hub – installiert und aktiv
  • [ ] Print Service App – installiert (AppSource oder Bereitstellung durch ALTENBRAND)
  • [ ] Modul-Lizenz – mindestens Demo-Lizenz für PRINTSERVICE
  • [ ] Windows-PC oder Server im Kundennetz für den MC.PrintService (Windows 10/11 oder Server 2016+)
  • [ ] Drucker – Windows-Druckertreiber (für PDF) oder Zebra-Drucker per TCP/IP erreichbar (für ZPL)
  • [ ] Bei Direkt-Push zusätzlich: feste öffentliche IP und Zugriff auf Router/Firewall

Schritt 1: MC.PrintService installieren

Der lokale Druckdienst wird einmalig auf einem Rechner im Kundennetz installiert, der dauerhaft läuft und die Drucker erreicht.

Variante A – Windows-Dienst (empfohlen, PDF + ZPL)

  1. ZIP-Paket entpacken.
  2. Install.bat doppelklicken → UAC-Dialog bestätigen.
  3. Das Skript installiert den Dienst, richtet die Autostart- und Firewall-Regel ein und generiert automatisch einen API-Key, der am Ende angezeigt wird.
  4. API-Key notieren – er wird in Schritt 3 in Business Central benötigt.

Der Dienst lauscht standardmäßig auf Port 5050. Konfigurationsoberfläche im Browser: http://localhost:5050/config.

API-Key später nachschlagen

Der Schlüssel steht in appsettings.json im Installationsverzeichnis unter Security:ApiKey. Die Konfigurationsoberfläche zeigt oben an, ob ein Schlüssel gesetzt ist.

Variante B – Docker (nur ZPL out of the box)

cd service
# API-Key setzen (Pflicht für Remote-Zugriff):
export MCPS_API_KEY="$(openssl rand -hex 32)"
docker compose up -d

Der Dienst ist dann unter http://localhost:5100 erreichbar. PDF-Druck im Container erfordert einen CUPS-Sidecar; für reinen ZPL-Betrieb (Zebra-Drucker per TCP) ist Docker ideal.

Ohne API-Key kein Remote-Zugriff

Ist kein Security:ApiKey gesetzt, akzeptiert der Dienst aus Sicherheitsgründen nur lokale Anfragen (localhost). Anfragen aus Business Central (Cloud) werden mit 401 abgelehnt. Der Schlüssel ist für den Remote-Betrieb also zwingend.


Teil A: Direkt-Push einrichten

Beim Direkt-Push erreicht Business Central den MC.PrintService über die feste öffentliche IP des Kunden. Drei Schutzschichten sichern den Zugang ab: API-Key, HTTPS und eine Firewall-Einschränkung auf Business Central.

A1 – HTTPS bereitstellen

Business Central (Cloud) sendet Druckaufträge aus dem Azure-Rechenzentrum und validiert dabei das Serverzertifikat. Selbstsignierte Zertifikate funktionieren nicht. Wählen Sie eine Option:

Option Beschreibung Geeignet für
Reverse Proxy (empfohlen) Caddy, nginx oder IIS vor dem Dienst, Subdomain je Kunde (z. B. print.kunde.de → feste IP), Let's-Encrypt-Zertifikat automatisch die meisten Kunden mit eigener Domain
Let's-Encrypt-IP-Zertifikat Zertifikat direkt auf die IP-Adresse (kurzlebig ~6 Tage, automatische Erneuerung per ACME) Kunden ohne Domain
Kestrel mit PFX HTTPS direkt im Dienst: Kestrel:Endpoints:Https in appsettings.json mit Pfad zum Zertifikat einfache Setups mit vorhandenem Zertifikat

Reverse Proxy mit Caddy

Caddy beschafft und erneuert Let's-Encrypt-Zertifikate vollautomatisch. Eine minimale Caddyfile lautet: print.kunde.de { reverse_proxy localhost:5050 }.

A2 – Port-Forwarding einrichten

Leiten Sie im Router/Firewall den öffentlichen HTTPS-Port (z. B. 443) auf den Rechner mit dem MC.PrintService weiter (Port 5050 bzw. den Port des Reverse Proxy).

A3 – Firewall auf Business Central beschränken

Damit der weitergeleitete Port nicht für das gesamte Internet offen steht, beschränken Sie den eingehenden Zugriff auf die IP-Adressen von Business Central. Diese sind im Azure-Service-Tag Dynamics365BusinessCentral zusammengefasst (von Microsoft automatisch gepflegt).

  • Firewalls mit Service-Tag-Unterstützung verwenden den Tag direkt.
  • Andernfalls die IP-Bereiche als JSON-Liste herunterladen und als Regel hinterlegen.

A4 – Drucker in Business Central anlegen

  1. In BC nach Print Service Printers suchen → Neu.
  2. Felder ausfüllen:
Feld Wert
Code Eindeutige Kennung, z. B. PDF-BÜRO oder ZPL-LAGER1
Description Sprechender Name
Service URL Öffentliche HTTPS-URL des Dienstes, z. B. https://print.kunde.de (für lokale Tests http://localhost:5050)
Print Method PDF (Windows-Drucker) oder ZPL (Zebra-Thermodrucker)
Printer Name Bei PDF: exakter Windows-Druckername. Bei ZPL: IP-Adresse des Zebra-Druckers
ZPL Port Nur bei ZPL: TCP-Port (Standard 9100)
  1. API-Key hinterlegen: Feld API Key anklicken (DrillDown) → den in Schritt 1 erzeugten Schlüssel eingeben. Er wird verschlüsselt im zentralen Credential Store gespeichert und nie im Klartext angezeigt.

HTTPS-Pflicht für Remote-URLs

Die Service URL muss https:// verwenden. http:// ist nur für localhost/127.0.0.1 (lokale Tests) zulässig und wird für entfernte Adressen abgewiesen.

A5 – Verbindung testen

Auf der Printer Card die Aktion Test Connection ausführen. Bei Erfolg wechselt der Status auf Online. Anschließend ein Testlabel drucken (siehe Nächste Schritte).

Fehler Ursache Lösung
Status bleibt Offline Dienst nicht erreichbar Port-Forwarding, Reverse Proxy, Dienststatus prüfen
401 Unauthorized API-Key fehlt/falsch Schlüssel in BC und appsettings.json abgleichen
Zertifikatsfehler Ungültiges/selbstsigniertes Zertifikat Gültiges Zertifikat (Let's Encrypt) verwenden

Teil C: Relay einrichten (für Kunden ohne feste IP)

Beim Relay-Modus betreibt der Kunde die Vermittlungskomponenten in seinem eigenen Azure. Business Central pusht den Druckauftrag dorthin; der MC.PrintService im Agent-Modus hält nur eine ausgehende Verbindung – keine eingehende Portfreigabe, keine feste IP, kein eigenes HTTPS-Zertifikat nötig. Die Druckdaten fließen ausschließlich durch die kunden-eigene Azure-Subscription, nie über ALTENBRAND.

BC  ──►  Azure Function ──►  Service Bus Queue          (Kunden-Azure)
                    │              │
                    │ Blob (Label) │ AMQP (ausgehend 443)
                    ▼              ▼
              Blob Storage    MC.PrintService (Agent-Modus, beim Kunden)  ──►  Drucker

Der Status-Rückweg läuft aktiv über die Function an Business Central zurück (Managed Identity, kein Polling) – ein Druckauftrag wechselt also auch im Relay-Modus von Sending auf Printed bzw. Failed.

Voraussetzungen für Relay

Zusätzlich zu den allgemeinen Voraussetzungen oben: eine Azure-Subscription des Kunden mit der Berechtigung, Ressourcen und Rollenzuweisungen anzulegen (Rolle Owner oder User Access Administrator), sowie Azure CLI und Azure Functions Core Tools v4 auf dem Rechner, der das Deployment ausführt.

C1 – Azure-Infrastruktur bereitstellen

Die mitgelieferte Bicep-/ARM-Vorlage (azure/deploy/ im Print-Service-Repository) erzeugt in der Kunden-Subscription mit einem Schritt: Service Bus (Basic) + Queue print-jobs, Storage Account + Blob-Container labels, eine Function App (Consumption) mit System-Managed-Identity sowie die nötigen Rollenzuweisungen.

Per Azure CLI:

az group create -n rg-mcps-relay -l westeurope

az deployment group create -g rg-mcps-relay \
  --template-file azure/deploy/main.bicep \
  --parameters \
      namePrefix=mcpsrelay \
      bcEnvironmentUrl="https://api.businesscentral.dynamics.com/v2.0/<tenantId>/<environment>" \
      bcCompanyId="<company-systemid-guid>"

Alternativ über den „Deploy to Azure"-Button in azure/README.md. Notieren Sie aus den Deployment-Outputs: functionBaseUrl, statusUrl, managedIdentityPrincipalId und den Service-Bus-Namen.

Company-SystemId ermitteln

Die bcCompanyId ist die SystemId der BC-Mandanten-Company. Sie steht in BC unter Companies (Feld Id) oder per API …/api/v2.0/companies.

C2 – Function-Code veröffentlichen

Die Vorlage erzeugt nur die leere Function App. Den Code einmalig veröffentlichen:

func azure functionapp publish <functionAppName>   # Name aus dem Deployment-Output

C3 – Managed Identity als BC Application User einrichten

Damit die Function den Druckstatus zurückmelden darf, wird ihre Managed Identity als Anwendungsbenutzer in Business Central registriert – der Agent selbst braucht keinen BC-Zugang.

  1. In Microsoft Entra ID die Enterprise-Application der Function-Managed-Identity öffnen (Object-/Principal-Id = Output managedIdentityPrincipalId, Anzeigename = Function-App-Name) und deren Application (Client) Id notieren.
  2. In Business Central nach Microsoft Entra Applications suchen → Neu → die Client Id eintragen, State = Enabled.
  3. Dem Eintrag das Berechtigungsset ALN MCPS Relay API zuweisen. Es ist bewusst minimal gehalten (nur der Status-Rückkanal), nicht der volle Admin-Zugriff.

S2S-Authentifizierung

Dies ist der einzige etwas aufwendigere Schritt. Er entspricht dem üblichen Service-to-Service-Muster in merchantCENTRAL (vgl. OAuth2 im Hub).

C4 – Schlüssel abrufen

Function-Key (wird in BC am Drucker hinterlegt):

az functionapp keys list -g rg-mcps-relay -n <functionAppName> --query "functionKeys.default" -o tsv

Service-Bus-Listen-SAS (wird in der Agent-Konfiguration hinterlegt):

az servicebus queue authorization-rule keys list -g rg-mcps-relay \
  --namespace-name <serviceBusName> --queue-name print-jobs --name AgentListen \
  --query primaryConnectionString -o tsv

C5 – Drucker in Business Central anlegen (Transport Relay)

  1. In BC nach Print Service Printers suchen → Neu.
  2. Transport Mode auf Relay (Azure Queue) stellen. Die Direkt-Push-Felder (Service URL, API Key) werden ausgeblendet, die Relay-Felder erscheinen.
  3. Felder ausfüllen:
Feld Wert
Code / Description wie bei Direkt-Push
Print Method PDF (Windows-Drucker) oder ZPL (Zebra)
Printer Name Windows-Druckername (PDF) bzw. IP-Adresse (ZPL) – der Agent druckt lokal damit
ZPL Port nur bei ZPL (Standard 9100)
Relay Function URL functionBaseUrl aus dem Deployment (z. B. https://mcpsrelay-func-....azurewebsites.net)
Relay Function Key DrillDown anklicken → Function-Key aus C4 eingeben (verschlüsselt im Credential Store)

C6 – Agent (MC.PrintService) im Agent-Modus starten

In der appsettings.json des in Schritt 1 installierten MC.PrintService den Relay-Abschnitt befüllen und den Dienst neu starten:

"Relay": {
  "Enabled": true,
  "ServiceBusConnectionString": "<Listen-SAS aus C4>",
  "QueueName": "print-jobs",
  "MaxDeliveryCount": 5,
  "StatusCallbackUrl": "<statusUrl aus C1>",
  "StatusCallbackKey": "<Function-Key aus C4>"
}

Der Agent läuft zusätzlich zum HTTP-Listener – eine Instanz kann also Direkt-Push- und Relay-Drucker gleichzeitig bedienen. Die Konfigurationsoberfläche (…/config) zeigt unter „Relay Mode" an, ob der Agent-Modus aktiv ist.

C7 – Testen

In BC ein Etikett auf den Relay-Drucker drucken. Ablauf: Auftrag → Sending → der Agent zieht ihn aus der Queue, druckt und meldet zurück → Printed.

Fehler Ursache Lösung
Job bleibt Sending Agent offline / falsche Listen-SAS Agent-Dienst, Relay:Enabled und Listen-SAS prüfen; nach MaxDeliveryCount Versuchen wird der Job Failed
401 beim Einstellen falscher/fehlender Function-Key Function-Key am Drucker (C5) prüfen
Status erreicht BC nicht Application User/Berechtigung fehlt C3 prüfen (Entra Application + Berechtigungsset ALN MCPS Relay API)

Kosten (trägt der Kunde, in seinem Azure)

Bei 100–1000 Etiketten/Tag bestimmen nicht die Datenmengen die Kosten, sondern die Tarifwahl: mit Service Bus Basic liegen die Gesamtkosten bei unter ~2 €/Monat.

→ Vollständige Setup-Anleitung mit allen Outputs und Fehlerbehebung: azure/README.md im Print-Service-Repository. Architektur, Authentifizierung und Kostenrechnung im Detail: docs/relay-mode-architecture.md.


Teil D: Poll einrichten (BC bleibt passiv)

Der Poll-Modus nutzt dieselbe Azure-Infrastruktur und denselben Agent-Modus wie Relay (Teil C) — nur holt die Function die Aufträge bei BC ab, statt dass BC sie pusht. So macht Business Central keine ausgehenden Webservice-Aufrufe (außer einem optionalen winzigen Wake-Ping). Ideal, wenn in BC kein Outbound-HTTP eingerichtet werden soll.

BC (passiv)  ◀──Poll/Status── Azure Function ──▶ Service Bus Queue
     │  (opt.) Wake-Ping ▲           │ Blob (Label)        │
     └─────────────────────┘         ▼                     ▼
                              Blob Storage    MC.PrintService (Agent) ──▶ Drucker

Unterschiede zu Teil C

Die Einrichtung folgt Teil C (Schritte 1, 2, 4 und 6 identisch), mit drei Abweichungen:

Schritt Bei Poll
Application User (Schritt 3) Berechtigungsset ALN MCPS Poll API zuweisen (statt ALN MCPS Relay API) — die Function braucht hier auch Leserecht auf die Aufträge
Drucker in BC (Schritt 5) Pro Drucker nur Transport Mode = Poll + Druckername. Die Azure-Anbindung wird einmal global unter Print Service Setup → Poll Connection hinterlegt (Function-URL + Function-Key), nicht pro Drucker
Wake-Ping (optional) Lässt man die Poll-Function-URL im Setup leer, bleibt BC zu 100 % passiv — die Function pollt nur über ihren Timer (Standard: alle 5 Min). Mit hinterlegter URL/Key meldet BC „es gibt Arbeit", und der Druck startet sofort

Nebenläufigkeit

Wake-Ping und Timer können gleichzeitig pollen. Ein Blob-Lease stellt sicher, dass immer nur ein Poll-Lauf gleichzeitig arbeitet; zusätzlich beansprucht die Function jeden Auftrag mit optimistischer Sperre (ETag), sodass kein Auftrag doppelt gedruckt wird.

Test

In BC ein Etikett auf den Poll-Drucker drucken. Ablauf: Auftrag → Sending (von der Function beansprucht) → der Agent druckt → Printed. Ohne Wake-Ping kann es bis zum nächsten Timer-Lauf dauern.


Fehlerbehebung

Eine ausführliche Übersicht der häufigsten Probleme finden Sie unter MC.PrintService – Referenz & Fehlerbehebung.

Schnellprüfung:

  1. Dienst läuft? → Windows-Dienste (services.msc) → „MC.PrintService" muss „Running" sein.
  2. Erreichbar?http://localhost:5050/health im Browser → muss Healthy liefern.
  3. Drucker sichtbar?http://localhost:5050/printers listet alle Windows-Drucker.
  4. API-Key gesetzt? → Konfigurationsoberfläche …/config zeigt den Status oben an.

Nächste Schritte