Integrating CrefoPay

Edit on GitHub

This document shows how to integrate the CrefoPay system into your project.

Prerequisites

Before integrating CrefoPay into your project, make sure you installed and configured the CrefoPay module.

Integrating CrefoPay into your project

To integrate CrefoPay, do the following:

  1. Add shipment step plugin, payment subform plugins, and payment method handlers:
\Pyz\Yves\CheckoutPage\CheckoutPageDependencyProvider
<?php

namespace Pyz\Yves\CheckoutPage;

use Spryker\Shared\Nopayment\NopaymentConfig;
use Spryker\Yves\Kernel\Container;
use Spryker\Yves\Kernel\Plugin\Pimple;
use Spryker\Yves\Nopayment\Plugin\NopaymentHandlerPlugin;
use Spryker\Yves\Payment\Plugin\PaymentFormFilterPlugin;
use Spryker\Yves\StepEngine\Dependency\Plugin\Form\SubFormPluginCollection;
use Spryker\Yves\StepEngine\Dependency\Plugin\Handler\StepHandlerPluginCollection;
use SprykerEco\Shared\CrefoPay\CrefoPayConfig;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\CrefoPayPaymentExpanderPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\CrefoPayQuoteExpanderPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayBillSubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayCashOnDeliverySubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayCreditCard3DSubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayCreditCardSubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayDirectDebitSubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayPayPalSubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPayPrepaidSubFormPlugin;
use SprykerEco\Yves\CrefoPay\Plugin\StepEngine\SubForm\CrefoPaySofortSubFormPlugin;
use SprykerShop\Yves\CheckoutPage\CheckoutPageDependencyProvider as SprykerShopCheckoutPageDependencyProvider;
use SprykerShop\Yves\CustomerPage\Form\CheckoutAddressCollectionForm;
use SprykerShop\Yves\CustomerPage\Form\CustomerCheckoutForm;
use SprykerShop\Yves\CustomerPage\Form\DataProvider\CheckoutAddressFormDataProvider;
use SprykerShop\Yves\CustomerPage\Form\GuestForm;
use SprykerShop\Yves\CustomerPage\Form\LoginForm;
use SprykerShop\Yves\CustomerPage\Form\RegisterForm;
use SprykerShop\Yves\SalesOrderThresholdWidget\Plugin\CheckoutPage\SalesOrderThresholdWidgetPlugin;

