Integrate Vertex

Edit on GitHub

This document describes how to integrate Vertex into a Spryker shop.

Prerequisites

Before integrating Vertex, ensure the following prerequisites are met:

  • Make sure that your deployment pipeline executes database migrations.

1. Install the module

Install the Vertex module using Composer:

composer require spryker-eco/vertex

2. Configure the module

Add the following configuration to config/Shared/config_default.php:

use SprykerEco\Shared\Vertex\VertexConstants;

$config[VertexConstants::IS_ACTIVE] = getenv('VERTEX_IS_ACTIVE');
$config[VertexConstants::CLIENT_ID] = getenv('VERTEX_CLIENT_ID');
$config[VertexConstants::CLIENT_SECRET] = getenv('VERTEX_CLIENT_SECRET');
$config[VertexConstants::SECURITY_URI] = getenv('VERTEX_SECURITY_URI');
$config[VertexConstants::TRANSACTION_CALLS_URI] = getenv('VERTEX_TRANSACTION_CALLS_URI');
// Optional: Tax ID Validator (requires Vertex Validator, previously known as Taxamo, see https://developer.vertexinc.com/vertex-e-commerce/docs/stand-alone-deployments)
$config[VertexConstants::TAXAMO_API_URL] = getenv('TAXAMO_API_URL');
$config[VertexConstants::TAXAMO_TOKEN] = getenv('TAXAMO_TOKEN');

// Optional: Vendor Code
$config[VertexConstants::VENDOR_CODE] = '';

Required configuration constants

Constant Description
IS_ACTIVE Enables or disables Vertex tax calculation.
CLIENT_ID OAuth client ID for the Vertex API.
CLIENT_SECRET OAuth client secret for the Vertex API.
SECURITY_URI Vertex OAuth security endpoint.
TRANSACTION_CALLS_URI Vertex transaction calls endpoint.

Optional configuration constants

Constant Description
TAXAMO_API_URL Vertex Validator API URL for tax ID validation. Details.
TAXAMO_TOKEN Vertex Validator API authentication token.
VENDOR_CODE Vendor code for Vertex tax calculations.
DEFAULT_TAXPAYER_COMPANY_CODE Default taxpayer company code.

3. Override feature flags

The isTaxIdValidatorEnabled, isTaxAssistEnabled, and isInvoicingEnabled methods default to false and are not driven by constants. To enable them, override src/Pyz/Zed/Vertex/VertexConfig.php:

namespace Pyz\Zed\Vertex;

use SprykerEco\Zed\Vertex\VertexConfig as SprykerEcoVertexConfig;

class VertexConfig extends SprykerEcoVertexConfig
{
    public function isTaxIdValidatorEnabled(): bool
    {
        return true;
    }

    public function isTaxAssistEnabled(): bool
    {
        return true;
    }

    public function isInvoicingEnabled(): bool
    {
        return true;
    }
}

Config methods

The following methods must be overridden in src/Pyz/Zed/Vertex/VertexConfig.php to enable the respective features:

Method Default Description
isTaxIdValidatorEnabled() false Enables tax ID validation via Vertex Validator. Requires TAXAMO_API_URL and TAXAMO_TOKEN to be set.
isTaxAssistEnabled() false Enables the tax assist feature. Return Assisted Parameters in the response that will provide more details about the calculation. The logs can be checked in the Vertex Dashboard.
isInvoicingEnabled() false Enables invoicing functionality. Requires OMS plugins to be registered. See Register OMS plugins.
getSellerCountryCode() '' Overrides the default seller country code (2-letter ISO code, for example, US). Defaults to the first country of the store.
getCustomerCountryCode() '' Overrides the default customer country code (applied only when no customer billing address is provided). Defaults to the first country of the store.

4. Set up the database schema

Install the database schema:

vendor/bin/console propel:install

5. Generate transfer objects

Generate transfer objects for the module:

vendor/bin/console transfer:generate

6. Register plugins

Register the tax calculation plugin

Add the Vertex calculation plugin to src/Pyz/Zed/Calculation/CalculationDependencyProvider.php:

use SprykerEco\Zed\Vertex\Communication\Plugin\Calculation\VertexCalculationPlugin;

protected function getQuoteCalculatorPluginStack(Container $container): array
{
    return [
        //...

        # Suggested plugins order is shown.

        new ItemDiscountAmountFullAggregatorPlugin(),

        # This plugin is replacing other tax calculation plugins in the stack and will use them as a fallback.
        # No other tax calculation plugins except for VertexCalculationPlugin should be present in the stack.
        new VertexCalculationPlugin(),

        new PriceToPayAggregatorPlugin(),

        //...
    ];
}

protected function getOrderCalculatorPluginStack(Container $container): array
{
    return [
        //...

        # Suggested plugins order is shown.

        new ItemDiscountAmountFullAggregatorPlugin(),

        # This plugin is replacing other tax calculation plugins in the stack and will use them as a fallback.
        # No other tax calculation plugins except for VertexCalculationPlugin should be present in the stack.
        new VertexCalculationPlugin(),

        new PriceToPayAggregatorPlugin(),

        //...
    ];
}

