Checkout - uniqcle/Bitrix GitHub Wiki

Delivery/Pay Systems

Магазин->Настройки->Службы доставки /bitrix/admin/sale_delivery_service_list.php

Магазин->Настройки->Платежные Системы /bitrix/admin/sale_pay_system.php

На 1 заказ в Битриксе создается сущность не только самого заказа, а также: Отгрузка и Оплата.

Свойства заказа /bitrix/admin/sale_order_props.php привязываются к типу плательщика, которого необходимо предварительно создать /bitrix/admin/sale_person_type.php.

Адрес вбивается в 1 поле, откуда идет выбор и города и адреса. Он и проверяет на корректность. И возвращает полезные данные индекс, классификатор КЛАДР или ФИАС. Например, https://dadata.ru/

Template

Как править компонент корзины

1 путь. Кастомизация на уровне css компонента sale.order.ajax.

2 путь. Кастомизация компонента sale.order.ajax, у которого 8000 строк. В этом случае слетаем с гарантии.

3 путь. Берем компонент Битрикса. И не модифицируя фронтовую часть, переписываем JS-код. script.js

Добавляем компонент на страницу

Оформление заказа /personal/order/make/

Магазин->Процедура оформления заказа->Оформление заказа или sale.order.ajax

Копировать шаблон компонента->custom_order

Бывает не дает "включить" шаблон. Тогда копированием local/templates/skillbox/components/bitrix/sale.order.ajax Копируем на локалку. Главное чтобы к данному сайту был привязан шаблон, в котором находится компонент.

Копируем в компонент sale.order.ajax на локалку
  • В PhpStorm Remove Path From Excluded на папке bitrix

  • На папке sale.order.ajax нажимаем Download from here (загружаем только этот компонент)

  • На папке bitrix нажимаем Exclude Path (обратно исключаем папки от отслеживание)

Копируем в свой шаблон

  • Создаем папку sale.order.ajax в local/templates/skillbox/components/bitrix/

  • Копируем шаблон .default в local/templates/skillbox/components/bitrix/sale.order.ajax и заменяем его на skillbox

  • Удаляем /bitrix/components/bitrix/sale.order.ajax на локалке

Создаем skillbox/order/index.php и устанавливаем туда компонент.

Установленный компонент
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("test");
?><?$APPLICATION->IncludeComponent(
    "bitrix:sale.order.ajax",
    "skillbox",
    Array(
        "ACTION_VARIABLE" => "soa-action",
        "ADDITIONAL_PICT_PROP_2" => "-",
        "ADDITIONAL_PICT_PROP_3" => "-",
        "ALLOW_APPEND_ORDER" => "Y",
        "ALLOW_AUTO_REGISTER" => "N",   // Автоматически регистрация пользователя
        "ALLOW_NEW_PROFILE" => "N",
        "ALLOW_USER_PROFILES" => "N",
        "BASKET_IMAGES_SCALING" => "adaptive",
        "BASKET_POSITION" => "after",
        "COMPATIBLE_MODE" => "Y",
        "DELIVERIES_PER_PAGE" => "9",
        "DELIVERY_FADE_EXTRA_SERVICES" => "N",
        "DELIVERY_NO_AJAX" => "N",
        "DELIVERY_NO_SESSION" => "Y",
        "DELIVERY_TO_PAYSYSTEM" => "d2p",
        "DISABLE_BASKET_REDIRECT" => "N",
        "EMPTY_BASKET_HINT_PATH" => "/",
        "HIDE_ORDER_DESCRIPTION" => "N",
        "ONLY_FULL_PAY_FROM_ACCOUNT" => "N",
        "PATH_TO_AUTH" => "/auth/",
        "PATH_TO_BASKET" => "/personal/cart/",
        "PATH_TO_PAYMENT" => "payment.php",
        "PATH_TO_PERSONAL" => "index.php",
        "PAY_FROM_ACCOUNT" => "N",
        "PAY_SYSTEMS_PER_PAGE" => "9",
        "PICKUPS_PER_PAGE" => "5",
        "PICKUP_MAP_TYPE" => "yandex",
        "PRODUCT_COLUMNS_HIDDEN" => array(),
        "PRODUCT_COLUMNS_VISIBLE" => array("PREVIEW_PICTURE","PROPS"),
        "PROPS_FADE_LIST_1" => array(),
        "PROPS_FADE_LIST_2" => array(),
        "SEND_NEW_USER_NOTIFY" => "Y",
        "SERVICES_IMAGES_SCALING" => "adaptive",
        "SET_TITLE" => "Y",
        "SHOW_BASKET_HEADERS" => "N",
        "SHOW_COUPONS" => "Y",
        "SHOW_COUPONS_BASKET" => "Y",
        "SHOW_COUPONS_DELIVERY" => "Y",
        "SHOW_COUPONS_PAY_SYSTEM" => "Y",
        "SHOW_DELIVERY_INFO_NAME" => "Y",
        "SHOW_DELIVERY_LIST_NAMES" => "Y",
        "SHOW_DELIVERY_PARENT_NAMES" => "Y",
        "SHOW_MAP_IN_PROPS" => "N",
        "SHOW_NEAREST_PICKUP" => "N",
        "SHOW_NOT_CALCULATED_DELIVERIES" => "L",
        "SHOW_ORDER_BUTTON" => "final_step",
        "SHOW_PAY_SYSTEM_INFO_NAME" => "Y",
        "SHOW_PAY_SYSTEM_LIST_NAMES" => "Y",
        "SHOW_PICKUP_MAP" => "Y",
        "SHOW_STORES_IMAGES" => "Y",
        "SHOW_TOTAL_ORDER_BUTTON" => "N",
        "SHOW_VAT_PRICE" => "Y",
        "SKIP_USELESS_BLOCK" => "Y",
        "SPOT_LOCATION_BY_GEOIP" => "Y",
        "TEMPLATE_LOCATION" => "popup",
        "TEMPLATE_THEME" => "site",
        "USER_CONSENT" => "N",
        "USER_CONSENT_ID" => "0",
        "USER_CONSENT_IS_CHECKED" => "Y",
        "USER_CONSENT_IS_LOADED" => "N",
        "USE_CUSTOM_ADDITIONAL_MESSAGES" => "N",
        "USE_CUSTOM_ERROR_MESSAGES" => "N",
        "USE_CUSTOM_MAIN_MESSAGES" => "N",
        "USE_ENHANCED_ECOMMERCE" => "N",
        "USE_PHONE_NORMALIZATION" => "Y",
        "USE_PRELOAD" => "Y",
        "USE_PREPAYMENT" => "N",
        "USE_YM_GOALS" => "N"
    )
);?><br><?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>

Refactor Component

При изминении настроек компонента смотрим Google Inspector->Headers.

Запрос отправляется на Request URL: http://shop-bx.uniqcle.ru/bitrix/components/bitrix/sale.order.ajax/ajax.php

