A crucial part of any Magento website – is payment methods! In the Magento Marketplace you can find a large number of payment method providers – but adapting them to work with ScandiPWA can require additional effort (unless the integration already exists on the ScandiPWA Marketplace).

In this tutorial, you'll learn the basics of building an extension for integrating a new payment method in ScandiPWA.

Like many other providers, Mollie redirects the user to another page after checkout to complete the payment. After the customer has entered their details on the 3rd party site, they are redirected back to the website, where they see a message about the current payment status. You'll need to adapt this logic so it also works in a ScandiPWA theme.

<aside> ⚠️ This tutorial assumes that you are using the Mollie payment integration for Magento in test mode. If you are not, please refer to Mollie's documentation.

</aside>

<aside> ⚠️ Mollie's workflow involves the use of webhooks, which will not work if you are developing on localhost. To make your application accessible for free, you can consider using the ngrok tool.

</aside>

To implement the Mollie payment method in ScandiPWA you need to:

  1. Create a plugin for Checkout.query.js to include the fields mollie_redirect_url and mollie_payment_token
  2. Create a plugin for Checkout.container.js to redirect the user to the mollie_redirect_url after placing the order
  3. Create a config file in Magento to set the URL the user should be redirected back to
  4. Add a step for Mollie payment method by plugging into the __construct and componentDidMount functions of the Checkout component.
  5. Create a plugin for Checkout.component.js to display the order status

<aside> ℹ️ Note: In this example, It’s implemented a specific payment method provider, Mollie. If you are making an extension for a different payment service, the steps outlined below might be slightly different. However, the general workflow of integrating a payment method will be similar: inspect the checkout source code and customize it through plugins.

</aside>

1 - Create a plugin for Checkout.query.js to include the fields mollie_redirect_url and mollie_payment_token

First, it is necessary to obtain the URL to which the user should be redirected. For many payment extensions, this URL is included in the placeOrder GraphQL mutation response. In fact, our example extension, Mollie, includes a mollie_redirect_url in the order field of the response.

In GraphQL, only the fields that have been explicitly requested are included in the response. Therefore, the mollie_redirect_url field, which is specific to the extension, is not included by default.

To allow ScandiPWA to access mollie_redirect_url, it is necessary to write a plugin that includes this field as part of the placeOrder mutation.

Upon inspecting the ScandiPWA source code, it becomes clear that the file responsible for creating the placeOrder mutation is located at scandipwa/src/query/Checkout.query.js.

<aside> ℹ️ All ScandiPWA query creators live in the query folder. If you need to find the file responsible for a specific query, you can search for this query's name there.

</aside>

First, take a look at the relevant parts of the original Checkout.query.js file to get an idea of what you'll be plugging into.

As you can see, the _getOrderField function is responsible for creating the order field and populating it with the order_id subfield. To add mollie_redirect_url as an additional subfield, you will need to modify this function.

Create the file Checkout.query.plugin.js in the plugin directory of your extension.

<aside> ℹ️ In ScandiPWA, plugins are functions that wrap around the original function (how to work with plugins?). It's a good idea to name it after what it plugs into.

</aside>

The Checkout.query.plugin.js file should look like this:

When completing an order with a Mollie payment method, you should see the mollie_redirect_url value returned in the GraphQL response.

<aside> ✅ You can check the "Network" tab in your browser's developer tools to see the GraphQL responses. This can be useful for debugging requests!

</aside>

2 - Create a plugin for Checkout.container.js to redirect the user to the mollie_redirect_url after placing the order

To identify the code responsible for guiding users through the checkout process, we can use the React Developer Tools extension. This tool will indicate that the Checkout route is responsible for this task.

The business logic, which pertains to what is important at present, is conventionally located in .container.js files. Therefore, please refer to the scandipwa/src/route/Checkout/Checkout.container.js file, and pay special attention to the savePaymentMethodAndPlaceOrder function.

This function sets the payment method for the order and places it. Once placed, the order transitions to the order success step (also known as the "details step").

It is necessary to modify this functionality. Instead of transitioning to the details step, the user needs to be redirected to the mollie_redirect_url returned when CheckoutQuery.getPlaceOrderMutation is fetched.

Write a plugin for savePaymentMethodAndPlaceOrder that will redirect the user if necessary. You can add it to our existing Checkout.container.plugin.js file:

As you may have noticed, this code is using some custom utility functions redirectToUrl and setPaymentToken. To use them, you must define them first.

<aside> ✅ It is common for extensions to require new utility functions. These can be implemented in the util directory, just like they would be in a theme.