Register Fallback Calculation Plugins

Add order and quote Fallback Calculation Plugins to src/Pyz/Zed/Vertex/VertexDependencyProvider.php:

use Spryker\Zed\Calculation\Communication\Plugin\Calculator\ItemTaxAmountFullAggregatorPlugin;
use Spryker\Zed\Calculation\Communication\Plugin\Calculator\PriceToPayAggregatorPlugin;
use Spryker\Zed\Tax\Communication\Plugin\Calculator\TaxAmountAfterCancellationCalculatorPlugin;
use Spryker\Zed\Tax\Communication\Plugin\Calculator\TaxAmountCalculatorPlugin;
use Spryker\Zed\Tax\Communication\Plugin\Calculator\TaxRateAverageAggregatorPlugin;

/**
 * {@inheritDoc}
 *
 * @return array<\Spryker\Zed\CalculationExtension\Dependency\Plugin\CalculationPluginInterface>
 */
protected function getFallbackQuoteCalculationPlugins(): array
{
    return [
        # These plugins will be called if Vertex configuration is missing or Vertex is disabled.
        # Please note that this list includes PriceToPayAggregatorPlugin - this plugin isn't a part of tax calculation logic but it's required by TaxRateAverageAggregatorPlugin.
        new TaxAmountCalculatorPlugin(),
        new ItemTaxAmountFullAggregatorPlugin(),
        new PriceToPayAggregatorPlugin(),
        new TaxRateAverageAggregatorPlugin(),
    ];
}

/**
 * {@inheritDoc}
 *
 * @return array<\Spryker\Zed\CalculationExtension\Dependency\Plugin\CalculationPluginInterface>
 */
protected function getFallbackOrderCalculationPlugins(): array
{
    return [
        # These plugins will be called if Vertex configuration is missing or Vertex is disabled.
        # Please note that this list includes PriceToPayAggregatorPlugin - this plugin isn't a part of tax calculation logic but it's required by TaxAmountAfterCancellationCalculatorPlugin.
        new TaxAmountCalculatorPlugin(),
        new ItemTaxAmountFullAggregatorPlugin(),
        new PriceToPayAggregatorPlugin(),
        new TaxAmountAfterCancellationCalculatorPlugin(),
    ];
}

In general, getFallbackQuoteCalculationPlugins() and getFallbackOrderCalculationPlugins() methods should contain the tax calculation plugins, which are replaced by VertexCalculationPlugin in \Pyz\Zed\Calculation\CalculationDependencyProvider. The code snippet above is an example of such configuration based on the Spryker default tax calculation plugins. Tax calculation plugins moved:

  • from getQuoteCalculatorPluginStack method: TaxAmountCalculatorPlugin, ItemTaxAmountFullAggregatorPlugin, PriceToPayAggregatorPlugin, TaxRateAverageAggregatorPlugin
  • from getOrderCalculatorPluginStack method: TaxAmountCalculatorPlugin, ItemTaxAmountFullAggregatorPlugin, PriceToPayAggregatorPlugin, TaxAmountAfterCancellationCalculatorPlugin
Fallback behavior

There are three different failure scenarios where VertexCalculationPlugin might need to use a fallback logic:

  1. Vertex isn’t connected: fallback plugins defined in getFallbackQuoteCalculationPlugins() and getFallbackOrderCalculationPlugins() will be used to calculate taxes.
  2. Vertex is disabled: fallback plugins defined in getFallbackQuoteCalculationPlugins() and getFallbackOrderCalculationPlugins() will be used to calculate taxes.
  3. Vertex is not responding or is responding with an error: tax value will be set to zero, and the customer will be able to proceed with the checkout.

Register CalculableObject and order expander plugins

Add order and CalculableObject expander plugins to src/Pyz/Zed/Vertex/VertexDependencyProvider.php. The proposed plugins are examples, you can select which ones to register based on your requirements or create custom ones if needed.

use SprykerEco\Zed\Vertex\Communication\Plugin\Order\OrderCustomerWithVertexCodeExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Order\OrderExpensesWithVertexCodeExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Order\OrderItemProductOptionWithVertexCodeExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Order\OrderItemWithVertexSpecificFieldsExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Quote\CalculableObjectCustomerWithVertexCodeExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Quote\CalculableObjectExpensesWithVertexCodeExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Quote\CalculableObjectItemProductOptionWithVertexCodeExpanderPlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Quote\CalculableObjectItemWithVertexSpecificFieldsExpanderPlugin;

