Aufspaltung des Zahlungs-POC: Architektur- und Design-Entscheidungen

Auf dieser Seite werden die architektonischen Optionen hinter dem aufgeteilten Zahlungsnachweis des Konzepts erläutert. Lesen Sie es, bevor Sie die Build-Eingabeaufforderungen in dieser Reihe verwenden, damit Sie verstehen, wie jede Komponente strukturiert ist und wie Sie die Muster in Ihrem eigenen Projekt anpassen können.

Das Grundprinzip

Bei dem Machbarkeitsnachweis geht es nicht um die eleganteste Split-Zahlungsimplementierung. Es geht darum zu zeigen wie man ohne eine Big-Bang-Umschreibung mit der Umstellung der Commerce-Logik auf App Builder.

Die Regel, die durchgängig angewendet wird, lautet:

Wenn etwas synchron im Commerce-Anfragezyklus laufen muss oder Commerce-interne APIs aufrufen muss, die keine saubere externe Oberfläche haben, bleibt es in PHP. Alles andere wandert nach App Builder.

Was lebt in Commerce (PHP) und warum

​1. Kreditantrag speichern: PlaceOrderPlugin

Store-Guthaben wird mit Magento\CustomerBalance\Api\BalanceManagementInterface::apply() auf den Warenkorb angewendet. Diese Methode funktioniert nur für einen aktiven Warenkorb. Der Warenkorb wird zum Zeitpunkt der Bestellung inaktiv. App Builder erhält das E/A Ereignis (nachdem die Bestellung aufgegeben wurde. Daher ist es nicht möglich, eine Gutschrift von App Builder zu beantragen.

Die Lektion Alles, was den Warenkorbstatus vor der Bestellplatzierung ändern muss, muss in Commerce ausgeführt werden. Es gibt keine Problemumgehung.

​2. Synchroner Schwellenwertwächter: CheckoutPlugin

Die Prüfung des Bestellschwellenwerts von 100 USD muss den Kunden bei der Zahlungsstufe blockieren, bevor er Place Order auswählt. Die Antwort muss im Commerce-Anfragezyklus synchron sein. App Builder ist ereignisgesteuert und asynchron, sodass in diesem Moment kein sofortiger Fehler zurückgegeben werden kann.

App Builder auch validiert den Schwellenwert (als Audit), aber das Kundenerlebnis hängt davon ab, dass die Commerce-Prüfung zuerst ausgeführt wird.

​3. Benutzerdefinierte REST-Endpunkte: webapi.xml und SplitPaymentManagement

Die folgenden Endpunkte müssen:

  • SplitInvoiceService aufrufen (Rechnungen, die den internen Rechnungsdienst von Commerce verwenden)
  • ShipOrder::execute() aufrufen (interner Versand-Service von Commerce)
  • Status und Status der Bestellung mit dem Auftragsstatus-Computer von Commerce aktualisieren

/V1/split-payment/orders/:id/cash-received und /V1/split-payment/orders/:id/cash-decline

Es gibt keine saubere öffentliche REST-Ebene für dieses Verhalten, sodass Commerce die Endpunkte verfügbar macht. App Builder nennt sie.

​4. Beträge nach Angebot und Bestellung aufteilen: Beobachter und Plug-ins

Commerce benötigt die aufgeteilten Beträge (split_store_credit_amount, split_cash_amount, split_cash_status) für die Bestellung, sowohl für die REST-Antworten, die App Builder liest, als auch für die Admin. Die Beträge werden mit Erweiterungsattributen angehängt und in einem Beobachter auf sales_model_service_quote_submit_before aus dem Angebot in den Auftrag kopiert.

Was lebt in App Builder und warum

​1. Ereignisgesteuerte Auftragsverarbeitung: payment-orchestrator

Nachdem sales_order_place_before ausgelöst wird, erhält App Builder das Ereignis. Er überprüft den Schwellenwert erneut (als Audit), zeichnet einen Kassenantrag Kommentar zur Bestellung auf und aktualisiert den Bestellstatus. Nichts davon erfordert neues PHP, nur REST zurück in Commerce.

​2. Barakzept: payment-accept

Wenn ein ERP (oder ein Benutzer im Dashboard) den Empfang von Bargeld bestätigt, werden payment-accept Anrufe POST /V1/split-payment/orders/:id/cash-received. Rechnung, Versand und Auftragsstatus werden in Commerce abgewickelt. App Builder ist der Trigger.

​3. Kassenrückgang: payment-decline

payment-decline ruft POST /V1/split-payment/orders/:id/cash-decline auf und Commerce storniert die Bestellung. Das gleiche Muster wie Barakzepte.

​4. Benutzer-Dashboard: demo-dashboard

Ein eigenständiges HTML-Dashboard, das von einer App Builder-Web-Aktion bereitgestellt wird. Es ruft Bestellungen, die auf Bargeld warten, aus Commerce REST ab und bietet Accept-/Decline-Aktionen, die die oben genannten App Builder-Aktionen aufrufen. Commerce Admin ist nicht erforderlich.

Der Schwellenwert: zweimal absichtlich erzwungen

Customer at checkout
        |
        v
[Commerce: CheckoutPlugin]     <- Synchronous, blocks immediately, user sees error
        |
        |  (if somehow bypassed: direct API call, and so on)
        v
[Order placed] -> I/O Event -> [App Builder: payment-orchestrator]
                                        |
                                        v
                              [evaluateThreshold()]  <- Async audit, records failure comment

Commerce steuert den für Benutzende gerichteten Schutz; App Builder steuert die Prüfung nach der Platzierung. Das ist Absicht.

Der Store-Abspann: Warum es in PHP bleibt

What you might think would work (it does not):
  Order placed -> I/O Event -> App Builder -> PUT /V1/carts/:id/store-credit
  (Fails: cart is inactive after place order)

What actually works:
  AroundPlaceOrder plugin
  -> BalanceManagementInterface::apply($cartId, $amount)  <- cart is still active
  -> place order
  -> order placed
  -> I/O event: App Builder (store credit is already applied)

Die store-credit.js Datei im Orchestrator dokumentiert dies. Es ist ein No-op-Stub mit Kommentaren, die erklären, warum es nicht verwendet wird.

Erweiterungsattribute: der Kleber

Aufspaltungsbeträge bewegen sich durch das System bei Erweiterungsattributen:

Checkout JavaScript (Knockout)
    |  POST /V1/split-payment/set
    v
SplitPaymentSession (PHP session)
    |  AroundPlaceOrder reads the session
    v
CartInterface extension attributes
    |  `sales_model_service_quote_submit_before` observer
    v
OrderInterface extension attributes -> `sales_order` flat columns
    |  I/O event payload includes these fields
    v
App Builder `payment-orchestrator` reads the split amounts

Datenmodell

sales_orderflache Spalten, die dieses Modul hinzufügt

Spalte
Typ
Zweck
split_store_credit_amount
floaten
Angewandte Gutschrift speichern
split_cash_amount
floaten
Fälliger Barbetrag
split_cash_status
varchar
pending, received oder declined
split_sc_invoice_id
int
Entitäts-ID der Filialgutschrift-Rechnung
split_cash_invoice_id
int
Entitäts-ID der Kassenrechnung

Erweiterungsattribute (in CartInterface, OrderInterface und OrderPaymentInterface)

  • split_store_credit_amount (float)
  • split_cash_amount (float)
  • split_cash_status (Zeichenfolge)

Payload-Felder des I/O-Ereignisses

observer.sales_order_place_before wird in io_events.xml konfiguriert, um Folgendes in das Ereignis einzuschließen:

entity_id, quote_id, increment_id, subtotal,
split_store_credit_amount, split_cash_amount, split_cash_status

App Builder verwendet entity_id als Auftrags-ID und split_store_credit_amount und split_cash_amount für die Schwellenwertvalidierung.

Die fünf Randfälle des Konzeptnachweises umfassen

1. CapCustomerBalanceCollectPlugin

Der native Customer balance-Gesamt-Collector von Commerce kann zu viel anwenden (er kann den vollständigen verfügbaren Saldo sehen, nicht den sitzungsdeklarierten Aufspaltungsbetrag). Dieses Plug-in begrenzt den Betrag auf den in der Sitzung deklarierten Wert.

2. FixSplitPaymentGrandTotalPlugin

Nachdem das Store-Guthaben angewendet wurde, kann der Grand Total auf den bargeldlosen Betrag fallen. Die Checkout-JavaScript muss die Bestellsumme für die Aufspaltungsvalidierung () diese Änderung berechnen. Das Plug-in wird nach der Gesamterfassung ausgeführt und korrigiert die Anzeige, während der JavaScript grand_total nicht vertraut und den Wert aus Zwischensummensegmenten rekonstruiert.

3. FixInvoiceCustomerBalanceAfterTotalsPlugin

Wenn die Rechnungssummen zurückgezogen werden, kann die Gutschrift des Geschäfts zweimal vorgenommen werden. Dieses Plug-in korrigiert customer_balance_amount auf Rechnungen.

4. SplitPaymentZeroTotalPlugin

Nachdem die Gutschrift für den Store angewendet wurde, kann die Grand Total für den Warenkorb $0 sein (vollständige Gutschrift für den Store). Die Zero subtotal checkout von Commerce kann in diesem Fall Code blockieren. Dieses Plug-in ermöglicht COD, wenn der Barbetrag der Sitzung größer als 0 ist.

​5. Erinnerung vor BalanceManagementInterface::apply() zitieren

apply() vergleicht den Betrag mit dem aktuellen Grand Total. Wenn die Summe bereits nur der Cash-Teil ist, kann apply() fehlschlagen oder die Obergrenze einschränken. PlaceOrderPlugin setzt die Gesamtreparatur vorübergehend aus, während der Saldo angewendet wird, mithilfe eines Sitzungs-Flags (beginBalanceApply / endBalanceApply).

Alle Ressourcen in dieser Reihe

Referenzressourcen

recommendation-more-help
commerce-learn-help-home