Новое в блогах


Техноблог HTTPS и Amiro.CMS  1
Личный опыт История от «Интер Электрик», #ОбновлениеЗаРассказ 
Личный опыт История от АвтоТехЦентр Субару Медведково, #ОбновлениеЗаРассказ 
Техноблог Как открыть интернет-магазин с нуля 
Личный опыт История от интернет-магазина ТД Зевс, #ОбновлениеЗаРассказ 
Личный опыт История от портала china-sky.ru, #ОбновлениеЗаРассказ 

Теги



Модификация процедуры заказа в интернет-магазине с использованием API

C версии 5.14.4, доработано и опубликовано API для управления оформлением заказов в интернет-магазине. API позволяет в асинхронном режиме обмениваться с сервером данными о заказе, получать данные о методах доставки, общей сумме заказа, о детализации заказа и комиссиях платёжных систем, без перезагрузки страницы. Этот функционал открывает широкие возможности для адаптации процессов в любом магазине.

Пример использования

Задача: необходимо перенести диалог выбора платёжной системы на шаг оформления заказа, а также вывести общую сумму заказа на этом же шаге.

Данные о доступных способах доставки

В рамках одного магазина может быть несколько видов доставки, распределённых по нескольким группам. Один и тот же вид доставки (например, Почтой России) может быть в нескольких группах. Существуют разные способы обработки случая, когда разные товары в корзине относятся к разным группам.

Получить данные о том, какие товары к каким группам относятся, можно двумя путями.

Самое простое — воспользоваться переменной ##cart_shipping## в сете purchase_form шаблона eshop_purchase.tpl.
Способ чуть сложнее — сделать AJAX запрос этой переменной на сервер.

В обоих случаях ответом будет объект, в формате JSON. Например, если на демоверсии редакции бизнес положить в корзину «Современную конюшню», «Ламборджини» и «Бинокль», то структура объекта будет такой:

 {
	"11": {
		"id": "11",
		"methods": [{
			"id": "11",
			"name": "Самовывоз"
		}, {
			"id": "12",
			"name": "Городская курьерская доставка"
		}, {
			"id": "55",
			"name": "Междугородняя курьерская доставка"
		}, {
			"id": "17",
			"name": "Почта России"
		}, {
			"id": "29",
			"name": "ЖД доставка"
		}, {
			"id": "78",
			"name": "Транспортная компания"
		}, {
			"id": "34",
			"name": "Доставка с помощью постаматов PickPoint"
		}],
		"items": [{
			"id": "171",
			"name": "Современная конюшня",
			...
		}, {
			"id": "181",
			"name": "LAMBORGHNI MURCIELAGO (1:18)",
			...
		}, {
			"id": "205",
			"name": "Бинокль",
			...
		}]
	}
}

Что можно понять из этого объекта? Во-первых, все три товара относятся к группе доставок «11», а значит, их можно заказать любым способом, который присутствует в этой группе. Во-вторых, отражено какие именно методы доставки присутствуют в группе «11». Причем, доступны как названия методов (например «ЖД доставка»), необходимые для покупателей, так и id методов, потенциально необходимые для дальнейшего общения с сервером.

Наконец, в-третьих, доступен массив items, который содержит исчерпывающую информацию по каждому товару (для краткости здесь показаны только id и name).

Чтобы получить полноценный JS объект прямо в шаблоне (первый способ), строка декодируется:

 varaCartShippings =
JSON.decode('##cart_shipping##');

