Zum Inhalt springen

Eine QuickBooks-Integration, die keine Felder löscht

QuickBooks Online ersetzt bei einem Update das ganze Objekt, wenn man nichts anderes sagt, und jeder Datensatz trägt eine Version, die man zurücksenden muss. Beides landet im Formular.

5 Min. Lesezeit

Eine QuickBooks-Online-Integration geht live. Eine Woche später merkt ein Kunde, dass bei einem Lieferanten die Rechnungsadresse, die Zahlungsbedingungen und der Steuerschlüssel fehlen. Niemand hat sie gelöscht. Jemand hat über ein Formular in Ihrer Anwendung die E-Mail-Adresse des Lieferanten geändert.

Das ist das Erste, was man über diese API wissen muss, und es reicht am weitesten ins Frontend.

Ein Update ist ein Ersetzen

Die meisten APIs behandeln den Body einer Anfrage als die Felder, die man ändern will. QuickBooks Online behandelt ihn standardmäßig als das Objekt, das der Datensatz danach sein soll. Was fehlt, ist nicht unverändert - es ist leer.

Ein Formular in einer Next.js-Anwendung ist genau das, was in diese Falle läuft. Die Bearbeitungsmaske kennt drei Felder, weil drei Felder geändert werden sollen. Die Server Action bekommt drei Felder und sendet drei Felder. Die Buchhaltung hat jetzt einen Lieferanten mit drei Feldern.

Es gibt zwei Absicherungen, und beide lohnen sich. Die Anfrage kann erklären, dass sie ein Teil-Update ist - ein Parameter am Aufruf, nichts Raffiniertes. Und der Handler kann den aktuellen Datensatz lesen, die Änderung darauf anwenden und das Ganze zurücksenden, sodass die Nutzlast vollständig ist, unabhängig davon, wie die API sie auslegt.

Das Zweite kostet einen Roundtrip. Es bedeutet aber auch, dass das Verhalten nicht davon abhängt, ob jemand an ein Flag denkt - und das ist in Code, der jemandes Buchhaltung anfasst, ein guter Tausch.

Die Version gehört ins Formular

Jeder Datensatz in QuickBooks Online trägt eine Version. Ein Update muss die Version mitsenden, auf der es beruht, und hat sich der Datensatz seitdem geändert, wird das Update abgelehnt.

Das ist richtig und das gewünschte Verhalten. Es ist zugleich eine Anforderung, die am Formular landet und nicht am API-Client, und genau dort machen Teams den Fehler.

Die Seite lädt einen Datensatz in Version 7 und rendert ein Formular. Die Person tippt vier Minuten. Währenddessen bearbeitet jemand aus der Buchhaltung denselben Datensatz in QuickBooks, und er wird Version 8. Das Formular schickt Version 7 und wird abgewiesen.

Die falsche Reaktion ist, das abzufangen, die aktuelle Version zu holen und erneut zu senden - denn das verwirft stillschweigend die Änderung der Buchhaltung. Die richtige ist, der Person zu sagen, was passiert ist, und zu zeigen, was sich geändert hat. Also muss die Version Teil des Formularzustands sein, durch die Server Action mitgeführt werden, und der Konflikt muss ein sichtbares Ergebnis sein statt einer Exception in einem Log.

Das ist nützlicherweise genau das Muster für optimistische Konkurrenz, das jedes Mehrbenutzer-Formular braucht. Die Buchhaltungs-API macht es nur verbindlich.

Wo die Teile der Integration tatsächlich liegen

Die Architekturfrage ist dieselbe wie bei jeder Buchhaltungsintegration, und die Antworten lohnen die Wiederholung, weil QuickBooks eine Besonderheit hinzufügt.

Der Autorisierungs-Callback ist ein Route Handler. Zusammen mit dem Autorisierungscode liefert QuickBooks die Kennung der autorisierten Firma, und beides muss in dieser einen Anfrage erfasst werden - der Code ist nutzlos, wenn man nicht weiß, zu welcher Firma er gehört. Der state-Parameter muss geprüft und nicht nur gelesen werden, denn das verhindert, dass die Autorisierung eines Fremden am Konto Ihres Nutzers landet.

Die Tokens gehören in eine Tabelle mit dieser Firmenkennung als Schlüssel. Nicht an den Nutzer, nicht in ein Cookie, nicht in etwas, das ein Client-Component erreichen kann. Eine Person kann mehrere Firmen autorisieren, womit die Verbindung der Datensatz ist und der Nutzer eine Referenz darauf.

Gewöhnliche Lese- und Schreibzugriffe gehören in Server Actions und Server-Components, wo die Zugangsdaten liegen und der Browser sie nie sieht.

Die lange Arbeit gehört nicht dorthin. Eine Server Action ist eine Anfrage mit einem Timeout, und ein Erstimport, ein Abstimmungslauf oder ein Nachlauf ist keine Anfrage. Das geht in eine Queue: die Server Action erzeugt einen Job-Datensatz, kehrt sofort zurück, und die Seite zeigt den Fortschritt. Das ist der häufigste strukturelle Fehler in diesen Integrationen und in der Entwicklung unsichtbar, wo die Testfirma elf Rechnungen hat.

Webhooks nennen die Kennung und sonst nichts

