Zum Inhalt springen

Stripe in Laravel: die Zahlung modellieren

Eine Zahlung ist ein Zustandsautomat mit zwei geldbewegenden Ereignissen, kein Boolean an der Bestellung. Was das für Ihr Schema heißt und wo Cashier aufhört.

5 Min. Lesezeit

Die meisten Stripe-Integrationen beginnen mit einem SDK-Aufruf und einer Spalte namens paid. Sie funktionieren etwa vier Monate, was ungefähr so lange dauert, bis die erste Teilerstattung kommt, die erste Rückbuchung, oder die erste Bestellung, bei der die Bank des Kunden eine Authentifizierung verlangte und der Kunde nie zurückkam.

Das Problem ist nie die API. Es ist, dass eine Zahlung als etwas modelliert wurde, das passiert ist, während sie etwas ist, das noch passiert.

Was Sie integrieren, ist ein Zustandsautomat

Ein PaymentIntent durchläuft Zustände: er braucht eine Zahlungsart, er braucht eine Handlung des Kunden, er wird verarbeitet, er war erfolgreich, er wurde abgebrochen. Mehrere dieser Übergänge steuert eine Bank und nicht Ihr Code, und manche dauern Minuten.

Daraus folgt eine Sache für Ihr Schema, und das ist der ganze Artikel in einem Satz: Ihre Zahlungszeile hält einen Status, kein Flag. Ist die Spalte ein Boolean, dann fallen "der Kunde steht gerade im 3-D-Secure-Dialog", "die Bank hat abgelehnt" und "das Geld ist autorisiert, aber nicht eingezogen" alle in false zusammen, und Ihr Support kann sie nicht unterscheiden.

Modellieren Sie die Zustände, auf die Sie tatsächlich reagieren. Die meisten Unternehmen brauchen fünf oder sechs: Handlung erforderlich, in Verarbeitung, autorisiert, eingezogen, fehlgeschlagen, abgebrochen. Geben Sie dem ein echtes Enum und machen Sie die Übergänge explizit - der Sinn einer Statusspalte ist, dass unzulässige Züge abgelehnt werden, nicht dass ein String überschrieben wird.

Autorisierung und Einzug sind zwei Ereignisse

Eine Kartenzahlung kann Geld reservieren, ohne es zu nehmen. Die Autorisierung hält den Betrag ein paar Tage, der Einzug ist der getrennte Akt, ihn tatsächlich zu kassieren. Stripe bildet das als capture_method: manual ab.

Wer Ware versendet, braucht das, denn Geld für etwas zu nehmen, das noch nicht verschickt ist, ist eine Erstattung mit Anlauf, und in manchen Rechtsordnungen zusätzlich ein regulatorisches Problem. Wer eine Leistung mit Anzahlung verkauft, braucht es. Wer einen Marktplatz betreibt, braucht es.

Fürs Schema heißt das: autorisierter Betrag und eingezogener Betrag sind verschiedene Spalten, und sie sind häufig verschiedene Zahlen. Sie autorisieren den vollen Warenkorb, dann ist ein Artikel nicht lieferbar, dann ziehen Sie weniger ein. Ein Bestellmodell mit einem amount kann das nicht ausdrücken, und es später nachzurüsten heißt Migration über jede historische Zeile, während die Buchhaltung wartet.

Außerdem: Eine Autorisierung verfällt. Zieht niemand innerhalb des Fensters ein, fällt die Reservierung weg und das Geld ist außer Reichweite. Das ist ein geplanter Job, der nach auslaufenden Autorisierungen sucht, und Stripe erinnert Sie nicht daran.

Eine Karte zu speichern heißt nicht, eine Karte zu speichern

Wenn ein Kunde "Karte merken" anhakt, speichern Sie nichts. Sie legen einen Nachweis über eine Erlaubnis an, und diese Erlaubnis hat Bedingungen: wofür Sie belasten dürfen, ob der Kunde anwesend sein muss, und ob seine Bank erneut eine Authentifizierung will.

Stripe trennt das in SetupIntent zum Einholen der Erlaubnis und off_session-Belastungen zur Nutzung. Die Unterscheidung zählt, weil eine Off-Session-Belastung mit der Forderung nach Authentifizierung fehlschlagen kann

  • und es ist kein Kunde da, der sich authentifizieren könnte. Ihr Code muss eine Zahlung behandeln, die auf eine Weise scheiterte, an der niemand schuld ist und die man mit einer E-Mail an den Kunden löst.

Hier landen auch die europäischen Regeln. Unter SCA muss eine unbeaufsichtigte Belastung unter eine Ausnahme fallen oder eine vorherige Vereinbarung tragen, was praktisch heißt: das Mandat muss beim Speichern der Karte korrekt eingerichtet worden sein. Das falsch zu machen ist unsichtbar, bis die Fehlerquote bei Ihren Verlängerungen bei fünfzehn Prozent liegt und niemand weiß, warum.

Wo Cashier aufhört

Cashier ist gute Software und eine Abo-Bibliothek. Wenn Sie Pläne mit Monats- und Jahresoption verkaufen, bringt sie den Lebenszyklus, die anteilige Rechnerei, die Kulanzfristen und die Rechnungsdatensätze mit, und das selbst zu schreiben ist ein verlorener Monat.

