There is no big eCommerce platform without payment by credit cards. The protection features and popularity of the credit cards themselves encourage the use of that method broadly. That’s why the modern online shop still needs credit cards on its checkout next to express transfers, eWallets and a whole variety of other local payment methods such as Polish BLIK. 

Table of content:

1. Article shows how to implement a basic credit cards integration for the Shopware PWA application using Adyen.

2. All the source code is included or linked in the content. 

3. The 3DS authentication will be covered in the next article. 

4. The code implemented in the actual project is at this repository.


Credit cards are still on top the most popular payment methods in eCommerce

Credit Cards as the most prererable payment mathod in the US - eMarketer
source: eMarketer

Credit cards are the leading payment method in the US, with over 45% of responders favoring the over - for example - debit card or other methods, according to eMarketer, and in eCommerce, it looks basically the same.

Most Popular Payment Methods in Stats by eMaketer
source: eMarketer

Given the most often far-from seamless checkout flows are responsible for the vast number of abandoned carts, eCommerce businesses must provide their customers exactly with what they need in terms of payment methods.

Adyen is fully aware of the need, so in its plugin marketplace, credit card payments plugins take a prominent place. Shopware PWA is not an exception. 

Let’s try to handle credit cards by using the official Shopware 6 plugin shipped by Adyen. 

Shopware PWA & Adyen Payment Plugin

Although the plugin offers asynchronous payment flow once the order is placed and no additional work is needed in this case, the credit card payment must be handled earlier during the checkout. 

Shopware PWA is built upon Nuxt.js, using Vue as the base library. Thanks to the official Adyen SDK written in JavaScript - implementation of the credit card component is way simpler. 

Among a range of features, Adyen offers web components, which technically are ready-to-use UI components, available for web purposes, but also for iOS and Android. Another good news for Shopware 6 platform is the official plugin, which is headless aware and offers features that help to implement credit cards handling on the detached frontend application.

For a better understanding of what happens under the hood, please learn from the sources below 

The flow of implementing Adyen payment methods with credit cards in Shopware PWA

The diagram below illustrates what the credit card’s flow may look like.

  1. Web components are configured, initialized & displayed. 
  2. The credit card data is being validated against Adyen rules.
  3. If the data is correct, it is stored in the database by invoking PATCH /context endpoint.
  4. Once the order is placed, the payment method triggers additional action between the backend and Adyen API. The process checks if the previously provided CC data can be used and the order can be paid.
  5. Depending on the response from Adyen API, the customer is redirected to the success or failure payment page on Shopware PWA.


Happily, the official plugin can be utilized by the headless application and there is no additional work needed on the backend - thanks to this line: GitHub: Adyen -  adyen-shopware6 - PaymentSubscriber.php 

Note that the Shopware 6 API also provides a unified way of passing extra payment data during handling a payment after the order is created! More details here.

This example uses that way to skip keeping extra data in the current session, but keep in mind that in the default scenario handling extra data relies rather on the handle-payment endpoint.

Installation of Adyen credit card payment

Let's get down to the business.

In order to have the whole flow working well, the are some mandatory requirements:

Backend and frontend stack

  1. Shopware 6 (v6.4.x)
  2. Shopware PWA (latest version, 0.9.1 or canary installed via CLI) 


More details on how to set it up are available here:
Shopware PWA Docs (Getting started) 

Dependencies

So, another step is the installation of required dependencies:

  1. Adyen plugin for Shopware 6 (v3.0.0) - manually from:
    GitHub (Adyen Shopware PW)
    or
    Shopware marketplace  (may require additional php dependency by using composer)
  2. @adyen/adyen-web module using npm or yarn in your shopware-pwa project
adyen-web module using npm or yarn in your shopware-pwa project

Configuration

In order to set up the Shopware 6 plugin properly, you will need at least the clientKey generated in the Adyen dashboard for a specific online shop. The same key will be used on the frontend side. If you are going to test it locally, don’t forget to add  http://localhost:3000 host to trusted hosts. 

Another annoying thing might be an anti-fraud system that works just perfectly! This is a common issue when your credit card is refused very often in the test environment. 

Happily, every card number and buyer can be trusted manually in the Adyen dashboard.

That’s it. If everything went well and you don’t see any errors, it’s time to get some code, finally!

Implementation of Adyen payment plugin

Overriding vs. plugin system

Shopware PWA gives full control of customization. Depending on your needs, you can overwrite every component or just use an existing plugin’s functionality to put your own component in the desired place. 

In order to not lose compatibility with the checkout, the shopware-pwa local plugin is a perfect solution in this case.

One place to rule them all

