Vue Storefront is now Alokai! Learn More
Migration Guide

Migration Guide

We created this migration guide to help you get up and running quickly with the new Adyen integration. If you have any questions, please reach out to us on Discord, or contact your dedicated Alokai Customer Support Contact.

There were breaking changes in v11. If you do not upgrade your extension and notification module to version ^11 payments will not work.

The extension and notification module versions ^11 are not compatible with @vsf-enterprise/adyen-commercetools You must manage the deployment so that compatible versions are deployed together.

See the compatibility matrix to see which versions are compatible with one another.

Prerequisites

Before you start, make sure you have a project that meets the following requirements:

1

Upgrade packages

Install new packages

yarn
yarn add @vsf-enterprise/sdk @vsf-enterprise/commercetools-sdk @vsf-enterprise/adyen-commercetools-sdk @vsf-enterprise/adyen-commercetools-api

Remove old packages

yarn
yarn remove @vsf-enterprise/adyen-commercetools

2

Update configuration

Remove payment error view

nuxt.config.js
- { 
-   name: 'adyen-payment-error',
-   path: '/adyen-payment-error',
-   component: resolve(__dirname, 'pages/AdyenPaymentError.vue')
- }

Update useRawSource configuration

nuxt.config.js
{
  useRawSource: {
-   dev: ['@vue-storefront/core', '@vsf-enterprise/commercetools', '@vsf-enterprise/adyen-commercetools'],
-   prod: ['@vue-storefront/core', '@vsf-enterprise/commercetools', '@vsf-enterprise/adyen-commercetools'],
+   dev: ['@vue-storefront/core', '@vsf-enterprise/commercetools', '@vsf-enterprise/adyen-commercetools-sdk'],
+   prod: ['@vue-storefront/core', '@vsf-enterprise/commercetools', '@vsf-enterprise/adyen-commercetools-sdk']
  }
}

Remove outdated Adyen module configuration

nuxt.config.js
- ['@vsf-enterprise/adyen-commercetools/nuxt', {
-   availablePaymentMethods: ['scheme', 'paypal', 'ideal', 'klarna', 'klarna_account', 'klarna_paynow', 'paywithgoogle'],
-   clientKey: '****',
-   environment: 'test',
-   recurringPayments: true,
-   methods: {
-     paypal: {
-       merchantId: '****',
-       intent: 'authorize'
-     }
-   }
- }],

Update Adyen commercetools integration's configuration in middleware.config.js

middleware.config.js
adyen: {
- location: '@vsf-enterprise/adyen-commercetools/server',
+ location: '@vsf-enterprise/adyen-commercetools-api/server',
  configuration: {
    ctApi: {
      apiHost: '<API_HOST>',
      authHost: '<AUTH_HOST>',
      projectKey: '<PROJECT_KEY>
      clientId: '<CLIENT_ID',
      clientSecret: '<CLIENT_SECRET>',
-     scopes: ['manage_project:<CT_PROJECT_KEY>']
+     scopes: ['manage_payments:<CT_PROJECT_KEY>', 'manage_orders:<CT_PROJECT_KEY>']
    },
    adyenMerchantAccount: '<ADYEN_MERCHANT_ACCOUNT>',
-   adyenRecurringApiBaseUrl: 'https://pal-test.adyen.com',
    adyenCheckoutApiBaseUrl: '<ADYEN_CHECKOUT_API_BASE_URL>',
    adyenApiKey: '<ADYEN_API_KEY>',
-   origin: 'http://localhost:3000',
-   buildRedirectUrlAfterAuth: (paymentAndOrder) => `/checkout/thank-you?paymentId=${paymentAndOrder.id}`,
-   buildRedirectUrlAfterError: () => '/adyen-payment-error'
+   returnUrl: 'http://localhost/adyen-redirect-back'
-   buildCustomPaymentAttributes: (client: CommercetoolsClient & { cartId: string, paymentId: string }): Promise<Record<string, any>> => {},
+   buildCustomPaymentAttributes: (params: BuildCustomPaymentAttributesParams): Promise<Record<string, any>> => {},
  }
}

