const query = readURLParams(); const storedAppId = window.localStorage.getItem("mifa-pay-application-id") || ""; const API_BASE_URL = "https://jvapi.haiyihy.com"; const LOCAL_API_BASE_URL = "http://127.0.0.1:1100"; const LOGO_SRC = "./mifapay-logo.png"; function readURLParams() { const result = new URLSearchParams(window.location.search); const hashQuery = window.location.hash.includes("?") ? window.location.hash.split("?")[1] : ""; const hashParams = new URLSearchParams(hashQuery); hashParams.forEach((value, key) => { if (!result.has(key)) { result.set(key, value); } }); return result; } function getPathApplicationId() { const segments = window.location.pathname.split("/").filter(Boolean); const pageIndex = segments.lastIndexOf("mifa-pay"); if (pageIndex === -1) { return ""; } const candidate = segments[pageIndex + 1] || ""; return /^\d+$/.test(candidate) ? candidate : ""; } const defaults = { applicationId: getPathApplicationId() || query.get("applicationId") || query.get("appId") || storedAppId || "2048200000000000701", productType: query.get("type") || "GOLD", }; const state = { applicationId: defaults.applicationId, productType: defaults.productType, application: null, userProfile: null, countries: [], regionId: "", selectedCountryId: "", commodityCard: null, selectedGoodsId: "", selectedGoods: null, pendingChannelCode: "", }; const els = { applicationId: document.getElementById("applicationId"), productList: document.getElementById("productList"), channelList: document.getElementById("channelList"), pageStatus: document.getElementById("pageStatus"), }; function setStatus(text = "") { if (!text) { els.pageStatus.textContent = ""; els.pageStatus.className = "status"; return; } els.pageStatus.textContent = text; els.pageStatus.className = "status show"; } function persistSettings() { window.localStorage.setItem("mifa-pay-application-id", state.applicationId); } function readRawParam(name) { const queries = [window.location.search.replace(/^\?/, "")]; if (window.location.hash.includes("?")) { queries.push(window.location.hash.split("?")[1]); } for (const item of queries) { for (const part of item.split("&")) { if (!part) { continue; } const equalIndex = part.indexOf("="); const rawKey = equalIndex >= 0 ? part.slice(0, equalIndex) : part; const rawValue = equalIndex >= 0 ? part.slice(equalIndex + 1) : ""; let decodedKey = ""; try { decodedKey = decodeURIComponent(rawKey); } catch (error) { continue; } if (decodedKey !== name) { continue; } try { return decodeURIComponent(rawValue.replace(/\+/g, "%2B")); } catch (error) { return rawValue; } } } return ""; } function apiBaseURL() { const useProdApi = query.get("prod") === "true"; const isLocalPage = window.location.protocol === "http:" && ["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"].includes( window.location.hostname ); if (isLocalPage && !useProdApi) { return LOCAL_API_BASE_URL; } if (useProdApi) { return API_BASE_URL; } const override = window.MIFAPAY_API_BASE_URL || query.get("apiBase"); return String(override || API_BASE_URL).replace(/\/+$/, ""); } function normalizeAuthorization(value) { const token = String(value || "").trim(); if (!token) { return ""; } return /^bearer\s+/i.test(token) ? token : `Bearer ${token}`; } function currentToken() { return ( readRawParam("token") || readRawParam("Authorization") || readRawParam("authorization") || readRawParam("accessToken") ); } function currentLanguage() { return query.get("lang") || document.documentElement.lang || navigator.language || "en"; } function authHeadersFromToken(token) { return { Accept: "application/json, text/plain, */*", Authorization: normalizeAuthorization(token), "req-lang": currentLanguage(), "req-client": "H5", "req-version": "V2", "req-zone": Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai", "req-app-intel": "version=1.0.0;build=1;model=H5;sysVersion=Web;channel=Web", "req-sys-origin": "origin=ATYOU;originChild=ATYOU", }; } function requestHeaders(hasBody = false) { const token = currentToken(); if (!token) { throw new Error("Missing token"); } const headers = authHeadersFromToken(token); if (hasBody) { headers["Content-Type"] = "application/json"; } return headers; } function buildRequestURL(path) { const base = `${apiBaseURL()}/`; const target = String(path || "").replace(/^\/+/, ""); return new URL(target, base).toString(); } async function requestJSON(path, options = {}) { const hasBody = options.body !== undefined; const request = { method: options.method || "GET", cache: "no-store", headers: requestHeaders(hasBody), }; if (hasBody) { request.body = JSON.stringify(options.body); } const response = await fetch(buildRequestURL(path), request); const data = await response.json().catch(() => ({})); if (!response.ok || data.status === false) { const error = new Error(data.errorMsg || data.message || `Request failed: ${response.status}`); error.response = data; throw error; } return data; } function apiGet(path) { return requestJSON(path); } function apiPost(path, body) { return requestJSON(path, { method: "POST", body, }); } function extractErrorMessage(error) { return ( error?.response?.errorMsg || error?.response?.body?.errorMsg || error?.errorMsg || error?.message || "Unknown error" ); } function readStoredUserProfile() { const raw = window.localStorage.getItem("userProfile"); if (!raw) { return null; } try { const parsed = JSON.parse(raw); return parsed && typeof parsed === "object" ? parsed : null; } catch (error) { return null; } } function resolveUserProfile(response = null) { if (response?.body && typeof response.body === "object") { return response.body; } return readStoredUserProfile(); } function currentUserId() { return String(state.userProfile?.id || "").trim(); } function currentCountryId() { return state.selectedCountryId; } function currentRegionId() { return state.regionId; } function currentUserAccount() { return String( state.userProfile?.account || state.userProfile?.actualAccount || state.userProfile?.ownSpecialId?.account || state.userProfile?.specialId?.account || "" ).trim(); } function getCountryLabel(item) { return ( item?.label || item?.countryName || item?.country?.aliasName || item?.country?.countryName || String(item?.id || "") ); } function getGoodsList() { return state.commodityCard?.commodity || []; } function getChannelList() { return state.commodityCard?.channels || []; } function getChannelCode(item) { return item?.details?.channelCode || item?.channel?.channelCode || ""; } function getAmountText(item) { const content = item?.content || item?.obtainGoldsQuantity || "-"; return `${content} ${item?.type || ""}`.trim(); } function getPriceText(item) { const currency = item?.currency || state.commodityCard?.payCountry?.currency || "USD"; return `${item?.amount || item?.amountUsd || "-"} ${currency}`; } function ensureSelectedGoods() { const goods = getGoodsList(); if (!goods.length) { state.selectedGoodsId = ""; state.selectedGoods = null; return; } const matched = goods.find((item) => String(item.id) === state.selectedGoodsId) || goods.find((item) => item.type === state.productType) || goods[0]; state.selectedGoods = matched; state.selectedGoodsId = String(matched.id); } function renderProducts() { const goods = getGoodsList(); ensureSelectedGoods(); if (!goods.length) { els.productList.innerHTML = '
No amount available.
'; return; } els.productList.innerHTML = goods .map((item) => { const selected = String(item.id) === state.selectedGoodsId; return ` `; }) .join(""); els.productList.querySelectorAll("[data-goods-id]").forEach((button) => { button.addEventListener("click", () => { const goodsId = button.getAttribute("data-goods-id"); state.selectedGoodsId = goodsId; state.selectedGoods = getGoodsList().find((item) => String(item.id) === goodsId) || null; renderProducts(); }); }); } function renderChannels() { const channels = getChannelList(); if (!channels.length) { els.channelList.innerHTML = '
No payment method available.
'; return; } els.channelList.innerHTML = channels .map((item) => { const code = getChannelCode(item); const pending = state.pendingChannelCode === code; return ` `; }) .join(""); els.channelList.querySelectorAll("[data-channel-code]").forEach((button) => { button.addEventListener("click", async () => { const channelCode = button.getAttribute("data-channel-code"); try { await createOrder(channelCode); } catch (error) { state.pendingChannelCode = ""; renderChannels(); setStatus(extractErrorMessage(error)); } }); }); } function selectCountryByProfile() { const userCountryCode = state.userProfile?.countryCode; if (!userCountryCode) { return false; } const matched = state.countries.find((item) => getCountryLabel(item).toUpperCase().includes(userCountryCode.toUpperCase()) ); if (!matched) { return false; } state.selectedCountryId = String(matched.id); return true; } async function connectSession() { const response = await apiGet("/team/member/profile"); const userProfile = resolveUserProfile(response); if (!userProfile?.id) { throw new Error("Account not available"); } state.userProfile = userProfile; } async function refreshMeta() { if (!state.applicationId) { throw new Error("Missing applicationId"); } persistSettings(); els.applicationId.value = state.applicationId; const applicationResp = await apiGet( `/order/web/pay/application/${encodeURIComponent(state.applicationId)}` ); state.application = applicationResp?.body || {}; const profileQuery = new URLSearchParams({ sysOrigin: state.application?.appCode || state.userProfile?.originSys || "", type: state.productType, }); const account = currentUserAccount(); if (account) { profileQuery.set("account", account); } if (currentUserId()) { profileQuery.set("userId", currentUserId()); } const profileResp = await apiGet( `/order/web/pay/user-profile?${profileQuery.toString()}` ); const payProfile = profileResp?.body || {}; if (payProfile.userProfile) { state.userProfile = { ...state.userProfile, ...payProfile.userProfile, }; } state.regionId = payProfile.regionId || ""; state.countries = Array.isArray(payProfile.countryList) ? payProfile.countryList : []; if (!state.countries.length) { state.selectedCountryId = ""; state.commodityCard = null; renderProducts(); renderChannels(); throw new Error("No supported country"); } if ( !state.selectedCountryId || !state.countries.some((item) => String(item.id) === String(state.selectedCountryId)) ) { if (!selectCountryByProfile()) { state.selectedCountryId = String(state.countries[0].id); } } const commodityResp = await apiGet( `/order/web/pay/commodity?applicationId=${encodeURIComponent( state.applicationId )}&payCountryId=${encodeURIComponent(currentCountryId())}&type=${encodeURIComponent( state.productType )}®ionId=${encodeURIComponent(currentRegionId())}` ); state.commodityCard = commodityResp?.body || {}; renderProducts(); renderChannels(); setStatus(""); } function safeDecodeUrl(url) { if (!url) { return ""; } try { return decodeURIComponent(url); } catch (error) { return url; } } async function createOrder(channelCode) { if (!state.selectedGoods) { throw new Error("Select an amount first"); } if (!currentUserId()) { throw new Error("Account not available"); } state.pendingChannelCode = channelCode; setStatus(""); renderChannels(); const payload = { applicationId: state.applicationId, goodsId: state.selectedGoodsId, payCountryId: currentCountryId(), userId: currentUserId(), channelCode, newVersion: true, }; const response = await apiPost("/order/web/pay/recharge", payload); const requestUrl = safeDecodeUrl(response?.body?.requestUrl || ""); if (!requestUrl) { throw new Error("Missing payment url"); } window.location.href = requestUrl; } async function reloadPageData() { await connectSession(); await refreshMeta(); } async function init() { renderProducts(); renderChannels(); try { await reloadPageData(); } catch (error) { setStatus(extractErrorMessage(error)); } } init();