В секции Form Data нужно реализовать метод order[soa-action]: saveOrderAjax

Т.е "правильно" отправляем запрос (с определенными полями) на стандартный компонент битрикса, который будет поддерживать всегда все фичи, которые там могут появиться.

order[sessid]: cbb1923491afcc461a4a0ed189fb9eae
order[soa-action]: saveOrderAjax
order[location_type]: code
order[BUYER_STORE]: 0
order[DELIVERY_ID]: 3
order[PERSON_TYPE]: 1
order[PERSON_TYPE_OLD]: 1
order[PROFILE_ID]: 1
order[ORDER_PROP_6]: 0000073738
order[RECENT_DELIVERY_VALUE]: 0000073738
order[ORDER_PROP_5]: Москва
order[ORDER_PROP_4]: 101000
order[ZIP_PROPERTY_CHANGED]: Y
order[PAY_SYSTEM_ID]: 1
order[ORDER_PROP_1]: Андрей Анучкин
order[ORDER_PROP_2]: [email protected]
order[ORDER_PROP_3]: 
order[ORDER_PROP_7]: 
order[ORDER_DESCRIPTION]: 
sessid: cbb1923491afcc461a4a0ed189fb9eae
via_ajax: Y
SITE_ID: s1
signedParamsString:

Для удобства можно сделать еще один шаблон skillbox_v2 удаляем там все кроме template.

Настройки местоположения

Магазин->Настройки->Местоположения //Настраивается выбор доставки
Настройки->Интернет магазин->Адрес магазина

На странице оформления встраивается стандартный компонент: Привязка к местоположению(строка поиска/списком)

bitrix:sale.location.selector.search
<?$APPLICATION->IncludeComponent(
	"bitrix:sale.location.selector.search",
	"",
	Array(
		"CACHE_TIME" => "36000000",
		"CACHE_TYPE" => "A",
		"CODE" => "",
		"FILTER_BY_SITE" => "N",
		"ID" => "",
		"INITIALIZE_BY_GLOBAL_EVENT" => "",
		"INPUT_NAME" => "LOCATION",
		"JS_CALLBACK" => "",
		"JS_CONTROL_GLOBAL_ID" => "",
		"PROVIDE_LINK_BY" => "id",
		"SHOW_DEFAULT_LOCATIONS" => "N",
		"SUPPRESS_ERRORS" => "N"
	)
);?>

Дорабатываем шаблон компонента и js скрипт.

// Для того чтобы сериализовалась форма необходимо полям добавить ID's, имена
DELIVERY_ID   // Назначаем названия полям доставки
PAY_SYSTEM_ID // Названия полям платежным системам
#orderForm    // ID для формы
// На странице /personal/order/make/ можно посмотреть названия полей
ORDER_PROP_1  // Поле ФИО
ORDER_PROP_2  // email
ORDER_PROP_3  // телефон
...
arRequest.push({name: 'soa-action', value: 'saveOrderAjax'});  // Проверить

Скрипты компонента

Script.js Template
function declOfNum(number, titles) {
    var cases = [2, 0, 1, 1, 1, 2];
    return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
}

function in_array(needle, haystack, strict) {
    var found = false, key, strict = !!strict;
    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
    }
    return found;
}

/*
 * Упрощенный класс для работы с битриксовой корзиной
 * */
var CustomBitrixCart = function (params) {
};
CustomBitrixCart.prototype.serialize = function (selector, noContainer) {
    var preparedData = $(selector).serializeArray(), i, arRequest = [],
        notInOrderContainer = [
            'sessid',
            'SITE_ID',
        ];
    for (i in preparedData) {
        if (preparedData.hasOwnProperty(i)) {
            if (in_array(preparedData[i].name, notInOrderContainer) || noContainer == true) {
                arRequest.push(
                    {
                        name: preparedData[i].name,
                        value: preparedData[i].value,
                    }
                );
            } else {
                arRequest.push(
                    {
                        name: 'order[' + preparedData[i].name + ']',
                        value: preparedData[i].value,
                    }
                );
            }
        }
    }

    arRequest.push({name: 'signedParamsString', value: sign});
    return arRequest;
};

CustomBitrixCart.prototype.updatePage = function (result) {
    //--------------------------доставки
    $('.js_delivery_block').hide();
    $('.js_delivery_block .form-group').each(function (index, value) {
        $(value).remove();
    });

    $.each(result.order.DELIVERY, function (index, value) {
        var check = '', priceStr = '', timeStr = '';
        if (value.CHECKED == 'Y') {
            check = 'checked="checked"';
        }
        if (value.PRICE == 0) {
            priceStr = 'Бесплатно';
        } else {
            priceStr = value.PRICE_FORMATED;
        }
        if (value.PERIOD_TEXT) {
            var newText = value.PERIOD_TEXT.replace('В днях:', '').trim();
            var endStr = declOfNum(newText, ['день', 'дня', 'дней']);
            timeStr = 'Срок доставки ' + newText + ' ' + endStr + ', с момента передачи заказа в транспортную компанию';
        }
        var content = '<div class="form-group white-box" id="delivery_id_' + value.ID + '"><div class="row"><div class="col-sm-10"><label class="radio"><input type="radio" name="DELIVERY_ID" value="' + value.ID + '" ' + check + '><span class="radio-indicator"></span><span class="radio-title">' + value.NAME + '</span><br>' + value.DESCRIPTION + '<span class="js_delivery_time">' + timeStr + '</span></label></div><div class="col-sm-2"><div class="order-form_price">' + priceStr + '</div></div></div></div>';
        $('.js_delivery_block').append(content);
    });
    $('.js_delivery_block').show();


    //--------------------------способы оплаты
    $('.js_paysystem_block').hide();
    $('.js_paysystem_block .form-group').each(function (index, value) {
        $(value).remove();
    });
    $.each(result.order.PAY_SYSTEM, function (index, value) {
        if (value.CHECKED == 'Y') {
            var check = 'checked="checked"';
        }
        var content = '<div class="form-group white-box" id="paysystem_id_' + value.ID + '"><div class="row"><div class="col-sm-10"><label class="radio"><input type="radio" name="PAY_SYSTEM_ID" value="' + value.ID + '" ' + check + '><span class="radio-indicator"></span><span class="radio-title">' + value.NAME + '</span><br>' + value.DESCRIPTION + '</label></div>        <div class="col-sm-2"><div class="order-form_price"></div></div></div></div>';
        $('.js_paysystem_block').append(content);
    });
    $('.js_paysystem_block').show();

    //--------------------------итого
    $('.js_delivery_price').html(result.order.TOTAL.DELIVERY_PRICE_FORMATED);
    $('.js_itogo_price').html(result.order.TOTAL.ORDER_TOTAL_PRICE_FORMATED);

    //поле адреса
    var showAddress = false;
    $.each(result.order.ORDER_PROP.properties, function (index, value) {
        if (value.ID == 21) {
            showAddress = true;
        }
    });

    if (showAddress) {
        $('#addressField').show();
    } else {
        $('#addressField').hide();
    }

    $('.preloaderOn').each(
        function () {
            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                next();
            });
        }
    );
}

