fix(support-chat): remove device verification prompt
This commit is contained in:
@@ -174,24 +174,6 @@ svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round
|
|||||||
.danger-button { border: 1px solid var(--danger); color: #fff; background: var(--danger); }
|
.danger-button { border: 1px solid var(--danger); color: #fff; background: var(--danger); }
|
||||||
.secondary-button:disabled, .primary-button:disabled, .danger-button:disabled { opacity: .5; cursor: not-allowed; }
|
.secondary-button:disabled, .primary-button:disabled, .danger-button:disabled { opacity: .5; cursor: not-allowed; }
|
||||||
|
|
||||||
.access-overlay { z-index: 60; background: rgba(15,23,42,.58); }
|
|
||||||
.access-dialog { width: min(100%, 420px); padding: 26px; }
|
|
||||||
.access-icon { width: 48px; height: 48px; margin-bottom: 16px; display: grid; place-items: center; border-radius: 15px; color: var(--theme); background: rgba(var(--theme-rgb), .1); box-shadow: inset 0 0 0 1px rgba(var(--theme-rgb), .1); }
|
|
||||||
.access-icon svg { width: 25px; height: 25px; stroke-width: 1.9; }
|
|
||||||
.access-dialog header { padding-right: 0; }
|
|
||||||
.access-methods { margin-top: 20px; padding: 4px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; border-radius: 13px; background: var(--muted); }
|
|
||||||
.access-method { height: 38px; border: 0; border-radius: 10px; color: var(--muted-foreground); background: transparent; cursor: pointer; font-size: 13px; font-weight: 600; }
|
|
||||||
.access-method.active { color: var(--foreground); background: var(--card); box-shadow: 0 3px 10px rgba(15,23,42,.08); }
|
|
||||||
.access-panel { margin-top: 18px; }
|
|
||||||
.access-panel label { margin: 12px 0 7px; display: block; color: var(--foreground); font-size: 12px; font-weight: 600; }
|
|
||||||
.access-panel input { width: 100%; height: 44px; padding: 0 13px; border: 1px solid var(--border); border-radius: 11px; color: var(--foreground); background: var(--card); outline: 0; }
|
|
||||||
.access-panel input:focus { border-color: rgba(var(--theme-rgb), .56); box-shadow: 0 0 0 3px rgba(var(--theme-rgb), .12); }
|
|
||||||
.access-code-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
|
|
||||||
.access-code-row .secondary-button { height: 44px; white-space: nowrap; }
|
|
||||||
.access-help { margin: 9px 0 0; color: var(--muted-foreground); font-size: 11px; line-height: 18px; }
|
|
||||||
.access-error { margin: 14px 0 0; padding: 10px 12px; border: 1px solid rgba(220,38,38,.18); border-radius: 10px; color: #b42318; background: rgba(254,226,226,.72); font-size: 12px; line-height: 18px; }
|
|
||||||
.access-actions { justify-content: stretch; }
|
|
||||||
.access-actions button { flex: 1; }
|
|
||||||
@keyframes fade-in { from { opacity: 0; } }
|
@keyframes fade-in { from { opacity: 0; } }
|
||||||
@keyframes dialog-in { from { transform: scale(.97); opacity: .4; } }
|
@keyframes dialog-in { from { transform: scale(.97); opacity: .4; } }
|
||||||
|
|
||||||
|
|||||||
@@ -41,20 +41,6 @@
|
|||||||
closeDialogX: byId("close-dialog-x"),
|
closeDialogX: byId("close-dialog-x"),
|
||||||
continueButton: byId("continue-button"),
|
continueButton: byId("continue-button"),
|
||||||
confirmClose: byId("confirm-close-button"),
|
confirmClose: byId("confirm-close-button"),
|
||||||
accessOverlay: byId("access-overlay"),
|
|
||||||
accessTarget: byId("access-target"),
|
|
||||||
accessPasswordTab: byId("access-password-tab"),
|
|
||||||
accessSMSTab: byId("access-sms-tab"),
|
|
||||||
accessPasswordPanel: byId("access-password-panel"),
|
|
||||||
accessSMSPanel: byId("access-sms-panel"),
|
|
||||||
accessPassword: byId("access-password"),
|
|
||||||
accessPhone: byId("access-phone"),
|
|
||||||
accessCode: byId("access-code"),
|
|
||||||
accessSendCode: byId("access-send-code"),
|
|
||||||
accessSMSHelp: byId("access-sms-help"),
|
|
||||||
accessError: byId("access-error"),
|
|
||||||
accessCancel: byId("access-cancel"),
|
|
||||||
accessSubmit: byId("access-submit"),
|
|
||||||
toasts: byId("toast-region"),
|
toasts: byId("toast-region"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,12 +69,10 @@
|
|||||||
queueTickTimer: null,
|
queueTickTimer: null,
|
||||||
queueSyncedAt: 0,
|
queueSyncedAt: 0,
|
||||||
initialScrollSettling: false,
|
initialScrollSettling: false,
|
||||||
accessBusy: false,
|
|
||||||
accessMethod: "password",
|
|
||||||
chatBinding: accessTarget ? loadChatBinding(accessTarget) : "",
|
chatBinding: accessTarget ? loadChatBinding(accessTarget) : "",
|
||||||
};
|
};
|
||||||
|
|
||||||
class CustomerAccessRequiredError extends Error {}
|
class CustomerSessionRefreshError extends Error {}
|
||||||
|
|
||||||
function getApiBase() {
|
function getApiBase() {
|
||||||
const explicit = (params.get("api_base_url") || "").trim();
|
const explicit = (params.get("api_base_url") || "").trim();
|
||||||
@@ -178,8 +162,8 @@
|
|||||||
try {
|
try {
|
||||||
window.sessionStorage.setItem(key, value);
|
window.sessionStorage.setItem(key, value);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// Private browsing may disable session storage; verification still works
|
// Private browsing may disable session storage; the chat entry can be
|
||||||
// for the current navigation and can simply be repeated after reload.
|
// established again on the next navigation.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,17 +211,17 @@
|
|||||||
}
|
}
|
||||||
if (!response.ok || payload?.ok === false || payload?.success === false) {
|
if (!response.ok || payload?.ok === false || payload?.success === false) {
|
||||||
const value = payload?.msg || payload?.message || payload?.code;
|
const value = payload?.msg || payload?.message || payload?.code;
|
||||||
if (accessTarget && isCustomerAccessError(value, response.status)) {
|
if (accessTarget && isCustomerSessionError(value, response.status)) {
|
||||||
clearChatBinding();
|
clearChatBinding();
|
||||||
showAccessDialog("客服身份验证已失效,请重新验证。");
|
window.location.reload();
|
||||||
throw new CustomerAccessRequiredError("请重新验证当前卡板或设备");
|
throw new CustomerSessionRefreshError("正在重新连接客服");
|
||||||
}
|
}
|
||||||
throw new Error(chineseError(value));
|
throw new Error(chineseError(value));
|
||||||
}
|
}
|
||||||
return Object.prototype.hasOwnProperty.call(payload || {}, "data") ? payload.data : payload;
|
return Object.prototype.hasOwnProperty.call(payload || {}, "data") ? payload.data : payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCustomerAccessError(value, status) {
|
function isCustomerSessionError(value, status) {
|
||||||
const text = String(value || "");
|
const text = String(value || "");
|
||||||
return status === 401 || /unauthorized|身份验证|二次验证|重新验证|验证已失效/i.test(text);
|
return status === 401 || /unauthorized|身份验证|二次验证|重新验证|验证已失效/i.test(text);
|
||||||
}
|
}
|
||||||
@@ -272,7 +256,7 @@
|
|||||||
try {
|
try {
|
||||||
payload = await response.json();
|
payload = await response.json();
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
throw new Error("验证服务暂时不可用,请稍后重试");
|
throw new Error("客服入口暂时不可用,请稍后重试");
|
||||||
}
|
}
|
||||||
if (!response.ok || payload?.ok === false || payload?.success === false) {
|
if (!response.ok || payload?.ok === false || payload?.success === false) {
|
||||||
throw new Error(chineseError(payload?.msg || payload?.message || payload?.code));
|
throw new Error(chineseError(payload?.msg || payload?.message || payload?.code));
|
||||||
@@ -280,98 +264,17 @@
|
|||||||
return Object.prototype.hasOwnProperty.call(payload || {}, "data") ? payload.data : payload;
|
return Object.prototype.hasOwnProperty.call(payload || {}, "data") ? payload.data : payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
function maskAccessNumber(value) {
|
async function establishCustomerChatSession() {
|
||||||
const text = String(value || "").trim();
|
if (!accessTarget) return false;
|
||||||
if (text.length <= 4) return text;
|
|
||||||
return `${text.slice(0, 2)}${"•".repeat(Math.min(6, Math.max(2, text.length - 6)))}${text.slice(-4)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAccessMethod(method) {
|
|
||||||
state.accessMethod = method === "sms" ? "sms" : "password";
|
|
||||||
const password = state.accessMethod === "password";
|
|
||||||
dom.accessPasswordTab.classList.toggle("active", password);
|
|
||||||
dom.accessPasswordTab.setAttribute("aria-selected", String(password));
|
|
||||||
dom.accessSMSTab.classList.toggle("active", !password);
|
|
||||||
dom.accessSMSTab.setAttribute("aria-selected", String(!password));
|
|
||||||
dom.accessPasswordPanel.hidden = !password;
|
|
||||||
dom.accessSMSPanel.hidden = password;
|
|
||||||
setAccessError("");
|
|
||||||
window.setTimeout(() => (password ? dom.accessPassword : dom.accessPhone).focus(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showAccessDialog(message = "") {
|
|
||||||
if (!accessTarget) return;
|
|
||||||
disconnectSocket(false);
|
|
||||||
dom.accessTarget.textContent = `${accessTarget.type === "device" ? "设备" : "卡板"} ${maskAccessNumber(accessTarget.number)} 涉及套餐、WiFi 密码或设备操作,请先完成二次验证。`;
|
|
||||||
dom.accessOverlay.hidden = false;
|
|
||||||
dom.app.setAttribute("aria-hidden", "true");
|
|
||||||
setAccessMethod(state.accessMethod);
|
|
||||||
setAccessError(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAccessError(message) {
|
|
||||||
dom.accessError.textContent = String(message || "");
|
|
||||||
dom.accessError.hidden = !String(message || "").trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAccessBusy(busy) {
|
|
||||||
state.accessBusy = busy;
|
|
||||||
dom.accessSubmit.disabled = busy;
|
|
||||||
dom.accessSendCode.disabled = busy;
|
|
||||||
dom.accessPassword.disabled = busy;
|
|
||||||
dom.accessPhone.disabled = busy;
|
|
||||||
dom.accessCode.disabled = busy;
|
|
||||||
dom.accessSubmit.textContent = busy ? "正在验证…" : "验证并进入客服";
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendAccessCode() {
|
|
||||||
if (!accessTarget || state.accessBusy) return;
|
|
||||||
setAccessBusy(true);
|
|
||||||
setAccessError("");
|
|
||||||
try {
|
try {
|
||||||
const result = await h5AccessRequest("/access/send-code", { method: "POST", body: "{}", headers: { "Content-Type": "application/json" } });
|
|
||||||
dom.accessSMSHelp.textContent = `验证码已发送到 ${result?.masked_phone || "已绑定手机号"},请输入完整手机号和验证码。`;
|
|
||||||
toast("验证码已发送");
|
|
||||||
dom.accessCode.focus();
|
|
||||||
} catch (error) {
|
|
||||||
setAccessError(error instanceof Error ? error.message : "验证码发送失败");
|
|
||||||
} finally {
|
|
||||||
setAccessBusy(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function submitCustomerAccess() {
|
|
||||||
if (!accessTarget || state.accessBusy) return;
|
|
||||||
const proof = state.accessMethod === "sms"
|
|
||||||
? { phone: dom.accessPhone.value.trim(), code: dom.accessCode.value.trim() }
|
|
||||||
: { password: dom.accessPassword.value };
|
|
||||||
if (state.accessMethod === "sms" && (!/^1\d{10}$/.test(proof.phone) || !proof.code)) {
|
|
||||||
setAccessError("请输入完整的已绑定手机号和短信验证码。");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (state.accessMethod === "password" && !String(proof.password || "").trim()) {
|
|
||||||
setAccessError("请输入卡板或设备密码。");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAccessBusy(true);
|
|
||||||
setAccessError("");
|
|
||||||
try {
|
|
||||||
const authorized = await h5AccessRequest("/access/authorize", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify(proof),
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
});
|
|
||||||
const accessToken = String(authorized?.access_token || "").trim();
|
|
||||||
if (!accessToken) throw new Error("验证结果无效,请重试");
|
|
||||||
const entry = await h5AccessRequest("/access/chat-entry", {
|
const entry = await h5AccessRequest("/access/chat-entry", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: "{}",
|
body: "{}",
|
||||||
headers: { "Content-Type": "application/json", "X-H5-Access-Token": accessToken },
|
headers: { "Content-Type": "application/json" },
|
||||||
});
|
});
|
||||||
const ticket = String(entry?.ticket || "").trim();
|
const ticket = String(entry?.ticket || "").trim();
|
||||||
const binding = String(entry?.session_binding || "").trim();
|
const binding = String(entry?.session_binding || "").trim();
|
||||||
if (!ticket || !binding) throw new Error("客服入口凭证无效,请重试");
|
if (!ticket || !binding) throw new Error("客服入口无效,请重试");
|
||||||
state.chatBinding = binding;
|
state.chatBinding = binding;
|
||||||
writeSessionStorage(chatBindingStorageKey(accessTarget), binding);
|
writeSessionStorage(chatBindingStorageKey(accessTarget), binding);
|
||||||
const destination = new URL(window.location.href);
|
const destination = new URL(window.location.href);
|
||||||
@@ -382,10 +285,11 @@
|
|||||||
destination.searchParams.set("access_ticket", ticket);
|
destination.searchParams.set("access_ticket", ticket);
|
||||||
destination.hash = "";
|
destination.hash = "";
|
||||||
window.location.replace(destination.toString());
|
window.location.replace(destination.toString());
|
||||||
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
clearChatBinding();
|
clearChatBinding();
|
||||||
setAccessError(error instanceof Error ? error.message : "身份验证失败,请重试");
|
fatal(error instanceof Error ? error.message : "客服入口建立失败,请重试");
|
||||||
setAccessBusy(false);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,9 +321,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (accessTarget && !state.chatBinding) {
|
if (accessTarget && !state.chatBinding) {
|
||||||
dom.loading.hidden = true;
|
state.initializing = true;
|
||||||
dom.app.setAttribute("aria-busy", "false");
|
updateConnectionStatus("connecting");
|
||||||
showAccessDialog();
|
await establishCustomerChatSession();
|
||||||
|
state.initializing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.initializing = true;
|
state.initializing = true;
|
||||||
@@ -437,7 +342,7 @@
|
|||||||
updateAvailability();
|
updateAvailability();
|
||||||
connectSocket();
|
connectSocket();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof CustomerAccessRequiredError) {
|
if (error instanceof CustomerSessionRefreshError) {
|
||||||
state.initialized = false;
|
state.initialized = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1382,18 +1287,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function bindEvents() {
|
function bindEvents() {
|
||||||
dom.accessPasswordTab.addEventListener("click", () => setAccessMethod("password"));
|
|
||||||
dom.accessSMSTab.addEventListener("click", () => setAccessMethod("sms"));
|
|
||||||
dom.accessSendCode.addEventListener("click", sendAccessCode);
|
|
||||||
dom.accessSubmit.addEventListener("click", submitCustomerAccess);
|
|
||||||
dom.accessCancel.addEventListener("click", () => {
|
|
||||||
clearCustomerAccessState();
|
|
||||||
closePage();
|
|
||||||
});
|
|
||||||
dom.accessOverlay.addEventListener("keydown", (event) => {
|
|
||||||
if (event.key !== "Enter" || event.shiftKey || state.accessBusy) return;
|
|
||||||
submitCustomerAccess();
|
|
||||||
});
|
|
||||||
dom.retry.addEventListener("click", retry);
|
dom.retry.addEventListener("click", retry);
|
||||||
dom.close.addEventListener("click", openCloseDialog);
|
dom.close.addEventListener("click", openCloseDialog);
|
||||||
dom.loadMore.addEventListener("click", loadOlder);
|
dom.loadMore.addEventListener("click", loadOlder);
|
||||||
@@ -1443,7 +1336,6 @@
|
|||||||
});
|
});
|
||||||
document.addEventListener("keydown", (event) => {
|
document.addEventListener("keydown", (event) => {
|
||||||
if (event.key !== "Escape") return;
|
if (event.key !== "Escape") return;
|
||||||
if (!dom.accessOverlay.hidden) return;
|
|
||||||
if (!dom.quickOverlay.hidden) closeQuickDialog();
|
if (!dom.quickOverlay.hidden) closeQuickDialog();
|
||||||
else if (!dom.closeOverlay.hidden) closeCloseDialog();
|
else if (!dom.closeOverlay.hidden) closeCloseDialog();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -111,42 +111,6 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="access-overlay" class="dialog-overlay access-overlay" hidden>
|
|
||||||
<section class="dialog-card access-dialog" role="dialog" aria-modal="true" aria-labelledby="access-title">
|
|
||||||
<div class="access-icon" aria-hidden="true">
|
|
||||||
<svg viewBox="0 0 24 24"><path d="M12 3 4.5 6v5.2c0 4.7 3.2 8.9 7.5 9.8 4.3-.9 7.5-5.1 7.5-9.8V6Z"/><path d="m9 12 2 2 4-4"/></svg>
|
|
||||||
</div>
|
|
||||||
<header>
|
|
||||||
<h2 id="access-title">验证当前设备</h2>
|
|
||||||
<p id="access-target">为保护套餐、WiFi 密码和设备操作,请先完成身份验证。</p>
|
|
||||||
</header>
|
|
||||||
<div class="access-methods" role="tablist" aria-label="验证方式">
|
|
||||||
<button id="access-password-tab" class="access-method active" type="button" role="tab" aria-selected="true">设备密码</button>
|
|
||||||
<button id="access-sms-tab" class="access-method" type="button" role="tab" aria-selected="false">短信验证</button>
|
|
||||||
</div>
|
|
||||||
<div id="access-password-panel" class="access-panel">
|
|
||||||
<label for="access-password">卡板/设备密码</label>
|
|
||||||
<input id="access-password" type="password" autocomplete="current-password" maxlength="64" placeholder="请输入密码" />
|
|
||||||
<p class="access-help">还没有设置密码?可切换到短信验证。</p>
|
|
||||||
</div>
|
|
||||||
<div id="access-sms-panel" class="access-panel" hidden>
|
|
||||||
<label for="access-phone">已绑定手机号</label>
|
|
||||||
<input id="access-phone" type="tel" inputmode="numeric" autocomplete="tel" maxlength="11" placeholder="请输入完整手机号" />
|
|
||||||
<label for="access-code">短信验证码</label>
|
|
||||||
<div class="access-code-row">
|
|
||||||
<input id="access-code" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="8" placeholder="请输入验证码" />
|
|
||||||
<button id="access-send-code" class="secondary-button" type="button">获取验证码</button>
|
|
||||||
</div>
|
|
||||||
<p id="access-sms-help" class="access-help">验证码只会发送到该卡板或设备已绑定的手机号。</p>
|
|
||||||
</div>
|
|
||||||
<p id="access-error" class="access-error" role="alert" hidden></p>
|
|
||||||
<footer class="dialog-actions access-actions">
|
|
||||||
<button id="access-cancel" class="secondary-button" type="button">返回</button>
|
|
||||||
<button id="access-submit" class="primary-button" type="button">验证并进入客服</button>
|
|
||||||
</footer>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="close-overlay" class="dialog-overlay" hidden>
|
<div id="close-overlay" class="dialog-overlay" hidden>
|
||||||
<section class="dialog-card close-dialog" role="dialog" aria-modal="true" aria-labelledby="close-title">
|
<section class="dialog-card close-dialog" role="dialog" aria-modal="true" aria-labelledby="close-title">
|
||||||
<button id="close-dialog-x" class="dialog-close icon-button" type="button" aria-label="关闭">
|
<button id="close-dialog-x" class="dialog-close icon-button" type="button" aria-label="关闭">
|
||||||
|
|||||||
@@ -160,20 +160,20 @@ func TestSupportChatStagesUploadsUntilExplicitSend(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSupportChatRequiresCurrentVerifiedNumberSession(t *testing.T) {
|
func TestSupportChatEstablishesNumberSessionWithoutVerificationDialog(t *testing.T) {
|
||||||
index, err := assets.ReadFile("assets/index.html")
|
index, err := assets.ReadFile("assets/index.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("read support chat index: %v", err)
|
t.Fatalf("read support chat index: %v", err)
|
||||||
}
|
}
|
||||||
for _, marker := range []string{
|
for _, forbidden := range []string{
|
||||||
`id="access-overlay"`,
|
`id="access-overlay"`,
|
||||||
`id="access-password-tab"`,
|
`id="access-password-tab"`,
|
||||||
`id="access-sms-tab"`,
|
`id="access-sms-tab"`,
|
||||||
`id="access-send-code"`,
|
`id="access-send-code"`,
|
||||||
`id="access-submit"`,
|
`id="access-submit"`,
|
||||||
} {
|
} {
|
||||||
if !strings.Contains(string(index), marker) {
|
if strings.Contains(string(index), forbidden) {
|
||||||
t.Fatalf("support chat verification dialog does not contain %q", marker)
|
t.Fatalf("support chat must not contain verification dialog marker %q", forbidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,10 +184,7 @@ func TestSupportChatRequiresCurrentVerifiedNumberSession(t *testing.T) {
|
|||||||
source := string(script)
|
source := string(script)
|
||||||
for _, marker := range []string{
|
for _, marker := range []string{
|
||||||
`new URLSearchParams(window.location.hash.replace(/^#/, ""))`,
|
`new URLSearchParams(window.location.hash.replace(/^#/, ""))`,
|
||||||
`h5AccessRequest("/access/send-code"`,
|
|
||||||
`h5AccessRequest("/access/authorize"`,
|
|
||||||
`h5AccessRequest("/access/chat-entry"`,
|
`h5AccessRequest("/access/chat-entry"`,
|
||||||
`"X-H5-Access-Token": accessToken`,
|
|
||||||
`headers.set("X-H5-Chat-Session", "required")`,
|
`headers.set("X-H5-Chat-Session", "required")`,
|
||||||
`headers.set("X-H5-Chat-Binding", state.chatBinding)`,
|
`headers.set("X-H5-Chat-Binding", state.chatBinding)`,
|
||||||
`query.set("h5_chat_session", "required")`,
|
`query.set("h5_chat_session", "required")`,
|
||||||
@@ -201,6 +198,10 @@ func TestSupportChatRequiresCurrentVerifiedNumberSession(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, forbidden := range []string{
|
for _, forbidden := range []string{
|
||||||
|
`h5AccessRequest("/access/send-code"`,
|
||||||
|
`h5AccessRequest("/access/authorize"`,
|
||||||
|
`"X-H5-Access-Token": accessToken`,
|
||||||
|
`showAccessDialog(`,
|
||||||
`localStorage.setItem("h5_access_token"`,
|
`localStorage.setItem("h5_access_token"`,
|
||||||
`sessionStorage.setItem("h5_access_token"`,
|
`sessionStorage.setItem("h5_access_token"`,
|
||||||
} {
|
} {
|
||||||
|
|||||||
Reference in New Issue
Block a user