class CheckoutPageDependencyProvider extends SprykerShopCheckoutPageDependencyProvider
{
    public const PLUGIN_CREFO_PAY_SHIPMENT_STEP = 'PLUGIN_CREFO_PAY_SHIPMENT_STEP';

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    public function provideDependencies(Container $container): Container
    {
        $container = parent::provideDependencies($container);
        $container = $this->extendShipmentHandlerPluginCollection($container);
        $container = $this->extendSubFormPluginCollection($container);
        $container = $this->extendPaymentMethodHandler($container);

        return $container;
    }

...

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function extendShipmentHandlerPluginCollection(Container $container): Container
    {
        $container->extend(static::PLUGIN_SHIPMENT_HANDLER, function (StepHandlerPluginCollection $shipmentHandlerPlugins) {
            $shipmentHandlerPlugins->add(new CrefoPayQuoteExpanderPlugin(), static::PLUGIN_CREFO_PAY_SHIPMENT_STEP);

            return $shipmentHandlerPlugins;
        });

        return $container;
    }

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function extendSubFormPluginCollection(Container $container): Container
    {
        $container->extend(static::PAYMENT_SUB_FORMS, function (SubFormPluginCollection $paymentSubFormPluginCollection) {
            $paymentSubFormPluginCollection->add(new CrefoPayBillSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayCashOnDeliverySubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayDirectDebitSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayPayPalSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayPrepaidSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPaySofortSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayCreditCardSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayCreditCard3DSubFormPlugin());

            return $paymentSubFormPluginCollection;
        });

        return $container;
    }

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function extendPaymentMethodHandler(Container $container): Container
    {
        $container->extend(static::PAYMENT_METHOD_HANDLER, function (StepHandlerPluginCollection $paymentMethodHandlerCollection) {
            $paymentMethodHandlerCollection->add(new NopaymentHandlerPlugin(), NopaymentConfig::PAYMENT_PROVIDER_NAME);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_BILL);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_CASH_ON_DELIVERY);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_DIRECT_DEBIT);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_PAY_PAL);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_PREPAID);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_SOFORT);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_CREDIT_CARD);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_CREDIT_CARD_3D);

            return $paymentMethodHandlerCollection;
        });

        return $container;
    }
}
...

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function extendShipmentHandlerPluginCollection(Container $container): Container
    {
        $container->extend(static::PLUGIN_SHIPMENT_HANDLER, function (StepHandlerPluginCollection $shipmentHandlerPlugins) {
            $shipmentHandlerPlugins->add(new CrefoPayQuoteExpanderPlugin(), static::PLUGIN_CREFO_PAY_SHIPMENT_STEP);

            return $shipmentHandlerPlugins;
        });

        return $container;
    }

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function extendSubFormPluginCollection(Container $container): Container
    {
        $container->extend(static::PAYMENT_SUB_FORMS, function (SubFormPluginCollection $paymentSubFormPluginCollection) {
            $paymentSubFormPluginCollection->add(new CrefoPayBillSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayCashOnDeliverySubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayDirectDebitSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayPayPalSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayPrepaidSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPaySofortSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayCreditCardSubFormPlugin());
            $paymentSubFormPluginCollection->add(new CrefoPayCreditCard3DSubFormPlugin());

            return $paymentSubFormPluginCollection;
        });

        return $container;
    }

    /**
     * @param \Spryker\Yves\Kernel\Container $container
     *
     * @return \Spryker\Yves\Kernel\Container
     */
    protected function extendPaymentMethodHandler(Container $container): Container
    {
        $container->extend(static::PAYMENT_METHOD_HANDLER, function (StepHandlerPluginCollection $paymentMethodHandlerCollection) {
            $paymentMethodHandlerCollection->add(new NopaymentHandlerPlugin(), NopaymentConfig::PAYMENT_PROVIDER_NAME);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_BILL);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_CASH_ON_DELIVERY);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_DIRECT_DEBIT);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_PAY_PAL);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_PREPAID);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_SOFORT);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_CREDIT_CARD);
            $paymentMethodHandlerCollection->add(new CrefoPayPaymentExpanderPlugin(), CrefoPayConfig::CREFO_PAY_PAYMENT_METHOD_CREDIT_CARD_3D);

            return $paymentMethodHandlerCollection;
        });

        return $container;
    }
}

  1. Extend ShipmentStep with the filtering logic for payment methods:

\Pyz\Yves\CheckoutPage\Process\Steps\ShipmentStep

<?php

namespace Pyz\Yves\CheckoutPage\Process\Steps;

use Generated\Shared\Transfer\CrefoPayApiCompanyTransfer;
use Pyz\Yves\CheckoutPage\CheckoutPageDependencyProvider;
use Spryker\Shared\Kernel\Transfer\AbstractTransfer;
use SprykerShop\Yves\CheckoutPage\Process\Steps\ShipmentStep as SprykerShopShipmentStep;
use Symfony\Component\HttpFoundation\Request;

class ShipmentStep extends SprykerShopShipmentStep
{
    /**
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @param \Generated\Shared\Transfer\QuoteTransfer $quoteTransfer
     *
     * @return \Generated\Shared\Transfer\QuoteTransfer
     */
    public function execute(Request $request, AbstractTransfer $quoteTransfer)
    {
        $quoteTransfer = parent::execute($request, $quoteTransfer);
        $crefoPayPlugin = $this->shipmentPlugins->get(CheckoutPageDependencyProvider::PLUGIN_CREFO_PAY_SHIPMENT_STEP);

        return $crefoPayPlugin->addToDataClass($request, $quoteTransfer);
    }
}
  1. Extend StepFactory to be used by project-level ShipmentStep:

