Custom Plugin Creation Guide

Creating Plugin

Plugin creation consists of several stages, which are covered below in this section.

Script Writing

Let us write a simple plugin for integration with European Central Bank (ECB) exchange rates API. ECB exchange rates can be received using an HTTP request at a special URL. For XML format it is https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml.

The main part of the plugin is its main script, named after plugin. In our case it is ECB.php. It will be responsible for processing of SDK requests. It must implement all mandatory methods from SDK API.

  1. The first method there is GetConfig. Because there are no client-specific parameters in ECB API, no configuration is required. For example, let us add a list of quote currency codes, for which we want the plugin to receive exchange rates.

    Copy
    function ECB_GetConfig()
    {
        return array(
            'friendlyName' => 'European Central Bank',
            'parameters' => array(
                array(
                    'name' => 'quote_currencies',
                    'friendlyName' => 'Comma separated list of quote currency ISO codes for Euro',
                    'type' => 'text',
                    'size' => 200,
                    'required' => false)
            )
        );
    }
  2. The method that lists currencies supported by the plugin (GetSupportedCurrencies) can be implemented as follows:

    Copy

    function ECB_GetSupportedCurrencies()

    function ECB_GetSupportedCurrencies()
    {
        $result = array();

        $document = new DOMDocument();
        $document->preserveWhiteSpace = FALSE;

        $response = file_get_contents(URL);
        $document->loadXML($response);

        $parentNode = $document->getElementsByTagName('Cube')->item(0);
        foreach ($parentNode->childNodes as $childNode) {
            foreach ($childNode->childNodes as $exchangeRateNode) {
                $currency = $exchangeRateNode->getAttribute('currency');
                array_push($result, $currency);
            }
        }

        sort($result);
        return $result;
    }
  3. The next methods to be implemented are ValidateConfig and TestConnection methods.

    Copy
    function ECB_ValidateConfig($params)
    {
        $result = array();
        if (isset($params['config']['quote_currencies'])) {
            $supported_currencies = ECB_GetSupportedCurrencies();
            $quote_currencies = array_unique(explode(',', $params['config']['quote_currencies']));
            foreach ($quote_currencies as $quote_currency) {
                $trimmed = trim($quote_currency);
                if ($trimmed === '') {
                    continue;
                }
                if (!in_array($trimmed, $supported_currencies)) {
                    $result['STATUS'] = 'DECLINED';
                    $result['TEXT'] = 'Not supported currency: ' . $trimmed;
                    return $result;
                }
            }
        }

        $result['STATUS'] = 'APPROVED';
        return $result;
    }

    const URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';

    function ECB_TestConnection($params)
    {
        $result = array();

        $headers = get_headers(URL);
        if (in_array('HTTP/1.1 200 OK', $headers)) {
            $result['STATUS'] = 'APPROVED';
        } else {
            $result['STATUS'] = 'DECLINED';
            $result['TEXT'] = 'Unexpected response status code received';
        }

        return $result;
    }
  4. And the last remaining is the method for getting exchange rates: GetRates.

    Copy
    function ECB_GetRates($params)
    {
        $rates = array();

        $document = new DOMDocument();
        $document->preserveWhiteSpace = FALSE;

        try {
            if (isset($params['config']['quote_currencies'])) {
                $quote_currencies = array_unique(explode(',', $params['config']['quote_currencies']));
            }

            $response = file_get_contents(URL);
            $document->loadXML($response);

            $parentNode = $document->getElementsByTagName('Cube')->item(0);
            foreach ($parentNode->childNodes as $childNode) {
                foreach ($childNode->childNodes as $exchangeRateNode) {
                    $currency = $exchangeRateNode->getAttribute('currency');
                    $rate = $exchangeRateNode->getAttribute('rate');

                    if (!isset($quote_currencies) || in_array($currency, $quote_currencies)) {
                        $exchangeRate = array('code' => $currency, 'rate' => $rate);
                        array_push($rates, $exchangeRate);
                    }
                }
            }
        } catch (Exception $e) {
                $error = array();
                $error['TEXT'] = $e->getMessage();
                return $error;
        }

        return array('code' => EUR, 'rates' => $rates);
    }

