Тестовая страница встраивания в CRM (postMessage auth + проверка в Supabase)

This commit is contained in:
crm-embed-test
2026-10-13 12:36:09 +00:00
parent d5f8b9cbb4
commit a92286d413
8 changed files with 281 additions and 0 deletions

107
public/index.html Normal file
View File

@@ -0,0 +1,107 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CRM embed test</title>
<style>
body { font: 15px/1.5 system-ui, sans-serif; margin: 16px; color: #222; }
h1 { font-size: 18px; margin: 0 0 12px; }
#status { padding: 8px 12px; border-radius: 6px; background: #fff4d6; }
#status.ok { background: #e3f6e3; } #status.err { background: #fde2e2; }
dl { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; }
dt { color: #666; } dd { margin: 0; word-break: break-all; }
button { margin-top: 12px; padding: 6px 14px; }
#log { margin-top: 16px; font-size: 13px; color: #555; padding-left: 18px; }
</style>
</head>
<body>
<h1>Тест встраивания в CRM Tvorymo</h1>
<div id="status">жду авторизацию от CRM</div>
<dl id="info" hidden>
<dt>Имя</dt><dd id="name"></dd>
<dt>Email</dt><dd id="email"></dd>
<dt>ID</dt><dd id="uid"></dd>
<dt>Origin отправителя</dt><dd id="origin"></dd>
<dt>expires_at</dt><dd id="expires"></dd>
<dt>Получено токенов</dt><dd id="count">0</dd>
</dl>
<button id="refresh" hidden>Обновить токен</button>
<ol id="log"></ol>
<script>
(() => {
// Сессия только в памяти, токен не выводится и не логируется.
let session = null; // { token, expiresAt }
let crmSource = null, crmOrigin = null, count = 0;
const $ = (id) => document.getElementById(id);
const inIframe = window.parent !== window;
function setStatus(text, cls) { const s = $("status"); s.textContent = text; s.className = cls || ""; }
function log(text) {
const li = document.createElement("li");
li.textContent = new Date().toLocaleTimeString() + " — " + text;
$("log").prepend(li);
}
function fmtTime(v) {
if (v == null) return "—";
const n = Number(v);
const d = new Date(Number.isFinite(n) ? (n < 1e12 ? n * 1000 : n) : v);
return isNaN(d) ? String(v) : d.toLocaleString() + " (" + d.toISOString() + ")";
}
async function onAuth(data, ev) {
crmSource = ev.source; crmOrigin = ev.origin;
$("origin").textContent = ev.origin;
const token = data.access_token;
if (typeof token !== "string" || !token) { setStatus("crm:auth без access_token", "err"); return; }
const changed = session && session.token !== token;
const prevExp = session && session.expiresAt;
session = { token, expiresAt: data.expires_at };
count++;
setStatus("проверяю токен в Supabase…");
try {
const r = await fetch("/api/verify", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ access_token: token }),
});
const res = await r.json();
if (!res.ok) { setStatus("Токен не принят: " + res.error, "err"); log("crm:auth от " + ev.origin + " — отклонён"); return; }
$("name").textContent = res.name || "имя не задано в Supabase";
$("email").textContent = res.email || "—";
$("uid").textContent = res.id;
$("expires").textContent = fmtTime(data.expires_at != null ? data.expires_at : res.exp);
$("count").textContent = String(count);
$("info").hidden = false; $("refresh").hidden = false;
setStatus(changed ? "Токен сменился, пользователь подтверждён Supabase" : "Пользователь подтверждён Supabase", "ok");
log("crm:auth от " + ev.origin + (changed
? " — новый токен, expires_at: " + fmtTime(prevExp) + " → " + fmtTime(data.expires_at)
: session && count > 1 ? " — тот же токен" : " — принят"));
} catch (e) {
setStatus("Ошибка проверки токена", "err");
}
}
window.addEventListener("message", (ev) => {
const data = ev.data;
if (!data || typeof data !== "object") return;
// Для теста принимаем от любого origin (решение владельца).
if (data.type === "crm:auth") onAuth(data, ev);
});
$("refresh").addEventListener("click", () => {
const target = crmSource || window.parent;
target.postMessage({ type: "crm:refresh" }, crmOrigin || "*");
setStatus("запросил новый токен (crm:refresh)…");
log("отправлен crm:refresh → " + (crmOrigin || "*"));
});
if (inIframe) {
window.parent.postMessage({ type: "crm:ready", version: 1 }, "*");
log("отправлен crm:ready");
} else {
log("страница открыта не в iframe");
}
})();
</script>
</body>
</html>