\Pyz\Yves\CheckoutPage\Process\StepFactory

<?php

namespace Pyz\Yves\CheckoutPage\Process;

use Pyz\Yves\CheckoutPage\Process\Steps\ShipmentStep;
use SprykerShop\Yves\CheckoutPage\Plugin\Router\CheckoutPageRouteProviderPlugin;
use SprykerShop\Yves\CheckoutPage\Process\StepFactory as SprykerShopStepFactory;

/**
 * @method \SprykerShop\Yves\CheckoutPage\CheckoutPageConfig getConfig()
 */
class StepFactory extends SprykerShopStepFactory
{
    /**
     * @return \SprykerShop\Yves\CheckoutPage\Process\Steps\ShipmentStep
     */
    public function createShipmentStep()
    {
        return new ShipmentStep(
            $this->getCalculationClient(),
            $this->getShipmentPlugins(),
            $this->createShipmentStepPostConditionChecker(),
            $this->createGiftCardItemsChecker(),
            CheckoutPageRouteProviderPlugin::ROUTE_NAME_CHECKOUT_SHIPMENT,
            $this->getConfig()->getEscapeRoute(),
            $this->getCheckoutShipmentStepEnterPreCheckPlugins()
        );
    }
}
  1. Extend CheckoutPageFactory to be used by the project-level StepFactory:

\Pyz\Yves\CheckoutPage\CheckoutPageFactory

<?php

/**
 * This file is part of the Spryker Suite.
 * For full license information, please view the LICENSE file that was distributed with this source code.
 */

namespace Pyz\Yves\CheckoutPage;

use Pyz\Yves\CheckoutPage\Process\StepFactory;
use SprykerShop\Yves\CheckoutPage\CheckoutPageFactory as SprykerShopCheckoutPageFactory;

class CheckoutPageFactory extends SprykerShopCheckoutPageFactory
{
    /**
     * @return \SprykerShop\Yves\CheckoutPage\Process\StepFactory
     */
    public function createStepFactory()
    {
        return new StepFactory();
    }
}
  1. Extend the checkout page layout to add jQuery:

Pyz/Yves/CheckoutPage/Theme/default/templates/page-layout-checkout/page-layout-checkout.twig

{% extends template('page-layout-checkout', '@SprykerShop:CheckoutPage') %}

{% block headScripts %}
    {{ parent() }}

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js" type="text/javascript"></script>
{% endblock %}

  1. Extend payment Twig with CrefoPay payment methods:

Demo Shop template extension (a B2C theme example)

Pyz/Yves/CheckoutPage/Theme/default/views/payment/payment.twig
{% extends view('payment', '@SprykerShop:CheckoutPage') %}

{% define data = {
    customForms: {
        'crefoPay/bill': ['bill', 'crefoPay'],
        'crefoPay/cash-on-delivery': ['cash-on-delivery', 'crefoPay'],
        'crefoPay/direct-debit': ['direct-debit', 'crefoPay'],
        'crefoPay/paypal': ['paypal', 'crefoPay'],
        'crefoPay/prepaid': ['prepaid', 'crefoPay'],
        'crefoPay/sofort': ['sofort', 'crefoPay'],
        'crefoPay/credit-card': ['credit-card', 'crefoPay'],
        'crefoPay/credit-card-3d': ['credit-card-3d', 'crefoPay']
    },
} %}