Localization

Because there are messages and strings that will be shown to CloudBlue Commerce users, we need to add support for localization. The exchange rate SDK has a built-in feature for localization.

All localized strings are stored in the dedicated [code].strings under the i18n directory, where [code] - is a two-letter language ISO code. For the English language, it will be en.strings, for Deutch: de.strings. Each of these localized strings must be assigned with a unique key and referenced from the PHP code by this key and the function pa_localized_string();

For example, let us add localization to the ECB_GetConfig method:

Copy
function ECB_GetConfig()
{
    return array(
        'friendlyName' => pa_localized_string('rates_provider_name'),
        'parameters' => array(
            array(
                'name' => 'quote_currencies',
                'friendlyName' => pa_localized_string('quote_currencies'),
                'type' => 'text',
                'size' => 200,
                'required' => false)
        )
    );
}

And localization files in the i18n folder:

en.strings

"rates_provider_name" "European Central Bank""quote_currencies" "Comma separated list of quote currency ISO codes for Euro"

de.strings

"rates_provider_name" "Europäische Zentralbank""quote_currencies" "Kommagetrennte Liste der ISO-Codes der Kurswährung für Euro"

Logging

Additionally we can add logging to our methods. This can be done using the built-in function pa_log(). For example, it will be useful to log response headers in case of a failure in the TestConnection method:

Copy
function ECB_TestConnection($params)
{
    $result = array();

    $headers = get_headers(URL);
    if (in_array('HTTP/1.1 200 OK', $headers)) {
        $result['STATUS'] = 'APPROVED';
    } else {
        pa_log('Test connection failed. Response headers: ' . join(', ', $headers));
        $result['STATUS'] = 'DECLINED';
        $result['TEXT'] = pa_localized_string('unexpected_response_status');
    }

    return $result;
}

Summary

This is just an example of a plugin and many things were not taken into account. But this example should give you the idea how to develop an exchange rate plugin. Now, you can try to install this plugin and receive exchange rates. The plugin is attached as a zip archive: ECB_plugin.zip.

Plugin Installation

During the first release all management operations on custom plugins, such as installation and configuration can only be done using CloudBlue Commerce Billing API. Integration with UX1 UI will be available in future releases.

Process of custom plug-in installation consists of the following general steps:

  • Add plug-in scripts to the exchange-rates-sdk pod.
  • Install plugin using CloudBlue Commerce API.
  • Configure plugin if necessary.

Plug-in Deployment

Plug-ins scripts are located inside the exchange-rate-sdk pod in the Kubernetes cluster. To add custom plug-in scripts and localization files we need to copy the whole folder to /custom directory in the pod. This directory is mounted to the persistent volume and its content can not be lost during pod restart. The SDK has a special logic that reads contents of the /custom directory, finds any new plugin and adds them to the plug-in list during startup.

kubectl -n <NAMESPACE> cp <PLUGIN_FOLDER> <PAYMENT_SDK_POD_NAME>:/custom

And then restart the pod:

kubectl -n <NAMESPACE> rollout restart deployment exchange-rate-sdk

Plug-in Installation in CloudBlue Commerce

Using API, first find the Plugin Management application resource. You must use the provider APS token. Example of such a call is:

http://[aps_host]:[aps_port]/aps/2/resources/?implementing(http://a8n.bss/exchangerates/plugin-manager)

Then call the install custom operation of this resource with the POST request. You can additionally pass configuration data as payload. It will be validated using ValidateConfig and saved, if valid. Example of such a call is:

http://[aps_host]:[aps_port]/aps/2/resources/[plugin_management_resource_aps_id]/applications/[plugin_name]/install

Using the Plugin

When the plugin is successfully installed, Currency Management starts to request exchange rates from this plugin periodically. For example, our ECB plugin will bring EUR to USD exchange rates. You can add EUR as a sales currency and configure automatic exchange rate updates for it using the ECB plugin.

CloudBlue, an Ingram Micro business, uses cookies to improve the usability of our site. By continuing to use this site and/or logging in you are accepting the use of these cookies. For more information, visit our Privacy Policy.