CustomBitrixCart.prototype.validation = function () {
    //TODO:придумать валидацию
    return true;
}
CustomBitrixCart.prototype.updateAjaxData = function () {
    $('#mainBlockOrder').addClass('preloaderOn');
    var arRequest = this.serialize('#orderForm');
    arRequest.push({name: 'action', value: 'refreshOrderAjax'});
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '/bitrix/components/bitrix/sale.order.ajax/ajax.php',
        data: arRequest,
        success: function (data) {
            cart.updatePage(data);
        }
    });
};
CustomBitrixCart.prototype.createOrder = function () {
    if (this.validation()) {
        $('#mainBlockOrder').addClass('preloaderOn');
        var arRequest = this.serialize('#orderForm', true);
        arRequest.push({name: 'action', value: 'saveOrderAjax'});
        $.ajax({
            type: 'POST',
            dataType: 'json',
            url: '/order/index.php',
            data: arRequest,
            success: function (data) {
                if (data.order.REDIRECT_URL) {
                    window.location.href = data.order.REDIRECT_URL;
                } else {
                    var text = '';
                    $.each(data.order.ERROR.PROPERTY, function (index, value) {
                        text += value + '<br>';
                    });
                    $('#error_text').show().html('Проверьте правильность полей!<br>' + text);
                    $('.preloaderOn').each(
                        function () {
                            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                                next();
                            });
                        }
                    );
                }
            }
        });
    }
}

var cart = new CustomBitrixCart();

$(function () {
    $('.js-client-order').on('click', function () {
        $(this).parent().toggleClass('open');
    });

    $(document).on('change', "input[name$='DELIVERY_ID']", function () {
        cart.updateAjaxData();
    });

    $(document).on('change', "input[name$='PAY_SYSTEM_ID']", function () {
        cart.updateAjaxData();
    });

    $(document).on('submit', '#orderForm', function (e) {
        e.preventDefault();
        cart.createOrder();
        return false;
    });

    cart.updateAjaxData();
});
My Template
<? if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
use Bitrix\Main,
    Bitrix\Main\Localization\Loc;

$signer = new \Bitrix\Main\Security\Sign\Signer;
$signedParams = $signer->sign(base64_encode(serialize($arParams)), 'sale.order.ajax');
?>

<p>Уже зарегестрированы? <a href="#">Нажми чтобы войти</a></p>
<section class="order-page">
    <form action="#" id="orderForm">

        <input type = "hidden" name = "location_type" value = "code">
        <input type = "hidden" name = "BUYER_STORE" value = "1">
        <input type = "hidden" name = "PERSON_TYPE" value = "1">  <!-- 1 - если только физ.лица и нет выбора -->
        <input type = "hidden" name = "PERSON_TYPE_OLD" value = "1">
        <input type = "hidden" name = "PROFILE_ID" value = "1">

        <?=bitrix_sessid_post()?>

        <input type="hidden" name="soa-action" value="saveOrderAjax"/>
        <input type="hidden" name="via_ajax" value="Y"/>
        <input type="hidden" name="SITE_ID" value="s1"/>
        <input type="hidden" name="signedParamsString" value="<?=$signedParams?>">

        <div class="block-cell">
            <h1>Заполните заявку</h1>
            <div class="form-line">

                <?$APPLICATION->IncludeComponent(
                    "bitrix:sale.location.selector.search",
                    "",
                    Array(
                        "CACHE_TIME" => "36000000",
                        "CACHE_TYPE" => "A",
                        "CODE" => "",
                        "FILTER_BY_SITE" => "N",
                        "ID" => "",
                        "INITIALIZE_BY_GLOBAL_EVENT" => "",

                        "INPUT_NAME" => "LOCATION",

                        "JS_CALLBACK" => "",
                        "JS_CONTROL_GLOBAL_ID" => "",
                        "PROVIDE_LINK_BY" => "id",
                        "SHOW_DEFAULT_LOCATIONS" => "N",
                        "SUPPRESS_ERRORS" => "N",

                        "PROVIDE_LINK_BY" => "code"
                    )
                );?>

            </div>

            <div class="form-line">
                <label>Адрес *</label>
                <input type="text" placeholder="Введите адрес" name="ORDER_PROP_7">
            </div>

            <div class="form-line two-line">
                <div class="two-block">
                    <label>ФИО *</label>
                    <input type="text" name = "ORDER_PROP_1" placeholder="Введите ФИО">
                </div>

            </div>
            <div class="form-line">
                <label>Контактная информация *</label>
                <input type="text" placeholder="Email" name="ORDER_PROP_2" id="email">
                <input type="text" placeholder="+7 (999) 000-00-00" name="ORDER_PROP_3" id="number">
            </div>

            <table class="price-total padding">
                <tr>
                    <th colspan="2">Итого</th>
                </tr>
                <tr>
                    <td class="title">Итог</td>
                    <td class="js_itogo_format">
                        <span class="js_total_price"><!--120 000 руб.--></span>
                    </td>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_DELIVERY');?></td>
                    <td>
                        <span class="js_delivery_price color green"><!--Бесплатная доставка--></span>
                    </td>
                </tr>
                <tr>
                    <td class="title">Стоимость заказа</td>
                    <td>
                        <span class="js_itogo_price color blue"><!--12 000 руб--></span>
                    </td>
                </tr>
            </table>




        </div>
        <div class="block-cell">

            <div class = "js_delivery_block">
                <h1>Способ доставки доставки</h1>

                <div class="form-line delivery-block">

                    <div class="delivery-item">
                      <label>
                        <input type="radio" class="circle" name="DELIVERY_ID" value="2">
                        Доставка курьером
                      </label>
                       </div>

                    <div class="delivery-item">
                        <label>
                            <input type="radio" class="circle" name = "DELIVERY_ID" value = "3">
                            Самовывоз
                        </label>
                    </div>
                </div>
            </div>


            <div class="js_paysystem_block">
                <h2>Способ оплаты оплаты</h2>

                    <div class="payment-item form-group">
                        <label>

                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "1">
                            Наличные курьеру

                        </label>
                    </div>
                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "2">
                            Наложенный платеж

                        </label>
                    </div>

                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "3">
                            Яндекс.Деньги
                        </label>
                    </div>

                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "4">
                            Банковские карты
                        </label>
                    </div>

                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "5">
                            Терминалы
                        </label>
                    </div>

                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "7">
                            Сбербанк
                        </label>
                    </div>

                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "8">
                            Банковский перевод
                        </label>
                    </div>

                    <div class="payment-item form-group">
                        <label>
                            <input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "9">
                            Внутренний счет
                        </label>
                    </div>


            </div>


            <div class="form-line">
                <input type="submit" value="Оформить заказ">
            </div>



        </div>
    </form>
