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.
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.
