# Installation

To install Paypal integration for the commercetools module in your Vue Storefront application, use the following command:

# Setup

Add @vsf-enterprise/paypal-commercetools to dev and prod arrays in useRawSource object:











 




 






// nuxt.config.js

export default {
  buildModules: [
    ['@vue-storefront/nuxt', {
      coreDevelopment: true,
      useRawSource: {
        dev: [
          '@vue-storefront/commercetools',
          '@vue-storefront/core',
          '@vsf-enterprise/paypal-commercetools'
        ],
        prod: [
          '@vue-storefront/commercetools',
          '@vue-storefront/core',
          '@vsf-enterprise/paypal-commercetools'
        ]
      }
    }]
  ]
};

Register the @vsf-enterprise/paypal-commercetools/nuxt module with the following configuration:

// nuxt.config.js

export default {
  modules: [
    ['@vsf-enterprise/paypal-commercetools/nuxt', {
      debug: true,
      clientId: '<PAYPAL_CLIENT_ID>',
      checkoutSummaryStepUrl: '/checkout/payment'
    }]
  ]
};

TIP

If you are also using the nuxt-i18n module, you must register both packages in the proper order. You can read more about it here (opens new window).

Generally, we recommend placing the @vsf-enterprise/paypal-commercetools/nuxt module at the very top of the array.

  • debug - debug mode indicator in Paypal JS library.
  • clientId - your Paypal's client ID. See Paypal's documentation to learn how to get your Client ID (opens new window).
  • checkoutSummaryStepUrl - URL to the the last step of the checkout (Summary & payment). Express checkout will redirect the user to it.

Add @vsf-enterprise/paypal-commercetools/server integration to the middleware with the following configuration:

// middleware.config.js

module.exports = {
  integrations: {
    // ...
    paypal: {
      location: '@vsf-enterprise/paypal-commercetools/server',
      configuration: {
        ctApi: {
          apiHost: '<CT_HOST_URL>',
          authHost: '<CT_AUTH_URL>',
          projectKey: '<CT_PROJECT_KEY>',
          clientId: '<CT_CLIENT_ID>',
          clientSecret: '<CT_CLIENT_SECRET>',
          scopes: [
            'manage_orders:<CT_PROJECT_KEY>',
            'manage_payments:<CT_PROJECT_KEY>'
          ]
        },
        paypalApi: {
          clientId: '<PAYPAL_CLIENT_ID>',
          clientSecret: '<PAYPAL_CLIENT_SECRET>',
          sandbox: true,
          webhookId: '<WEBHOOK_ID>'
        }
      }
    }
  }
}
  • configuration:
    • ctApi - An object containing credentials of your commercetools API client. Please refer to our documentation for commercetools integration (opens new window) for more information. Two notable differences are that:

      • the scopes array must contain manage_orders and manage_payments and your API client must have access to these scopes,
      • apiHost should only contain the base URL, without the path to the GraphQL endpoint. For example, https://<SHOP_DOMAIN>.com/ instead of https://<SHOP_DOMAIN>.com/vsf-ct-dev/graphql.
    • paypalApi:

      • clientId - Paypal client ID.
      • clientSecret - Paypal client secret.
      • sandbox - Whether to use a self-contained, virtual testing environment that simulates the live PayPal production environment. You can read more about it here (opens new window).
      • webhookId - ID of created webhook.

# Add a new payment type

To add a new payment type in commercetools:

  1. Open commercetools ImpEx (opens new window).
  2. Go to API Playground.
  3. Select your project in the navbar.
  4. Select Types inside the Endpoint field.
  5. Select Create inside the Command field.
  6. Paste the following JSON object into the Payload field:
{
  "key": "vsf-paypal-integration-payment-type",
  "name": {
    "en": "commercetools Paypal integration payment custom type"
  },
  "resourceTypeIds": ["payment"],
  "fieldDefinitions": [
    {
      "name": "paypalExpirationDate",
      "label": {
        "en": "Paypal Expiration Date"
      },
      "required": false,
      "type": {
        "name": "DateTime"
      },
      "inputHint": "SingleLine"
    },
    {
      "name": "paypalResultCode",
      "label": {
        "en": "Paypal Result Code"
      },
      "required": false,
      "type": {
        "name": "String"
      },
      "inputHint": "SingleLine"
    },
    {
      "name": "captureUrl",
      "label": {
        "en": "Capture URL"
      },
      "required": false,
      "type": {
        "name": "String"
      },
      "inputHint": "SingleLine"
    },
    {
      "name": "paypalAuthorizationId",
      "label": {
        "en": "Paypal Authorization ID"
      },
      "required": false,
      "type": {
        "name": "String"
      },
      "inputHint": "SingleLine"
    },
    {
      "name": "paypalCaptureId",
      "label": {
        "en": "Paypal Capture ID"
      },
      "required": false,
      "inputHint": "SingleLine",
      "type": {
        "name": "String"
      }
    },
    {
      "name": "refundUrl",
      "label": {
        "en": "Refund URL"
      },
      "required": false,
      "type": {
        "name": "String"
      },
      "inputHint": "SingleLine"
    },
    {
      "name": "paypalRefundId",
      "label": {
        "en": "Paypal Refund ID"
      },
      "required": false,
      "inputHint": "SingleLine",
      "type": {
        "name": "String"
      }
    }
  ]
}
  1. Click the Go!!! button.

# Usage on the frontend

Add PaymentPaypalProvider.vue components to the last step of the checkout process. This component will mount Paypal's button and handle the payment process for you.



 
 
 




 



 




<template>
  <div>
    <PaymentPaypalProvider
      :afterPay="afterPayAndOrder"
    />
  </div>
</template>

<script>
import PaymentPaypalProvider from '@vsf-enterprise/paypal-commercetools/src/components/PaymentPaypalProvider';

export default {
  components: {
    PaymentPaypalProvider
  }
};
</script>

afterPay props expect a callback function called after authorizing the payment is authorized and placing an order. You can redirect the user to the order confirmation page and clear the cart inside this callback.

<script>
export default {
  setup() {
    const afterPayAndOrder = ({ order }) => {
      router.push({ path: localePath(`/checkout/thank-you?order=${order.id}`) });
      setCart(null);
    };

    return {
      afterPayAndOrder
    };
  }
};
</script>

afterPay signature:

import type { Payment, Order } from '@vsf-enterprise/paypal-commercetools';
type PaymentAndOrder = Payment & { order: Order }

(params: PaymentAndOrder) => void;

# Placing an order

The integration will place an order in commercetools and add the order object to the response if the transaction is authorized. It only makes one request from the client to finalize/authorize payment and make an order.

# Webhook

In PayPal's dashboard, add a webhook with the following configuration:

  • Webhook URL: https://<your_vsf2_app_domain>/api/paypal/webhook,
  • Event types: Payment capture completed, Payment capture refunded,

Save it, and then copy created webhook's Webhook ID. Open middleware.config.js and paste it as a value for integrations.paypal.paypalApi.webhookId. Webhook takes care of updating payment status in commercetools. It adds Charge or Refund transactions and updates Order status to Paid.

# Testing webhook locally

If you want to check if webhook works during local development, use the ngrok (opens new window) or localtunnel (opens new window) tools and set Sandbox Webhook URL to generated tunnel's URL.