The signature of the buildCustomPaymentAttributes function changed. What's more, in the previous versions it has been used to extend payload sent to the POST /payments, and now it's used for same purpose but with a different endpoint, namely POST /sessions.

3

Delete pages/AdyenPaymentError.vue

Delete AdyenPaymentError.vue from pages directory

4

Create AdyenRedirectBack.vue view

Add "redirect back" view to the router

nuxt.config.js
+ { 
+   name: 'adyen-redirect-back',
+   path: '/adyen-redirect-back',
+   component: resolve(__dirname, 'pages/AdyenRedirectBack.vue')
+ }

Create a file AdyenRedirectBack.vue in pages directory:

5

Initialize SDK

Create a directory and file for the SDK configuration (@/sdk/index.ts):

It's fine to still use composable to communicate with commercetools. But not for Adyen anymore. We installed both here for simplicity.

sdk/index.ts
import { ctModule, CTModuleType } from '@vsf-enterprise/commercetools-sdk';
import { initSDK, buildModule } from '@vsf-enterprise/sdk';
import { adyenCtModule } from '@vsf-enterprise/adyen-commercetools-sdk';

export const sdk = initSDK({
  commerce: buildModule<CTModuleType>(
    ctModule,
    {
      apiUrl: 'http://localhost/api/ct'
    }
  ),
  adyen: buildModule(
    adyenCtModule, {
      apiUrl: 'http://localhost/api/adyen',
      adyenClientKey: '<ADYEN_CLIENT_KEY>',
      adyenEnvironment: '<ADYEN_ENV>'
    }
  )
});

6

Update pages/Checkout/Payment.vue

Replace PaymentAdyenProvider in template:

pages/Checkout/Payment.vue
<template>
  ...
  <PaymentAdyenProvider
      :afterPay="afterPayAndOrder"
  />
  ...
</template>

With:

pages/Checkout/Payment.vue
<template>
  ...
  <div id="payment-element"></div>
  ...
</template>

Import useRoute:

pages/Checkout/Payment.vue
- import { ref, computed, watch, onMounted, useRouter, useContext } from '@nuxtjs/composition-api';
+ import { ref, computed, watch, onMounted, useRoute, useRouter, useContext } from '@nuxtjs/composition-api';

Remove PaymentAdyenProvider import:

pages/Checkout/Payment.vue
- import PaymentAdyenProvider from '@vsf-enterprise/adyen-commercetools/src/PaymentAdyenProvider';

Import sdk:

pages/Checkout/Payment.vue
<script>
import { sdk } from '~/sdk';
</script>

Add useRoute to setup:

pages/Checkout/Payment.vue
<script>
export default {
  setup() {
    const route = useRoute();
    ...
  }
}
</script>

Replace afterPayAndOrder with createAdyenDropin in setup:

Remove afterPayAndOrder function and return statement:

