Magento 2 REST API Checkout Zahlungsgateway-Weiterleitung

7

Ich erstelle einen Magento 2-Shop, der virtuelle Produkte verkauft. Diese Website hat ihre Kasse direkt auf der Produktseite. Die Kunden werden niemals mehr als ein Produkt gleichzeitig kaufen.

Diese Kaufabwicklung ajax callsrichtet sich an die REST-APIs für die Schritte beim Kauf.

Bisher kann ich einen neuen Warenkorb erstellen, ein Produkt hinzufügen, eine Rechnungsadresse festlegen, eine Zahlungsmethode festlegen, Summen sammeln und eine Bestellung aufgeben. ABER! Eine der von uns verwendeten Zahlungsmethoden ist ein externes Kreditkarten-Gateway . Ich habe hierfür ein benutzerdefiniertes Zahlungsmethodenmodul erstellt, das über die APIs eingestellt werden kann. Die Antwort, die ich vom "placeOrder()"API-Aufruf erhalte, enthält jedoch nur die Bestellung entity_id.

Meine Intuition sagt mir, dass ein solcher API-Aufruf je nach Zahlungsmethode der Antwort etwas hinzufügen würde, um dem Frontend mitzuteilen, dass eine Umleitung stattfinden sollte.

Ich habe wahrscheinlich etwas verpasst, vielleicht einen API-Aufruf, der vorher getätigt werden sollte, um die placeorderZahlung zu verarbeiten, und dann im Falle einer Umleitung über placeorderdie Rückruf-URL?

Hat jemand eine Idee, wie das gemacht werden soll?

nenne
quelle
Die Antwort von placeOrderwird nur die Bestellnummer enthalten, nichts abhängig von der Zahlungsmethode.
Alex Paliarush
1
Ich weiß, aber wo im Fluss wäre der logische Ort, um Anmeldeinformationen für Zahlungsmethoden zu laden und sie an den Javascript-Client zu senden? Damit kann die ordnungsgemäße Nachanforderung an die Zahlungsmethode erfolgen. Nach Bestellung oder vorher? Hat Magento einen API-Aufruf speziell für einen Thin wie diesen oder sollte ich meinen eigenen schreiben?
Nenne

Antworten:

3

Die Tatsache, dass dieser Endpunkt das Ergebnis des Aufrufs als einzelnes int anstelle von mindestens einem Objekt mit Auftrags-ID und Erweiterungsattribut definiert, ist schrecklich und wird sich wahrscheinlich nicht ändern. Wir werden sehen, was das Magento-Team für 2.3 erwartet, wenn es seine eigene PWA einführt und hoffentlich einen neuen Endpunkt mit besserer Unterstützung für Erweiterungen von Drittanbietern erstellt. Im Moment gibt es jedoch zwei Möglichkeiten:

Angenommen, Sie stellen eine Anfrage an /V1/guest-carts/:cartId/payment-informationoder /V1/carts/mine/payment-informationSie können:

  1. Wenn für Ihr Zahlungsgateway eine GETUmleitung erforderlich ist, haken Sie einfach nach Magento\Checkout\Api\PaymentInformationManagementInterface::savePaymentInformationAndPlaceOrder()und legen Sie die Umleitungs-URL entsprechend Ihren Anforderungen fest. Magento sollte den Weiterleitungsheader erkennen.

  2. Wenn Ihre Umleitung tatsächlich eine POSTAnforderung sein muss, müssen Sie die Definition des Endpunkts überschreiben und eine eigene Schnittstelle bereitstellen, die ein vernünftigeres Ergebnis deklariert, das Sie im Browser verarbeiten können. Dies erfordert jedoch, dass auch native Magento-Klassen abgedeckt werden. Wenn Sie an dem Projekt für einen einzelnen Client arbeiten, funktioniert dies möglicherweise.

Erstellen Sie Ihr eigenes Modul, dh. Vendor_CheckoutExtals separates Komponistenmodul oder in app/code/Vendor/CheckoutExt. Stellen Sie sicher, dass Sie Magento_Checkoutdem sequenceTag hinzufügen , module.xmldamit Ihre Definition nach Magento 1 gelesen wird.

In etc/webapi.xmlsetzen Sie eine Definition wie:

<route url="/V1/carts/mine/payment-information" method="POST">
    <service class="Vendor\CheckoutExt\Api\PaymentInformationManagementInterface" method="savePaymentInformationAndPlaceOrder"/>
    <resources>
        <resource ref="self" />
    </resources>
    <data>
        <parameter name="cartId" force="true">%cart_id%</parameter>
    </data>
</route>