Sie deckt keine Einmalzahlungen mit manuellem Einzug ab, keine Marktplatz-Aufteilungen, keine mehrseitige Auszahlung und keinen Checkout, dessen Betrag sich aus einem veränderlichen Warenkorb ergibt. Das ist das SDK direkt, und das ist erwartbar und kein Versagen der Bibliothek.

Der zu vermeidende Fehler ist, Cashiers Tabellen für Ihr Zahlungsmodell zu halten. Sie beschreiben Abonnements. Ihre Bestellungen, Ihre Einzüge, Ihre Erstattungen und Ihre Gebühren gehören Ihnen und müssen existieren, ob ein Abo im Spiel ist oder nicht.

Die Zeile, die Sie wirklich brauchen

Mindestens, je Zahlungsversuch:

  • Ihre eigene Kennung und die des Anbieters, indiziert.
  • Status als Enum, mit dem Zeitstempel des letzten Übergangs.
  • Autorisierter, eingezogener und erstatteter Betrag - drei Ganzzahlen in der kleinsten Einheit der Währung, so wie Geld immer gespeichert gehört.
  • Der Währungscode, getrennt.
  • Die Gebühr, sobald Sie sie kennen, denn Ihr Umsatz ist nicht das, was der Kunde gezahlt hat.
  • Der Idempotenzschlüssel, den Sie gesendet haben.
  • Ein Fremdschlüssel auf das, wofür gezahlt wird.

Die letzten beiden leisten mehr, als sie aussehen. Der Idempotenzschlüssel verhindert, dass ein wiederholter Job zweimal belastet, und die Queue darunter wird wiederholen. Stripe nimmt den Schlüssel bei jeder verändernden Anfrage an und gibt die ursprüngliche Antwort zurück, statt erneut zu belasten - aber nur, wenn Sie einen senden, und nur, wenn er aus dem Versuch abgeleitet und nicht frisch erzeugt ist.

Was zuerst gebaut wird

Bauen Sie den Zustandsautomaten und den Webhook-Empfänger vor dem Checkout-Bildschirm. Der Bildschirm ist ein Nachmittag; die Zustände sind das System. Ein Checkout, der perfekt aussieht und den Erfolg aus der Rückleitung meldet, ist die Variante, die still Bestellungen verliert, denn die Rückleitung sagt Ihnen nicht, dass eine Zahlung erfolgreich war.

Dann gleichen Sie ab. Fragen Sie Stripe einmal täglich nach allem, was sich geändert hat, und vergleichen Sie es mit Ihren Zeilen. Nicht weil die Webhooks unzuverlässig wären, sondern weil Sie wissen wollen, wenn etwas auseinandergelaufen ist, und die einzige Alternative ist, es vom Kunden zu erfahren.

Wir machen diese Arbeit als Teil von E-Commerce-Projekten und für sich, und die erste Frage ist immer dieselbe: Autorisierung und Einzug zusammen oder getrennt? Die Antwort verändert das Schema, und sie ist in Woche eins leichter zu geben als in Monat sechs.

Verwandte Fragen

Cashier oder das Stripe-SDK direkt?
Cashier, wenn Sie wiederkehrende Pläne mit einigermaßen üblicher Form verkaufen, denn es bringt Abo-Lebenszyklus, anteilige Abrechnung und Rechnungsverwaltung mit, die Sie sonst schlecht selbst schreiben. Das SDK direkt für Einmalzahlungen, Marktplätze, geteilte Auszahlungen oder alles, wo Sie jetzt autorisieren und später einziehen. Beides zu mischen ist normal und in Ordnung.
Können wir einfach das Stripe-Objekt speichern und bei Bedarf abfragen?
Nein, und das ist die teuerste Abkürzung in diesen Projekten. Stripe ist nicht Ihre Datenbank - es begrenzt Anfragen, es fällt aus, und eine Seite mit der Bestellhistorie eines Kunden darf nicht davon abhängen. Führen Sie eine eigene Zeile mit eigenem Status, behandeln Sie Stripe als führendes System für Geldbewegungen, und gleichen Sie beides bewusst ab.
Wo legen wir den Betrag ab?
Als Ganzzahl in der kleinsten Einheit der Währung, mit dem Währungscode als eigener Spalte - so hält es Stripe auch. Niemals als Fließkommazahl. Und auch nicht als einen einzigen Betrag: eingezogener Betrag, erstatteter Betrag und Gebühr sind drei verschiedene Zahlen, die beim ersten Teilstorno auseinanderlaufen.
Brauchen wir dafür eine PCI-Zertifizierung?
Nicht, solange Kartendaten Ihren Server nie erreichen, und genau dafür gibt es Stripe Elements oder eine gehostete Bezahlseite. Die Karte wird im Browser direkt bei Stripe tokenisiert, Ihre Anwendung sieht nur eine Kennung. Sobald eine Kartennummer Ihre Anwendung berührt, in einer Logzeile oder einem Formularfeld, ändert sich das vollständig.

← Zurück zu allen Artikeln

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