PageSourceSearch

https://goloskaspia.ru/js/payment.js?v=1.2

js goloskaspia.ru collected 2026-10-08 13:57:17 UTC 8,436 bytes, 274 lines download raw bytes

1// Payment System for Voice of Caspian
2// Т-Банк (Tinkoff) Payment Integration
3
4// Payment configuration
5const PAYMENT_CONFIG = {
6  // Для production замените на реальные данные
7  merchantId: "your_merchant_id",
8  terminalKey: "your_terminal_key",
9  apiUrl: "https://securepay.tinkoff.ru/v2/",
10  successUrl: window.location.origin + "/payment-success.html",
11  failUrl: window.location.origin + "/payment-fail.html",
12};
13
14// Organization details
15const ORGANIZATION = {
16  name: 'ООО "МУЛЬТИФУНКЦИОНАЛЬНЫЙ МОНИТОРИНГОВЫЙ ЦЕНТР"',
17  inn: "9704251448",
18  kpp: "770401001",
19  account: "40702810710001714283",
20  bank: "АО «ТБанк»",
21  bik: "044525974",
22  correspondentAccount: "30101810145250000974",
23  address:
24    "119121, Россия, г.Москва, вн.тер.г. муниципальный округ Хамовники, б-р Смоленский, д. 7, помещ. 3/1",
25};
26
27// Modal management
28function openPaymentModal() {
29  const modal = document.getElementById("paymentModal");
30  modal.classList.add("show");
31  document.body.style.overflow = "hidden";
32
33  // Initialize amount buttons
34  initializeAmountButtons();
35}
36
37function closePaymentModal() {
38  const modal = document.getElementById("paymentModal");
39  modal.classList.remove("show");
40  document.body.style.overflow = "auto";
41}
42
43// Tab switching
44function initializePaymentTabs() {
45  const tabs = document.querySelectorAll(".payment-tab");
46  const contents = document.querySelectorAll(".payment-tab-content");
47
48  tabs.forEach((tab) => {
49    tab.addEventListener("click", () => {
50      const targetTab = tab.getAttribute("data-tab");
51
52      // Remove active class from all tabs and contents
53      tabs.forEach((t) => t.classList.remove("active"));
54      contents.forEach((c) => c.classList.remove("active"));
55
56      // Add active class to clicked tab and corresponding content
57      tab.classList.add("active");
58      document.getElementById(targetTab + "Tab").classList.add("active");
59    });
60  });
61}
62
63// Amount buttons functionality
64function initializeAmountButtons() {
65  const amountButtons = document.querySelectorAll(".amount-btn");
66  const paymentAmountInput = document.getElementById("paymentAmount");
67
68  amountButtons.forEach((button) => {
69    button.addEventListener("click", () => {
70      // Remove active class from all buttons
71      amountButtons.forEach((btn) => btn.classList.remove("active"));
72
73      // Add active class to clicked button
74      button.classList.add("active");
75
76      // Set amount in payment form
77      const amount = button.getAttribute("data-amount");
78      if (paymentAmountInput) {
79        paymentAmountInput.value = amount;
80      }
81    });
82  });
83}
84
85// Copy to clipboard functionality
86function copyToClipboard(text) {
87  navigator.clipboard
88    .writeText(text)
89    .then(() => {
90      showNotification("Скопировано в буфер обмена!", "success");
91    })
92    .catch((err) => {
93      console.error("Failed to copy: ", err);
94      // Fallback for older browsers
95      const textArea = document.createElement("textarea");
96      textArea.value = text;
97      document.body.appendChild(textArea);
98      textArea.select();
99      document.execCommand("copy");
100      document.body.removeChild(textArea);
101      showNotification("Скопировано в буфер обмена!", "success");
102    });
103}
104
105// Notification system
106function showNotification(message, type = "info") {
107  const notification = document.createElement("div");
108  notification.className = `notification notification-${type}`;
109  notification.innerHTML = `
110    <i class="fas fa-${
111      type === "success" ? "check-circle" : "info-circle"
112    }"></i>
113    <span>${message}</span>
114  `;
115
116  notification.style.cssText = `
117    position: fixed;
118    top: 20px;
119    right: 20px;
120    background: ${type === "success" ? "#10b981" : "#3b82f6"};
121    color: white;
122    padding: 15px 20px;
123    border-radius: 8px;
124    display: flex;
125    align-items: center;
126    gap: 10px;
127    z-index: 10000;
128    animation: slideInRight 0.3s ease-out;
129    box-shadow: 0 10px 25px rgba(0,0,0,0.2);
130  `;
131
132  document.body.appendChild(notification);
133
134  setTimeout(() => {
135    notification.style.animation = "slideOutRight 0.3s ease-out";
136    setTimeout(() => {
137      document.body.removeChild(notification);
138    }, 300);
139  }, 3000);
140}
141
142// Удалено: Payment form handler для карт больше не нужен
143
144// Удалено: processPayment больше не нужна для новой структуры без карт
145
146// Удалено: Mock функции для карт больше не нужны
147
148// Generate unique order ID
149function generateOrderId() {
150  const timestamp = Date.now();
151  const random = Math.floor(Math.random() * 1000);
152  return `VOC_${timestamp}_${random}`;
153}
154
155// QR Code generation
156function generatePaymentQR(amount) {
157  const qrContainer = document.getElementById("paymentQR");
158  const customAmountInput = document.getElementById("customAmountInput");
159
160  if (amount === "custom") {
161    customAmountInput.style.display = "block";
162    qrContainer.innerHTML = `
163      <div class="qr-placeholder">
164        <i class="fas fa-qrcode"></i>
165        <p>Введите сумму и нажмите "Создать QR"</p>
166      </div>
167    `;
168    return;
169  } else {
170    customAmountInput.style.display = "none";
171  }
172
173  if (amount) {
174    // Generate QR code with payment data
175    const qrData = generateQRPaymentData(amount);
176    qrContainer.innerHTML = `
177      <img src="https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=${encodeURIComponent(
178        qrData
179      )}" 
180           alt="QR код для оплаты ${amount} ₽" 
181           style="width: 180px; height: 180px;" />
182    `;
183  }
184}
185
186function generateCustomQR() {
187  const customAmount = document.getElementById("customAmount").value;
188  if (customAmount && customAmount >= 100) {
189    generatePaymentQR(customAmount);
190  } else {
191    showNotification("Минимальная сумма: 100 ₽", "error");
192  }
193}
194
195// Generate QR payment data in SBP format
196function generateQRPaymentData(amount) {
197  // Simplified QR format for demo
198  // In production use proper SBP QR format
199  return `ST00012|Name=${ORGANIZATION.name}|PersonalAcc=${
200    ORGANIZATION.account
201  }|BankName=${ORGANIZATION.bank}|BIC=${ORGANIZATION.bik}|CorrespAcc=${
202    ORGANIZATION.correspondentAccount
203  }|PayeeINN=${
204    ORGANIZATION.inn
205  }|Purpose=Организационный взнос за участие в конкурсе|Sum=${amount * 100}`;
206}
207
208// Initialize all payment functionality
209document.addEventListener("DOMContentLoaded", function () {
210  initializePaymentTabs();
211
212  // Add CSS animations
213  const style = document.createElement("style");
214  style.textContent = `
215    @keyframes slideInRight {
216      from { transform: translateX(100%); opacity: 0; }
217      to { transform: translateX(0); opacity: 1; }
218    }
219    
220    @keyframes slideOutRight {
221      from { transform: translateX(0); opacity: 1; }
222      to { transform: translateX(100%); opacity: 0; }
223    }
224    
225    .payment-confirmation-content {
226      background: white;
227      padding: 40px;
228      border-radius: 16px;
229      text-align: center;
230      max-width: 500px;
231      margin: 20px;
232    }
233    
234    .payment-confirmation-content h3 {
235      margin-bottom: 20px;
236      color: #0f172a;
237    }
238    
239    .payment-confirmation-content p {
240      margin-bottom: 15px;
241      color: #475569;
242    }
243    
244    .confirmation-actions {
245      display: flex;
246      gap: 15px;
247      justify-content: center;
248      margin-top: 30px;
249    }
250    
251    .notification {
252      font-weight: 500;
253    }
254  `;
255  document.head.appendChild(style);
256});
257
258// Close modal when clicking outside
259document.addEventListener("click", function (e) {
260  const modal = document.getElementById("paymentModal");
261  if (e.target === modal) {
262    closePaymentModal();
263  }
264});
265
266// Close modal with Escape key
267document.addEventListener("keydown", function (e) {
268  if (e.key === "Escape") {
269    const modal = document.getElementById("paymentModal");
270    if (modal && modal.classList.contains("show")) {
271      closePaymentModal();
272    }
273  }
274});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.