</section>
My Script.js
function declOfNum(number, titles) {
    var cases = [2, 0, 1, 1, 1, 2];
    return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
}

function in_array(needle, haystack, strict) {
    var found = false, key, strict = !!strict;
    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
    }
    return found;
}
/*
 * Упрощенный класс для работы с битриксовой корзиной
 * */
var CustomBitrixCart = function (params) {
};
CustomBitrixCart.prototype.serialize = function (selector, noContainer) {
    var preparedData = $(selector).serializeArray(), i, arRequest = [],
        notInOrderContainer = [
            'sessid',
            'SITE_ID',
            'via_ajax',
            'signedParamsString',
        ];
    for (i in preparedData) {
        if (preparedData.hasOwnProperty(i)) {
            if (in_array(preparedData[i].name, notInOrderContainer) || noContainer == true) {
                arRequest.push(
                    {
                        name: preparedData[i].name,
                        value: preparedData[i].value,
                    }
                );
            } else {
                arRequest.push(
                    {
                        name: 'order[' + preparedData[i].name + ']',
                        value: preparedData[i].value,
                    }
                );
            }
        }
    }

    //arRequest.push({name: 'signedParamsString', value: $('#signedParamsString').val()});
    return arRequest;
};
CustomBitrixCart.prototype.updatePage = function (result) {


    //--------------------------доставки
    $('.js_delivery_block').hide();
    $('.js_delivery_block .delivery-item').each(function (index, value) {
        $(value).remove();
    });

    $.each(result.order.DELIVERY, function (index, value) {
        var check = '', priceStr = '', timeStr = '';
        if(value.CHECKED == 'Y'){
            check = 'checked';
        }
        if (value.PRICE == 0) {
            priceStr = 'Бесплатно!';
        } else {
            priceStr = value.PRICE_FORMATED;
        }

        var content = '<div class="delivery-item form-group">' +
            '<label class="circle ' + check + '">' +
            '<div class="jq-radio circle ' + check + '" unselectable="on" style="user-select: none; display: inline-block; position: relative;">' +
            '<input type="radio" class="circle" name="DELIVERY_ID"'  + check + ' value="' + value.ID + '" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">' +
            '<div class="jq-radio__div"></div></div>' + value.NAME +
            //'<div class="delivery-text">' + /*value.DESCRIPTION*/ + ' ' +
            //'</div>' +
            '</label>' +
            '</div>';

        $('.js_delivery_block').append(content);
    });

    $('.js_delivery_block').show();



    //--------------------------способы оплаты
    $('.js_paysystem_block').hide();
    $('.js_paysystem_block .payment-block .payment-item').each(function (index, value) {
        $(value).remove();
    });
    $.each(result.order.PAY_SYSTEM, function (index, value) {
        var check = '';
        if (value.CHECKED == 'Y') {
            check = 'checked';
        }

        var content = '<div class="payment-item form-group">' +
            '<label class="circle ' + check + '"><input type="radio" class="circle" name = "PAY_SYSTEM_ID" value = "1"> Наличные курьеру </label>' +
            '</div>';

        $('.js_paysystem_block .payment-block').append(content);
    });
    $('.js_paysystem_block').show();



    //--------------------------итого
    $('.js_delivery_price').html(result.order.TOTAL.DELIVERY_PRICE_FORMATED);
    $('.js_itogo_price').html(result.order.TOTAL.ORDER_TOTAL_PRICE_FORMATED);

    //поле адреса
    var showAddress = false;
    $.each(result.order.ORDER_PROP.properties, function (index, value) {
        if (value.ID == 21) {
            showAddress = true;
        }
    });

    if (showAddress) {
        $('#addressField').show();
    } else {
        $('#addressField').hide();
    }

    $('.preloaderOn').each(
        function () {
            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                next();
            });
        }
    );
}
CustomBitrixCart.prototype.validation = function () {
    //TODO:придумать валидацию
    return true;
}
CustomBitrixCart.prototype.updateAjaxData = function () {
    $('#mainBlockOrder').addClass('preloaderOn');
    var arRequest = this.serialize('#orderForm');

  arRequest.push({name: 'soa-action', value: 'refreshOrderAjax'});
  $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '/bitrix/components/bitrix/sale.order.ajax/ajax.php',
        data: arRequest,
        success: function (data) {
            cart.updatePage(data);
        }
    });
};
CustomBitrixCart.prototype.createOrder = function () {
    if (this.validation()) {
        $('#orderForm').addClass('preloaderOn');
        var arRequest = this.serialize('#orderForm', true);
        arRequest.push({name: 'soa-action', value: 'saveOrderAjax'});
        $.ajax({
            type: 'POST',
            dataType: 'json',
            url: '/skillbox/order/index.php',
            data: arRequest,
            success: function (data) {
                if (data.order.REDIRECT_URL) {
                    window.location.href = data.order.REDIRECT_URL;
                   /* console.log(data);
                    debugger;*/

                } else {
                    var text = '';
                    $.each(data.order.ERROR.PROPERTY, function (index, value) {
                        text += value + '<br>';
                    });
                    $('#error_text').show().html('Проверьте правильность полей!<br>' + text);
                    $('.preloaderOn').each(
                        function () {
                            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                                next();
                            });
                        }
                    );
                }
            }
        });
    }
}


var cart = new CustomBitrixCart();

$(function () {
    $('.js-client-order').on('click', function () {
        $(this).parent().toggleClass('open');
    });

    $(document).on('change', "input[name$='DELIVERY_ID']", function () {

        cart.updateAjaxData();
    });

    $(document).on('change', "input[name$='PAY_SYSTEM_ID']", function () {

        cart.updateAjaxData();
    });

    $(document).on('submit', '#orderForm', function (e) {
        e.preventDefault();
        cart.createOrder();
        return false;
    });

    cart.updateAjaxData();
});
Template
<? if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
use Bitrix\Main\Localization\Loc;
?>
<!--<script src="--><?//=$_SERVER['HTTP_HOST']?><!--/local/js/application.min.js"></script>-->
<style src="<?=$_SERVER['HTTP_HOST']?>/local/css/application.css"></style>

<section class="order-page">
    <form action="#" id="orderForm" class="orderForm">
<!--        --><?//=pre($arResult["JS_DATA"], 1);?>
<!--        <input type="hidden" name="location_type" value="code"/>-->
        <input type="hidden" name="BUYER_STORE" value="<?=$arResult["JS_DATA"]["BUYER_STORE"];?>"/>
        <input type="hidden" name="PERSON_TYPE" value="1"/>
        <input type="hidden" name="PERSON_TYPE_OLD" value="1"/>
        <input type="hidden" name="ZIP_PROPERTY_CHANGED" value="<?=$arResult["JS_DATA"]["ZIP_PROPERTY_CHANGED"];?>"/>
        <?=bitrix_sessid_post()?>
        <input type="hidden" name="soa-action" value="saveOrderAjax"/>
        <input type="hidden" name="via_ajax" value="Y"/>
        <input type="hidden" name="PROFILE_ID" value="9"/>
        <input type="hidden" name="SITE_ID" value="s1"/>