{% block content %}
    {% include molecule('script-loader') with {
        class: 'js-crefopay-payment-form__script-loader',
        attributes: {
            src: 'https://libs.crefopay.de/3.0/secure-fields.js'
        },
    } only %}

    {% include atom('crefopay-checkbox-helper', 'CrefoPay') with {
        attributes: {
            'trigger-selector': '.toggler-radio__input',
            'payment-container-selector': '.js-payment-method-crefoPay',
            'target-selector': '.radio__input',
            'custom-attribute-name': 'data-crefopay',
            'custom-attribute-value': 'paymentMethod',
        },
    } only %}

    {% embed molecule('form') with {
        modifiers: ['checkout-actions', 'checkout-form-elements'],
        data: {
            form: data.forms.payment,
            submit: {
                enable: true,
                text: 'checkout.step.summary' | trans,
                class: 'form__action--checkout button  button--large button--expand',
            },
            cancel: {
                enable: true,
                url: data.backUrl,
                text: 'general.back.button' | trans,
                class: 'form__action--checkout button button--hollow button--expand',
            },
            options: {
                attr: {
                    novalidate: 'novalidate',
                    id: 'payment-form',
                }
            },
        },
        embed: {
            customForms: data.customForms,
        },
    } only %}
        {% block fieldset %}
            {% for name, choices in data.form.paymentSelection.vars.choices %}
                {% set paymentProviderIndex = loop.index0 %}

                <div class="js-payment-method-{{ name }}">
                    {% embed molecule('list-switches') with {
                        modifiers: ['register-type', 'layout-width', 'one-column'],
                        data: {
                            form: data.form.paymentSelection,
                            choices: choices,
                            rowAttrClass: 'toggler-radio--with-bg',
                            targetClassName: 'js-payment-method-',
                            providerIndex: paymentProviderIndex,
                        },
                    } only %}
                        {% block item %}
                            {% set fullIndex = loop.index ~ '-' ~ data.providerIndex %}

                            {{ form_row(data.form[key], {
                                label: data.form[key].vars.label,
                                required: false,
                                component: data.targetClassName ? molecule('toggler-radio'),
                                rowAttr: {
                                    class: data.rowAttrClass,
                                },
                                attributes: {
                                    'target-class-name': data.targetClassName ? data.targetClassName ~ fullIndex,
                                    checked: choice.value == data.providerIndex,
                                    'target-payment-form-class-name': 'js-payment-method-' ~ loop.index ~ '-' ~ data.providerIndex,
                                },
                            }) }}

                            {% if key == 0 %}
                                <div class="{{ config.name }}__img-wrap">
                                    <img class="{{ config.name }}__img" src="{{ publicPath('images/logo-visa.png') }}" alt="Visa">
                                    <img class="{{ config.name }}__img" src="{{ publicPath('images/logo-mastercard.png') }}" alt="Mastercard">
                                </div>
                            {% endif %}
                        {% endblock %}
                    {% endembed %}

                    {% for key, choice in choices %}
                        {% embed molecule('form') with {
                            class: 'spacing-bottom spacing-bottom--bigger',
                            modifiers: ['grid-indent', 'checkout-form-elements'],
                            data: {
                                form: data.form[data.form.paymentSelection[key].vars.value],
                                enableStart: false,
                                enableEnd: false,
                                layout: {
                                    'card_number': 'col col--sm-12 col--lg-6',
                                    'name_on_card': 'col col--sm-12 col--lg-6',
                                    'card_expires_month': 'col col--sm-12 col--md-6 col--lg-3 col--bottom',
                                    'card_expires_year': 'col col--sm-12 col--md-6 col--lg-3 col--bottom',
                                    'card_security_code': 'col col--sm-12 col--lg-6 col--bottom',
                                },
                            },
                            embed: {
                                name: name,
                                customForms: embed.customForms,
                                index: loop.index ~ '-' ~ paymentProviderIndex,
                                toggler: data.form.paymentSelection[key],
                            },
                        } only %}
                            {% block fieldset %}
                                <div class="js-payment-method-{{ embed.index }} js-payment-form-{{ embed.name }} {% if embed.index != '1-0' %} is-hidden{% endif %}">
                                    <h2 class="title title--primary">{{ embed.toggler.vars.label | trans }}</h2>

                                    {% if embed.customForms[data.form.vars.template_path] is not defined %}
                                        {{ parent() }}
                                    {% else %}
                                        {% set viewName = embed.customForms[data.form.vars.template_path] | first %}
                                        {% set moduleName = embed.customForms[data.form.vars.template_path] | last %}
                                        {% include view(viewName, moduleName) ignore missing with {
                                            form: data.form.parent,
                                        } only %}
                                    {% endif %}
                                </div>
                            {% endblock %}
                        {% endembed %}
                    {% endfor %}
                </div>
            {% endfor %}
        {% endblock %}
    {% endembed %}
{% endblock %}

  1. In the project root, add an alias for the CrefoPay module to tsconfig.json:

