mirror of
https://github.com/wasrusgen/zashita-brandbook.git
synced 2026-06-03 15:44:47 +00:00
pay: ЮKassa widget (card + SBP, mockup-ready, prod hook marked)
This commit is contained in:
parent
1b7c818c4a
commit
95c3e2ec49
152
mockup.html
152
mockup.html
@ -185,6 +185,41 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
|
||||
|
||||
|
||||
|
||||
/* ── ЮKASSA ВИДЖЕТ ── */
|
||||
.yk-overlay{position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:99990;display:none;align-items:flex-end;justify-content:center}
|
||||
.yk-overlay.open{display:flex}
|
||||
@media(min-width:520px){.yk-overlay{align-items:center}}
|
||||
.yk-sheet{background:#fff;border-radius:20px 20px 0 0;width:100%;max-width:420px;padding:24px 20px 32px;position:relative;box-shadow:0 -8px 40px rgba(0,0,0,.18);animation:ykUp .25s ease}
|
||||
@media(min-width:520px){.yk-sheet{border-radius:20px}}
|
||||
@keyframes ykUp{from{transform:translateY(60px);opacity:0}to{transform:none;opacity:1}}
|
||||
.yk-close{position:absolute;top:14px;right:16px;background:none;border:none;font-size:20px;cursor:pointer;color:#9ca3af;line-height:1}
|
||||
.yk-header{display:flex;align-items:center;gap:10px;margin-bottom:20px}
|
||||
.yk-logo{font-size:13px;font-weight:800;color:#0057FF;letter-spacing:-.5px}
|
||||
.yk-logo span{color:#FF3D00}
|
||||
.yk-amount{margin-left:auto;font-size:18px;font-weight:800;color:#111}
|
||||
.yk-field{margin-bottom:14px}
|
||||
.yk-field label{display:block;font-size:12px;color:#6b7280;font-weight:600;margin-bottom:5px;font-family:inherit}
|
||||
.yk-field input{width:100%;border:1.5px solid #e5e7eb;border-radius:10px;padding:11px 14px;font-size:15px;font-family:inherit;outline:none;color:#111;background:#fff;box-sizing:border-box;transition:border-color .15s}
|
||||
.yk-field input:focus{border-color:#0057FF}
|
||||
.yk-field input.yk-error{border-color:#ef4444}
|
||||
.yk-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
|
||||
.yk-sbp{display:flex;align-items:center;justify-content:center;gap:8px;border:1.5px solid #e5e7eb;border-radius:10px;padding:11px 14px;cursor:pointer;font-size:14px;font-weight:600;color:#111;margin-bottom:14px;transition:border-color .15s;font-family:inherit;background:#fff;width:100%;box-sizing:border-box}
|
||||
.yk-sbp:hover{border-color:#0057FF;color:#0057FF}
|
||||
.yk-sbp-icon{width:24px;height:14px;background:linear-gradient(90deg,#1D63D8 33%,#fff 33% 66%,#ED1C24 66%);border-radius:3px;font-size:9px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:900;letter-spacing:-.5px}
|
||||
.yk-sep{display:flex;align-items:center;gap:8px;color:#9ca3af;font-size:12px;margin:12px 0}
|
||||
.yk-sep::before,.yk-sep::after{content:'';flex:1;height:1px;background:#e5e7eb}
|
||||
.yk-pay-btn{width:100%;background:#0057FF;color:#fff;border:none;border-radius:12px;padding:15px;font-size:16px;font-weight:800;cursor:pointer;font-family:inherit;margin-top:4px;transition:background .15s}
|
||||
.yk-pay-btn:hover{background:#0046CC}
|
||||
.yk-pay-btn:disabled{background:#9ca3af;cursor:default}
|
||||
.yk-footer{text-align:center;font-size:11px;color:#9ca3af;margin-top:12px}
|
||||
.yk-footer a{color:#9ca3af}
|
||||
.yk-spinner{display:none;width:20px;height:20px;border:3px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:ykSpin .7s linear infinite;margin:0 auto}
|
||||
@keyframes ykSpin{to{transform:rotate(360deg)}}
|
||||
.yk-success{display:none;text-align:center;padding:20px 0 8px}
|
||||
.yk-success .yk-check{font-size:48px;margin-bottom:12px}
|
||||
.yk-success .yk-sttl{font-size:18px;font-weight:800;color:#111;margin-bottom:6px}
|
||||
.yk-success .yk-ssub{font-size:13px;color:#6b7280}
|
||||
|
||||
/* ── ЭКРАН СТАТУСА ЗАКАЗА ── */
|
||||
.os-wrap{max-width:560px;margin:0 auto;padding:24px 20px 60px}
|
||||
.os-ok{text-align:center;margin:8px 0 20px}
|
||||
@ -578,7 +613,7 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
|
||||
|
||||
<div class="field"><label>Куда прислать результат</label><input placeholder="Telegram или телефон"></div>
|
||||
<div class="pdn">Нажимая «Оплатить», вы соглашаетесь с <a href="oferta.html" target="_blank">офертой</a> и <a href="privacy.html" target="_blank">обработкой ПДн</a>. Данные договора остаются на вашем устройстве.</div>
|
||||
<button class="btn btn-p" id="pay-price-btn" style="width:100%" onclick="showOrderStatus();go('order-status')">Оплатить 2 480 ₽</button>
|
||||
<button class="btn btn-p" id="pay-price-btn" style="width:100%" onclick="ykOpen()">Оплатить 2 480 ₽</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1369,6 +1404,72 @@ function selectPlan(n) {
|
||||
|
||||
|
||||
|
||||
/* ── ЮKASSA ВИДЖЕТ ── */
|
||||
function ykOpen() {
|
||||
const priceEl = document.getElementById('pay-price-btn');
|
||||
const price = priceEl ? priceEl.textContent.replace('Оплатить ', '') : '';
|
||||
const set = (id, v) => { const el = document.getElementById(id); if (el) el.textContent = v; };
|
||||
set('yk-amount', price);
|
||||
set('yk-btn-amount', price);
|
||||
document.getElementById('yk-overlay').classList.add('open');
|
||||
document.getElementById('yk-form').style.display = '';
|
||||
document.getElementById('yk-success').style.display = 'none';
|
||||
document.getElementById('yk-card').value = '';
|
||||
document.getElementById('yk-exp').value = '';
|
||||
document.getElementById('yk-cvv').value = '';
|
||||
}
|
||||
|
||||
function ykClose(e) {
|
||||
if (e && e.target !== document.getElementById('yk-overlay')) return;
|
||||
document.getElementById('yk-overlay').classList.remove('open');
|
||||
}
|
||||
|
||||
function ykFmtCard(el) {
|
||||
let v = el.value.replace(/\D/g,'').slice(0,16);
|
||||
el.value = v.match(/.{1,4}/g)?.join(' ') || v;
|
||||
}
|
||||
function ykFmtExp(el) {
|
||||
let v = el.value.replace(/\D/g,'').slice(0,4);
|
||||
if (v.length >= 3) v = v.slice(0,2) + ' / ' + v.slice(2);
|
||||
el.value = v;
|
||||
}
|
||||
|
||||
function ykPaySBP() {
|
||||
// В проде: редирект на deeplink СБП с payment_id
|
||||
ykFinish();
|
||||
}
|
||||
|
||||
function ykSubmit() {
|
||||
const card = document.getElementById('yk-card').value.replace(/\s/g,'');
|
||||
const exp = document.getElementById('yk-exp').value;
|
||||
const cvv = document.getElementById('yk-cvv').value;
|
||||
let ok = true;
|
||||
if (card.length < 16) { document.getElementById('yk-card').classList.add('yk-error'); ok = false; }
|
||||
else document.getElementById('yk-card').classList.remove('yk-error');
|
||||
if (exp.length < 7) { document.getElementById('yk-exp').classList.add('yk-error'); ok = false; }
|
||||
else document.getElementById('yk-exp').classList.remove('yk-error');
|
||||
if (cvv.length < 3) { document.getElementById('yk-cvv').classList.add('yk-error'); ok = false; }
|
||||
else document.getElementById('yk-cvv').classList.remove('yk-error');
|
||||
if (!ok) return;
|
||||
|
||||
const btn = document.getElementById('yk-pay-btn');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<div class="yk-spinner" style="display:inline-block"></div>';
|
||||
|
||||
// В проде: POST на /api/payment → получить payment_id → confirm
|
||||
setTimeout(ykFinish, 1600);
|
||||
}
|
||||
|
||||
function ykFinish() {
|
||||
document.getElementById('yk-form').style.display = 'none';
|
||||
document.getElementById('yk-success').style.display = 'block';
|
||||
setTimeout(() => {
|
||||
document.getElementById('yk-overlay').classList.remove('open');
|
||||
showOrderStatus();
|
||||
go('order-status');
|
||||
}, 1200);
|
||||
}
|
||||
|
||||
/* ── СТАТУС ЗАКАЗА ── */
|
||||
const OS_DEADLINES = {
|
||||
protocol: { 1:'до 12 часов', 2:'до 24 часов', 3:'до 48 часов', sub:'после получения файла договора' },
|
||||
@ -1574,4 +1675,53 @@ function tab(name){
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- ── ЮKASSA ВИДЖЕТ ── -->
|
||||
<div class="yk-overlay" id="yk-overlay" onclick="ykClose(event)">
|
||||
<div class="yk-sheet" id="yk-sheet">
|
||||
<button class="yk-close" onclick="ykClose()">✕</button>
|
||||
|
||||
<div id="yk-form">
|
||||
<div class="yk-header">
|
||||
<div class="yk-logo">ЮMoney<span>·</span>Kassa</div>
|
||||
<div class="yk-amount" id="yk-amount">2 480 ₽</div>
|
||||
</div>
|
||||
|
||||
<button class="yk-sbp" onclick="ykPaySBP()">
|
||||
<div class="yk-sbp-icon">СБП</div>
|
||||
Оплатить через СБП
|
||||
</button>
|
||||
|
||||
<div class="yk-sep">или картой</div>
|
||||
|
||||
<div class="yk-field">
|
||||
<label>Номер карты</label>
|
||||
<input id="yk-card" type="text" inputmode="numeric" placeholder="0000 0000 0000 0000" maxlength="19" oninput="ykFmtCard(this)" autocomplete="cc-number">
|
||||
</div>
|
||||
<div class="yk-row">
|
||||
<div class="yk-field">
|
||||
<label>Срок действия</label>
|
||||
<input id="yk-exp" type="text" inputmode="numeric" placeholder="ММ / ГГ" maxlength="7" oninput="ykFmtExp(this)" autocomplete="cc-exp">
|
||||
</div>
|
||||
<div class="yk-field">
|
||||
<label>CVV / CVC</label>
|
||||
<input id="yk-cvv" type="password" inputmode="numeric" placeholder="•••" maxlength="4" autocomplete="cc-csc">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="yk-pay-btn" id="yk-pay-btn" onclick="ykSubmit()">Оплатить <span id="yk-btn-amount">2 480 ₽</span></button>
|
||||
<div class="yk-footer">
|
||||
Платёж защищён · <a href="https://yookassa.ru" target="_blank">ЮKassa</a> ·
|
||||
<a href="oferta.html" target="_blank">Оферта</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="yk-success" id="yk-success">
|
||||
<div class="yk-check">✅</div>
|
||||
<div class="yk-sttl">Оплата прошла!</div>
|
||||
<div class="yk-ssub">Переходим к заказу…</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user