<!--        <input type="hidden" name="LOCATION" value=""/>-->
        <?
        $signer = new \Bitrix\Main\Security\Sign\Signer;
        $signedParams = $signer->sign(base64_encode(serialize($arParams)), 'sale.order.ajax');
        ?>
        <input type="hidden" name="signedParamsString" value="<?=$signedParams?>">
<!--        <input type="hidden" id="signedParamsString" name="signedParamsString" value="--><?//=CUtil::JSEscape($signedParams)?><!--"/>-->

        <!--        <input type="hidden" name="sign" value="1"/>-->
        <!--        signedParamsString в скрытое поле из шаблона-->
<!--                --><?//= //pre($arResult,1);?>
        <div class="block-cell">
            <h1><?=Loc::getMessage('H1_COMPLETE_ORDER');?></h1>
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_CITY');?> *</label>
<!--                <input type="text" autocomplete="off" name="ORDER_PROP_6" value="" class="dropdown-field"-->
<!--                       placeholder="Введите название ..." style="display: none;">-->
                <!--                <select>-->
                <!--                    <option value="1">Росийская Федерация 1</option>-->
                <!--                </select>-->
            </div>
            <div class="form-line">
<!--                <label>Город *</label>-->
                <? $APPLICATION->IncludeComponent(
                    "bitrix:sale.location.selector.search",
                    "location_searcher",
                    Array(
//                        "CACHE_TIME" => "36000000",
//                        "CACHE_TYPE" => "A",
//                        "CODE" => "Y",
//                        "FILTER_BY_SITE" => "N",
//                        "ID" => "",
//                        "INITIALIZE_BY_GLOBAL_EVENT" => "",
                        "INPUT_NAME" => "ORDER_PROP_6",
//                        "JS_CALLBACK" => "",
//                        "JS_CONTROL_GLOBAL_ID" => "",
//                        "PROVIDE_LINK_BY" => "id",
//                        "SHOW_DEFAULT_LOCATIONS" => "",
//                        "SUPPRESS_ERRORS" => "N"
                    )
                ); ?>
            </div>

            <!--            <div class="form-line">-->
            <!--                <label>Город *</label>-->
            <!--                <input type="text" placeholder="Введите город">-->
            <!--            </div>-->
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_ADDRESS');?> *</label>
                <input id="addressField" class="addressField" type="text" placeholder="<?=Loc::getMessage('INPUT_ADDRESS');?>" name="ORDER_PROP_7">
            </div>
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_FIO');?> *</label>
                <input type="text" placeholder="<?=Loc::getMessage('INPUT_FIO');?>" name="ORDER_PROP_1">

                <!--                <div class="two-block">-->
                <!--                    <label>Фамилия *</label>-->
                <!--                    <input type="text" placeholder="Введите фамилию">-->
                <!--                </div>-->
            </div>
            <!--            <div class="form-line two-line">-->
            <!--                <div class="two-block">-->
            <!--                    <label>Индекс *</label>-->
            <!--                    <input type="text" placeholder="Введите индекс">-->
            <!--                </div>-->
            <!--            </div>-->
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_CONTACTS');?> *</label>
                <input type="text" placeholder="Email" name="ORDER_PROP_2">
                <input type="text" placeholder="+7 (999) 000-00-00" name="ORDER_PROP_3">
            </div>
            <table class="price-total padding">
                <tr>
                    <th colspan="2"><?=Loc::getMessage('TITLE_ITOGO');?></th>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_ITOG');?></td>
                    <td class="js_itogo_format">
                        <span class="js_total_price"><!--120 000 руб.--></span>
                    </td>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_DELIVERY');?></td>
                    <td>
                        <span class="js_delivery_price color green"><!--Бесплатная доставка--></span>
                    </td>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_FULL_PRICE');?></td>
                    <td>
                        <span class="js_itogo_price color blue"><!--12 000 руб--></span>
                    </td>
                </tr>
            </table>
        </div>
        <div class="block-cell">

            <div class="js_delivery_block">
                <h1><?=Loc::getMessage('TITLE_DELIVERY_TYPE');?></h1>

                <div class="form-line delivery-block">
<!--                    <div class="delivery-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="DELIVERY_ID" value="2" checked>-->
<!--                            Доставка курьером-->
<!--                        </label>-->
<!--                    </div>-->
<!--                    <div class="delivery-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="DELIVERY_ID" value="3">-->
<!--                            Самовывоз-->
<!--                        </label>-->
<!--                    </div>-->
                </div>
            </div>
            <div class="js_paysystem_block">
                <h2><?=Loc::getMessage('TITLE_PAYMENT_TYPE');?></h2>
                <div class="form-line payment-block">
<!--                    <div class="payment-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="PAY_SYSTEM_ID" value="2" checked>-->
<!--                            Банковский перевод-->
<!--                        </label>-->
<!--                    </div>-->
<!--                    <div class="payment-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="PAY_SYSTEM_ID" value="1">-->
<!--                            Оплата наличными-->
<!--                        </label>-->
<!--                    </div>-->
                </div>
            </div>
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_COMMENTS');?></label>
                <input type="text" name="ORDER_DESCRIPTION">
            </div>
            <div class="form-line">
                <input type="submit" value="<?=Loc::getMessage('COMPLETE_ORDER');?>">
            </div>
        </div>
    </form>
</section>
Script.js
function declOfNum(number, titles) {
    var cases = [2, 0, 1, 1, 1, 2];
    return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
}

function in_array(needle, haystack, strict) {
    var found = false, key, strict = !!strict;
    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
    }
    return found;
}

/*
 * Упрощенный кла�� дл� работы � битрик�овой корзиной
 * */
var CustomBitrixCart = function (params) {
};
CustomBitrixCart.prototype.serialize = function (selector, noContainer) {
    var preparedData = $(selector).serializeArray(), i, arRequest = [],
        notInOrderContainer = [
            'sessid',
            'SITE_ID',
            'via_ajax',
            'signedParamsString',
        ];
    for (i in preparedData) {
        if (preparedData.hasOwnProperty(i)) {
            if (in_array(preparedData[i].name, notInOrderContainer) || noContainer == true) {
                arRequest.push(
                    {
                        name: preparedData[i].name,
                        value: preparedData[i].value,
                    }
                );
            } else {
                arRequest.push(
                    {
                        name: 'order[' + preparedData[i].name + ']',
                        value: preparedData[i].value,
                    }
                );
            }
        }
    }

    //arRequest.push({name: 'signedParamsString', value: sign});
    return arRequest;
};

