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)
- ZIP-Paket entpacken.
Install.batdoppelklicken → UAC-Dialog bestätigen.- Das Skript installiert den Dienst, richtet die Autostart- und Firewall-Regel ein und generiert automatisch einen API-Key, der am Ende angezeigt wird.
- 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
- In BC nach Print Service Printers suchen → Neu.
- 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) |
- 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.
- 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. - In Business Central nach Microsoft Entra Applications suchen → Neu → die Client Id eintragen, State = Enabled.
- Dem Eintrag das Berechtigungsset
ALN MCPS Relay APIzuweisen. 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)
- In BC nach Print Service Printers suchen → Neu.
- Transport Mode auf Relay (Azure Queue) stellen. Die Direkt-Push-Felder (Service URL, API Key) werden ausgeblendet, die Relay-Felder erscheinen.
- 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:
- Dienst läuft? → Windows-Dienste (
services.msc) → „MC.PrintService" muss „Running" sein. - Erreichbar? →
http://localhost:5050/healthim Browser → mussHealthyliefern. - Drucker sichtbar? →
http://localhost:5050/printerslistet alle Windows-Drucker. - API-Key gesetzt? → Konfigurationsoberfläche
…/configzeigt den Status oben an.
Nächste Schritte
- Drucker verwalten – Druckerliste, Status, Fallback
- Routing-Regeln – Druckaufträge automatisch dem richtigen Drucker zuweisen
- Print Subscriptions – automatischer Druck nach Buchungsvorgängen
- Einrichtung (Referenz) – alle Felder der Setup-Seite
- MC.PrintService – Referenz – Endpunkte, Konfiguration, Fehlerbehebung