Обратите внимание на объект JSON – он появился только в пятой редакции ECMAScript, поэтому для браузера InternetExplorer версии 8 и ниже придётся подключать библиотеку json2.js (https://github.com/douglascrockford/JSON-js).

 AMI.$(document).ready(function(){
	AMI.$.ajax({
		url: "##www_root##ami_service.php",
		data: {
			service: "eshop_cart",
			action: "get_available_shippings"
		}
	}).done(function(content){
		window.aCartShippings= JSON.parse(content);
	});
});

Обратите внимание на конструкцию «AMI.$» – это «стабильная» проверенная версия jQuery (на момент написания статьи – 1.7.2), подключённая на любой сайт на Amiro.CMS версии 5.14.4+, с серверов Яндекса. По-умолчанию эта же версия доступна и через имя $, но лишь до тех пор, пока вы не подключаетена сайт собственную версию jQuery.

Что же делает этот скрипт и куда его вставить? Вставить его можно в любой сет шаблона eshop_purchase.tpl,который выводится на этапе оформления заказа, например в сетpurchase_formлибо в файл common.js. Разберемся, что делаетэтот код.

Код состоит из двух частей: «асинхронный запрос на сервер» (ajax()) и «обработчик ответа сервера» (done()). Запрос имеет три параметра, имена, структура и значения которых указаны в коде. При получении ответа с сервера jQuery вызывает обработчик с одним параметром (в данном случае он назван content). Этот параметр и есть JSON строка, которую можно преобразовать в JS объект.

Полученный первым или вторым способом объект нужен не только для формирования элементов формы, при помощи которых покупатель мог бы выбрать нужный ему способ доставки (кстати, это реализовано и в прежних версиях шаблона eshop_purchase.tpl), но, прежде всего — для составления второго запроса.

Общая стоимость заказа

Для второго запроса на сервер потребуется модифицированный объект aCartShipping, полученный выше. Модификация заключается в установке выбранного метода доставки для каждой группы методов. Например, если в группе методов, у которой id равен 11, выбран метод, id которого равен 13, модификация и второй запрос будут такими:

 functionsetShippingMethod(shippings, method_id, groud_id) {
	shippings[groud_id].selected_method = method_id;
	returnshippings;
}

AMI.$(document).ready(function(){
	varaCartShippings= setShippingMethod(aCartShippings, 13, 11);

	AMI.$.ajax({
		url: "##www_root##ami_service.php",
		data: {
			service: "eshop_order",
			action: "get_order_cost",
			json_data: JSON.stringify(aCartShippings)
		}
	}).done(function(content){
		window.priceAjaxResponce = JSON.parse(content);
	});
});

Конечно, в таком виде код не пойдёт: id группы и метода доставки, жестко прописаны в коде. Ниже будет описан более общий способ модификации объекта.

В запросе общей стоимости заказа без AJAX запроса не обойтись, потому что для расчёта этой стоимости нужно знать, какие именно способы доставки покупатель выбрал. Сам выбор задаётся через добавление переменной selected_method внутри каждой группы методов.

В этом запросе присутствует дополнительный параметр json_data, в котором и должен находиться модифицированный (то есть с выставленной переменной selected_method внутри каждой группы) сериализованный объект aCartShippings в формате JSON.

Примерный ответ сервера (содержимое переменной content):

 {
	"error": "",
	"items": [{
		"name": "Современная конюшня",
		"property_caption": "",
		"cat_name": "Предметные",
		"sku": "PM4190",
		"qty": "1",
		"price_caption": "(Цена)",
		"original_price": "119.97",
		"percentage_discount": " ",
		"absolute_discount": "0.00",
		"price": "119.97",
		"price_tax": "119.97",
		"total_weight": "0",
		"weight": "0",
		"size": "",
		"total": "119.97",
		"total_tax": "119.97"
	}, {
		...
	}],
	"total": {
		"id": "total",
		"price_value": 119.97,
		"tax_value": 0,
		"excise_tax": 0,
		"shipping_tax": 0,
		"shipping_value": 0,
		"shipping": null,
		"price": "119.97",
		"tax": "0.00",
		"total_weight": 0,
		"subtotal": 0,
		"grand_discount": 0,
		"grand_total": 119.97
	},
	"drivers": {
		"stub": {
			"currency": "USD",
			"fee": {
				"percent": 0,
				"const": 0,
				"curr": "USD"
			},
			"fee_amount": "0.00",
			"pay_charge_const": "",
			"pay_charge_percent": "",
			"pay_amount": "119.97",
			"amount": "119.97"
		},
		"webmoney": {
			...
		},
		...
	}
}

Для краткости пропущена часть свойств и большинство платёжных систем.

Объект total содержит суммарную стоимость заказа, с учётом всех налогов и скидок, с учётом стоимости всех доставок, но до учёта комиссии платёжной системы. Комиссия, а также общая стоимость с учётом этой комиссии, содержится в массиве drivers, для каждой платёжной системы в отдельности. «stub» соответствует пункту «оплатить потом».

Пример

Необходимо вывести список платёжных систем на этапе оформления заказа и, в зависимости от выбранных способов доставки и платёжной системы, вывести на экран общую сумму заказа. Для этого необходимо:

1. Сформировать список платёжных систем, как элемент формы типа select

Это можно сделать средствами шаблонаeshop_purchase.tpl. Сеты payment_methods_natural_item и payment_methods_juridical_item задают структуру вывода одной платёжной системы для физических и юридических лиц (это два разных списка). Код для шаблона выглядит примерно так (здесь и далее код для юридических лиц пропущен, более подробно про типы лиц можно найти в документации):

 <!--#set
var="payment_methods_natural_item" value="<option
value="paymentform##name##"
data-ami-payment-method="##name##">%%pay_with_##name##_option%%</option>"-->

Здесь ##name## – уникальное имя платёжной системы (stub, webmoney, yandex и т.д.), сохраняемое в атрибут data-ami-payment-method. При этом покупатель видит переменные локализации типа %%pay_with_ stub%% и т.д.

Полный набор платёжных систем будет содержаться в переменных ##payment_methods_natural## и ##payment_methods_juridical## в сете purchase_form. Достаточно обернуть их select`ами и расположить в этом же сете:

 <select id="naturalPaymentMethods">
##payment_methods_natural##
</select>

Логику скрытия select`ов, в зависимости от выбранного типа лица (физическое или юридическое), также пропущена.

2. Назначить JS обработчики на смену методов доставки

С точки зрения браузера смена метода доставки – это клик по радиокнопке, привязанной к любому из методов. Поэтому, сначала радиокнопки помечаются для дальнейшего назначения обработчиков.

Сетshipping_method_radio_row – выводит один (каждый) метод доставки. Находится элемент с тегом input и ему задаются атрибуты:

 <input type="radio"
id="shipping_method_##id_type##_##id##" name="get_type"
value="##id##" data-ami-method-id="##id##"
data-ami-group-id="##id_type##" />

В данном коде всем радиокнопкам был задан id, который начинается с префикса sipping_method_. Дополнительно, чтобы не усложнять JS код операциями со строками, добавлены два атрибута: data-ami-method-id и data-ami-group-id, значения которых подставляет система, их смысл – id метода доставки и id группы, к которой данный метод принадлежит. Помним, что один метод может принадлежать сразу нескольким группам. Атрибуты name и value необходимы для корректной работы системы после отправки формы.

Теперь находятся все эти радиокнопки и привязываются (bind()) к событию click функцию, которая будет делать всё необходимое:

 AMI.$(document).ready(function(){
	AMI.$('input[id^="shipping_method_"]').bind('click', function(){
		// Определяем id выбранного метода доставки
		varmethod_id = parseInt(AMI.$(this).attr('data-ami-method-id'));
		
		// Определяем id группы, которой принадлежит метод
		vargroup_id = parseInt(AMI.$(this).attr('data-ami-group-id'));
		
		// Добавляем в объект выбранный метод доставки данной группы
		aCartShippings = setShippingMethod(aCartShippings, method_id, group_id);
		
		// Делаем запрос на сервер о стоимости заказа с учётом выбранного метода доставки
		AMI.$.ajax({
			url: "##www_root##ami_service.php",
			data: {
				service: "eshop_order",
				action: "get_order_cost",
				json_data: JSON.stringify(aCartShippings)
			}
		}).done(function(content){
			window.priceAjaxResponce = JSON.parse(content);
		});
		
		// Выставляем общую цену для драйвера по-умолчанию
		setTotalPrice(priceAjaxResponce);
	});
});

Конструкция «id^="shipping_method_"» заставит jQuery найти все элементы с id, начинающихся с shipping_method_. При клике будет вызван код, который определит метод и группу, модифицирует объект и сделает запрос на сервер, после чего выставит цену вызовом функции:

 functionsetTotalPrice(responce, driver_name) {
	if ( driver_name === undefined ) {
		driver_name = 'stub';
	}
	
	// Выставляем цену заказа с учётом комиссии драйвера driver_name
	AMI.$('total-price').html(responce.drivers[driver_name].amount);
}

Код функции setShippingMethod описан выше.

Осталось совсем ничего, а именно

3. Задать обработчики смены платёжной системы

Когда покупатель меняет платёжную систему, меняется и общая сумма заказа. Для удобства, сразу все «итоговые суммы» заказа, для каждой платёжной системы в отдельности, есть в одном ответе сервера. Поэтому обработчику достаточно определить имя новой платёжной системы и вызвать функцию setTotalPrice():

 AMI.$(document).ready(function(){
	AMI.$('#naturalPaymentMethods').bind('change', function(){
		// Определяем имя выбранной платёжной системы
		vardriver_name = AMI.$(this).find('option:selected').attr('data-ami-payment-method');
		
		// Обновляем цену со вторым параметром
		setTotalPrice(priceAjaxResponce, driver_name);
	});
});

Теперь при смене способа доставки, так и при смене способа оплаты, будет обновляться итоговая цена заказа.

В стандартной поставке реализована более сложная схема, с несколько группами доставки, переключением на юридическое лицо, формированием детализированного списка товаров заказа, кешированием ответов сервера. Посмотреть в действии всё это можно на демоверсии редакции бизнес, а найти код – там же, в объекте AMI.Eshop.Purchase, который находится в шаблоне eshop_purchase.tpl.

[29.11.12]  
Рейтинг: 3 (голосов: 4)
Комментировать

Теги: инструкцияинтернет-магазинпримерыинтеграцияAPIhow-toПрограммированиеPHP
 
Вернуться к списку
Комментарии (3)

 (Партнер)  27.01.13 19:00
-1

Стоит дополнительно указывать параметр запроса
ami_locale: 'ru', иначе все цены идут в USD, не смотря на
то, что основные цены везде проставлены в рублях.

 (Партнер)  27.01.13 19:38
-1

Второе дополнение:
в методе $.ajax (то же самое, что и AMI.$.ajax по тексту), по умолчанию метод запроса установлен, как GET и используется, если явно не указать другой. При таком методе вторым запросом цена доставки в ответе не придет, будет null. Для правильного запроса надо дополнить его так, что бы он выглядел примерно след. образом:

        
AMI.$.ajax({
            url: "##www_root##ami_service.php",
            data: {
                service: "eshop_order",
                action: "get_order_cost",
                json_data: JSON.stringify(aCartShippings),
                ami_locale: 'ru'
            },
            type: 'post'
        })
.done(function(content){
            window.priceAjaxResponce = JSON.parse(content);
});

   18.04.13 06:02
1


Ваш комментарий