Типовая интеграция Сайта SuperPaint.ru
И так, у нас есть пример сайта интернет магазина по продаже ЛКМ superpaint.ru. На его примере мы решим основные проблемы и задачи при интеграции Robotint

1 - Внедрение основгого кода в шаблон сайта
2 - Настроить параметры округления объема колеровки
3 - Настроить параметры округления стоимости колеровки в зависимости от системы колеровки и стоимости
4 - Передать данные о колеровке в корзину
Список файлов:

Шаблон
index.php

Пользовательские скрипты
robotintSettings.js

Карточка товара
product.php

Корзина
basket.php
Файл шаблона сайта
// Файл Шаблона сайта superpaint.ru index.html 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>SuperPaint.ru</title>


// Подключаем JQuery 
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

// если вы используетt JQuery версии выше 1.5 добавляем еще  скрипт миграции 
<script src="https://code.jquery.com/jquery-migrate-3.3.0.js"></script>

// подключаем код Robotint
<script src="https://core.robotint.ru/s.js"></script>

// определяем настройки подключения и обработчики событий сохраненные в файл robotintSettings.js 
<script src="robotintSettings.js"> </script> 

</head>
  <body>
    <!-- page content -->
  </body>
</html>
robotintSettings.js
в этом файле мы сохраним все пользовательские скрипты для работы с Robotint
var aRobotintOptions={ 
	tintSettings:{ 
		CLIENT_ID: 99, //Ваш ID в системе Robotint, для тестового подключения оставьте 0
		SECRET: "free_test", // Ключ для подключения 
		WITH_PRICE: 1, // осуществлять онлайн расчет цены
	}, 
	siteSettings:{ 
		colorSelect: obRobotint .colorSelect, // функция обратного вызова
		processPrice: obRobotint .processPrice,
		bgZindex: 10000,
		basketURL: "/personal/cart/" // путь для добавления товара в корзину
	} 
}; 

