Import Customer Prices from an external REST-API

What can this connector do?

This connector fills the customer individual prices database table. The connector retrieves the customer-specific prices from an external REST API for each customer created in Shopware and writes them into the b2b_customer_prices database table.

This plugin has been developed in such a way that you can easily extend it to your individual API. We from B2Bsellers will also add more connectors in due course.

Currently, the SAGE 100 - OMNISELLER B2B-API client is already connected. Therefore, SAGE100 customers can already use our connector without additional development.

We recommend setting up a cron job that collects the customer-specific prices, e.g. once a day. Please note that the cron job can run for a while depending on the customer size and interface response time.

Available shell command: b2b:price-connector:import

Alternatively, you can specify a parameter: customerNumber to update only the prices of one customer.

Procedure and information:

  • You can create your own connectors with your own plugin and derive them accordingly.

  • The endpoints of the API must be maintained in the plugin config of the connector. See figure 1

  • A BEARER authentication is already integrated and can be used

  • Please maintain the connector name in the plugin config. If you use the Omniseller, enter "omniseller". If you have developed your own "connector", please enter the "technical connector name".

  • Please execute the command: b2b:price-connector:import

  • In our PriceImporter class, all customers will then be passed through and accordingly asked for individual prices at the external API. The connector itself returns a ready array for insertion into the "b2b_customer_prices" database.

  • Note: Before inserting new customised prices, the customised prices of each customer will be deleted. An update of the prices is from our experience not possible.

Current plans for future extensions:

Due to the amount of data, it may often be necessary to pick up and process only one specific customer instead of all at once. For this purpose, the following function can already be used

$this->priceImporter->importSingleCustomerPrices($io, $customerNumber).

However, we are planning to extend this in one of the future updates so that an activity log API can be used to query which customers were last processed and therefore only a few customers will be updated.

Example request and response of the OMNISELLER REST API:

Request URL: POST api.omniseller365.com/b2b-prices/specialPrices This request returns all customer-specific prices.

On the other hand, this request only returns the individual prices of a customer and then inserts them into Shopware.

Response from the API is an array of customised prices:

[
          {
                   "SKU": "22805867",
                   "Price": 3.69,
                   "SalesDiscount": 0.00,
                   "Amount": 1.00,
                   "Type": "P",
                   "Info": "",
                   "IsGrossPrice": false
          }
]

If you have the possibility that the interface to your ERP system can develop an individual response, you can send the sample response from Omniseller to the interface contact person.

Settings in the plug-in config

Source code preview

In the following source code block you can see how a new connector is created and which functions are possible here.

<?php

namespaceB2bPriceConnector\Components\Connectors;

useDoctrine\DBAL\Connection;
useGuzzleHttp\Client;
useGuzzleHttp\Exception\RequestException;
useShopware\Core\Checkout\Customer\CustomerEntity;
useShopware\Core\Framework\Uuid\Uuid;
useShopware\Core\System\SystemConfig\SystemConfigService;

classOmnisellerPriceConnectorimplementsPriceConnectorInterface
{
privateClient$client;
privatearray$config;
privateConnection$connection;
private ?string$currencyId;

publicfunction__construct(
SystemConfigService$configService,
Connection$connection
    )
    {
$this->client = newClient();
$this->connection = $connection;
$this->config = $configService->get('B2bPriceConnector.config');
$this->currencyId = $this->getCurrencyIdByIsoCode($this->config['omnisellerCurrency']);
    }

privateconstCONNECTOR_NAME = 'omniseller';

publicfunctionsupports(string$connectorName): bool
    {
return$connectorName === self::CONNECTOR_NAME;
    }

publicfunctiongetConnectorName(): string
    {
returnself::CONNECTOR_NAME;
    }

publicfunctiongetPriceByCustomer(CustomerEntity$customer): array
    {
$data = [];
$prices = $this->fetchCustomerPrices($customer->getCustomerNumber());

if (empty($prices)) {
return$data;
        }

foreach ($pricesas$price) {
$productId = $this->getProductIdByNumber($price['SKU']);

if (empty($productId)) {
continue;
            }

$data[] = [
'customerId' =>$customer->getId(),
'customerNumber' =>$customer->getCustomerNumber(),
'productId' =>$productId,
'productNumber' =>$price['SKU'],
'currencyId' =>$this->currencyId,
'currencyIsoCode' =>$this->config['omnisellerCurrency'],
'from' => (int)$price['Amount'],
'to' =>null,
'priceNet' =>$price['Price'],
            ];
        }

return$data;
    }

privatefunctionfetchCustomerPrices(string$customerNumber): array
    {
try {
$url = $this->config['omnisellerApiUrl'];
$url .= '?shopID=' . $this->config['omnisellerShopId'];
$url .= '&customerID=D' . $customerNumber;
$url .= '&currency=' . $this->config['omnisellerCurrency'];
$url .= '&hasCount=true';

$response = $this->client->get($url, [
'headers' => [
'Bearer' =>$this->config['omnisellerToken'],
'Dev-Key' =>$this->config['omnisellerDevKey']
                ]
            ]);

$content = $response->getBody()->getContents();

if (empty($content)) {
return [];
            }

$result = json_decode($content, true);

if (empty($result)) {
return [];
            }

if (count($result) === 1&&isset($result[0]) &&isset($result[0]['RESPONSE'])) {
return [];
            }
        } catch (RequestException$e) {
return [];
        }

return$result;
    }

privatefunctiongetProductIdByNumber(string$productNumber): ?string
    {
$id = $this->connection->fetchOne("SELECT id FROM product WHERE product_number = :productNumber LIMIT 1", [
'productNumber' =>$productNumber
        ]);

if(!empty($id)) {
returnUuid::fromBytesToHex($id);
        }

returnnull;
    }

privatefunctiongetCurrencyIdByIsoCode(string$isoCode): ?string
    {
$id = $this->connection->fetchOne("SELECT id FROM currency WHERE iso_code = :isoCode LIMIT 1", [
'isoCode' =>$isoCode
        ]);

if(!empty($id)) {
returnUuid::fromBytesToHex($id);
        }

returnnull;
    }
}

Last updated