Erstellen Sie eine Schnittstelle Vendor\CheckoutExt\Api\PaymentInformationManagementInterface, die so aussieht

namespace Vendor\CheckoutExt\Api;

use Magento\Checkout\Api\PaymentInformationManagementInterface as MagentoPaymentInformationManagementInterface;

interface PaymentInformationManagementInterface extends MagentoPaymentInformationManagementInterface
{

    /**
     * Set payment information and place order for a specified cart.
     *
     * @param int $cartId
     * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod
     * @param \Magento\Quote\Api\Data\AddressInterface|null $billingAddress
     * @throws \Magento\Framework\Exception\CouldNotSaveException
     * @return \Vendor\CheckoutExt\Api\Data\ResultInterface place order result data.
     */
    public function savePaymentInformationAndPlaceOrder(
        $cartId,
        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
        \Magento\Quote\Api\Data\AddressInterface $billingAddress = null
    );
}

Erstellen Sie nun eine Schnittstelle für die Antwort

namespace Vendor\CheckoutExt\Api\Data;

interface ResultInterface
{
    /**
     * @param string $orderId
     * @return Vendor\CheckoutExt\Api\Data\ResultInterface 
     */
    public function setOrderId($orderId);

    /**
     * @return string
     */
    public function getOrderId();

    /**
     * Retrieve existing extension attributes object or create a new one.
     *
     * @return Vendor\CheckoutExt\Api\Data\ResultInterface 
     */
    public function getExtensionAttributes();

    /**
     * Set an extension attributes object.
     *
     * @param Vendor\CheckoutExt\Api\Data\ResultExtensionInterface $extensionAttributes
     * @return $this
     */
    public function setExtensionAttributes(
        Vendor\CheckoutExt\Api\Data\ResultExtensionInterface $extensionAttributes
    );

}

Wir haben Schnittstellen bereit, damit das Rest-API-Modul es zur Vorbereitung der Ausgabe verwenden kann. Jetzt müssen wir sie irgendwie implementieren, damit die Anfrage tatsächlich funktioniert. Hier gibt es zwei Möglichkeiten: Sie können entweder einfach die ursprüngliche bevorzugen und die Ausgabe mit dem Plugin vorbereiten oder selbst implementieren. Lassen Sie uns mit der ersten Option fortfahren, in etc/di.xmloder besser in etc/webapi/di.xmlPräferenz definieren

<preference for="Vendor\CheckoutExt\Api\PaymentInformationManagementInterface" type="\Magento\Checkout\Model\PaymentInformationManagement" />

Dies funktioniert, da unsere Schnittstelle das native Magento One erweitert und wir die Funktionsdefinition nicht geändert haben, sondern nur das, was von der Funktion zurückgegeben werden soll. Die Magento-Klasse gibt jedoch eine einfache Ganzzahl zurück, und nur weil wir andere Ausgaben definiert haben, wird Magento diese nicht generieren. Wir müssen dazu. Implementieren wir also zuerst eine Klasse, die wir in der Antwort verwenden werden

<preference for="Vendor\CheckoutExt\Api\Data\ResultInterface" type="Vendor\CheckoutExt\Model\Data\OrderResponse" />

namespace Vendor\CheckoutExt\Model\Data;

use Vendor\CheckoutExt\Api\Data\ResultInterface;
use Vendor\CheckoutExt\Api\Data\ResultExtensionInterface;
use Magento\Framework\Model\AbstractExtensibleModel;

class Result extends AbstractExtensibleModel implements ResultInterface
{
    /**
     * @param string $orderId
     * @return \Vendor\CheckoutExt\Api\Data\ResultInterface
     */
    public function setOrderId($orderId)
    {
        return $this->setData(self::ORDER_ID, $orderId);
    }

    /**
     * @return string
     */
    public function getOrderId()
    {
        return $this->_getData(self::ORDER_ID);
    }

    /**
     * @param string $incrementId
     * @return \Vendor\CheckoutExt\Api\Data\ResultInterface
     */
    public function setOrderRealId($incrementId)
    {
        return $this->setData(self::ORDER_REAL_ID, $incrementId);
    }

    /**
     * @return string
     */
    public function getOrderRealId()
    {
        return $this->_getData(self::ORDER_REAL_ID);
    }

    /**
     * @return \Vendor\CheckoutExt\Api\Data\ResultExtensionInterface
     */
    public function getExtensionAttributes()
    {
        $extensionAttributes = $this->_getExtensionAttributes();
        if (!$extensionAttributes) {
            /** @var ResultExtensionInterface $extensionAttributes */
            $extensionAttributes = $this->extensionAttributesFactory->create(ResultInterface::class);
        }

        return $extensionAttributes;
    }