// устанавливаем настройки 
obColorer.setOptions (aRobotintOptions); 

	var obRobotint = {
		prices:[], // в эту переменную мы поместим все варианты настроек для обработчика цен варианты конфигураторов смотри ниже
		clientSettings:{}, // прочие настройки 
		canRound:[], // настройки окрубления 
		processPrice: function($priceObj, data){ 
			// эту функцию. мы передадим в obColorer для обработки цен до того как их показать клиенту 
			// $priceObj  - данные о расчете стоимости  
			// data - данные о коллекции цветов
			console.log($priceObj);
			console.log(data);
			var data_raw = $priceObj.data();
					
			var ppl_raw = parseFloat(data_raw.pricePerLitr);
			var ppc_raw = parseFloat(data_raw.pricePerCan);
			var ppl = ppl_raw; // сохраняем в отдельную переменную с которой будем работать 
			var ppc = ppc_raw; // сохраняем в отдельную переменную с которой будем работать 
			var ref_vol = parseFloat(data_raw.priceRef_can_volume); // объем колеруемого продукта .. по данным базы 
			
			// объем колеруемого продукта 
			var iVolume = ref_vol ;
			
			// применяем правила округления объема колеровки 
			
			iVolumeNew = 0;
			for (i in obRobotint.canRound){
				curCanRound = obRobotint.canRound[i]
				if(iVolume > curCanRound.roundMin && iVolume < curCanRound.roundMax  ){
					if(curCanRound.round == 'math'){
						iVolumeNew = Math.round(iVolume); 
					}else if(curCanRound.round == 'up'){
						iVolumeNew = Math.ceil(iVolume); 
					}else if(curCanRound.round == 'down'){
						iVolumeNew = Math.floor(iVolume); 
					}else{
						iVolumeNew = Math.round(iVolume); 
					}
				}
			}
			if(iVolumeNew > 0){
				iVolume = iVolumeNew
			}

			CVID = data.COLLECTION_VENDOR_ID 
			// заглушка если по какой то причине нет Vendor ID
			if(!CVID) CVID = 2 // берем в данном случае Tikkurila 
			
			// здесь у нас будет храниться выбранный конфиг, но пока он false 
			var cur_set = false;


			// обходим цены из конфига для того что бы выбрать нужный 
			// в соответствующем ценовом диапазоне и соответствующей системы
							
			for(var i in obRobotint.prices) {
				// массив конфига ценовых уровней и округлений	
				rt_price = obRobotint.prices[i];
					if(rt_price['tint_system'] == CVID){
							// если цена попадает в диапазон, то берем этот блок конфигуратора цены
						if(ppl > rt_price.price_from ){
							cur_set = rt_price
						}
					}
				}		

				// если конфиг  не установлен то устанавливаем значения по умолчанию 
				if(!cur_set){
					cur_set = {
						'price_from': 0,
						'tint_system': CVID , // тут у нас tikkurila 
						'set_price': false,
						'round': false,
						'scale': false,
						};
				}

				// приводим цену к уровню  
				if(cur_set.set_price){
						ppl = cur_set.set_price; 
				}
						
						// округляем 
				if(cur_set.round){
						
					// если не указана кратность округления то =1 
					// а так же фисксим возможные ошибки
					cur_set.scale  = parseInt(cur_set.scale);

					if(!cur_set.scale  || cur_set.scale  == 0){
							cur_set.scale = 1;
					}				

					// типы округления
					if(cur_set.round == 'math'){
							ppl = Math.round(ppl/cur_set.scale)*cur_set.scale; 
					}else if(cur_set.round == 'up'){
							ppl = Math.ceil(ppl/cur_set.scale)*cur_set.scale; 
					}else if(cur_set.round == 'down'){
							ppl = Math.floor(ppl/cur_set.scale)*cur_set.scale; 
					}else{
							ppl = Math.round(ppl/cur_set.scale)*cur_set.scale; 
					}
				}

				// стоимость колеровки за банку 
				ppc = ppl*iVolume;
								
				if(ppc!=ppc_raw){
					// переписываем значение кнопки на клиентские, приведенные к нужному уровню
					$priceObj.attr("data-price-shop",ppc);
					$priceObj.text(obRobotint.numberFormat(ppc,0,"."," ")+" ₽");
				}
			},
			numberFormat: function ( number, decimals, dec_point, thousands_sep ) {	
				// эта функция отформатирует нам цену так как нам нужно
				// Format a number with grouped thousands
				//
				// +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
				// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
				// +	 bugfix by: Michael White (http://crestidg.com)
				var i, j, kw, kd, km;
				
				// input sanitation & defaults
				if( isNaN(decimals = Math.abs(decimals)) ){
								decimals = 2;
				}
				if( dec_point == undefined ){
								dec_point = ",";
				}
				if( thousands_sep == undefined ){
								thousands_sep = ".";
				}
				
				i = parseInt(number = (+number || 0).toFixed(decimals)) + "";
				
				if( (j = i.length) > 3 ){
								j = j % 3;
				} else{
								j = 0;
				}
				
				km = (j ? i.substr(0, j) + thousands_sep : "");
				kw = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep);
				//kd = (decimals ? dec_point + Math.abs(number - i).toFixed(decimals).slice(2) : "");
				kd = (decimals ? dec_point + Math.abs(number - i).toFixed(decimals).replace(/-/, 0).slice(2) : "");
				
				
				return km + kw + kd;
			},
	
		// эта функция для добавления в корзину, вы ее уже видели 	выше	
			select: function (data) {
				var iProductID = parseInt(data.PRODUCT_ID); //получение идентификатора колеруемого продукта в базе интернет-магазина
				var $itemObject = obColorer.itemObject;
				if (iProductID) { //если выбран колеруемый продукт
					var basketAction = "add"; //по умолчанию считать, что ведется добавление новой услуги колеровки в корзину
					var iBasketID = data.BASKET_ID; //получить значение с идентификатором позиции в корзине, если это значение передано

					if (iBasketID) { //если передан идентификатор товара в корзине
						basketAction = "update"; //значит для этого товара ранее уже был выбран оттенок колеровки. Установить действие в состояние "обновление" колеровки — update
						obColorer.close(); //закрыть интерфейс RoboTint
					}

					data.basketAction = basketAction; //определить выполняемую операцию в рабочем объекте
					console.log(data);
					$.ajax({ //отправить запрос
						type: "POST", //методом POST
						url: "/ajax/add_tinting_to_cart.php", //путь до скрипта добавления/обновления  цвета и товара в корзине  (зависит от используемой вами CMS) 
						data: data, //в значении data передать объект со всеми возвращаемыми параметрами
						timeout: 15000, //ожидать ответа от сервера в течение 15 секунд. После — прекратить ожидание
						beforeSend: function () { //функция, которую можно использовать для исполнения логики на время ожидания ответа от сервера. Например — показ спиннера
						},
						success: function (data, textstatus) { //функция в которую вернётся результат ajax-запроса
						},
						error: function () { //функция обработчик ошибки ajax-запроса, если что-то пошло не так
						}
					});
				}
			}
		};

