Changing Credit Card Icons on the Magento 2 Checkout

When using a default payment method on the Magento checkout, such as Braintree, you may notice the use of different credit card type icons. Going about changing credit card icons on the Magento 2 checkout can be done by following the steps within this post.

Changing Credit Card Icons on the Magento 2 Checkout

Magento by default adds a grayscale filter to the credit card icons to make them appear black and white.

.checkout-payment-method .credit-card-types img {
    -webkit-filter: grayscale(100%);
    -webkit-transition: all .6s ease;
}

This can be removed using LESS/CSS should you not want this effect.

The template responsible for rendering the payment icons is the cc-form.html Knockout template found within the vendor/magento/module-payment/view/frontend/web/template/payment. Note that the template path may differ if you are using a different/third party payment method that uses the same Magento payment icons.

Within this template, locate the <img> element, and you’ll notice that the src attribute contains $parent.getIcons(item.value).url,.

<!--ko if: $parent.getIcons(item.value) -->
<img data-bind="attr: {
    'src': $parent.getIcons(item.value).url,
    'alt': item.type,
    'width': $parent.getIcons(item.value).width,
    'height': $parent.getIcons(item.value).height
}">
<!--/ko-->

The getIcons() function is used within the vendor/magento/module-payment/view/frontend/web/js/view/payment/cc-form.js file.

/**
 * Get payment icons
 * @param {String} type
 * @returns {Boolean}
 */
getIcons: function (type) {
    return window.checkoutConfig.payment.ccform.icons.hasOwnProperty(type) ?
        window.checkoutConfig.payment.ccform.icons[type]
        : false;
},

window.checkoutConfig is defined within the vendor/magento/module-checkout/view/frontend/templates/onepage.phtml template file.

window.checkoutConfig = <?= /* @escapeNotVerified */ $block->getSerializedCheckoutConfig() ?>;

The corresponding block to the onepage.phtml file, vendor/magento/module-checkout/Block/Onepage.php contains the getSerializedCheckoutConfig() and subsequent getCheckoutConfig() methods.

<?php
namespace Magento\Checkout\Block;

class Onepage extends \Magento\Framework\View\Element\Template
{
    ....

    /**
     * Retrieve checkout configuration
     *
     * @return array
     * @codeCoverageIgnore
     */
    public function getCheckoutConfig()
    {
        return $this->configProvider->getConfig();
    }

    ....

    /**
     * @return bool|string
     * @since 100.2.0
     */
    public function getSerializedCheckoutConfig()
    {
        return json_encode($this->getCheckoutConfig(), JSON_HEX_TAG);
    }
}

Magento’s CompositeConfigProvider class contains the getConfig() method, which iterates over the configProviders and merges and returns their configuration.

<?php
namespace Magento\Checkout\Model;

/**
 * Composite checkout configuration provider.
 *
 * @see \Magento\Checkout\Model\ConfigProviderInterface
 * @api
 */
class CompositeConfigProvider implements ConfigProviderInterface
{
    /**
     * @var ConfigProviderInterface[]
     */
    private $configProviders;

    /**
     * @param ConfigProviderInterface[] $configProviders
     * @codeCoverageIgnore
     */
    public function __construct(
        array $configProviders
    ) {
        $this->configProviders = $configProviders;
    }

    /**
     * {@inheritdoc}
     */
    public function getConfig()
    {
        $config = [];
        foreach ($this->configProviders as $configProvider) {
            $config = array_merge_recursive($config, $configProvider->getConfig());
        }
        return $config;
    }
}

One of the configProviders includes the Magento\Payment\Model\CcConfigProvider class. This class contains the getIcons() method.

<?php
namespace Magento\Payment\Model;

use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Framework\View\Asset\Source;

/**
 * Class CcConfigProvider
 *
 * @api
 * @since 100.0.2
 */
class CcConfigProvider implements ConfigProviderInterface
{
    /**
     * @var array
     */
    private $icons = [];

    /**
     * @var CcConfig
     */
    protected $ccConfig;

    /**
     * @var \Magento\Framework\View\Asset\Source
     */
    protected $assetSource;

    /**
     * @param CcConfig $ccConfig
     * @param Source $assetSource
     */
    public function __construct(
        CcConfig $ccConfig,
        Source $assetSource
    ) {
        $this->ccConfig = $ccConfig;
        $this->assetSource = $assetSource;
    }

    /**
     * {@inheritdoc}
     */
    public function getConfig()
    {
        return [
            'payment' => [
                'ccform' => [
                    'icons' => $this->getIcons()
                ]
            ]
        ];
    }

    /**
     * Get icons for available payment methods
     *
     * @return array
     */
    public function getIcons()
    {
        if (!empty($this->icons)) {
            return $this->icons;
        }

        $types = $this->ccConfig->getCcAvailableTypes();
        foreach (array_keys($types) as $code) {
            if (!array_key_exists($code, $this->icons)) {
                $asset = $this->ccConfig->createAsset('Magento_Payment::images/cc/' . strtolower($code) . '.png');
                $placeholder = $this->assetSource->findSource($asset);
                if ($placeholder) {
                    list($width, $height) = getimagesize($asset->getSourceFile());
                    $this->icons[$code] = [
                        'url' => $asset->getUrl(),
                        'width' => $width,
                        'height' => $height
                    ];
                }
            }
        }

        return $this->icons;
    }
}

Here, Magento uses the credit card type code to create an image asset using the createAsset() method.

A plugin can be used to override the images using a afterGetIcons() method.

Assuming that you have registered a custom module with a registration.php and module.xml file, add a di.xml declaring the plugin class.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Payment\Model\CcConfigProvider">
        <plugin name="[module]_ccicons_plugin" type="[Vendor]\[Module]\Plugin\CcConfigProviderPlugin" sortOrder="1" />
    </type>
</config>

Now add the plugin class, which includes the afterGetIcons() method.

In the below example, the VI credit card type’s image is modified.

<?php
namespace [Vendor]\[Module]\Plugin;

class CcConfigProviderPlugin
{
    /**
     * @var \Magento\Framework\View\Asset\Repository
     */
    private $assetRepo;

    /**
     * CcConfigProviderPlugin constructor.
     *
     * @param \Magento\Framework\View\Asset\Repository $assetRepo
     */
    public function __construct(
        \Magento\Framework\View\Asset\Repository $assetRepo
    )
    {
        $this->assetRepo = $assetRepo;
    }

    /**
     * @param \Magento\Payment\Model\CcConfigProvider $subject
     * @param $result
     * @return mixed
     */
    public function afterGetIcons(\Magento\Payment\Model\CcConfigProvider $subject, $result)
    {
        if (isset($result['VI'])) {
            $result['VI']['url'] = $this->assetRepo->getUrl('[Vendor]_[Module]::images/46x30.png');
            $result['VI']['width'] = 46;
            $result['VI']['height'] = 30;
        }
        return $result;
    }
}

The placeholder image is added within the custom module’s view/frontend/web/images directory.

Upon refreshing the checkout page, the placeholder image is used instead of the default Visa icon.

Changing Credit Card Icons on the Magento 2 Checkout

Note: This article is based on Magento Open Source version 2.2.