(function () { 'use strict'; console.log('itteration: 3'); var PREFIX = '[GSOC]'; var DEBUG = true; function log() { if (!DEBUG) return; try { console.log.apply(console, [PREFIX].concat([].slice.call(arguments))); } catch (e) {} } function warn() { try { console.warn.apply(console, [PREFIX].concat([].slice.call(arguments))); } catch (e) {} } function err() { try { console.error.apply(console, [PREFIX].concat([].slice.call(arguments))); } catch (e) {} } var CONFIG = { STORE_PATH: '/_ofert-admin', MARKER: '.gsoc-settings', KEY_SETTINGS: 'gsoc_settings_cache', SETTINGS_TTL: 5 * 60 * 1000, DEFAULT_STYLE: { bg: '#FFFFFF', text: '#333333', link: '#337AB7', fontSize: 14, radius: 4, borderColor: '#DDDDDD', borderWidth: 1 }, SNAPSHOT_TITLE: 'Вы дали следующие согласия', PAY_PATH: /\/sales\/shop\/dealPay\//, PAY_ROOTS: ['.allPayments', '.xdget-payform', '#pay-methods', 'form[action*="Init"]', '#payment-page', '.payment-page'], PAY_BUTTONS: '.gc-payment-method-button, button.pay-button, button[type=submit], a[href*="Init"], .pay-btn-sber-pay, .pay-btn-sbp-pay, .pay-btn-alpha-pay, .pay-btn-split, .pay-btn-fresh-credit', LOCK_CLASS: 'gsoc-pay-locked', HIDE_CLASS: 'gsoc-pay-hidden', ORDER_CARD_PATH: '/sales/control/userProduct/update/id/', ADD_FIELDS_URL: '/pl/user/user/get-user-additional-form-data?id=', ORDER_BLOCK_ATTR: 'data-gsoc-order-block', CONFIRM_PAGE: '/_ofert-confirm', FIELD: 'user_order_details', READY_TIMEOUT: 8000, SAVE_TIMEOUT: 15000, READ_TIMEOUT: 15000, STYLES_ID: 'gsoc-styles' }; function b64encode(str) { var bytes = new TextEncoder().encode(String(str == null ? '' : str)); var bin = ''; var chunk = 0x8000; for (var i = 0; i < bytes.length; i += chunk) { bin += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk)); } return btoa(bin); } function b64decode(b64) { var bin = atob(b64); var bytes = new Uint8Array(bin.length); for (var i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i); return new TextDecoder().decode(bytes); } function esc(str) { return String(str == null ? '' : str) .replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"').replace(/'/g, '''); } function currentUserId() { if (typeof window.accountUserId !== 'undefined' && window.accountUserId) return String(window.accountUserId); if (window.gcUser && window.gcUser.id) return String(window.gcUser.id); return null; } function isAdminViewer() { var ui = window.userInfo || {}; return !!(ui.isAdmin || ui.canCms); } function injectStyles() { if (document.getElementById(CONFIG.STYLES_ID)) return; var css = [ '.gsoc-pay{margin:0 0 24px}', '.gsoc-pay-body{border-radius:8px;padding:20px 22px}', '.gsoc-pay-title{font-weight:700;margin:0 0 14px;font-size:1.08em;line-height:1.4}', '.gsoc-pay-item{display:flex;align-items:flex-start;gap:10px;margin:0 0 12px;line-height:1.5;cursor:pointer}', '.gsoc-pay-item:last-of-type{margin-bottom:0}', '.gsoc-pay-item input{flex:0 0 auto;width:18px;height:18px;margin:3px 0 0;cursor:pointer}', '.gsoc-pay-body a{color:var(--gsoc-link, inherit);text-decoration:underline;text-underline-offset:2px}', '.gsoc-pay-status{margin-top:14px;font-size:13px;line-height:1.45;opacity:.85}', '.gsoc-pay-status.error{color:#c0392b;opacity:1}', '.gsoc-pay-hidden{display:none !important}', '.gsoc-frame{position:absolute;width:1px;height:1px;left:-9999px;top:0;border:0}', '.gsoc-order-plain .gsoc-pay-body{padding:0;background:transparent;border:0;border-radius:0;color:inherit;font-size:inherit}', '.gsoc-order-plain .gsoc-pay-title{font-weight:700;margin:0 0 8px}', '.gsoc-order-plain .gsoc-pay-item{display:block;cursor:default;margin:0 0 8px;line-height:1.45}', '.gsoc-order-when{margin-top:6px}', '.gsoc-order-empty{font-size:13px;color:#8b8b9e}' ].join(''); var el = document.createElement('style'); el.id = CONFIG.STYLES_ID; el.textContent = css; document.head.appendChild(el); } var frame = null; var frameReady = null; function ensureFrame() { if (frame && frame.parentNode && frameReady) return frameReady; frame = document.createElement('iframe'); frame.className = 'gsoc-frame'; frame.setAttribute('aria-hidden', 'true'); frame.setAttribute('tabindex', '-1'); frame.src = CONFIG.CONFIRM_PAGE; document.body.appendChild(frame); frameReady = new Promise(function (resolve, reject) { var done = false; var timer = setTimeout(function () { if (done) return; done = true; window.removeEventListener('message', onReady); reject(new Error('страница ' + CONFIG.CONFIRM_PAGE + ' не ответила')); }, CONFIG.READY_TIMEOUT); function onReady(e) { if (done) return; if (e.origin !== location.origin) return; if (e.source !== frame.contentWindow) return; var d = e.data || {}; if (d.type !== 'gsoc:ready' && d.type !== 'gsoc:pong') return; done = true; clearTimeout(timer); window.removeEventListener('message', onReady); log('страница подтверждений готова'); resolve(frame); } window.addEventListener('message', onReady); frame.addEventListener('load', function () { try { frame.contentWindow.postMessage({ type: 'gsoc:ping' }, location.origin); } catch (e) {} }); }); return frameReady; } function frameRequest(type, payload, answerType, timeout) { return ensureFrame().then(function (fr) { return new Promise(function (resolve, reject) { var timer = setTimeout(function () { window.removeEventListener('message', onReply); reject(new Error('таймаут ответа страницы подтверждений')); }, timeout || CONFIG.SAVE_TIMEOUT); function onReply(e) { if (e.origin !== location.origin) return; if (e.source !== fr.contentWindow) return; var d = e.data || {}; if (d.type !== answerType) return; clearTimeout(timer); window.removeEventListener('message', onReply); if (d.ok) resolve(d); else reject(new Error(d.error || 'ошибка страницы подтверждений')); } window.addEventListener('message', onReply); var msg = { type: type }; if (payload) msg.payload = payload; log('запрос к ' + CONFIG.CONFIRM_PAGE + ': ' + type); fr.contentWindow.postMessage(msg, location.origin); }); }); } function saveToConfirm(payload) { return frameRequest('gsoc:save', payload, 'gsoc:saved', CONFIG.SAVE_TIMEOUT).then(function (d) { return d.result || { ok: true }; }); } function readFromConfirm() { return frameRequest('gsoc:read', null, 'gsoc:value', CONFIG.READ_TIMEOUT).then(function (d) { return d.value || null; }); } function unescapeDeep(text) { var out = String(text || ''); for (var i = 0; i < 6; i++) { var next = out.replace(/\\\\/g, '\\').replace(/\\"/g, '"').replace(/\\'/g, "'"); if (next === out) break; out = next; } return out; } function parseRecordJson(text) { var marker = "'orders':"; var idx = text.indexOf(marker); if (idx === -1) return null; var start = text.lastIndexOf('{', idx); if (start === -1) return null; var depth = 0; var inStr = false; for (var i = start; i < text.length; i++) { var ch = text.charAt(i); if (inStr) { if (ch === '\\') { i++; continue; } if (ch === "'") inStr = false; continue; } if (ch === "'") { inStr = true; continue; } if (ch === '{') depth++; else if (ch === '}') { depth--; if (depth === 0) { try { return JSON.parse(text.slice(start, i + 1).replace(/'/g, '"')); } catch (e) { return null; } } } } return null; } function decodeStoredValue(rawValue) { var raw = String(rawValue || '').trim(); if (raw.indexOf('\\"') === 0 && raw.lastIndexOf('\\"') === raw.length - 2) raw = raw.slice(2, -2); return parseRecordJson(unescapeDeep(raw)); } function recordsForDeals(data, dealIds) { var orders = (data && data.orders) || {}; var found = []; dealIds.forEach(function (id) { if (orders[id]) found.push({ dealId: id, record: orders[id] }); }); return found; } function formatDate(iso) { if (!iso) return ''; var d = new Date(iso); if (isNaN(d.getTime())) return iso; var pad = function (n) { return (n < 10 ? '0' : '') + n; }; return pad(d.getDate()) + '.' + pad(d.getMonth() + 1) + '.' + d.getFullYear() + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()); } var pay = { ready: false, saving: false, saved: false, locked: false, dealId: null, offerIds: [], userId: null, settings: null, items: [], payRoot: null, blockEl: null }; function isPayPage() { if (CONFIG.PAY_PATH.test(location.pathname)) return true; var signals = 0; if (document.querySelector('input[name="deal_id"]')) signals++; if (document.querySelector('.gc-payment-method-button')) signals++; if (document.querySelector('.xdget-payform')) signals++; return signals >= 2; } function findPayRoot() { for (var i = 0; i < CONFIG.PAY_ROOTS.length; i++) { var el = document.querySelector(CONFIG.PAY_ROOTS[i]); if (el) return el; } return null; } function payContext() { var m = /\/id\/(\d+)/.exec(location.pathname); var input = document.querySelector('input[name="deal_id"]'); var dealId = m ? m[1] : (input ? String(input.value) : ''); var offers = []; var nodes = document.querySelectorAll('[data-offer-id]'); for (var i = 0; i < nodes.length; i++) { var v = String(nodes[i].getAttribute('data-offer-id') || '').trim(); if (v && offers.indexOf(v) === -1) offers.push(v); } if (!offers.length) { var lis = document.querySelectorAll('li[class*="offer-position-"]'); for (var j = 0; j < lis.length; j++) { var id = (String(lis[j].className).match(/offer-position-(\d+)/) || [])[1]; if (id && offers.indexOf(id) === -1) offers.push(id); } } return { dealId: dealId, offerIds: offers, userId: currentUserId() }; } function readSettingsFromDom() { var marker = document.querySelector(CONFIG.MARKER); var raw = marker ? marker.getAttribute('data-gsoc') : null; if (!raw) return null; try { return JSON.parse(b64decode(raw)); } catch (e) { return null; } } function cacheSettings(settings) { try { localStorage.setItem(CONFIG.KEY_SETTINGS, JSON.stringify({ at: Date.now(), settings: settings })); } catch (e) {} } function cachedSettings() { try { var parsed = JSON.parse(localStorage.getItem(CONFIG.KEY_SETTINGS) || 'null'); if (!parsed || !parsed.at || !parsed.settings) return null; if (Date.now() - parsed.at > CONFIG.SETTINGS_TTL) return null; return parsed.settings; } catch (e) { return null; } } function loadSettings() { var fromDom = readSettingsFromDom(); if (fromDom) { pay.settings = fromDom; cacheSettings(fromDom); return Promise.resolve(fromDom); } var cached = cachedSettings(); return fetch(CONFIG.STORE_PATH + '?gsoc=' + Date.now(), { credentials: 'include' }) .then(function (r) { return r.text(); }) .then(function (html) { var m = /data-gsoc="([A-Za-z0-9+/=]+)"/.exec(html || ''); if (!m) throw new Error('в ' + CONFIG.STORE_PATH + ' не найден блок настроек'); var settings = JSON.parse(b64decode(m[1])); pay.settings = settings; cacheSettings(settings); log('настройки прочитаны со страницы-хранилища'); return settings; })['catch'](function (error) { if (cached) { warn('нет доступа к настройкам, беру кэш (' + (error.message || error) + ')'); pay.settings = cached; return cached; } throw error; }); } function pickItems(settings, offerIds) { var offers = settings.offers || {}; var keys = Object.keys(offers); for (var i = 0; i < keys.length; i++) { var set = offers[keys[i]] || {}; if (offerIds.indexOf(String(set.id)) !== -1) { log('набор предложения ' + set.id + ' (' + (set.name || '') + ')'); return (set.items || []).filter(function (it) { return it.active !== false; }); } } log('набор по умолчанию'); var def = settings.default && settings.default.items ? settings.default.items : []; return def.filter(function (it) { return it.active !== false; }); } function itemMarkup(item) { var html = esc(item.prefix || ''); if (item.linkText) { html += (html ? ' ' : '') + '' + esc(item.linkText) + ''; } if (item.suffix) html += ' ' + esc(item.suffix); return html; } function payStyleCss() { var def = CONFIG.DEFAULT_STYLE; var st = (pay.settings && pay.settings.style) || {}; return 'background:' + (st.bg || def.bg) + ';color:' + (st.text || def.text) + ';--gsoc-link:' + (st.link || def.link) + ';border-radius:' + (st.radius == null ? def.radius : st.radius) + 'px' + ';border:' + (st.borderWidth == null ? def.borderWidth : st.borderWidth) + 'px solid ' + (st.borderColor || def.borderColor) + ';font-size:' + (st.fontSize || def.fontSize) + 'px'; } function payBlockHtml() { var items = pay.items.map(function (item) { return '