// здесь мы будем определять как мы будем округлять объем колеровки 
// в данном примере любая фасовка < 1л  будет трактоваться как 1л . т.е. 0.9л = 1л, 0.225л = 1л
// так же фасовка не кратная 1л  будет округляться в большую сторону  т.е. 2.7л = 3л, 2.5л = 3л
// третий блок округлит до 10л т.е. 9л = 10л, 18л = 20л, 15л = 20л
// для вашего сайта вы можете добавлять по аналогии любые диапазоны  и варианты округления
obRobotint.canRound  = [
	{
		'roundCanVolume': true,  // округление объема Банки true - да  false нет 
		'round':'up', // правила округления объема колеровки  up down math
		'roundMin':0, // диапазон действия округления 
		'roundMax':1, // диапазон действия округления 
		'scale': 1, // округлять до 1 / 10 / 100 л
	},
	{
		'roundCanVolume': true,  // округление объема Банки true - да  false нет 
		'round':'up', // правила округления объема колеровки  up down math
		'roundMin':1, // диапазон действия округления 
		'roundMax':9, // диапазон действия округления 
		'scale': 1, // округлять до 1 / 10 / 100 л
	},			
	{
		'roundCanVolume': true,  // округление объема Банки
		'round':'up', // up down math
		'roundMin':9,  
		'roundMax':999,
		'scale': 10, // округлять до 1 / 10 / 100 л
	},
];

// следующий блок - округление стоимости колеровки.
// обычно это очень некруглое число с большим количеством знаков после запятой, 
// в корзине это смотрится не очень аккуратно 

// в данном примере каджый диапазон цен повторяется 3 раза для возможности индивидуальной настройки правил для каждой системы колеровки отдельно
// первый от 0 до 30 рублей за литр не зависимо от реальной стоимости колорантов будет для клиента стоить 30р. т.е. 14.50р = 30р, 1.20 = 30р.
// это определено параметром: 
// 'set_price': 30,

// второй от 30 р будет округляться до 10 рублей  т.е. 35.49 = 40р, 323,33 = 330р 
// это определено параметрами: 
// 'round': 'up',  // округляем вверх 
// 'scale': 10,  // до 10 рублей 

obRobotint.prices = [
	{
		'price_from': 0,
		'tint_system': 2, // tikkurila 
		'set_price': 30,
		'round': false,
		'scale': false,
	},
	{
		'price_from': 0,
		'tint_system': 5, // akzo 
		'set_price': 30,
		'round': false,
		'scale': false,
	},
	{
		'price_from': 0,
		'tint_system': 6, // tikkurila 
		'set_price': 30,
		'round': false,
		'scale': false,
	},
	{
		'price_from': 30,
		'tint_system': 2, // tikkurila 
		'set_price': false,
		'round': 'up',  // округление в up, down , math
		'scale': 10, // округлять до 1 / 10 / 100 рублей
	},
	{
		'price_from': 30,
		'tint_system': 6, // ceresit 
		'set_price': false,
		'round': 'up',  // округление в up, down , math
		'scale': 10, // округлять до 1 / 10 / 100 рублей
	},
	{
		'price_from': 30,
		'tint_system': 5, // akzo 
		'set_price': false,
		'round': 'up',  // округление в up, down , math
		'scale': 10, // округлять до 1 / 10 / 100 рублей
	}
]
Карточка товара product.php
Код для карточки товара для выбора цвета колеровки
...
  <body>
    <!-- page content -->

<?php
// собираем данные для передачи в Robotint
// обязательно передать BARCODE для идентификации продукта в базе данных Robotint
// и PRODUCT_ID что бы потом положить в корзину соответствующий продукт с доп свойствами колеровки
$array = {
    "BARCODE"=> "0000000000000", // штрихкод колеруемого товара
    "PRODUCT_PRICE"=>370, // цена продукта
    "PRODUCT_ID"=> 123, // id продукта
}
// упаковываем в JSON 
$json = json_encode($array);
?>
<!-- сама кнопка Robotint-->
<tint-button disabled="disabled" data-basket-id='0' data-tint-button="1" data-tint-button-vertical="1" data-tint-data='<?= $json?>' onclick="obColorer.show(this)">
    <tint-span>выбрать</tint-span>
    <tint-span>цвет</tint-span>
</tint-button>

  </body>
</html>
Корзина basket.php
Скоро...