chatapp-h5/h5/recharge/script.js
2026-06-01 21:00:03 +08:00

1121 lines
40 KiB
JavaScript

(function () {
const API_BASE_URL = "https://jvapi.haiyihy.com";
const RECHARGE_APPLICATION_ID = "1963531459019739137";
const supportedLanguages = ["en", "ar", "tr", "id"];
const languageOptions = [
{ type: "en", label: "EN" },
{ type: "ar", label: "AR" },
{ type: "tr", label: "TR" },
{ type: "id", label: "ID" }
];
const languageLabels = languageOptions.reduce((result, item) => {
result[item.type] = item.label;
return result;
}, {});
const params = readURLParams();
const isMock = params.get("mock") === "1";
const hasTokenParam = Boolean(readRawParam("token") || readRawParam("accessToken") || readRawParam("authorization") || readRawParam("Authorization"));
let activeLang = normalizeLanguage(params.get("lang") || "en");
let headers = {
Authorization: "",
"req-app-intel": "version=1.0.0;build=1;model=H5;sysVersion=Web;channel=Web",
"req-client": "H5",
"req-lang": "en",
"req-sys-origin": "origin=ATYOU;originChild=ATYOU",
"req-version": "V2",
"req-zone": Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai"
};
let appConnectionPromise = null;
const fallbackMessages = {
en: {
documentTitle: "Recharge Center",
back: "Back",
title: "Recharge Center",
languageButtonAria: "Change language",
authMissingTitle: "Login token not found",
authMissingDesc: "Open this page from the app or include token in the URL.",
searchTitle: "Find account",
searchGuide: "Confirm the account before payment. Completed recharges cannot be refunded.",
loadingAccount: "Loading account...",
accountPlaceholder: "Enter User ID",
search: "Search",
searching: "Searching...",
userId: "ID:",
country: "Country:",
normalUser: "Normal user",
dealer: "Dealer",
superDealer: "Super dealer",
lowFee: "Low fee",
change: "Change",
packageTitle: "Recharge package",
methodTitle: "Payment methods",
selectPackageFirst: "Select a package first.",
selectPaymentMethod: "Select a payment method first.",
createOrder: "Create order",
creatingOrder: "Creating...",
usdtOrderTitle: "USDT TRC20 order",
trc20Address: "TRC20 address",
copy: "Copy",
copied: "Copied",
amount: "Amount",
orderInputLabel: "Enter order no. (transfer address)",
orderInputPlaceholder: "Enter order no.",
queryPaymentStatus: "Query payment status",
queryingStatus: "Querying...",
paymentPending: "Payment is not confirmed yet.",
paymentStatusFailed: "Payment status query failed.",
loading: "Loading...",
noOptions: "No available recharge methods.",
searchFirst: "Search an account first.",
orderNo: "Order no.",
done: "Done",
paymentSuccessTitle: "Payment successful",
paymentSuccessMessage: "The order result has been returned.",
paymentFailTitle: "Payment failed",
paymentFailMessage: "Please retry or change payment method.",
userNotFound: "User info not found",
noCountry: "No supported country",
noPackage: "No recharge packages",
paymentUnavailable: "Payment not available",
orderCreated: "Order created",
orderCreatedMessage: "Please finish payment according to the payment channel instructions.",
redirecting: "Redirecting to payment..."
},
ar: {},
tr: {},
id: {}
};
supportedLanguages.forEach((lang) => {
fallbackMessages[lang] = { ...fallbackMessages.en, ...(fallbackMessages[lang] || {}) };
});
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 readRawParam(name) {
const queries = [window.location.search.replace(/^\?/, "")];
if (window.location.hash.includes("?")) queries.push(window.location.hash.split("?")[1]);
for (const query of queries) {
for (const part of query.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 normalizeLanguage(lang) {
const value = String(lang || "en").toLowerCase();
if (value.startsWith("ar")) return "ar";
if (value.startsWith("tr")) return "tr";
if (value.startsWith("id") || value.startsWith("in")) return "id";
return supportedLanguages.includes(value) ? value : "en";
}
async function loadMessages(lang) {
const normalizedLang = normalizeLanguage(lang);
if (window.location.protocol === "file:") return fallbackMessages[normalizedLang] || fallbackMessages.en;
try {
const response = await fetch(`./locales/${normalizedLang}.json?v=20260601-0600`, { cache: "no-store" });
if (response.ok) {
const data = await response.json();
return { ...fallbackMessages.en, ...data };
}
} catch (error) {}
return fallbackMessages[normalizedLang] || fallbackMessages.en;
}
function splitHeaderPairs(value) {
const result = {};
if (!value) return result;
String(value).split(";").forEach((item) => {
const index = item.indexOf("=");
if (index > -1) result[item.slice(0, index)] = item.slice(index + 1);
});
return result;
}
function mapHeaderValue(target, key, value) {
if (value === null || value === undefined || value === "" || target[key]) return;
target[key] = String(value);
}
function normalizeHeaderCandidate(value, depth = 0) {
if (depth > 4 || value === null || value === undefined) return {};
if (typeof value === "string") {
const trimmed = value.trim();
if (!trimmed) return {};
if (trimmed[0] === "{" || trimmed[0] === "[") {
try {
return normalizeHeaderCandidate(JSON.parse(trimmed), depth + 1);
} catch (error) {
return {};
}
}
return /^bearer\s+/i.test(trimmed) ? { authorization: trimmed } : {};
}
if (Array.isArray(value)) {
return value.reduce((result, item) => ({ ...result, ...normalizeHeaderCandidate(item, depth + 1) }), {});
}
if (typeof value !== "object") return {};
const appIntel = splitHeaderPairs(value["Req-App-Intel"] || value["req-app-intel"]);
const sysOrigin = splitHeaderPairs(value["Req-Sys-Origin"] || value["req-sys-origin"]);
const normalized = {};
mapHeaderValue(normalized, "authorization", value.Authorization || value.authorization || value.token || value.accessToken);
mapHeaderValue(normalized, "reqLang", value["Req-Lang"] || value["req-lang"] || value.reqLang || value.lang || value.language);
mapHeaderValue(normalized, "appVersion", appIntel.version || value["App-Version"] || value.appVersion);
mapHeaderValue(normalized, "buildVersion", appIntel.build || value["Build-Version"] || value.buildVersion);
mapHeaderValue(normalized, "channel", appIntel.channel || value["App-Channel"] || value.appChannel || value.channel);
mapHeaderValue(normalized, "reqImei", value["Req-Imei"] || value["req-imei"] || value.reqImei || appIntel.reqImei);
mapHeaderValue(normalized, "origin", sysOrigin.origin || value["Sys-Origin"] || value.sysOrigin || value.origin);
mapHeaderValue(normalized, "child", sysOrigin.originChild || sysOrigin.child || value["Sys-Origin-Child"] || value.sysOriginChild || value.child);
["headerInfo", "headers", "auth", "data", "state"].forEach((key) => {
Object.assign(normalized, normalizeHeaderCandidate(value[key], depth + 1));
});
return normalized;
}
function normalizeAuthorization(value) {
const token = String(value || "").trim();
if (!token) return "";
return /^bearer\s+/i.test(token) ? token : `Bearer ${token}`;
}
function setHeadersFromApp(rawOrObject) {
const data = normalizeHeaderCandidate(rawOrObject || {});
const next = {};
if (data.authorization) next.Authorization = normalizeAuthorization(data.authorization);
if (data.reqLang) next["req-lang"] = normalizeLanguage(data.reqLang);
if (data.appVersion || data.buildVersion || data.channel) {
next["req-app-intel"] = [
data.appVersion ? `version=${data.appVersion}` : "",
data.buildVersion ? `build=${data.buildVersion}` : "",
data.channel ? `channel=${data.channel}` : ""
].filter(Boolean).join(";");
}
if (data.reqImei) next["req-imei"] = data.reqImei;
if (data.origin) {
next["req-sys-origin"] = [`origin=${data.origin}`, data.child ? `originChild=${data.child}` : ""].filter(Boolean).join(";");
}
headers = { ...headers, ...next };
}
function collectHeaderCandidate(collected, value) {
const normalized = normalizeHeaderCandidate(value);
if (Object.keys(normalized).length) collected.push(normalized);
}
function collectHeadersFromStorage(collected, storage) {
if (!storage) return;
["authorization", "Authorization", "token", "accessToken", "headerInfo", "headersFromApp", "appHeaders", "user", "userInfo"].forEach((key) => {
try {
collectHeaderCandidate(collected, storage.getItem(key));
} catch (error) {}
});
}
function queryHeaderCandidate() {
return {
authorization: readRawParam("authorization") || readRawParam("Authorization") || readRawParam("token") || readRawParam("accessToken"),
reqLang: params.get("lang"),
appVersion: params.get("appVersion"),
buildVersion: params.get("buildVersion"),
channel: params.get("appChannel") || params.get("channel"),
reqImei: params.get("reqImei"),
origin: params.get("sysOrigin"),
child: params.get("sysOriginChild")
};
}
function discoverAppHeaders() {
const collected = [{ reqLang: activeLang }, queryHeaderCandidate()];
collectHeaderCandidate(collected, window.__APP_HEADERS__);
collectHeaderCandidate(collected, window.__HEADER_INFO__);
collectHeaderCandidate(collected, window.headerInfo);
collectHeadersFromStorage(collected, window.localStorage);
collectHeadersFromStorage(collected, window.sessionStorage);
return collected.reduce((result, item) => ({ ...result, ...item }), {});
}
function applyDiscoveredHeaders() {
const discovered = discoverAppHeaders();
if (Object.keys(discovered).length) setHeadersFromApp(discovered);
return discovered;
}
function isAppEnvironment() {
return Boolean(window.app || window.webkit || window.FlutterPageControl || window.FlutterApp);
}
function requestAccessOrigin() {
return new Promise((resolve) => {
let settled = false;
let timeoutId = null;
const finish = (raw) => {
if (settled) {
if (raw) setHeadersFromApp(raw);
return;
}
settled = true;
if (timeoutId) window.clearTimeout(timeoutId);
resolve(raw || null);
};
window.renderData = finish;
window.getIosAccessOriginParam = finish;
if (!isAppEnvironment()) {
setHeadersFromApp({
reqLang: activeLang,
appVersion: "1.0.0",
buildVersion: "1",
channel: "Web",
reqImei: "H5-STATIC",
origin: "ATYOU",
child: "ATYOU"
});
finish(null);
return;
}
const requestFromFlutter = () => {
if (window.FlutterApp && typeof window.FlutterApp.postMessage === "function") {
window.FlutterApp.postMessage("requestAccessOrigin");
}
};
if (window.app && typeof window.app.getAccessOrigin === "function") {
finish(window.app.getAccessOrigin());
return;
}
requestFromFlutter();
timeoutId = window.setTimeout(() => finish(null), 12000);
let attempt = 0;
const poll = () => {
attempt += 1;
if (window.app && typeof window.app.getAccessOrigin === "function") {
finish(window.app.getAccessOrigin());
return;
}
if (attempt < 50) {
window.setTimeout(poll, 100);
return;
}
requestFromFlutter();
};
poll();
});
}
async function connectToApp() {
if (!appConnectionPromise) {
applyDiscoveredHeaders();
appConnectionPromise = requestAccessOrigin()
.then((raw) => {
if (raw) setHeadersFromApp(raw);
else applyDiscoveredHeaders();
return {
success: true,
environment: isAppEnvironment() ? "app" : "browser",
authenticated: Boolean(headers.Authorization)
};
})
.finally(() => {
appConnectionPromise = null;
});
}
return appConnectionPromise;
}
function apiBaseURL() {
const override = window.HYAPP_API_BASE_URL || params.get("apiBase");
return String(override || API_BASE_URL).replace(/\/+$/, "");
}
function buildRequestURL(path) {
const base = `${apiBaseURL()}/`;
const target = String(path || "").replace(/^\/+/, "");
return new URL(target, base).toString();
}
async function requestJSON(path, options = {}) {
if (isMock) return mockRequest(path, options);
applyDiscoveredHeaders();
const requestHeaders = { ...headers };
if (!requestHeaders.Authorization && readRawParam("token")) {
requestHeaders.Authorization = normalizeAuthorization(readRawParam("token"));
}
const request = {
method: options.method || "GET",
cache: "no-store",
headers: requestHeaders
};
if (options.body !== undefined) {
requestHeaders["Content-Type"] = "application/json";
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.body ?? data.data ?? null;
}
function closePage() {
try {
const from = params.get("from");
if (from) {
const target = new URL(from, window.location.origin);
const currentLang = params.get("lang");
if (currentLang && !target.searchParams.has("lang")) target.searchParams.set("lang", currentLang);
window.location.href = `${target.pathname}${target.search}${target.hash}`;
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");
return;
}
if (window.history.length > 1) window.history.back();
} catch (error) {
if (window.history.length > 1) window.history.back();
}
}
function endpointOpenSearch(account) {
return `/user/user-profile/open-search?account=${encodeURIComponent(account)}`;
}
function endpointSelfProfile() {
return "/team/member/profile";
}
function endpointApplication() {
return `/order/web/pay/application/${encodeURIComponent(RECHARGE_APPLICATION_ID)}`;
}
function endpointPayProfile(appCode, account, type) {
const query = new URLSearchParams({ sysOrigin: appCode, account, type });
return `/order/web/pay/user-profile?${query.toString()}`;
}
function endpointCommodity(countryId, regionId, type) {
const query = new URLSearchParams({
applicationId: RECHARGE_APPLICATION_ID,
payCountryId: countryId,
regionId: regionId || "",
type
});
return `/order/web/pay/commodity?${query.toString()}`;
}
function endpointOrderStatus(orderId) {
const query = new URLSearchParams({ orderId });
return `/order/web/pay/order-status?${query.toString()}`;
}
function profileId(profile) {
return profile?.id || profile?.userId || profile?.uid || "";
}
function profileAccount(profile) {
return profile?.account || profile?.userAccount || profile?.ownSpecialId?.account || profile?.goodId || profile?.goodID || "-";
}
function profileName(profile) {
return profile?.userNickname || profile?.nickName || profile?.nickname || profile?.name || "-";
}
function avatarUrl(profile) {
return profile?.userAvatar || profile?.avatar || profile?.avatarUrl || "";
}
function isDealerProfile(profile) {
const role = String(profile?.role || profile?.userRole || profile?.identity || profile?.type || "").toUpperCase();
return Boolean(profile?.isSuperFreightAgent || profile?.isFreightAgent || role.includes("DEALER") || role.includes("SELLER") || role.includes("FREIGHT"));
}
function commodityType(profile) {
if (profile?.isSuperFreightAgent) return "FREIGHT_GOLD_SUPER";
if (isDealerProfile(profile)) return "FREIGHT_GOLD";
return "GOLD";
}
function countryName(item) {
return item?.countryName || item?.country?.aliasName || item?.country?.countryName || item?.name || "-";
}
function countryId(item) {
return item?.id || item?.countryId || item?.country?.id || item?.country?.countryId || "";
}
function channelCode(item) {
return item?.channel?.channelCode || item?.details?.channelCode || item?.channelCode || "";
}
function channelName(item) {
return item?.channel?.channelName || item?.channelName || channelCode(item) || "-";
}
function channelIcon(item) {
return item?.channel?.channelIcon || item?.channelIcon || "";
}
function usdtAddress(item) {
return (
item?.details?.trc20Address ||
item?.details?.usdtTrc20Address ||
item?.details?.usdtAddress ||
item?.details?.walletAddress ||
item?.channel?.trc20Address ||
item?.channel?.usdtAddress ||
item?.channel?.address ||
item?.trc20Address ||
item?.usdtAddress ||
item?.walletAddress ||
item?.address ||
params.get("trc20Address") ||
window.USDT_TRC20_ADDRESS ||
"TMockTrc20RechargeAddress000000000001"
);
}
function isUsdtChannel(item) {
const value = `${channelCode(item)} ${channelName(item)} ${item?.details?.factoryChannel || ""}`.toUpperCase();
return value.includes("USDT") || value.includes("UDST") || value.includes("TRC20") || value.includes("BEP20");
}
function isUsdtTrc20Channel(item) {
const value = `${channelCode(item)} ${channelName(item)} ${item?.details?.factoryChannel || ""}`.toUpperCase();
return value.includes("TRC20") && (value.includes("USDT") || value.includes("UDST"));
}
function isBankTransferChannel(item) {
const code = String(channelCode(item) || "").trim().toUpperCase();
const value = `${code} ${channelName(item)} ${item?.details?.factoryChannel || ""}`.toUpperCase();
return code === "BANK" || value.includes("BANK TRANSFER") || value.includes("BANKTRANSFER") || value.includes("BANK_TRANSFER");
}
function isSuccessfulPaymentStatus(data) {
if (data?.success === true || data?.paid === true || data?.paySuccess === true || data?.orderPaid === true) return true;
const status = String(data?.status || data?.orderStatus || data?.payStatus || data?.tradeStatus || "").trim().toUpperCase();
return ["SUCCESS", "SUCCEEDED", "PAID", "DONE", "COMPLETED"].includes(status);
}
async function copyText(value) {
const text = String(value || "");
if (!text) return;
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(text);
return;
}
const input = document.createElement("textarea");
input.value = text;
input.setAttribute("readonly", "readonly");
input.style.position = "fixed";
input.style.top = "-1000px";
document.body.appendChild(input);
input.select();
document.execCommand("copy");
document.body.removeChild(input);
}
function pickDefaultCountry(list, regionId) {
const countries = Array.isArray(list) ? list : [];
if (!countries.length) return null;
const region = String(regionId || "").toUpperCase();
return countries.find((item) => {
const values = [
item?.id,
item?.countryId,
item?.regionId,
item?.country?.id,
item?.country?.countryId,
item?.country?.regionId,
item?.countryCode,
item?.country?.countryCode
].map((value) => String(value || "").toUpperCase());
return region && values.includes(region);
}) || countries[0];
}
function parseExpand(value) {
if (!value) return {};
if (typeof value === "object") return value;
try {
return JSON.parse(value);
} catch (error) {
return {};
}
}
function payEnvironment() {
const value = String(window.AIRWALLEX_ENV || params.get("payEnv") || window.ENV || "").toLowerCase();
if (value === "production" || value === "prod") return "prod";
if (value === "staging") return "staging";
if (value === "dev") return "dev";
if (value === "local") return "local";
return "demo";
}
function airwallexHost(env) {
const hosts = {
prod: "checkout.airwallex.com",
demo: "checkout-demo.airwallex.com",
staging: "checkout-staging.airwallex.com",
dev: "checkout-dev.airwallex.com",
local: "localhost:3000"
};
return `https://${hosts[env] || hosts.prod}`;
}
function loadAirwallex(env) {
if (window.Airwallex) {
window.Airwallex.init({ env });
return Promise.resolve(window.Airwallex);
}
const src = `${airwallexHost(env)}/assets/elements.bundle.min.js?version=1.160.0`;
const existing = document.querySelector(`[data-airwallex-script="${env}"]`);
const script = existing || document.createElement("script");
if (!existing) {
script.src = src;
script.crossOrigin = "anonymous";
script.dataset.airwallexScript = env;
document.head.appendChild(script);
}
return new Promise((resolve, reject) => {
script.addEventListener("load", () => {
if (!window.Airwallex) {
reject(new Error("Failed to load Airwallex"));
return;
}
window.Airwallex.init({ env });
resolve(window.Airwallex);
}, { once: true });
script.addEventListener("error", () => reject(new Error("Failed to load Airwallex")), { once: true });
});
}
function mockRequest(path, options) {
return new Promise((resolve) => {
window.setTimeout(() => {
const account = params.get("account") || "80008888";
if (path.includes("/application/")) {
resolve({ appCode: "ATYOU" });
return;
}
if (path.includes("/team/member/profile")) {
const dealer = String(account).startsWith("8");
resolve({
id: dealer ? "9001" : "1001",
account,
userNickname: dealer ? "India Dealer" : "India User",
userAvatar: "",
isFreightAgent: dealer
});
return;
}
if (path.includes("/open-search")) {
const requested = decodeURIComponent(path.split("account=")[1] || account);
const dealer = String(requested).startsWith("8");
resolve({
id: dealer ? "9001" : "1001",
account: requested,
userNickname: dealer ? "India Dealer" : "India User",
userAvatar: "",
isFreightAgent: dealer
});
return;
}
if (path.includes("/user-profile")) {
resolve({
regionId: "IN",
countryList: [
{ id: "101", countryName: "India", country: { countryName: "India" } },
{ id: "102", countryName: "Saudi Arabia", country: { countryName: "Saudi Arabia" } }
]
});
return;
}
if (path.includes("/commodity")) {
resolve({
commodity: [
{ id: "g1", content: "10,000 coins", amountUsd: 1 },
{ id: "g2", content: "50,000 coins", amountUsd: 5, awardContent: "+5,000 bonus" },
{ id: "g3", content: "100,000 coins", amountUsd: 10, awardContent: "+12,000 bonus" }
],
channels: [
{ channel: { channelCode: "UPI_BHIM", channelName: "BHIM UPI", channelIcon: "../mifa-pay/logos/bhim.png" } },
{ channel: { channelCode: "UPI_PHONEPE", channelName: "PhonePe", channelIcon: "../mifa-pay/logos/phonepe.png" } },
{ channel: { channelCode: "UPI_GOOGLEPAY", channelName: "Google Pay", channelIcon: "../mifa-pay/logos/googlepay.png" } },
{ channel: { channelCode: "UPI_PAYTM", channelName: "Paytm", channelIcon: "../mifa-pay/logos/paytm.png" } },
{ channel: { channelCode: "UPI_MOBIKWIK", channelName: "Mobikwik", channelIcon: "../mifa-pay/logos/mobikwik.png" } },
{ channel: { channelCode: "UPI", channelName: "UPI", channelIcon: "../mifa-pay/logos/upi.png" } },
{
channel: { channelCode: "USDT_TRC20", channelName: "USDT TRC20" },
details: { trc20Address: "TMockTrc20RechargeAddress000000000001" }
}
]
});
return;
}
if (path.includes("/pay/recharge")) {
resolve({ orderId: "RCMOCK202606010001", factoryCode: "MANUAL" });
return;
}
if (path.includes("/order-status")) {
const orderId = new URLSearchParams(path.split("?")[1] || "").get("orderId") || "";
const failed = !orderId || /fail|pending/i.test(orderId);
resolve({
orderId,
status: failed ? "PENDING" : "SUCCESS",
success: !failed,
finished: !failed,
reason: failed ? "Payment is not confirmed yet." : ""
});
return;
}
resolve({});
}, 260);
});
}
const app = Vue.createApp({
data() {
return {
lang: activeLang,
languages: languageOptions,
languageMenuOpen: false,
messages: fallbackMessages[activeLang] || fallbackMessages.en,
isMock,
selfMode: hasTokenParam,
authenticated: false,
account: params.get("account") || params.get("targetAccount") || "",
searching: false,
loadingOptions: false,
ordering: false,
statusText: "",
statusType: "",
toastText: "",
targetProfile: null,
application: null,
appCode: "",
rechargeType: "GOLD",
payProfile: null,
countryList: [],
selectedCountryId: "",
regionId: "",
commodity: [],
selectedGoodsId: "",
selectedChannelKey: "",
channels: [],
orderResult: null,
usdtModalOpen: false,
usdtOrderInput: "",
usdtOrderError: "",
queryingPayment: false,
paymentReturn: null
};
},
computed: {
text() {
return this.messages || fallbackMessages.en;
},
languageLabel() {
return languageLabels[this.lang] || "EN";
},
isRtl() {
return this.lang === "ar";
},
selectedCountry() {
return this.countryList.find((item) => String(countryId(item)) === String(this.selectedCountryId)) || this.countryList[0] || null;
},
selectedGoods() {
return this.commodity.find((item) => String(item?.id) === String(this.selectedGoodsId)) || null;
},
selectedChannel() {
return this.visibleChannels.find((item) => this.channelKey(item) === this.selectedChannelKey) || null;
},
usdtAddressText() {
return usdtAddress(this.selectedChannel);
},
isDealer() {
return isDealerProfile(this.targetProfile);
},
roleLabel() {
if (this.targetProfile?.isSuperFreightAgent) return this.text.superDealer;
if (this.isDealer) return this.text.dealer;
return this.text.normalUser;
},
visibleChannels() {
const usdtTrc20 = this.channels.filter(isUsdtTrc20Channel);
const thirdParty = this.channels.filter((channel) => !isUsdtChannel(channel) && !isBankTransferChannel(channel));
return [...thirdParty, ...usdtTrc20];
}
},
async mounted() {
document.documentElement.lang = this.lang;
document.documentElement.dir = this.isRtl ? "rtl" : "ltr";
await this.applyLanguage(this.lang);
this.readPaymentReturn();
connectToApp().then((result) => {
this.authenticated = Boolean(result.authenticated || headers.Authorization || isMock);
});
if (this.selfMode) {
this.loadSelfAccount();
} else if (this.account && params.get("autoSearch") === "1") {
this.searchAccount();
}
},
methods: {
closePage,
profileName,
profileAccount,
avatarUrl,
countryName,
countryId,
channelCode,
channelName,
channelIcon,
usdtAddress,
isUsdtChannel,
isUsdtTrc20Channel,
fallbackInitial(profile) {
return String(profileName(profile) || profileAccount(profile) || "U").trim().slice(0, 1).toUpperCase();
},
hideBrokenImage(event) {
event.currentTarget.style.display = "none";
},
toggleLanguageMenu() {
this.languageMenuOpen = !this.languageMenuOpen;
},
closeLanguageMenu() {
this.languageMenuOpen = false;
},
async applyLanguage(lang) {
this.lang = normalizeLanguage(lang);
activeLang = this.lang;
this.messages = await loadMessages(this.lang);
headers["req-lang"] = this.lang;
document.documentElement.lang = this.lang;
document.documentElement.dir = this.isRtl ? "rtl" : "ltr";
document.title = this.text.documentTitle || this.text.title || "Recharge Center";
this.languageMenuOpen = false;
if (this.paymentReturn) this.readPaymentReturn();
},
showToast(text) {
this.toastText = text;
window.clearTimeout(this.toastTimer);
this.toastTimer = window.setTimeout(() => {
this.toastText = "";
}, 2400);
},
setStatus(text, type = "") {
this.statusText = text;
this.statusType = type;
},
selectGoods(goods) {
this.selectedGoodsId = String(goods?.id || "");
},
selectChannel(channel) {
this.selectedChannelKey = this.channelKey(channel);
this.usdtOrderError = "";
},
readPaymentReturn() {
const status = params.get("paymentStatus") || params.get("appStatus");
if (status === "0" || status === "success") {
this.paymentReturn = {
type: "success",
title: this.text.paymentSuccessTitle,
message: this.text.paymentSuccessMessage
};
} else if (status === "1" || status === "fail") {
this.paymentReturn = {
type: "error",
title: this.text.paymentFailTitle,
message: this.text.paymentFailMessage
};
}
},
resetTarget() {
this.targetProfile = null;
this.payProfile = null;
this.countryList = [];
this.selectedCountryId = "";
this.regionId = "";
this.commodity = [];
this.selectedGoodsId = "";
this.selectedChannelKey = "";
this.channels = [];
this.usdtModalOpen = false;
this.setStatus("");
},
async ensureApplication() {
if (this.appCode) return;
this.application = await requestJSON(endpointApplication());
this.appCode = this.application?.appCode || this.application?.sysOrigin || "ATYOU";
},
async loadSelfAccount() {
if (this.searching) return;
this.searching = true;
this.setStatus(this.text.loadingAccount);
this.targetProfile = null;
this.countryList = [];
this.commodity = [];
this.selectedGoodsId = "";
this.selectedChannelKey = "";
this.channels = [];
try {
await connectToApp();
const profile = await requestJSON(endpointSelfProfile());
if (!profile || !profileId(profile)) throw new Error(this.text.userNotFound);
this.targetProfile = profile;
this.account = profileAccount(profile);
this.rechargeType = commodityType(profile);
await this.loadRechargeOptions();
this.setStatus("");
} catch (error) {
const text = error.response?.errorMsg || error.message || this.text.userNotFound;
this.setStatus(text, "error");
this.showToast(text);
} finally {
this.searching = false;
}
},
async searchAccount() {
if (!this.account || this.searching) return;
this.searching = true;
this.setStatus(this.text.searching);
this.targetProfile = null;
this.countryList = [];
this.commodity = [];
this.selectedGoodsId = "";
this.selectedChannelKey = "";
this.channels = [];
try {
await connectToApp();
const profile = await requestJSON(endpointOpenSearch(this.account));
if (!profile || !profileId(profile)) throw new Error(this.text.userNotFound);
this.targetProfile = profile;
this.rechargeType = commodityType(profile);
await this.loadRechargeOptions();
this.setStatus("");
} catch (error) {
const text = error.response?.errorMsg || error.message || this.text.userNotFound;
this.setStatus(text, "error");
this.showToast(text);
} finally {
this.searching = false;
}
},
async loadRechargeOptions() {
this.loadingOptions = true;
try {
await this.ensureApplication();
const data = await requestJSON(endpointPayProfile(this.appCode, profileAccount(this.targetProfile), this.rechargeType));
this.payProfile = data || {};
if (data?.userProfile) this.targetProfile = { ...this.targetProfile, ...data.userProfile };
this.countryList = Array.isArray(data?.countryList) ? data.countryList : [];
this.regionId = data?.regionId || "";
if (!this.countryList.length) throw new Error(this.text.noCountry);
const country = pickDefaultCountry(this.countryList, this.regionId);
this.selectedCountryId = String(countryId(country));
await this.loadCommodity();
} finally {
this.loadingOptions = false;
}
},
async loadCommodity() {
const country = this.selectedCountry;
const id = countryId(country);
if (!id) {
this.commodity = [];
this.channels = [];
this.selectedChannelKey = "";
return;
}
const data = await requestJSON(endpointCommodity(String(id), this.regionId, this.rechargeType));
this.commodity = Array.isArray(data?.commodity) ? data.commodity : [];
this.channels = Array.isArray(data?.channels) ? data.channels : [];
this.selectedGoodsId = "";
this.selectedChannelKey = "";
if (!this.commodity.length) this.setStatus(this.text.noPackage, "error");
},
channelKey(channel) {
return `${channelCode(channel)}:${channelName(channel)}`;
},
formatPrice(goods) {
const currency = goods.currency || "USD";
const amount = goods.amountUsd ?? goods.amount ?? goods.price ?? "";
if (amount === "") return "";
return currency === "USD" ? `$${amount}` : `${currency} ${amount}`;
},
paymentResultURL(status) {
const url = new URL(window.location.origin + window.location.pathname);
url.searchParams.set("paymentStatus", status);
url.searchParams.set("lang", this.lang);
if (this.account) url.searchParams.set("account", this.account);
return url.toString();
},
async redirectAirwallex(result) {
const env = payEnvironment();
const expand = parseExpand(result.expand);
if (!expand.id || !expand.client_secret) throw new Error(this.text.paymentUnavailable);
await loadAirwallex(env);
window.Airwallex.redirectToCheckout({
env,
mode: "payment",
currency: result.currency,
intent_id: expand.id,
client_secret: expand.client_secret,
methods: result.factoryChannelCode ? [result.factoryChannelCode] : undefined,
logoUrl: window.sysOriginLog || "",
successUrl: this.paymentResultURL("0"),
failUrl: this.paymentResultURL("1")
});
},
async handlePaymentResponse(result) {
if (!result) throw new Error(this.text.paymentUnavailable);
if (result.factoryCode === "AIRWALLEX") {
this.showToast(this.text.redirecting);
await this.redirectAirwallex(result);
return;
}
if (result.requestUrl) {
this.showToast(this.text.redirecting);
window.location.href = decodeURIComponent(result.requestUrl);
return;
}
this.orderResult = {
type: "info",
title: this.text.orderCreated,
message: this.text.orderCreatedMessage,
orderNo: result.orderNo || result.orderId || result.tradeNo || ""
};
},
async createOrder() {
if (!this.selectedGoods) {
this.showToast(this.text.selectPackageFirst);
return;
}
if (!this.selectedChannel) {
this.showToast(this.text.selectPaymentMethod);
return;
}
if (isUsdtTrc20Channel(this.selectedChannel)) {
this.openUsdtModal();
return;
}
await this.placeOrder(this.selectedChannel);
},
openUsdtModal() {
this.usdtOrderInput = "";
this.usdtOrderError = "";
this.usdtModalOpen = true;
},
closeUsdtModal() {
this.usdtModalOpen = false;
this.usdtOrderInput = "";
this.usdtOrderError = "";
this.queryingPayment = false;
},
async copyUsdtAddress() {
try {
await copyText(this.usdtAddressText);
this.showToast(this.text.copied);
} catch (error) {
this.showToast(this.usdtAddressText);
}
},
async queryUsdtPaymentStatus() {
if (!this.usdtOrderInput || this.queryingPayment) return;
this.queryingPayment = true;
this.usdtOrderError = "";
try {
const result = await requestJSON(endpointOrderStatus(this.usdtOrderInput));
if (isSuccessfulPaymentStatus(result)) {
this.closeUsdtModal();
this.showToast(this.text.paymentSuccessTitle);
return;
}
this.usdtOrderError = result?.reason || result?.message || result?.status || this.text.paymentPending;
} catch (error) {
this.usdtOrderError = error.response?.errorMsg || error.message || this.text.paymentStatusFailed;
} finally {
this.queryingPayment = false;
}
},
async placeOrder(channel) {
const country = this.selectedCountry;
const goods = this.selectedGoods;
const id = countryId(country);
const code = channelCode(channel);
const userId = profileId(this.targetProfile);
if (!id || !goods?.id || !userId || !code) {
this.showToast(!goods?.id ? this.text.selectPackageFirst : this.text.paymentUnavailable);
return;
}
this.ordering = true;
try {
const result = await requestJSON("/order/web/pay/recharge", {
method: "POST",
body: {
applicationId: RECHARGE_APPLICATION_ID,
payCountryId: String(id),
goodsId: String(goods.id),
userId: String(userId),
channelCode: code,
newVersion: true
}
});
await this.handlePaymentResponse(result);
} catch (error) {
const text = error.response?.errorMsg || error.message || this.text.paymentUnavailable;
this.orderResult = { type: "error", title: this.text.paymentUnavailable, message: text };
this.showToast(text);
} finally {
this.ordering = false;
}
}
}
});
app.mount("#app");
})();