pages/Checkout/Payment.vue
<script>
export default {
  setup() {
    ...
-    const afterPayAndOrder = async ({ order }) => {
-      context.root.$router.push(`/checkout/thank-you?order=${order.id}`);
-      setCart(null);
-    };

    return {
-      afterPayAndOrder,
    ...
  }
}
</script>

Create session and mount payment element:

You don't need to export the sdk variable for the template

pages/Checkout/Payment.vue
<script>
import { useCart } from '@vsf-enterprise/commercetools';
import { useRoute, useRouter, onMounted } from '@nuxtjs/composition-api';

export default {
  setup() {
    ...
    const route = useRoute();
    const router = useRouter();
    const { setCart } = useCart();
    const createAdyenDropin = async () => {
      const session = await sdk.adyen.createSession();
      await sdk.adyen.mountPaymentElement({
        session,
        paymentDOMElement: '#payment-element',
        adyenConfiguration: {
          async onPaymentCompleted(result, component) {
            if (['Refused', 'Cancelled', 'Error'].includes(result.resultCode)) {
              // Handling negative result codes and unmounting the Adyen Drop-in
              // To allow the user to try again by recreating session and component
              component.unmount();
              // Show some meaningful error message
              await createAdyenDropin();
            } else {
              // Handling positive result codes + Pending, by placing an order and
              // redirecting to the thank you page
              const { data: { me } } = await sdk.commerce.getMe();
              const { data: { order } } = await sdk.commerce.createMyOrderFromCart({
                cartId: me.activeCart.id,
                cartVersion: me.activeCart.version
              });
              router.push(localePath({
                name: 'thank-you',
                query: {
                  order: order.id
                }
              }));
              setCart(null);
            }
          }
          onError(err) {
            // You need to decide what to do here on your own
            console.error(err);
          }
        },
        dropinConfiguration: {
          showRemovePaymentMethodButton: true,
          async onDisableStoredPaymentMethod(recurringDetailReference, resolve, reject) {
            try {
              await sdk.adyen.removeCard({ recurringDetailReference });
              return resolve();
            } catch (err) {
              // Do something with err...
              return reject();
            }
          }
        }
      });
    };

    onMounted(async () => {
      // ...
      await createAdyenDropin();
    });
  // ...
  }
}
</script>

7

Updating Payment Type In Commercetools

Upgrade Adyen Payment Type

In the face of the breaking changes introduced in [commercetools-adyen-integration v11](https://github.com/Adyen/adyen-commercetools/tree/v11.1.1), we need to ensure that our application remains resilient. This guide will walk you through extending the ctp-adyen-integration-web-components-payment-type` in the commercetools impex with new fields while maintaining legacy ones.

This guide helps in bridging the gap between v10 and v11 of the commercetools-adyen-integration. By updating the payment type, you ensure smooth operations and data compatibility. Remember, always test the changes in a staging environment before applying them to the production setup.

Step-by-Step Instructions

1. Initial Steps

  • Always take a backup of your data before proceeding.
  • Visit the commercetools impex: Impex Playground

2. Locating the Existing Type

  • In the top right corner, select your project.
  • Set the Endpoint dropdown to Types.
  • Set the Command dropdown to Query.
  • Set the 'Where' field to key="ctp-adyen-integration-web-components-payment-type".
  • Click the Go button.

Image

3. Understanding the Response

  • Expect a response with 1 element. If no results appear, this indicates that the commercetools-adyen-integration has not been previously installed. If that's the case, follow the installation guide instead.
  • Copy the id and version from the result. The id should resemble "ebb88811-3024-4ff5-898d-2d3696137be4", and the version might typically be 1.

4. Updating the Type

  • Set the Endpoint dropdown to Types again.
  • Change the Command dropdown to Update.

Payload

In the Payload section, paste the following JSON. Make sure to replace the version with the one you found in the previous step:

{
  "version": 1,
  "actions": [
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "getCarbonOffsetCostsRequest",
        "label": {
          "en": "getCarbonOffsetCostsRequest"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "getCarbonOffsetCostsResponse",
        "label": {
          "en": "getCarbonOffsetCostsResponse"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "amountUpdatesRequest",
        "label": {
          "en": "amountUpdatesRequest"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "amountUpdatesResponse",
        "label": {
          "en": "amountUpdatesResponse"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "disableStoredPaymentRequest",
        "label": {
          "en": "disableStoredPaymentRequest"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "disableStoredPaymentResponse",
        "label": {
          "en": "disableStoredPaymentResponse"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "createSessionRequest",
        "label": {
          "en": "createSessionRequest"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    },
    {
      "action": "addFieldDefinition",
      "fieldDefinition": {
        "name": "createSessionResponse",
        "label": {
          "en": "createSessionResponse"
        },
        "type": {
          "name": "String"
        },
        "inputHint": "MultiLine",
        "required": false
      }
    }
  ]
}
  • In the Resource ID field, paste the id value you copied earlier (without the quotation marks).
  • Click Go.
  • Your type is now updated and should be compatible with both older and newer integrations.

8

Update the extension and notification module to version ^11.

You still need to update the extension and notification module to version ^11.

See:

Was this guide helpful? Let us know on Discord!