tsconfig.json:

{
    "compilerOptions": {
        ...
        "paths": {
            ...
            "SprykerEcoCrefoPay/*": [
                "./vendor/spryker-eco/crefo-pay/src/SprykerEco/Yves/CrefoPay/Theme/default/*"
            ]
        }
    },
    ...
}
  1. Extend the crefopay-checkbox-helper atom of the CrefoPay module:

\Pyz\Yves\CrefoPay\Theme\default\components\atoms\crefopay-checkbox-helper\crefopay-checkbox-helper.ts

import SprykerEcoCrefopayCheckboxHelper from 'SprykerEcoCrefoPay/components/atoms/crefopay-checkbox-helper/crefopay-checkbox-helper';

export default class CrefopayCheckboxHelper extends SprykerEcoCrefopayCheckboxHelper {

    protected readyCallback(): void {}

    protected init(): void {
        super.readyCallback();
    }

    protected checkCheckbox(checkboxTrigger: EventTarget): void {
        const targetFormContainerClassName = this.getTargetPaymentFormClassName(<HTMLElement>checkboxTrigger);
        const formContainer = <HTMLElement>this.paymentForm.getElementsByClassName(targetFormContainerClassName)[0];
        const checkbox: HTMLInputElement = formContainer.querySelector(this.targetSelector);

        checkbox.checked = true;
    }

    protected getTargetPaymentFormClassName(element: HTMLElement): string {
        return element.getAttribute('target-payment-form-class-name');
    }
}

  1. Add an entry point for the extended crefopay-checkbox-helper atom:

\Pyz\Yves\CrefoPay\Theme\default\components\atoms\crefopay-checkbox-helper\index.ts

import register from 'ShopUi/app/registry';
export default register('crefopay-checkbox-helper', () => import(/* webpackMode: "lazy" */'./crefopay-checkbox-helper'));
  1. Override layout of the crefopay-payment-form molecule:
\Pyz\Yves\CrefoPay\Theme\default\components\molecule\crefopay-payment-form\crefopay-payment-form.twig
{% extends model('component') %}

{% define config = {
    name: 'crefopay-payment-form',
    tag: 'crefopay-payment-form',
} %}

{% define data = {
    paymentMethodSubForm: required,
    shopPublicKey: required,
    orderId: required,
    fields: [],
    endpointUrl: required,
    placeholders: required
} %}

{% set crefoPayConfig = {
    url: data.endpointUrl,
    placeholders: {
        accountHolder: data.placeholders.accountHolder,
        number: data.placeholders.number,
        cvv: data.placeholders.cvv
    }
} %}

{% define attributes = {
    'shop-public-key': data.shopPublicKey,
    'order-id': data.orderId,
    'crefo-pay-config': crefoPayConfig | json_encode(),
    'payment-form-selector': '#payment-form',
    'class-to-toggle': 'is-hidden',
    'payment-container-selector': '.form',
    'payment-toggler-selector': '[class*="js-payment-form-crefoPay"]',
    'toggle-class-to-check': 'is-hidden'
} %}

