Search by

tietge / silverstripe-shipping-ups

moritz-sauer-13

UPS-Paketdienst für tietge/silverstripe-shipping — Etiketten über die UPS Shipping API (REST/OAuth).

Package info

git.innomedia.de/Tietge/silverstripe-shipping-ups

Type:silverstripe-vendormodule

pkg:composer/tietge/silverstripe-shipping-ups

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

1.0.0 2026-08-06 08:14 UTC

This package is auto-updated.

Last update: 2026-09-17 08:00:26 UTC


README

UPS für tietge/silverstripe-shipping — Etiketten über die UPS Shipping API v2409 (REST/JSON, OAuth2 Client Credentials).

Handgeschrieben gegen die offizielle Shipping.yaml aus UPS-API/api-documentation. Zwei REST-Aufrufe, keine SDK-Abhängigkeit.

Installation

composer require tietge/silverstripe-shipping-ups
vendor/bin/sake db:build --flush

Braucht einen PSR-18-Client — php-http/guzzle7-adapter genügt.

Zugangsdaten

Der Zugang ist reine Selbstbedienung — kein Antrag, keine Abnahme, keine Wartezeit. Damit ist UPS von den angebundenen Diensten der einzige, der ohne Vertragsvorlauf produktiv nutzbar ist.

  1. Auf developer.ups.com anmelden, Apps → Add Apps.
  2. „I want to integrate UPS shipping capabilities into my business" wählen. Das ist der Schalter für Client Credentials — die andere Variante wäre der Authorization-Code-Fluss für Anwendungen, die im Namen fremder UPS-Konten versenden, und bräuchte eine Callback-URL.
  3. Callback-URL leer lassen. Der Client-Credentials-Fluss kennt keine Redirect-URI.
  4. Produkte: Shipping (Pflicht), Tracking (für später gleich mitnehmen). Rating nicht — der Versandtarif dieses Moduls ist bewusst dienstleisterunabhängig.
Tietge\Shipping\Ups\UpsCarrier:
  sandbox: true
  client_id: ''
  client_secret: ''
  account_number: ''     # 6-stellige „Shipper Number"

Kontonummer ≠ Client ID. Die Client ID identifiziert die App, die Kontonummer das Versandkonto; UPS prüft beide gegeneinander. Sie steht auf ups.com unter „Account Summary" oder oben rechts auf jeder UPS-Rechnung und ist nicht rein numerisch (etwa A1B2C3).

Weitere Schalter

  services: ['11']                    # 11 = UPS Standard (DE/EU-Straßendienst)
  shipment_description: 'Buecher'     # Warenbeschreibung aufs Etikett (Vorgabe: 'Warenlieferung')
  api_version: 'v2409'                # laut Spezifikation der einzige gültige Wert

Weitere Servicecodes, nur wenn vertraglich freigeschaltet: 07 Express, 08 Expedited, 54 Express Plus, 65 Express Saver, 70 Access Point Economy, 74 Express 12:00.

Etikettenformat

Im CMS unter Website-Einstellungen → Shop → Versand → UPS. Beide Wahlmöglichkeiten liefern ein PDF; sie unterscheiden sich in der Seitengröße:

AuswahlSeitengrößeWofür
PDF auf Blatt612 × 792 pt (Letter)Bürodrucker; Etikett sitzt gedreht auf dem Blatt
PDF in Etikettengröße288 × 432 pt = 4 × 6 ZollEtikettendrucker, ohne Skalierung

Zwei Stellen, an denen die Spezifikation danebenliegt

Beide am laufenden Dienst gemessen, beide mit praktischer Wirkung:

1. PDF als Etikettenformat. Das Anfrageschema nennt für LabelImageFormat nur GIF, ZPL, EPL und SPL; PDF steht ausschließlich bei der LabelRecovery-Schnittstelle. Der Versandaufruf nimmt es trotzdem an und liefert ein echtes PDF.

2. LabelStockSize bei PDF. Laut Schema gilt der Block nur für Thermoformate. Tatsächlich entscheidet er auch beim PDF über die Seitengröße — ohne ihn ein Letter-Blatt, mit ihm exakt 4 × 6 Zoll.

Ohne Punkt 1 wäre UPS der einzige Dienst mit GIF-Dateien geworden, und das Basismodul hätte umgebaut werden müssen. Ohne Punkt 2 müsste jeder Etikettendrucker ein Letter-PDF herunterrechnen, was Barcodes unscharf macht.

Kein ZPL im Angebot

UPS kann ZPL, das Modul bietet es nicht an. ZPL ist eine Druckersprache, kein Dokument — ein Browser kann die Steuerbefehle weder anzeigen noch drucken. Damit sie beim Drucker ankommen, braucht es ein Hilfsprogramm auf dem Arbeitsplatz (bei Zebra: Browser Print, localhost:9100), das von Hand je Rechner zu installieren ist, ein bestätigtes Zertifikat verlangt und nur mit Zebra-Druckern funktioniert.

Das Etiketten-PDF erreicht dasselbe Ergebnis ohne all das. Für ein Modul, das auch anderswo laufen soll, ist das der einzige Weg ohne Voraussetzungen.

Testumgebung

wwwcie.ups.com (CIE) — dieselben Zugangsdaten wie produktiv, es unterscheidet sich nur der Host. Kein Antrag, keine getrennte Nutzerverwaltung.

Zwei Dinge sehen dort anders aus und sind kein Fehler:

  • Auf dem Etikett steht „SAMPLE", die Barcodefelder tragen Platzhaltertexte.
  • Die Sendungsnummer kommt als 1ZXXXXXXXXXXXXXXXX zurück.

Weil es keine echten Sendungsnummern gibt, lässt sich das Storno in der CIE nicht prüfen — UPS antwortet mit „No shipment found within the allowed void period" (190102). Produktiv funktioniert es (DELETE /shipments/{version}/void/cancel/{nummer}, bis zum Tagesabschluss).

Eigenheiten

  • Zahlen reisen als Zeichenketten. Weight, Length, Height sind im Schema durchweg type: string; ein echter Zahlwert wird abgewiesen.
  • Gewicht in KGS, Maße in CM. Das Basismodul führt Gramm und Millimeter.
  • Die Kontonummer steht zweimal im Auftrag — als ShipperNumber beim Absender und unter PaymentInformation. UPS trennt „wer versendet" von „wer zahlt".
  • ShipFrom wird mitgeschickt, obwohl es entfallen dürfte: Fehlt es, nimmt UPS die Absenderanschrift und tarifiert von dort.
  • Ein fehlendes api_version erzeugt einen nackten 404 — die Fassung steckt im Pfad. Das Modul hat dafür einen harten Rückfall.