const API_BASE_URL = "https://jvapi.haiyihy.com"; const DEFAULT_AVATAR = "/assets/defaultAvatar-CdxWBK1k-1776148661448.png"; const PAYEE_KEY = "transfer.payee"; const icons = { back: "../host-center/icons/back.svg", search: "./icons/search.svg" }; let commonHeaders = { authorization: "Bearer undefined", "req-app-intel": "version=1.0.0;build=1;model=SM-G9550;sysVersion=9;channel=Google", "req-client": "Android", "req-imei": "8fa54d728ab449e04f9292329ed44bda", "req-lang": "id-ID", "req-sys-origin": "origin=ATYOU;originChild=ATYOU", "req-version": "V2", "req-zone": "Asia/Shanghai" }; const i18n = { en: { search_payee: "Search Payee", search_user: "Search user", search: "Search", cancel: "Cancel", searching: "Searching", tips: "Tips", confirm_transfer_to_user: "Confirm transfer to this user?", confirm: "Confirm", add: "Add", user_id_prefix: "ID:", user_not_found_or_search_failed: "User not found or search failed" }, ar: { search_payee: "بحث عن المستلم", search_user: "ابحث عن المستخدم", search: "بحث", cancel: "إلغاء", searching: "جاري البحث", tips: "نصائح", confirm_transfer_to_user: "تأكيد التحويل إلى هذا المستخدم؟", confirm: "تأكيد", add: "إضافة", user_id_prefix: "ID:", user_not_found_or_search_failed: "لم يتم العثور على المستخدم أو فشل البحث" }, tr: { search_payee: "Alıcı Ara", search_user: "Kullanıcı ara", search: "Ara", cancel: "İptal", searching: "Aranıyor", tips: "İpuçları", confirm_transfer_to_user: "Bu kullanıcıya transferi onaylıyor musunuz?", confirm: "Onayla", add: "Ekle", user_id_prefix: "ID:", user_not_found_or_search_failed: "Kullanıcı bulunamadı veya arama başarısız" }, bn: { search_payee: "প্রাপক সার্চ", search_user: "ব্যবহারকারী সার্চ", search: "সার্চ", cancel: "বাতিল", searching: "সার্চ হচ্ছে", tips: "টিপস", confirm_transfer_to_user: "এই ব্যবহারকারীকে ট্রান্সফার নিশ্চিত করবেন?", confirm: "নিশ্চিত", add: "যোগ", user_id_prefix: "ID:", user_not_found_or_search_failed: "ব্যবহারকারী পাওয়া যায়নি বা সার্চ ব্যর্থ" } }; const state = { lang: resolveLanguage(), query: "", results: [], loading: false, searched: false, selected: null }; const $ = (selector) => document.querySelector(selector); const $$ = (selector) => Array.from(document.querySelectorAll(selector)); const t = (key) => (i18n[state.lang] && i18n[state.lang][key]) || i18n.en[key] || key; function resolveLanguage() { const params = new URLSearchParams(window.location.search); const lang = params.get("lang") || navigator.language || "en"; if (lang.startsWith("ar")) return "ar"; if (lang.startsWith("tr")) return "tr"; if (lang.startsWith("bn")) return "bn"; return "en"; } function splitHeaderPairs(value) { const result = {}; if (!value) return result; value.split(";").forEach((item) => { const index = item.indexOf("="); if (index > -1) result[item.slice(0, index)] = item.slice(index + 1); }); return result; } function parseAccessOrigin(raw) { const data = JSON.parse(raw); const appIntel = splitHeaderPairs(data["Req-App-Intel"]); const sysOrigin = splitHeaderPairs(data["Req-Sys-Origin"]); return { reqLang: data["Req-Lang"], authorization: data.Authorization, buildVersion: appIntel.build, appVersion: appIntel.version, appChannel: appIntel.channel, reqImei: appIntel["Req-Imei"], sysOrigin: sysOrigin.origin, sysOriginChild: sysOrigin.child }; } function setHeadersFromApp(headers) { const next = {}; if (headers.authorization) next.authorization = headers.authorization; if (headers.reqLang) next["req-lang"] = headers.reqLang; if (headers.appVersion || headers.buildVersion || headers.appChannel) { const intel = []; if (headers.appVersion) intel.push(`version=${headers.appVersion}`); if (headers.buildVersion) intel.push(`build=${headers.buildVersion}`); if (headers.appChannel) intel.push(`channel=${headers.appChannel}`); next["req-app-intel"] = intel.join(";"); } if (headers.reqImei) next["req-imei"] = headers.reqImei; if (headers.sysOrigin) { const origin = [`origin=${headers.sysOrigin}`]; if (headers.sysOriginChild) origin.push(`child=${headers.sysOriginChild}`); next["req-sys-origin"] = origin.join(";"); } commonHeaders = { ...commonHeaders, ...next }; } function connectToApp() { return new Promise((resolve) => { window.renderData = resolve; window.getIosAccessOriginParam = resolve; if (!(window.app || window.webkit || window.FlutterPageControl)) { setHeadersFromApp({ authorization: "", reqLang: state.lang, appVersion: "1.0.0", buildVersion: "1", appChannel: "Web", reqImei: "H5-STATIC", sysOrigin: "LIKEI", sysOriginChild: "LIKEI" }); resolve({ success: true }); return; } let attempt = 0; const poll = () => { attempt += 1; if (window.app && typeof window.app.getAccessOrigin === "function") { const raw = window.app.getAccessOrigin(); if (raw) setHeadersFromApp(parseAccessOrigin(raw)); resolve({ success: true }); return; } if (attempt < 50) { window.setTimeout(poll, 100); return; } if (window.FlutterApp && typeof window.FlutterApp.postMessage === "function") { window.FlutterApp.postMessage("requestAccessOrigin"); } resolve({ success: true }); }; poll(); }).then((result) => { if (typeof result === "string") setHeadersFromApp(parseAccessOrigin(result)); return result; }); } async function apiGet(path) { const response = await fetch(`${API_BASE_URL}${path}`, { method: "GET", headers: commonHeaders }); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { const error = new Error(data.errorMsg || data.message || `HTTP ${response.status}`); error.response = data; throw error; } return data; } async function searchPayee() { const query = $("#searchInput").value.trim(); state.query = query; if (!query) { state.results = []; renderResults(); return; } state.loading = true; state.searched = false; renderResults(); try { const result = await apiGet(`/wallet/bank/search/user-profile?account=${encodeURIComponent(query)}&type=AGENT&searchType=TRANSFER`); if (result.status && result.body) { state.results = [{ id: result.body.id, account: result.body.account, name: result.body.userNickname, avatar: result.body.userAvatar, sex: result.body.userSex, age: result.body.age, countryName: result.body.countryName, countryCode: result.body.countryCode, accountStatus: result.body.accountStatus, goodID: result.body.ownSpecialId?.account }]; } else { state.results = []; } } catch (error) { console.error("Search failed:", error); state.results = []; showToast(t("user_not_found_or_search_failed")); } finally { state.loading = false; state.searched = true; renderResults(); } } function resetSearch() { state.searched = false; state.query = ""; state.results = []; $("#searchInput").value = ""; renderResults(); } function showToast(message) { const toast = $("#toast"); toast.textContent = message || "Request failed"; toast.hidden = false; window.clearTimeout(showToast.timer); showToast.timer = window.setTimeout(() => { toast.hidden = true; }, 2500); } function showConfirm(user) { state.selected = user; $("#confirmModal").hidden = false; } function hideConfirm() { state.selected = null; $("#confirmModal").hidden = true; } function normalizeRoute(target) { const url = new URL(target, window.location.origin); const currentLang = new URLSearchParams(window.location.search).get("lang"); if (currentLang && !url.searchParams.has("lang")) url.searchParams.set("lang", currentLang); return `${url.pathname}${url.search}${url.hash}`; } function goBackToTransfer() { const from = new URLSearchParams(window.location.search).get("from") || "/transfer"; window.location.href = normalizeRoute(from); } function closePage() { if (window.history.length > 1) { window.history.back(); return; } if (window.app && typeof window.app.closePage === "function") { window.app.closePage(); return; } if (window.FlutterPageControl && typeof window.FlutterPageControl.postMessage === "function") { window.FlutterPageControl.postMessage("close_page"); } } function renderI18n() { document.documentElement.lang = state.lang; document.documentElement.dir = state.lang === "ar" ? "rtl" : "ltr"; $(".lang-button").textContent = state.lang.toUpperCase(); $$("[data-i18n]").forEach((node) => { node.textContent = t(node.dataset.i18n); }); $$("[data-i18n-placeholder]").forEach((node) => { node.placeholder = t(node.dataset.i18nPlaceholder); }); } function renderIcons() { $("#backIcon").src = icons.back; $("#searchIcon").src = icons.search; } function renderSearchActions() { const hasQuery = Boolean($("#searchInput").value.trim()); $("#searchButton").hidden = state.searched || !hasQuery; $("#cancelButton").hidden = !state.searched && !hasQuery; } function renderResults() { $("#loadingState").hidden = !state.loading; renderSearchActions(); const root = $("#results"); root.innerHTML = ""; if (state.loading) return; state.results.forEach((user) => { const card = document.createElement("div"); card.className = "result-card"; card.innerHTML = `
${t("user_id_prefix")}
`; card.querySelector(".result-name").textContent = user.name; card.querySelector(".result-id span:last-child").textContent = user.goodID || user.account || "-"; card.querySelector(".add-button").addEventListener("click", () => showConfirm(user)); card.querySelector("img").addEventListener("error", (event) => { event.target.onerror = null; event.target.src = DEFAULT_AVATAR; }); root.appendChild(card); }); } function render() { renderI18n(); renderIcons(); renderResults(); } function bindEvents() { $("[data-action='back']").addEventListener("click", closePage); $(".lang-button").addEventListener("click", () => { window.location.href = normalizeRoute("/language"); }); $("#searchInput").addEventListener("input", () => { if (state.searched) state.searched = false; renderSearchActions(); }); $("#searchInput").addEventListener("keyup", (event) => { if (event.key === "Enter") searchPayee(); }); $("#searchButton").addEventListener("click", searchPayee); $("#cancelButton").addEventListener("click", resetSearch); $("#confirmModal").addEventListener("click", hideConfirm); $(".modal-card").addEventListener("click", (event) => event.stopPropagation()); $("[data-action='cancel-select']").addEventListener("click", hideConfirm); $("[data-action='confirm-select']").addEventListener("click", () => { if (!state.selected) return; sessionStorage.setItem(PAYEE_KEY, JSON.stringify(state.selected)); hideConfirm(); goBackToTransfer(); }); } async function init() { bindEvents(); render(); await connectToApp(); } init();