CustomBitrixCart.prototype.updatePage = function (result) {
    //alert('!!!!!!!!!!!!!!');
    //--------------------------до�тавки
    $('.js_delivery_block').hide();
    $('.js_delivery_block .delivery-item').each(function (index, value) {
        $(value).remove();
    });

    $.each(result.order.DELIVERY, function (index, value) {
        var check = '', priceStr = '', timeStr = '';
        if (value.CHECKED == 'Y') {
            check = 'checked';
        }
        if (value.PRICE == 0) {
            priceStr = 'Бе�платно';
        } else {
            priceStr = value.PRICE_FORMATED;
        }
        if (value.PERIOD_TEXT) {
            var newText = value.PERIOD_TEXT.replace('В дн�х:', '').trim();
            var endStr = declOfNum(newText, ['день', 'дн�', 'дней']);
            timeStr = 'Срок до�тавки ' + newText + ' ' + endStr + ', � момента передачи заказа в тран�портную компанию';
        }

        var content = '<div class="delivery-item form-group">' +
            '<label class="circle ' + check + '">' +
            '<div class="jq-radio circle ' + check + '" unselectable="on" style="user-select: none; display: inline-block; position: relative;">' +
            '<input type="radio" class="circle" name="DELIVERY_ID"'  + check + ' value="' + value.ID + '" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">' +
            '<div class="jq-radio__div"></div></div>' + value.NAME +
            //'<div class="delivery-text">' + /*value.DESCRIPTION*/ + ' ' +
            //'</div>' +
            '</label>' +
            '</div>';

        // var content2 = '<div class="delivery-item">' +
        //     '<label class="radio">' +
        //     '<input type="radio" name="DELIVERY_ID" value="' + value.ID + '" ' + check + '>' +
        //     '<span class="radio-title">' + value.NAME + '</span>' +
        //     '</label>' +
        //     '</div>';

        $('.js_delivery_block .delivery-block').append(content);
    });
    $('.js_delivery_block').show();


    //--------------------------�по�обы оплаты
    $('.js_paysystem_block').hide();
    $('.js_paysystem_block .payment-item').each(function (index, value) {
        $(value).remove();
    });
    $.each(result.order.PAY_SYSTEM, function (index, value) {
        var check = '';
        if (value.CHECKED == 'Y') {
            check = 'checked';
        }
        var content = '<div class="payment-item form-group">' +
            '<label class="circle ' + check + '">' +
            '<div class="jq-radio circle ' + check + '" unselectable="on" style="user-select: none; display: inline-block; position: relative;">' +
            '<input type="radio" class="circle" name="PAY_SYSTEM_ID"' + check + ' value="' + value.ID + '" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">' +
            '<div class="jq-radio__div"></div></div>' + value.NAME +
            //'<div class="payment-text">' + /*value.DESCRIPTION*/ + ' ' +
            //'</div>' +
            '</label>' +
            '</div>';

        // var content2 = '<div class="payment-item">' +
        //     '<div class="row"><label class="radio">' +
        //     '<input type="radio" name="PAY_SYSTEM_ID" value="' + value.ID + '" ' + check + '>' +
        //     '<span class="radio-title">' + value.NAME + '</span>' +
        //     '</label>' +
        //     '</div>' +
        //     '</div>';

        $('.js_paysystem_block .payment-block').append(content);
    });
    $('.js_paysystem_block').show();

    //--------------------------итого
    $('.js_total_price').html(result.order.TOTAL.ORDER_PRICE_FORMATED);
    $('.js_delivery_price').html(result.order.TOTAL.DELIVERY_PRICE_FORMATED);
    $('.js_itogo_price').html(result.order.TOTAL.ORDER_TOTAL_PRICE_FORMATED);

    //поле адре�а
    // var showAddress = false;
    // $.each(result.order.ORDER_PROP.properties, function (index, value) {
    //     if (value.ID == 21) {
    //         showAddress = true;
    //     }
    // });
    //
    // if (showAddress) {
    //     $('#addressField').show();
    // } else {
    //     $('#addressField').hide();
    // }

    $('.preloaderOn').each(
        function () {
            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                next();
            });
        }
    );
}

CustomBitrixCart.prototype.validation = function () {
    //TODO:придумать валидацию
    return true;
}

CustomBitrixCart.prototype.updateAjaxData = function () {
    $('#orderForm').addClass('preloaderOn');
    var arRequest = this.serialize('#orderForm');
    arRequest.push({name: 'soa-action', value: 'refreshOrderAjax'}); //refreshOrderAjax было
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '/bitrix/components/bitrix/sale.order.ajax/ajax.php',
        data: arRequest,
        success: function (data) {
            cart.updatePage(data);
        }
    });
};

CustomBitrixCart.prototype.createOrder = function () {
    if (this.validation()) {
        $('#orderForm').addClass('preloaderOn');
        var arRequest = this.serialize('#orderForm', true);
        arRequest.push({name: 'soa-action', value: 'saveOrderAjax'});
        $.ajax({
            type: 'POST',
            dataType: 'json',
            url: '/skillbox/order/index.php',
            data: arRequest,
            success: function (data) {
                if (data.order.REDIRECT_URL) {
                    window.location.href = data.order.REDIRECT_URL;
                } else {
                    var text = '';
                    $.each(data.order.ERROR.PROPERTY, function (index, value) {
                        text += value + '<br>';
                    });
                    $('#error_text').show().html('Проверьте правильно�ть полей!<br>' + text);
                    $('.preloaderOn').each(
                        function () {
                            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                                next();
                            });
                        }
                    );
                }
            }
        });
    }
}

var cart = new CustomBitrixCart();

$(function () {
    // $('.js-client-order').on('click', function () {
    //     $(this).parent().toggleClass('open');
    // });

    $(document).on('change', "input[name$='DELIVERY_ID']", function () {
        cart.updateAjaxData();
    });

    $(document).on('change', "input[name$='PAY_SYSTEM_ID']", function () {
         cart.updateAjaxData();
    });

    $(document).on('submit', '#orderForm', function (e) {
        e.preventDefault();
        cart.createOrder();
        return false;
    });

    cart.updateAjaxData();
});
Template 1
<? if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
use Bitrix\Main\Localization\Loc;
?>
<!--<script src="--><?//=$_SERVER['HTTP_HOST']?><!--/local/js/application.min.js"></script>-->
<style src="<?=$_SERVER['HTTP_HOST']?>/local/css/application.css"></style>

<section class="order-page">
    <form action="#" id="orderForm" class="orderForm">
<!--        --><?//=pre($arResult["JS_DATA"], 1);?>
<!--        <input type="hidden" name="location_type" value="code"/>-->
        <input type="hidden" name="BUYER_STORE" value="<?=$arResult["JS_DATA"]["BUYER_STORE"];?>"/>
        <input type="hidden" name="PERSON_TYPE" value="1"/>
        <input type="hidden" name="PERSON_TYPE_OLD" value="1"/>
        <input type="hidden" name="ZIP_PROPERTY_CHANGED" value="<?=$arResult["JS_DATA"]["ZIP_PROPERTY_CHANGED"];?>"/>
        <?=bitrix_sessid_post()?>
        <input type="hidden" name="soa-action" value="saveOrderAjax"/>
        <input type="hidden" name="via_ajax" value="Y"/>
        <input type="hidden" name="PROFILE_ID" value="9"/>
        <input type="hidden" name="SITE_ID" value="s1"/>
