I am creating a Magento 2 store that sells virtual products, this site have its checkout directly at the product page. The customers will never buy more than 1 product at a time.
This checkout uses ajax calls
aimed at the REST API's for the steps in the purchase.
So far I can create new cart, add product, set billing address, set payment method, collect totals and place order. BUT! One of the payment methods we use is an external credit card gateway. I have created a custom payment method module for this and it is settable through the APIs. However, the response that i get from "placeOrder()"
API call contains only the order entity_id.
My intuition tells me that depending on payment method such an API call would add something to the response to tell the frontend that a redirect should take place.
I have probably missed something, maybe an API call that should be made before placeorder
to process payment and then in case of redirect do placeorder
at the callback url?
Does anyone have an idea of how this is supposed to be done?
Best Answer
The fact that this endpoint defines result of the call as single int instead of at least object with order id and extension attribute is awful and probably won't change. We will see what the Magento team will come up for 2.3 when they will introduce their own PWA and hopefully create new endpoint with better support for 3rd party extensions. Right now however there are 2 possibilities to do:
Assuming you are making a request to
/V1/guest-carts/:cartId/payment-information
or/V1/carts/mine/payment-information
you can:If your payment gateway requires
GET
redirect simply hook afterMagento\Checkout\Api\PaymentInformationManagementInterface::savePaymentInformationAndPlaceOrder()
and set redirect url according to your needs. Magento should recognize redirect header.If your redirect need to be actually a
POST
request you need to override definition of the endpoint and provide your own interface which will declare more reasonable result which you will be able to process in the browser. This however will require to make sure native Magento classes are also covered. If you are working on the project for single client this might work.Create your own module, ie.
Vendor_CheckoutExt
as separate composer module or inapp/code/Vendor/CheckoutExt
. Make sure to addMagento_Checkout
tosequence
tag inmodule.xml
so your definition will be read after magento one.In
etc/webapi.xml
put a definition like:Create an interface
Vendor\CheckoutExt\Api\PaymentInformationManagementInterface
to look likeNow create interface for the response
We have interfaces ready so rest api module will be able to use it to prepare output. Now we need to implement them somehow to actually make the request work. Here there are 2 possibilities, you can either simply make a preference for the original one and prepare output using plugin or implement it itself. Let's go with the first option, in
etc/di.xml
or better inetc/webapi/di.xml
define preferenceThis will work because our interface extends native Magento one and we didn't change the function definition, only what should be returned from the function. But Magento class returns simple integer and just because we defined other output Magento won't generate it. We need to to this. So first let's implement class that we will use in the response
And last piece of the puzzle is the plugin which will hook after original place order method is called to change returned integer into object we need. Again in
di.xml
defineAnd the plugin code
So now the result is the object that implements extension_attributes. In your custom payment api module you can define similar plugin, just make sure sortOrder there is higher than the above one so you already get
Vendor\CheckoutExt\Api\Data\ResultInterface
object as an argument.In payment module create file
etc/extension_attributes.xml
withCreate interface and its implementation according to your needs and in plugin
Now the response is proper json with extension_attributes in it which you can check and hook into. There might be some other elements to cover as magento by default redirect to success page, so you need to make sure you disable it when preparing your redirect. Also similar overwrites need to be done for classes handling guest checkout.