    /**
     * @param \Vendor\CheckoutExt\Api\Data\ResultExtensionInterface $extensionAttributes
     * @return \Vendor\CheckoutExt\Api\Data\ResultInterface
     */
    public function setExtensionAttributes(ResultExtensionInterface $extensionAttributes)
    {
        return $this->_setExtensionAttributes($extensionAttributes);
    }
}

Und das letzte Puzzleteil ist das Plugin, das nach dem Aufruf der ursprünglichen Bestellmethode verknüpft wird, um die zurückgegebene Ganzzahl in das von uns benötigte Objekt umzuwandeln. Wieder in di.xmldefinieren

<type name="Magento\Checkout\Api\PaymentInformationManagementInterface">
    <plugin name="vendorCheckoutExtSaveOrderResultPlugin" type="Vendor\CheckoutExt\Plugin\Checkout\PaymentInformationManagement" sortOrder="1" />
</type>

Und der Plugin-Code

namespace Vendor\CheckoutExt\Plugin\Checkout;

use Vendor\CheckoutExt\Api\Data\ResultInterface;
use Vendor\CheckoutExt\Api\Data\ResultInterfaceFactory;
use Magento\Checkout\Api\PaymentInformationManagementInterface;

class PaymentInformationManagement
{
    /** @var ResultFactory */
    private $resultFactory;

    /**
     * @param ResultInterfaceFactory $resultFactory
     */
    public function __construct(ResultInterfaceFactory $resultFactory)
    {
        $this->resultFactory = $resultFactory;
    }

    /**
     * @param PaymentInformationManagementInterface $subject
     * @param int $orderId
     * @return ResultInterface
     */
    public function afterSavePaymentInformationAndPlaceOrder(
        PaymentInformationManagementInterface $subject,
        $orderId
    ) {
        /** @var ResultInterface $obj */
        $obj = $this->resultFactory->create();
        $obj->setOrderId($orderId);

        return $obj;
    }
}

Das Ergebnis ist nun das Objekt, das extension_attributes implementiert. In Ihrem benutzerdefinierten Zahlungs-API-Modul können Sie ein ähnliches Plugin definieren. Stellen Sie einfach sicher, dass sortOrder höher als das oben genannte ist, damit Sie bereits ein Vendor\CheckoutExt\Api\Data\ResultInterfaceObjekt als Argument erhalten.

Im Zahlungsmodul Datei erstellen etc/extension_attributes.xmlmit

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Vendor\ChecoutExt\Api\Data\ResultInterface">
        <attribute code="my_payment_gateway_data" type="Vendor\CustomPayment\Api\Data\RedirectInterface" />
    </extension_attributes>
</config>

Erstellen Sie eine Schnittstelle und deren Implementierung gemäß Ihren Anforderungen und im Plugin

namespace Vendor\CustomPayment\Plugin\Checkout;

use Vendor\CustomPayment\Api\Data\RedirectInterface;
use Vendor\CustomPayment\Api\Data\RedirectInterfaceFactory;
use Vendor\CheckoutExt\Api\Data\ResultInterface;
use Magento\Checkout\Api\PaymentInformationManagementInterface;

class PaymentInformationManagement
{
    /** @var RedirectInterfaceFactory */
    private $redirectFactory;

    /**
     * @param RedirectInterfaceFactory $redirectFactory
     */
    public function __construct(RedirectInterfaceFactory $redirectFactory)
    {
        $this->redirectFactory = $redirectFactory;
    }

    /**
     * @param PaymentInformationManagementInterface $subject
     * @param ResultInterface $orderId
     * @return ResultInterface
     */
    public function afterSavePaymentInformationAndPlaceOrder(
        PaymentInformationManagementInterface $subject,
        $orderId
    ) {
        /** @var ResultInterface $obj */
        $redirect = $this->redirectFactory->create();

        $extensionAttributes = $orderId->getExtensionAttributes();
        $extensionAttributes->setMyPaymentGatewayData($redirect);
        $orderId->setExtensionAttributes($extensionAttributes);

        return $orderId;
    }
}

Jetzt ist die Antwort richtig json mit extension_attributes, die Sie überprüfen und einbinden können. Möglicherweise müssen einige andere Elemente standardmäßig als Magento-Seite zur Erfolgsseite umgeleitet werden. Sie müssen daher sicherstellen, dass Sie sie deaktivieren, wenn Sie Ihre Weiterleitung vorbereiten. Ähnliche Überschreibungen müssen auch für Klassen vorgenommen werden, die das Auschecken von Gästen durchführen.

Zefiryn
quelle