protected function getCalculableObjectVertexExpanderPlugins(): array
{
    return [
        // ... other plugins
        new CalculableObjectCustomerWithVertexCodeExpanderPlugin(),
        new CalculableObjectExpensesWithVertexCodeExpanderPlugin(),
        new CalculableObjectItemProductOptionWithVertexCodeExpanderPlugin(),
        new CalculableObjectItemWithVertexSpecificFieldsExpanderPlugin(),
    ];
}

protected function getOrderVertexExpanderPlugins(): array
{
    return [
        // ... other plugins
        new OrderCustomerWithVertexCodeExpanderPlugin(),
        new OrderExpensesWithVertexCodeExpanderPlugin(),
        new OrderItemProductOptionWithVertexCodeExpanderPlugin(),
        new OrderItemWithVertexSpecificFieldsExpanderPlugin(),
    ];
}

7. Configure the Shop Application dependency provider

Add the following code to src/Pyz/Yves/ShopApplication/ShopApplicationDependencyProvider.php:


namespace Pyz\Yves\ShopApplication;

use SprykerShop\Yves\ShopApplication\ShopApplicationDependencyProvider as SprykerShopApplicationDependencyProvider;
use SprykerShop\Yves\CartPage\Widget\CartSummaryHideTaxAmountWidget;

class ShopApplicationDependencyProvider extends SprykerShopApplicationDependencyProvider
{
    /**
     * @phpstan-return array<class-string<\Spryker\Yves\Kernel\Widget\AbstractWidget>>
     *
     * @return array<string>
     */
    protected function getGlobalWidgets(): array
    {
        return [
            //...

            # This widget is replacing Spryker default tax display in cart summary page with text stating that tax amount will be calculated during checkout process.
            CartSummaryHideTaxAmountWidget::class,
        ];
    }
}

If you have custom Yves templates or make your own Frontend, add CartSummaryHideTaxAmountWidget to your template. The core template is located at SprykerShop/Yves/CartPage/Theme/default/components/molecules/cart-summary/cart-summary.twig.

Here is an example with CartSummaryHideTaxAmountWidget:


<li class="list__item spacing-y">
    {{ 'cart.total.tax_total' | trans }}
    {% widget 'CartSummaryHideTaxAmountWidget' args [data.cart] only %}
    {% nowidget %}
        <span class="float-right">{{ data.cart.totals.taxTotal.amount | money(true, data.cart.currency.code) }}</span>
    {% endwidget %}
</li>

8. Optional: Sending tax invoices to Vertex and handling refunds

Configure payment config/Zed/oms/{your_payment_oms}.xmlas in the following example:

<?xml version="1.0"?>
<statemachine
    xmlns="spryker:oms-01"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="spryker:oms-01 http://static.spryker.com/oms-01.xsd"
>

    <process name="SomePaymentProcess" main="true">

        <!-- other configurations -->

        <states>

            <!-- other states -->

            <state name="tax invoice submitted" reserved="true" display="oms.state.paid"/>

            <!-- other states -->

        </states>

        <transitions>

            <!-- other transitions -->

            <transition happy="true">
                <source>paid</source> <!-- Suggested that paid transition should be the source, but it's up to you -->
                <target>tax invoice submitted</target>
                <event>submit tax invoice</event>
            </transition>

            <!-- other transitions -->

            <transition happy="true">
                <source>tax invoice submitted</source>

                <!-- Here are the contents of the target transition -->

            </transition>

            <!-- other transitions -->

        </transitions>

        <events>

            <!-- other events -->

            <event name="submit tax invoice" onEnter="true" command="Vertex/SubmitPaymentTaxInvoice"/>

            <!-- other events -->

        </events>

    </process>

</statemachine>

Register OMS plugins

Optional

This step is required only if you want to use invoicing functionality. Make sure isInvoicingEnabled() is set to true in VertexConfig.php.

Add OMS plugins to src/Pyz/Zed/Oms/OmsDependencyProvider.php:

use SprykerEco\Zed\Vertex\Communication\Plugin\Oms\Command\VertexSubmitPaymentTaxInvoicePlugin;
use SprykerEco\Zed\Vertex\Communication\Plugin\Oms\VertexOrderRefundedEventListenerPlugin;

# This configuration is necessary for Invoice functionality
protected function extendCommandPlugins(Container $container): Container
{
    $container->extend(self::COMMAND_PLUGINS, function (CommandCollectionInterface $commandCollection) {
        // ... other command plugins
        $commandCollection->add(new VertexSubmitPaymentTaxInvoicePlugin(), 'Vertex/SubmitPaymentTaxInvoice');

        return $commandCollection;
    });

    return $container;
}

# This configuration is necessary for Refund functionality
protected function getOmsEventTriggeredListenerPlugins(Container $container): array
{
    return [
        // ... other plugins
        new VertexOrderRefundedEventListenerPlugin(),
    ];
}

This configuration of getOmsEventTriggeredListenerPlugins method is required to ensure that the correct tax amount will be used during the refund process.

OMS configuration requirement

The refund functionality will only work if the OMS event is called refund.

Next step

Configure Vertex-specific metadata