(function () { 'use strict'; var publicId = 'pk_80339e8adae722516a89a891d1106'; /** СНО из настроек ГК → CloudPayments (0 ОСН … 5 патент) */ var taxationSystem = 1; var paymentDescription = 'Обучение на курсах'; /** Код НДС CloudPayments (5 = НДС 5%). null — не передавать */ var defaultVat = 5; var saveCard = 0; var minInstallmentRub = 3500; /** Подпись нативной кнопки ГК «Выбрать рассрочку или кредит» (.credit). Пусто — не менять. */ var gcSberCreditButtonLabel = 'СБЕР Рассрочки'; var cardPaymentSequence = ['Sbp', 'ForeignCard', 'Card', 'TinkoffPay', 'SberPay', 'Dolyame', 'MirPay']; var cardPaymentRestricted = [ 'TcsInstallment', 'ApplePay', 'GooglePay', 'YandexPay', 'Som', ]; var installmentPaymentSequence = ['TcsInstallment']; var installmentPaymentRestricted = [ 'Sbp', 'TinkoffPay', 'SberPay', 'MirPay', 'Dolyame', 'ForeignCard', 'YandexPay', 'ApplePay', 'GooglePay', 'Card', ]; var dealId, description, amountNumber, email, phone, currency; function money(n) { return Math.round(Number(n) * 100) / 100; } function itemsTotal(items) { return money( (items || []).reduce(function (s, it) { return s + (it.amount || 0); }, 0) ); } function reconcileItemsTotal(items, total) { if (!items || !items.length) return items; var sum = itemsTotal(items); var target = money(total); if (Math.abs(target - sum) <= 0.009) return items; items[0].amount = target; items[0].price = money(target / (items[0].quantity || 1)); return items; } var style = document.createElement('style'); style.textContent = '.cp-btn-loading {' + 'position: relative;' + 'pointer-events: none;' + 'opacity: 0.7;' + '}' + '.cp-btn-loading::after {' + 'content: "";' + 'position: absolute;' + 'top: 50%;' + 'left: 50%;' + 'width: 24px;' + 'height: 24px;' + 'margin: -12px 0 0 -12px;' + 'border: 3px solid rgba(0,0,0,0.15);' + 'border-top-color: #333;' + 'border-radius: 50%;' + 'animation: cp-spin 0.6s linear infinite;' + '}' + '@keyframes cp-spin {' + 'to { transform: rotate(360deg); }' + '}'; document.head.appendChild(style); function setButtonLoading(buttonEl, loading) { if (!buttonEl) return; buttonEl.classList.toggle('cp-btn-loading', !!loading); } function createPaymentBlock(blockId, imglink, buttonText) { var div = document.createElement('div'); div.innerHTML = '
'; return div.firstElementChild; } function canShowInstallment() { return amountNumber >= minInstallmentRub; } function customizeGcNativeCreditButton(container) { if (!container || !gcSberCreditButtonLabel) return; var buttons = container.querySelectorAll('.gcpay-widget-payment-method-btn.credit'); for (var i = 0; i < buttons.length; i++) { var btn = buttons[i]; var span = btn.querySelector('span'); if (span) { span.textContent = gcSberCreditButtonLabel; } else { btn.textContent = gcSberCreditButtonLabel; } } } function mountCustomPaymentButtons(container) { if (!container) return; var existingInst = container.querySelector('#pay-widget-cloudINST'); if (existingInst) existingInst.remove(); var rfBlock = container.querySelector('#pay-widget-cloudRF'); if (!rfBlock) { rfBlock = createPaymentBlock( 'pay-widget-cloudRF', '/saas/images/card-logo-triple.png?v=1', 'Оплата' ); container.prepend(rfBlock); } if (canShowInstallment()) { var instBlock = createPaymentBlock( 'pay-widget-cloudINST', '/saas/images/t-credit.png', 'В рассрочку' ); rfBlock.after(instBlock); } customizeGcNativeCreditButton(container); } function getDealId() { var scriptEl = document.querySelector('.form-result-block script'); if (scriptEl) { var match = scriptEl.textContent.match(/let\s+dealId\s*=\s*(\d+)/); if (match) return match[1]; match = scriptEl.textContent.match(/dealId\s*[=:]\s*['"]?(\d+)/); if (match) return match[1]; } var href = location.href; var m = href.match(/\/sales\/shop\/dealPay\/id\/(\d+)/); if (m) return m[1]; m = href.match(/\/sales\/shop\/dealPaid\/id\/(\d+)/); if (m) return m[1]; m = href.match(/[?&]dealId=(\d+)/i); if (m) return m[1]; return null; } function getPaymentSumStr() { var priceElement = document.querySelector('.gcpay-widget-order-price p'); if (priceElement && priceElement.textContent) return priceElement.textContent; var inp = document.querySelector('input[name="params[Amount]"]'); if (inp && /^\d+$/.test(String(inp.value || ''))) { return String(parseInt(inp.value, 10) / 100); } var dealInfoElements = document.querySelectorAll('.xdget-dealInfo > p'); for (var i = 0; i < dealInfoElements.length; i++) { var el = dealInfoElements[i]; if (el.textContent.indexOf('Итого к оплате') !== -1) { var b = el.querySelector('b'); if (b) return b.textContent; } } for (var j = 0; j < dealInfoElements.length; j++) { var el2 = dealInfoElements[j]; if (el2.textContent.indexOf('Сумма заказа') !== -1) { var b2 = el2.querySelector('b'); if (b2) return b2.textContent; } } return false; } function getHidden(key) { var input = document.querySelector('input[name="params[DATA]"]'); if (!input) return ''; var m = (input.value || '').match(new RegExp(key + '=([^&]+)', 'i')); if (!m) return ''; try { return decodeURIComponent(m[1].replace(/\+/g, '%20')); } catch (e) { return m[1]; } } function parseULongPayload() { try { var raw = window.ULong; if (!raw || typeof raw !== 'string') return null; var b64 = raw.split('.')[0]; if (!b64) return null; var pad = b64.length % 4; if (pad) b64 += '===='.slice(pad); var json = atob(b64.replace(/-/g, '+').replace(/_/g, '/')); var data = JSON.parse(json); return Array.isArray(data) ? data : null; } catch (e) { return null; } } function getEmailFromULong() { var arr = parseULongPayload(); if (!arr) return ''; for (var i = 0; i < arr.length; i++) { var v = arr[i]; if (typeof v === 'string' && v.indexOf('@') > 0) return v.trim(); } return ''; } function getPhoneFromULong() { var arr = parseULongPayload(); if (!arr) return ''; for (var i = arr.length - 1; i >= 0; i--) { var v = arr[i]; if (typeof v !== 'string' || v.indexOf('@') >= 0) continue; var ph = normalizePhone(v); if (ph) return ph; } return ''; } function normalizePhone(raw) { var digits = (raw || '').replace(/\D/g, ''); if (digits.length === 11 && (digits[0] === '7' || digits[0] === '8')) return '+7' + digits.slice(1); if (digits.length === 10) return '+7' + digits; return ''; } function getEmailFromUserData() { var items = document.querySelectorAll('.user-data__item, .gcpay-widget-user-data tr, .gcpay-widget-order-details tr'); for (var i = 0; i < items.length; i++) { var label = items[i].querySelector('.user-data__item-label, th, td:first-child'); var value = items[i].querySelector('.user-data__item-value, td:last-child'); if (!label || !value) continue; if (/e-?mail|почт/i.test(label.textContent || '')) { var em = (value.textContent || value.innerText || '').trim(); if (em && em.indexOf('@') > 0) return em; } } return ''; } function getPhoneFromUserData() { var items = document.querySelectorAll('.user-data__item, .gcpay-widget-user-data tr, .gcpay-widget-order-details tr'); for (var i = 0; i < items.length; i++) { var label = items[i].querySelector('.user-data__item-label, th, td:first-child'); var value = items[i].querySelector('.user-data__item-value, td:last-child'); if (!label || !value) continue; if (/тел|phone/i.test(label.textContent || '')) { var ph = normalizePhone(value.textContent || value.innerText || ''); if (ph) return ph; } } return ''; } function getEmail() { var selectors = [ 'input[name="formParams[email]"]', 'input[name="params[email]"]', 'input[name="params[Email]"]', 'input[type="email"]', '.gcpay-widget input[type="email"]', ]; for (var i = 0; i < selectors.length; i++) { var el = document.querySelector(selectors[i]); if (el && el.value && String(el.value).trim().indexOf('@') > 0) { return String(el.value).trim(); } } var fromHidden = getHidden('Email').trim(); if (fromHidden && fromHidden.indexOf('@') > 0) return fromHidden; var fromULong = getEmailFromULong(); if (fromULong) return fromULong; return getEmailFromUserData(); } function getPhone() { var selectors = [ 'input[name="formParams[phone]"]', 'input[name="params[phone]"]', 'input[name="params[Phone]"]', 'input[type="tel"]', '.gcpay-widget input[type="tel"]', ]; for (var i = 0; i < selectors.length; i++) { var el = document.querySelector(selectors[i]); if (el && el.value) { var ph = normalizePhone(el.value); if (ph) return ph; } } var fromHidden = normalizePhone(getHidden('Phone')); if (fromHidden) return fromHidden; var fromULong = getPhoneFromULong(); if (fromULong) return fromULong; return getPhoneFromUserData(); } function refreshContactFields() { email = getEmail(); phone = getPhone(); } function getTitleFromParamsData() { var keys = ['OfferTitle', 'ProductTitle', 'ProductName', 'Title', 'offer_title', 'product']; for (var i = 0; i < keys.length; i++) { var v = getHidden(keys[i]).trim(); if (v) return v.slice(0, 128); } return ''; } function expandOrderInfoIfNeeded() { if (document.querySelector('.gcpay-widget-order-position-title')) { return Promise.resolve(); } var btn = document.querySelector('.gcpay-widget-btn--info'); if (!btn) return Promise.resolve(); btn.click(); return new Promise(function (resolve) { setTimeout(resolve, 450); }); } function getPrimaryPositionTitle() { var el = document.querySelector('.gcpay-widget-order-position-title, [class*="order-position-title"]'); if (!el) return ''; return (el.textContent || el.innerText || '').replace(/\s+/g, ' ').trim(); } function pushReceiptItem(items, label, price, qty) { qty = Math.max(1, parseInt(qty, 10) || 1); var unit = money(price); if (!(unit > 0)) return; var item = { label: String(label || paymentDescription).slice(0, 128), price: unit, quantity: qty, amount: money(unit * qty), method: 4, object: 4, }; if (defaultVat != null) { item.tax = defaultVat; item.vat = defaultVat; } items.push(item); } function parseGcpayOrderPositionsTable() { var items = []; var seen = {}; document.querySelectorAll('.gcpay-widget-order-positions-table tr').forEach(function (tr) { var titleEl = tr.querySelector('.gcpay-widget-order-position-title'); if (!titleEl) return; var label = (titleEl.textContent || titleEl.innerText || '').replace(/\s+/g, ' ').trim(); if (!label) return; var qty = 1; var countTd = tr.querySelector('.position-count, td[data-mobile-count]'); if (countTd) { var qSrc = countTd.getAttribute('data-mobile-count') || countTd.textContent || ''; var qm = qSrc.match(/(\d+)/); if (qm) qty = parseInt(qm[1], 10) || 1; } var tds = tr.querySelectorAll('td'); var priceTd = tds.length ? tds[tds.length - 1] : null; var unitPrice = money(String(priceTd ? priceTd.textContent : '').replace(',', '.').replace(/[^\d.]/g, '')); if (!(unitPrice > 0)) return; var key = label + '|' + unitPrice + '|' + qty; if (seen[key]) return; seen[key] = true; pushReceiptItem(items, label, unitPrice, qty); }); return items; } function getEmailFromHiddenField() { return getEmail(); } function validateDealId(id) { if (!id || String(id).trim() === '' || !/^\d+$/.test(String(id))) { alert('Ошибка создания платежа. Пожалуйста, перезагрузите страницу.'); return false; } return true; } /** Чек как в нативном модуле ГК: email, phone, taxationSystem, amounts, Items */ function buildReceiptItems() { var fromDom = parseGcpayOrderPositionsTable(); if (fromDom.length) return reconcileItemsTotal(fromDom, amountNumber); var label = getPrimaryPositionTitle() || getTitleFromParamsData() || paymentDescription; var items = []; pushReceiptItem(items, label, amountNumber, 1); return reconcileItemsTotal(items, amountNumber); } function buildGcCustomerReceipt(items) { var total = itemsTotal(items) || money(amountNumber); var gcItems = (items || []).map(function (it) { var row = { quantity: it.quantity || 1, price: money(it.price), amount: money(it.amount), label: it.label, }; if (it.tax != null && it.tax !== '') row.tax = it.tax; if (it.object != null) row.object = it.object; if (it.method != null) row.method = it.method; if (it.vat != null && it.vat !== '') row.vat = it.vat; return row; }); var receipt = {}; if (email) receipt.email = email; if (phone) receipt.phone = phone; receipt.taxationSystem = taxationSystem; receipt.amounts = { electronic: total }; receipt.Items = gcItems; return receipt; } /** * Модуль ГК: invoiceId = dealId + "TO" + window.accountId (ID аккаунта школы в GetCourse). * window.accountId ≠ accountUserId и ≠ accountId в charge (там email или -1). */ function resolveOrderSuffix() { if (typeof window.accountId !== 'undefined' && window.accountId != null && window.accountId !== '') { return 'TO' + String(window.accountId); } return ''; } function resolveInvoiceId() { return String(dealId) + resolveOrderSuffix(); } function getGcOrderNumberLabel() { var span = document.querySelector('.gcpay-widget-head h1 span'); if (!span) return ''; var n = String(span.textContent || '').replace(/\D/g, ''); return /^\d+$/.test(n) ? '#' + n : ''; } /** Модуль ГК: accountId = email; без email — -1 (гость), как встроенная оплата CP в GetCourse */ function resolveAccountId() { if (email) return email; return '-1'; } function loadCloudPayments(cb) { if (window.cp && window.cp.CloudPayments) return cb(); var scriptUrl = 'https://widget.cloudpayments.ru/bundles/cloudpayments.js'; if (window.jQuery && jQuery.getScript) { jQuery.getScript(scriptUrl, cb); return; } var s = document.createElement('script'); s.src = scriptUrl; s.onload = cb; s.onerror = function () { alert('Не удалось загрузить CloudPayments'); }; document.head.appendChild(s); } function sendPrepayment(opt) { var url = '/pl/sales/prepayment/cloud-payment-prepayment?dealId=' + dealId; var paramsJson = JSON.stringify(opt); return new Promise(function (resolve, reject) { if (window.jQuery && jQuery.ajax) { jQuery .ajax({ url: url, data: { params: paramsJson }, type: 'POST' }) .done(function () { resolve(); }) .fail(function (xhr) { var t = xhr && xhr.responseText ? String(xhr.responseText).slice(0, 160) : ''; reject(new Error('prepayment HTTP ' + (xhr && xhr.status ? xhr.status : '') + (t ? ': ' + t : ''))); }); return; } var fd = new FormData(); fd.append('params', paramsJson); fetch(url, { method: 'POST', body: fd, credentials: 'same-origin' }) .then(function (r) { if (r.ok) { resolve(); return; } return r.text().then(function (t) { reject(new Error('prepayment HTTP ' + r.status + (t ? ': ' + t.slice(0, 160) : ''))); }); }) .catch(reject); }); } function buildGcDataPayload(customerReceipt) { return { publicId: publicId, cloudPayments: { customerReceipt: customerReceipt }, saveCard: saveCard, }; } function buildPrepayOpt() { refreshContactFields(); var items = buildReceiptItems(); var customerReceipt = buildGcCustomerReceipt(items); var extId = resolveInvoiceId(); var accountId = resolveAccountId(); return { extId: extId, accountId: accountId, items: items, customerReceipt: customerReceipt, prepay: { publicId: publicId, description: paymentDescription, amount: amountNumber, currency: currency, invoiceId: extId, data: buildGcDataPayload(customerReceipt), accountId: accountId, email: email || undefined, }, }; } function finishPaymentUi(buttonEl, result) { setButtonLoading(buttonEl, false); if (result && result.type === 'cancel') return; var closeBtn = document.querySelector('.gcpay-widget-close-btn'); if (closeBtn) closeBtn.click(); } function handlePayError(buttonEl, error) { setButtonLoading(buttonEl, false); console.error('[elara-cp]', error); } function buildCpIntentOptions(ctx, methodSequence, restricted) { var cr = ctx.customerReceipt; return { publicTerminalId: publicId, description: paymentDescription, culture: 'ru-RU', paymentSchema: 'Single', amount: amountNumber, currency: currency, externalId: ctx.extId, receiptEmail: email, receipt: { items: ctx.items, taxationSystem: taxationSystem, email: email || undefined, phone: phone || undefined, amounts: cr.amounts, }, userInfo: { accountId: String(ctx.accountId), email: email || undefined, phone: phone || undefined, }, extra: buildGcDataPayload(cr), paymentMethodSequence: methodSequence, restrictedPaymentMethods: restricted, paymentMethodsNotfoldedCount: methodSequence.length, }; } function runCpPayment(buttonEl, methodSequence, restricted, logTag) { if (!validateDealId(dealId)) return; setButtonLoading(buttonEl, true); expandOrderInfoIfNeeded().then(function () { refreshContactFields(); loadCloudPayments(function () { var ctx = buildPrepayOpt(); console.log('[elara-cp] prepay payload (как модуль ГК)', ctx.prepay); console.log('[elara-cp]', logTag || 'pay', '→', { dealId: dealId, invoiceId: ctx.extId, publicId: publicId, accountId: ctx.accountId, methods: methodSequence, }); sendPrepayment(ctx.prepay) .then(function () { return new cp.CloudPayments().start( buildCpIntentOptions(ctx, methodSequence, restricted) ); }) .then(function (result) { finishPaymentUi(buttonEl, result); }) .catch(function (error) { handlePayError(buttonEl, error); }); }); }); } function payByCard(buttonEl) { runCpPayment(buttonEl, cardPaymentSequence, cardPaymentRestricted, 'card'); } function payByInstallment(buttonEl) { if (!canShowInstallment()) { return; } runCpPayment( buttonEl, installmentPaymentSequence, installmentPaymentRestricted, 'installment' ); } function RFHandler(buttonEl) { payByCard(buttonEl); } function InstallmentsHandler(buttonEl) { payByInstallment(buttonEl); } function bindClicks() { if (window.jQuery) { jQuery(document).off('click.elaraCp', '#pay-widget-cloudRF-button'); jQuery(document).off('click.elaraCp', '#pay-widget-cloudINST-button'); jQuery(document).on('click.elaraCp', '#pay-widget-cloudRF-button', function (e) { e.preventDefault(); RFHandler(this); }); jQuery(document).on('click.elaraCp', '#pay-widget-cloudINST-button', function (e) { e.preventDefault(); InstallmentsHandler(this); }); return; } document.addEventListener('click', function (e) { var rf = e.target.closest('#pay-widget-cloudRF-button'); if (rf) { e.preventDefault(); e.stopPropagation(); RFHandler(rf); return; } var inst = e.target.closest('#pay-widget-cloudINST-button'); if (inst) { e.preventDefault(); e.stopPropagation(); InstallmentsHandler(inst); } }); } bindClicks(); function onPaymentOverlayAppeared(paymentMethodsEl) { dealId = getDealId(); currency = 'RUB'; email = getEmail(); phone = getPhone(); var descEl = document.querySelector('.gcpay-widget-head'); var baseDesc = descEl ? descEl.innerText.replace(/\s+/g, ' ').trim() : 'Оплата заказа'; var orderLbl = getGcOrderNumberLabel(); description = orderLbl && baseDesc.indexOf(orderLbl) < 0 ? baseDesc + ' ' + orderLbl : baseDesc; var paymentSumStr = getPaymentSumStr(); var amountStr = paymentSumStr ? String(paymentSumStr).replace(',', '.').replace(/\s+/g, '').match(/[\d.]+/) : '0'; amountNumber = amountStr ? Number(amountStr[0]) : 0; mountCustomPaymentButtons(paymentMethodsEl); console.log('[elara-cp] кнопки CP, dealId=', dealId, 'сумма=', amountNumber, 'рассрочка=', canShowInstallment()); } function checkForPaymentMethods() { var appEl = document.getElementById('app'); if (appEl) { var inApp = appEl.querySelector('.gcpay-widget-payment-methods'); if (inApp) return inApp; } return document.querySelector('.gcpay-widget-payment-methods'); } var existing = checkForPaymentMethods(); var isVisible = !!existing; if (existing) onPaymentOverlayAppeared(existing); var observer = new MutationObserver(function () { var el = checkForPaymentMethods(); if (el && !isVisible) { isVisible = true; onPaymentOverlayAppeared(el); } else if (!el && isVisible) { isVisible = false; } }); observer.observe(document.body, { childList: true, subtree: true }); })();