Ein QuickBooks-Webhook kommt an einem Route Handler an, ist signiert und sagt, dass sich eine Entität eines bestimmten Typs mit einer bestimmten Kennung geändert hat. Er sagt nicht, was sich geändert hat oder was der Datensatz jetzt enthält.

Also prüft der Handler die Signatur, schreibt die Benachrichtigung weg, kehrt schnell zurück, und ein Job holt den Datensatz danach. Das Holen inline zu machen heißt, dass die Antwortzeit Ihres Webhook-Endpunkts eine Funktion der Antwortzeit der Buchhaltungs-API ist - und eine langsame API wird zu fehlgeschlagenen Zustellungen.

Die Benachrichtigung kann auch zweimal kommen, und sie kann relativ zu Ihrer eigenen Änderung in der falschen Reihenfolge kommen. Beides ist normal. Dass der Handler gefahrlos zweimal laufen kann - und eine Benachrichtigung zu einer Version ignoriert, die er schon hält - ist der Unterschied zwischen einer Synchronisation, die konvergiert, und einer, die schwingt.

Der Kundenabgleich ist das Projekt

Die technische Arbeit oben ist zwei Wochen. Die restliche Zeit geht an eine Stelle, die nicht nach Entwicklung aussieht.

QuickBooks verlangt, dass der Anzeigename eines Kunden innerhalb einer Firma eindeutig ist. Damit sind „Acme GmbH" in Ihrer Anwendung und „Acme Gmbh" in der Buchhaltung zwei verschiedene Kunden und bleiben es, bis jemand entscheidet, welcher welcher ist. Das mal zweitausend Datensätze und ein Jahrzehnt inkonsistenter Erfassung.

Dieser Abgleich - welche Seite einen Namen besitzt, was mit den Fast-Duplikaten passiert, welches Feld der Schlüssel ist - ist ein Gespräch mit der Buchhaltung und keine Entwicklungsschätzung. Teams, die ihn als Datenimportproblem behandeln, entdecken ihn drei Wochen vor dem Launch.

Wann man das nicht baut

Wenn die Anforderung ist, dass Rechnungen in QuickBooks erscheinen und nichts zurückfließt, und das Volumen bei Dutzenden pro Monat liegt, macht ein fertiger Connector das heute Nachmittag gegen eine Gebühr. Eine zweiseitige Integration lohnt sich, wenn das Mapping für Ihr Geschäft spezifisch ist, wenn das Volumen manuelle Korrektur teuer macht, oder wenn die Daten in Ihrem eigenen System liegen müssen, um nützlich zu sein.

Sie lohnt sich nicht, um eine kleine monatliche Gebühr zu vermeiden. Die Zeit geht in die Abstimmungsregeln, und die werden nicht billiger, weil Sie den API-Client selbst geschrieben haben.

Verwandte Fragen

Warum hat das Ändern einer E-Mail-Adresse die Anschrift gelöscht?
Weil QuickBooks Online ein Update als Ersetzen des gesamten Objekts behandelt, solange die Anfrage nichts anderes sagt. Ein Formular, das drei Felder kennt, sendet drei Felder, und alles Fehlende fehlt danach auch in der Buchhaltung. Die Lösung ist, das Update ausdrücklich als Teil-Update zu senden, und die sicherere Angewohnheit darüber hinaus ist, den aktuellen Datensatz zu lesen, die Änderung darauf anzuwenden und das Ergebnis zu senden - dann ist die Anfrage vollständig, wie auch immer die API sie auslegt.
Wozu dient der SyncToken?
Er ist die Version des Datensatzes, und ein Update muss die Version mitsenden, auf der es beruht. Hat jemand den Datensatz in QuickBooks geändert, seit Ihre Seite ihn geladen hat, ist Ihr Token veraltet und das Update wird abgelehnt - was richtig ist und genau das, was man will. Für das Frontend heißt das, dass ein Bearbeitungsformular die geladene Version mitführen und einen echten Konflikthinweis zeigen muss, statt den Token neu zu holen und die Änderung des anderen zu überschreiben.
Kann eine Server Action die ganze Synchronisation machen?
Nur wenn sie innerhalb einer Anfrage fertig wird. Eine Server Action ist eine Anfrage, also gehört alles, was in Minuten gemessen wird - ein Erstimport, eine vollständige Abstimmung, ein Nachlauf - in eine Queue, die von der Server Action gestartet wird. Das Muster, das trägt - ein Job-Datensatz wird sofort erzeugt, eine Seite zeigt den Fortschritt, und die lange Arbeit läuft dort, wo kein Timeout sie auf halbem Weg beendet.
Wo liegen die Tokens?
Nur serverseitig, in einer Tabelle mit der autorisierten Firma als Schlüssel, nie in einem Cookie, das der Browser lesen kann, und nie in etwas, das ein Client-Component berührt. Ein Login kann mehr als eine Firma autorisieren, also ist die Verbindung das zu speichernde Objekt und nicht der Nutzer. Das ist dieselbe Form wie bei jeder Buchhaltungsintegration und der Grund, warum es eine Tabelle und nicht zwei Spalten an einem Nutzer ist.

← Zurück zu allen Artikeln

Anrufen+1 848 272 7583WhatsApp+90 850 308 5436E-Mailinfo@codefacture.comKontaktseite