Before we start implementing the presentation layer (vue component itself), we need to get some place to keep the AdyenCheckout instance and corresponding methods that can be used over the entire application. For instance, you can use the AdyenCheckout instance in PLP to implement the express checkout once the “buy” button is clicked.

The good place would be a Nuxt plugin because it can be injected in the nuxt context and used wherever you want. But it could be implemented as a singleton in a different way as well (using shared reference via composition api, for instance).

The nuxt plugin may look like this:

<code javascript here>

from GitHub Gist 

</code>

The `adyen.client.js` file with content from the snipper above should be placed in `src/plugins` directory. Thanks to this, it will be registered automatically after the next Nuxt.js run.

Note that the plugin has a “client” name before the extension. It tells the nuxt that the plugin is being run only on the client side (CSR). We don’t need it on the server-side rendering process.

The plugin uses the config from the `nuxt.config.js` file and make sure you have configured it accordingly as in the example below:

// nuxt.config.js in the project’s root dir 

import extendNuxtConfig from '@shopware-pwa/nuxt-module/config'
 
export default extendNuxtConfig({
 head: {
   title: 'Shopware PWA',
   meta: [{ hid: 'description', name: 'description', content: '' }],
 },
 publicRuntimeConfig: {
   adyen: {
     environment: "test",
     clientKey: "test_IZNMQ3ZCVBDYBMFPDWTFO7Z6F4NOMRTP",
     adyenOrigin: "http://localhost:8000",
   }
 }
})

Vue component inside the Shopware PWA plugin

All right. Now we’ve got a service that can manage the AdyenCheckout instance and our component. But where to put it? As a component?

Let’s use the mentioned Shopware PWA plugin system to make it easy.

I’ve tried to look for a proper slot to put my Adyen credit card in the right place, and that’s what I found:

There is a slot with the name “checkout-payment-method-Cards” that corresponds to the slot I would like to use (comes with Adyen CC payment method!)

The place of the slot fits perfect for the credit card’s form (it’s under the payment method’s description)

1. Firstly, we need to create a plugin structure inside the `sw-plugins` directory, to be like:

├── sw-plugins

│   ├── adyen-credit-card

│   │   ├── AdyenCreditCard.vue

│   │   └── config.json

│   ├── local-plugins.json

2. Point the plugin you want to use in order to display Adyen component:

// sw-plugins/adyen-credit-card/config.json
{
 "slots": [
   {
     "name": "checkout-payment-method-Cards",
     "file": "AdyenCreditCard.vue"
   }
 ],
 "settings": {}
}

3. Register a local plugin

// sw-plugins/local-plugins.json
 
{
 "my-local-plugin": false,
 "adyen-credit-card": true
}

4. Put the Vue component inside the plugin’s directory:

// AdyenCreditCard.vue placed in @/sw-plugins/adyen-credit-card dir


<template>
 <div id="adyen-cards-container"></div>
</template>
 
<script>
import { onMounted } from '@vue/composition-api';
export default {
 name: "AdyenCreditCard",
 setup(props, { root: { context: { $adyen } } }) {
   onMounted(() => {
     // show the Card form component with custom configuration
     // inside adyen-cards-container div element
     $adyen && $adyen.mountCardContainer('#adyen-cards-container', {
       enableStoreDetails: false,
       hasHolderName: false,
       holderNameRequired: false,
       billingAddressRequired: false,
       showPayButton: false,
     });
   })
 },
};
</script>
  1. What happens here is: we use the $adyen plugin instance registered before to mount card form under the specific div with id “#adyen-cards-container”. 
  2. We pass the options described in the Adyen documentation here.
  3. The Adyen’s nuxt plugin takes care of further actions like triggering another actions if the credit card data is valid.

Don’t forget to restart a nuxt application to see the effects!

The effect

Now your Shopware PWA-based project is ready to handle the credit cards payment method shipped by the Adyen plugin. The credit card data is saved during the checkout, and it’s used when the order is created and the payment process is triggered.

What next?

Keeping everything in just one place

To be honest, the solution can be implemented in many different ways. Let’s say you want everything in just one place, and it’s understandable. To do so, we can move all the logic from nuxt plugin into Shopware PWA plugin, it’s related to loading Adyen sdk & css directly from CDN. (and find out sharing state for further usage). Nevertheless, it’s doable and I encourage you to make some experiments :)

What about 3DS additional authentication?

Yes, it’s possible and doable! 

This is the most obvious question regarding credit cards and the topic will be covered in the next article because that will affect few more files and the guide wouldn’t be clear enough.

Additional validation on the checkout

It would be good to block a possibility for placing an order when the credit card data is not valid. A composable that shares a state sounds like a good idea here, and I will cover the issue in the following article.