{% block body %}
    {% macro crefopayField(name, attribute, blockName) %}
        <div class="spacing-y">
            <label class="label label--required">{{ name }}</label>
            <div class="{{ blockName }}__input-container" data-crefopay-placeholder="{{ attribute }}"></div>
        </div>
    {% endmacro %}

    {% block requestForm %}
        {% import _self as macros %}

        <div class="is-hidden">
            {{ form_widget(data.paymentMethodSubForm) }}
        </div>

        {% for field in data.fields %}
            {{ macros.crefopayField(field.name, field.attribute, config.name) }}
        {% endfor %}

        <div class="{{ config.name }}__error {{ config.jsName }}__error spacing-y is-hidden">
            {{ 'crefopay.required_notification' | trans }}
        </div>
    {% endblock %}
{% endblock %}

  1. Add a route provider plugin:

\Pyz\Yves\Router\RouterDependencyProvider.php

<?php

namespace Pyz\Yves\Router;

use Spryker\Yves\Router\RouterDependencyProvider as SprykerRouterDependencyProvider;
use SprykerEco\Yves\CrefoPay\Plugin\Router\CrefoPayRouteProviderPlugin;

class RouterDependencyProvider extends SprykerRouterDependencyProvider
{
    /**
     * @return \Spryker\Yves\RouterExtension\Dependency\Plugin\RouteProviderPluginInterface[]
     */
    protected function getRouteProvider(): array
    {
        return [
            ...
            new CrefoPayRouteProviderPlugin(),
        ];
    }
}
  1. Add checkout plugins:
\Pyz\Zed\Checkout\CheckoutDependencyProvider.php
<?php

namespace Pyz\Zed\Checkout;

use Spryker\Zed\Checkout\CheckoutDependencyProvider as SprykerCheckoutDependencyProvider;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Checkout\CrefoPayDoSaveOrderPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Checkout\CrefoPayPostSaveHookPlugin;

class CheckoutDependencyProvider extends SprykerCheckoutDependencyProvider
{
    /**
     * @param \Spryker\Zed\Kernel\Container $container
     *
     * @return \Spryker\Zed\Checkout\Dependency\Plugin\CheckoutSaveOrderInterface[]
     */
    protected function getCheckoutOrderSavers(Container $container)
    {
        /** @var \Spryker\Zed\Checkout\Dependency\Plugin\CheckoutSaveOrderInterface[] $plugins */
        $plugins = [
            ...
            new CrefoPayDoSaveOrderPlugin(),
        ];

        return $plugins;
    }

    /**
     * @param \Spryker\Zed\Kernel\Container $container
     *
     * @return \Spryker\Zed\Checkout\Dependency\Plugin\CheckoutPostSaveHookInterface[]
     */
    protected function getCheckoutPostHooks(Container $container)
    {
        return [
            ...
            new CrefoPayPostSaveHookPlugin(),
        ];
    }
}
  1. Add OMS commands and conditions:
\Pyz\Zed\Oms\OmsDependencyProvider.php
<?php

namespace Pyz\Zed\Oms;

use Spryker\Zed\Oms\OmsDependencyProvider as SprykerOmsDependencyProvider;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Command\CancelPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Command\CapturePlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Command\FinishPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Command\RefundPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsAcknowledgePendingReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsCanceledReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsCancelCallSuccessfulPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsCiaPendingReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsPaidReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsCaptureCallSuccessfulPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsDoneReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsExpiredReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsFinishCallSuccessfulPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsChargeBackReceivedPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsRefundCallSuccessfulPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsReserveCallSuccessfulPlugin;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\Oms\Condition\IsMerchantPendingReceivedPlugin;

class OmsDependencyProvider extends SprykerOmsDependencyProvider
{
    /**
     * @param \Spryker\Zed\Kernel\Container $container
     *
     * @return \Spryker\Zed\Kernel\Container
     */
    public function provideBusinessLayerDependencies(Container $container): Container
    {
        $container = parent::provideBusinessLayerDependencies($container);
        $container = $this->extendCommandPlugins($container);
        $container = $this->extendConditionPlugins($container);

        return $container;
    }