<!--        <input type="hidden" name="LOCATION" value=""/>-->
        <?
        $signer = new \Bitrix\Main\Security\Sign\Signer;
        $signedParams = $signer->sign(base64_encode(serialize($arParams)), 'sale.order.ajax');
        ?>
        <input type="hidden" name="signedParamsString" value="<?=$signedParams?>">
<!--        <input type="hidden" id="signedParamsString" name="signedParamsString" value="--><?//=CUtil::JSEscape($signedParams)?><!--"/>-->

        <!--        <input type="hidden" name="sign" value="1"/>-->
        <!--        signedParamsString в скрытое поле из шаблона-->
<!--                --><?//= //pre($arResult,1);?>
        <div class="block-cell">
            <h1><?=Loc::getMessage('H1_COMPLETE_ORDER');?></h1>
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_CITY');?> *</label>
<!--                <input type="text" autocomplete="off" name="ORDER_PROP_6" value="" class="dropdown-field"-->
<!--                       placeholder="Введите название ..." style="display: none;">-->
                <!--                <select>-->
                <!--                    <option value="1">Росийская Федерация 1</option>-->
                <!--                </select>-->
            </div>
            <div class="form-line">
<!--                <label>Город *</label>-->
                <? $APPLICATION->IncludeComponent(
                    "bitrix:sale.location.selector.search",
                    "location_searcher",
                    Array(
//                        "CACHE_TIME" => "36000000",
//                        "CACHE_TYPE" => "A",
//                        "CODE" => "Y",
//                        "FILTER_BY_SITE" => "N",
//                        "ID" => "",
//                        "INITIALIZE_BY_GLOBAL_EVENT" => "",
                        "INPUT_NAME" => "ORDER_PROP_6",
//                        "JS_CALLBACK" => "",
//                        "JS_CONTROL_GLOBAL_ID" => "",
//                        "PROVIDE_LINK_BY" => "id",
//                        "SHOW_DEFAULT_LOCATIONS" => "",
//                        "SUPPRESS_ERRORS" => "N"
                    )
                ); ?>
            </div>

            <!--            <div class="form-line">-->
            <!--                <label>Город *</label>-->
            <!--                <input type="text" placeholder="Введите город">-->
            <!--            </div>-->
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_ADDRESS');?> *</label>
                <input id="addressField" class="addressField" type="text" placeholder="<?=Loc::getMessage('INPUT_ADDRESS');?>" name="ORDER_PROP_7">
            </div>
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_FIO');?> *</label>
                <input type="text" placeholder="<?=Loc::getMessage('INPUT_FIO');?>" name="ORDER_PROP_1">

                <!--                <div class="two-block">-->
                <!--                    <label>Фамилия *</label>-->
                <!--                    <input type="text" placeholder="Введите фамилию">-->
                <!--                </div>-->
            </div>
            <!--            <div class="form-line two-line">-->
            <!--                <div class="two-block">-->
            <!--                    <label>Индекс *</label>-->
            <!--                    <input type="text" placeholder="Введите индекс">-->
            <!--                </div>-->
            <!--            </div>-->
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_CONTACTS');?> *</label>
                <input type="text" placeholder="Email" name="ORDER_PROP_2">
                <input type="text" placeholder="+7 (999) 000-00-00" name="ORDER_PROP_3">
            </div>
            
            <table class="price-total padding">
                <tr>
                    <th colspan="2"><?=Loc::getMessage('TITLE_ITOGO');?></th>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_ITOG');?></td>
                    <td class="js_itogo_format">
                        <span class="js_total_price"><!--120 000 руб.--></span>
                    </td>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_DELIVERY');?></td>
                    <td>
                        <span class="js_delivery_price color green"><!--Бесплатная доставка--></span>
                    </td>
                </tr>
                <tr>
                    <td class="title"><?=Loc::getMessage('ORDER_FULL_PRICE');?></td>
                    <td>
                        <span class="js_itogo_price color blue"><!--12 000 руб--></span>
                    </td>
                </tr>
            </table>

            
        </div>
        <div class="block-cell">

            <div class="js_delivery_block">
                <h1><?=Loc::getMessage('TITLE_DELIVERY_TYPE');?></h1>

                <div class="form-line delivery-block">
<!--                    <div class="delivery-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="DELIVERY_ID" value="2" checked>-->
<!--                            Доставка курьером-->
<!--                        </label>-->
<!--                    </div>-->
<!--                    <div class="delivery-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="DELIVERY_ID" value="3">-->
<!--                            Самовывоз-->
<!--                        </label>-->
<!--                    </div>-->
                </div>
            </div>
            <div class="js_paysystem_block">
                <h2><?=Loc::getMessage('TITLE_PAYMENT_TYPE');?></h2>
                <div class="form-line payment-block">
<!--                    <div class="payment-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="PAY_SYSTEM_ID" value="2" checked>-->
<!--                            Банковский перевод-->
<!--                        </label>-->
<!--                    </div>-->
<!--                    <div class="payment-item">-->
<!--                        <label>-->
<!--                            <input type="radio" class="circle" name="PAY_SYSTEM_ID" value="1">-->
<!--                            Оплата наличными-->
<!--                        </label>-->
<!--                    </div>-->
                </div>
            </div>
            <div class="form-line">
                <label><?=Loc::getMessage('TITLE_COMMENTS');?></label>
                <input type="text" name="ORDER_DESCRIPTION">
            </div>
            <div class="form-line">
                <input type="submit" value="<?=Loc::getMessage('COMPLETE_ORDER');?>">
            </div>
        </div>
    </form>
</section>
Script1.js
function declOfNum(number, titles) {
    var cases = [2, 0, 1, 1, 1, 2];
    return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
}

function in_array(needle, haystack, strict) {
    var found = false, key, strict = !!strict;
    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
    }
    return found;
}

/*
 * Упрощенный класс для работы с битриксовой корзиной
 * */
var CustomBitrixCart = function (params) {
};
CustomBitrixCart.prototype.serialize = function (selector, noContainer) {
    var preparedData = $(selector).serializeArray(), i, arRequest = [],
        notInOrderContainer = [
            'sessid',
            'SITE_ID',
            'via_ajax',
            'signedParamsString',
        ];
    for (i in preparedData) {
        if (preparedData.hasOwnProperty(i)) {
            if (in_array(preparedData[i].name, notInOrderContainer) || noContainer == true) {
                arRequest.push(
                    {
                        name: preparedData[i].name,
                        value: preparedData[i].value,
                    }
                );
            } else {
                arRequest.push(
                    {
                        name: 'order[' + preparedData[i].name + ']',
                        value: preparedData[i].value,
                    }
                );
            }
        }
    }

    //arRequest.push({name: 'signedParamsString', value: sign});
    return arRequest;
};