</aside>

The redirectToUrl in Redirect.js is a really simple function. Still, it's nice to have it as a reusable function so the rest of the code is more readable.

export const redirectToUrl = (url) => {
    window.location.replace(url);
};

The setPaymentToken and getPaymentToken functions are straightforward. While the latter has not yet been used, it will utilize the BrowserDatabase utility to store and retrieve the payment token. This token will remain accessible even after the user is redirected to the payment provider's page and returns.

And with that, the redirection step is complete! If you wish, you can complete an order using Mollie's payment methods to verify that you are indeed redirected.

3 - Create a config file in Magento to set the URL the user should be redirected back to.

<aside> 👶 You can set the return URL by going: Mollie -> Advanced -> PWA Storefront Integration -> Use custom return URL -> yes And change the Custom return url

</aside>

After the customer has entered the payment details on the 3rd party page it should be redirected to ScandiPWA. Mollie allows you to easily set the return URL by configuring some database values.

As all ScandiPWA checkout steps begin with checkout, you can use checkout/mollie_result for the final order processing and displaying the result.

It is also important to include parameters in the URL. This way, ScandiPWA can identify if someone is returning from Mollie's third-party site. The parameters included in this case are order_id, mollie_payment_token, and mollie_order_hash.

You should create a file InstallData.php in <VENDOR>/<MODULE>/Setup/ and include:

<?php
namespace ScandiTutorials\\MollieScandiConfig\\Setup;
//^^ don't forget to update the namespace

use Magento\\Framework\\App\\Config\\ConfigResource\\ConfigInterface;
use Magento\\Framework\\Setup\\InstallDataInterface;
use Magento\\Framework\\Setup\\ModuleContextInterface;
use Magento\\Framework\\Setup\\ModuleDataSetupInterface;
use Mollie\\Payment\\Config;

class InstallData implements InstallDataInterface
{
    /** @var ConfigInterface */
    protected $config;

    public function __construct(ConfigInterface $config) {
        $this->config = $config;
    }

    public function install(
			ModuleDataSetupInterface $setup, ModuleContextInterface $context
		) {
       $setup->startSetup();
       $this->config->saveConfig(Config::GENERAL_USE_CUSTOM_REDIRECT_URL, true);
       $this->config->saveConfig(
           Config::GENERAL_CUSTOM_REDIRECT_URL,
           '{{secure_base_url}}checkout/mollie_result?order_id={{increment_id}}&mollie_payment_token={{payment_token}}&mollie_order_hash={{order_hash}}'
       );
        $setup->endSetup();
    }
}

Now, you need to make sure that the correct business logic takes place after this redirect.

4 - Add a step for Mollie's payment method by plugging into the __construct and componentDidMount functions of the Checkout component.

When the user is redirected back, it’s necessary to use the mollieProcessTransaction GraphQL mutation to process the order and get the transaction result.

First, look at some relevant methods in the CheckoutContainer, which renders all checkout routes, and thus will be involved in checkout/mollie_result as well:

You will need to modify the behavior of the __construct method. Otherwise, it could cause issues by setting an incorrect initial state, such as BILLING_STEP or SHIPPING_STEP, when a custom MOLLIE_PROCESSING_STEP is actually desired.

To achieve this, you can write a plugin that has a function similar to the original one but sets the correct initial step, if applicable.

Also plug into componentDidMount, since that is a good place to put business logic that needs to run once when the component is initialized. The original function contains some logic that you want to suppress for the Mollie processing step, so check it before calling.

The plugin mentioned above utilizes the MollieQuery class, which serves as a query creator utility for mollieProcessTransaction. The mollieProcessTransaction function must be defined:

Finally, remember to update the plugin configuration for Checkout.container.plugin.js.

export default {
    "Route/Checkout/Container": {
        "member-function": {
            __construct,
            componentDidMount,
            savePaymentMethodAndPlaceOrder
        },
    },
}

5 - Create a plugin for Checkout.component.js to display the order status.

After processing an order, it is necessary to inform the user of the order status. To do this, you can define a utility function to retrieve the status message.

You can now create a plugin for the Checkout.component.js file, which is responsible for the presentation logic of the checkout flow.

At this point, the main steps in integrating a payment method extension in ScandiPWA were covered. Usually, you would need to do some debugging to make sure everything is working properly – payment integration can be tricky! You should be able to test your extension using the test mode of the payment provider.

<aside> ✅ When you're done with the extension, consider publishing it on the ScandiPWA Marketplace so others can benefit from your creation!

</aside>