    /**
     * @param \Spryker\Zed\Kernel\Container $container
     *
     * @return \Spryker\Zed\Kernel\Container
     */
    protected function extendCommandPlugins(Container $container): Container
    {
        $container->extend(self::COMMAND_PLUGINS, function (CommandCollectionInterface $commandCollection) {
            ...
            $commandCollection->add(new CancelPlugin(), 'CrefoPay/Cancel');
            $commandCollection->add(new CapturePlugin(), 'CrefoPay/Capture'); //Or you can use CaptureSplitPlugin instead. OMS command name (second param) should not be changed.
            $commandCollection->add(new RefundPlugin(), 'CrefoPay/Refund'); ////Or you can use RefundSplitPlugin instead. OMS command name (second param) should not be changed.
            $commandCollection->add(new FinishPlugin(), 'CrefoPay/Finish');

            return $commandCollection;
        });

        return $container;
    }

    /**
     * @param \Spryker\Zed\Kernel\Container $container
     *
     * @return \Spryker\Zed\Kernel\Container
     */
    protected function extendConditionPlugins(Container $container): Container
    {
        $container->extend(OmsDependencyProvider::CONDITION_PLUGINS, function (ConditionCollectionInterface $conditionCollection) {
            ...
            $conditionCollection->add(new IsReserveCallSuccessfulPlugin(), 'CrefoPay/IsReserveCallSuccessful');
            $conditionCollection->add(new IsAcknowledgePendingReceivedPlugin(), 'CrefoPay/IsAcknowledgePendingReceived');
            $conditionCollection->add(new IsMerchantPendingReceivedPlugin(), 'CrefoPay/IsMerchantPendingReceived');
            $conditionCollection->add(new IsCiaPendingReceivedPlugin(), 'CrefoPay/IsCiaPendingReceived');
            $conditionCollection->add(new IsCancelCallSuccessfulPlugin(), 'CrefoPay/IsCancelCallSuccessful');
            $conditionCollection->add(new IsCanceledReceivedPlugin(), 'CrefoPay/IsCanceledReceived');
            $conditionCollection->add(new IsExpiredReceivedPlugin(), 'CrefoPay/IsExpiredReceived');
            $conditionCollection->add(new IsCaptureCallSuccessfulPlugin(), 'CrefoPay/IsCaptureCallSuccessful');
            $conditionCollection->add(new IsPaidReceivedPlugin(), 'CrefoPay/IsPaidReceived');
            $conditionCollection->add(new IsRefundCallSuccessfulPlugin(), 'CrefoPay/IsRefundCallSuccessful');
            $conditionCollection->add(new IsChargeBackReceivedPlugin(), 'CrefoPay/IsChargeBackReceived');
            $conditionCollection->add(new IsFinishCallSuccessfulPlugin(), 'CrefoPay/IsFinishCallSuccessful');
            $conditionCollection->add(new IsDoneReceivedPlugin(), 'CrefoPay/IsDoneReceived');

            return $conditionCollection;
        });

        return $container;
    }
}
  1. Extend PaymentDependencyProvider with a plugin for filtering payment methods:

Pyz\Zed\Payment\PaymentDependencyProvider.php

<?php

namespace Pyz\Zed\Payment;

use Spryker\Zed\Payment\PaymentDependencyProvider as SprykerPaymentDependencyProvider;
use SprykerEco\Zed\CrefoPay\Communication\Plugin\CrefoPayPaymentMethodFilterPlugin;

class PaymentDependencyProvider extends SprykerPaymentDependencyProvider
{
    /**
     * @return \Spryker\Zed\Payment\Dependency\Plugin\Payment\PaymentMethodFilterPluginInterface[]
     */
    protected function getPaymentMethodFilterPlugins()
    {
        return [
			...
            new CrefoPayPaymentMethodFilterPlugin(),
        ];
    }
}
Note

If an additional validation for input fields that are filled by a customer is needed, we recommend creating a plugin that implements \Spryker\Zed\CheckoutExtension\Dependency\Plugin\CheckoutPreConditionPluginInterface. The plugin must be added to the Pyz\Zed\Checkout\CheckoutDependencyProvider::getCheckoutPreConditions() method.

For more details, see Checkout process review and implementation.