CustomBitrixCart.prototype.updatePage = function (result) {
    //alert('!!!!!!!!!!!!!!');
    //--------------------------доставки
    $('.js_delivery_block').hide();
    $('.js_delivery_block .delivery-item').each(function (index, value) {
        $(value).remove();
    });

    $.each(result.order.DELIVERY, function (index, value) {
        var check = '', priceStr = '', timeStr = '';
        if (value.CHECKED == 'Y') {
            check = 'checked';
        }
        if (value.PRICE == 0) {
            priceStr = 'Бесплатно';
        } else {
            priceStr = value.PRICE_FORMATED;
        }
        if (value.PERIOD_TEXT) {
            var newText = value.PERIOD_TEXT.replace('В днях:', '').trim();
            var endStr = declOfNum(newText, ['день', 'дня', 'дней']);
            timeStr = 'Срок доставки ' + newText + ' ' + endStr + ', с момента передачи заказа в транспортную компанию';
        }

        var content = '<div class="delivery-item form-group">' +
            '<label class="circle ' + check + '">' +
            '<div class="jq-radio circle ' + check + '" unselectable="on" style="user-select: none; display: inline-block; position: relative;">' +
            '<input type="radio" class="circle" name="DELIVERY_ID"'  + check + ' value="' + value.ID + '" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">' +
            '<div class="jq-radio__div"></div></div>' + value.NAME +
            //'<div class="delivery-text">' + /*value.DESCRIPTION*/ + ' ' +
            //'</div>' +
            '</label>' +
            '</div>';

        // var content2 = '<div class="delivery-item">' +
        //     '<label class="radio">' +
        //     '<input type="radio" name="DELIVERY_ID" value="' + value.ID + '" ' + check + '>' +
        //     '<span class="radio-title">' + value.NAME + '</span>' +
        //     '</label>' +
        //     '</div>';

        $('.js_delivery_block .delivery-block').append(content);
    });
    $('.js_delivery_block').show();


    //--------------------------способы оплаты
    $('.js_paysystem_block').hide();
    $('.js_paysystem_block .payment-item').each(function (index, value) {
        $(value).remove();
    });
    $.each(result.order.PAY_SYSTEM, function (index, value) {
        var check = '';
        if (value.CHECKED == 'Y') {
            check = 'checked';
        }
        var content = '<div class="payment-item form-group">' +
            '<label class="circle ' + check + '">' +
            '<div class="jq-radio circle ' + check + '" unselectable="on" style="user-select: none; display: inline-block; position: relative;">' +
            '<input type="radio" class="circle" name="PAY_SYSTEM_ID"' + check + ' value="' + value.ID + '" style="position: absolute; z-index: -1; opacity: 0; margin: 0px; padding: 0px;">' +
            '<div class="jq-radio__div"></div></div>' + value.NAME +
            //'<div class="payment-text">' + /*value.DESCRIPTION*/ + ' ' +
            //'</div>' +
            '</label>' +
            '</div>';

        // var content2 = '<div class="payment-item">' +
        //     '<div class="row"><label class="radio">' +
        //     '<input type="radio" name="PAY_SYSTEM_ID" value="' + value.ID + '" ' + check + '>' +
        //     '<span class="radio-title">' + value.NAME + '</span>' +
        //     '</label>' +
        //     '</div>' +
        //     '</div>';

        $('.js_paysystem_block .payment-block').append(content);
    });
    $('.js_paysystem_block').show();

    //--------------------------итого
    $('.js_total_price').html(result.order.TOTAL.ORDER_PRICE_FORMATED);
    $('.js_delivery_price').html(result.order.TOTAL.DELIVERY_PRICE_FORMATED);
    $('.js_itogo_price').html(result.order.TOTAL.ORDER_TOTAL_PRICE_FORMATED);

    //поле адреса
    // var showAddress = false;
    // $.each(result.order.ORDER_PROP.properties, function (index, value) {
    //     if (value.ID == 21) {
    //         showAddress = true;
    //     }
    // });
    //
    // if (showAddress) {
    //     $('#addressField').show();
    // } else {
    //     $('#addressField').hide();
    // }

    $('.preloaderOn').each(
        function () {
            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                next();
            });
        }
    );
}

CustomBitrixCart.prototype.validation = function () {
    //TODO:придумать валидацию
    return true;
}

CustomBitrixCart.prototype.updateAjaxData = function () {
    $('#orderForm').addClass('preloaderOn');
    var arRequest = this.serialize('#orderForm');
    arRequest.push({name: 'soa-action', value: 'refreshOrderAjax'}); //refreshOrderAjax было
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '/bitrix/components/bitrix/sale.order.ajax/ajax.php',
        data: arRequest,
        success: function (data) {
            cart.updatePage(data);
        }
    });
};

CustomBitrixCart.prototype.createOrder = function () {
    if (this.validation()) {
        $('#orderForm').addClass('preloaderOn');
        var arRequest = this.serialize('#orderForm', true);
        arRequest.push({name: 'soa-action', value: 'saveOrderAjax'});
        $.ajax({
            type: 'POST',
            dataType: 'json',
            url: '/skillbox/order/index.php',
            data: arRequest,
            success: function (data) {
                if (data.order.REDIRECT_URL) {
                    window.location.href = data.order.REDIRECT_URL;
                } else {
                    var text = '';
                    $.each(data.order.ERROR.PROPERTY, function (index, value) {
                        text += value + '<br>';
                    });
                    $('#error_text').show().html('Проверьте правильность полей!<br>' + text);
                    $('.preloaderOn').each(
                        function () {
                            $(this).addClass("preAnimation").delay(1000).queue(function (next) {
                                $(this).removeClass("preAnimation").removeClass('preloaderOn');
                                next();
                            });
                        }
                    );
                }
            }
        });
    }
}

var cart = new CustomBitrixCart();

$(function () {
    // $('.js-client-order').on('click', function () {
    //     $(this).parent().toggleClass('open');
    // });

    $(document).on('change', "input[name$='DELIVERY_ID']", function () {
        cart.updateAjaxData();
    });

    $(document).on('change', "input[name$='PAY_SYSTEM_ID']", function () {
         cart.updateAjaxData();
    });

    $(document).on('submit', '#orderForm', function (e) {
        e.preventDefault();
        cart.createOrder();
        return false;
    });

    cart.updateAjaxData();
});

https://www.youtube.com/watch?v=7221k3boS2o&t=26s

https://www.youtube.com/watch?v=C6jW9dqLPvo

https://www.youtube.com/watch?v=7gsuLHGy8CQ

⚠️ **GitHub.com Fallback** ⚠️