indrajitghosh20006/Igstore_01botPublic ยท Bot Template
AIThe bot provides an admin interface for a digital store, allowing the owner or coโadmins to add balances, products, plans, and categories. It supports payment workflows via UPI and Binance Pay, automatically generating QR codes and handling manual approval of deposits. The code patches inline keyboards to use premium emoji icons and includes helper functions for user and bot properties. Overall, it serves as a commerce management tool for a Telegram-based storefront.
Commercestoreadminbalanceproductplancategory
170 commands0 envUpdated 8h agoCreated Oct 30, 2026
commands/_onBuyCheck.js
javascript ยท 580 lines
1/**#command2name: /onBuyCheck3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12/**#command13name: /onBuyCheck14answer: 15keyboard: 16parse_mode: markdown17aliases: 18allow_only_group: false19need_reply: 020case_insensitive: false21is_web: 022#command**/23 24/**#command25name: /onBuyCheck26answer: 27keyboard: 28parse_mode: markdown29aliases: 30allow_only_group: false31need_reply: false32case_insensitive: false33is_web: 034#command**/35 36function resolveApiDuration(plan, cleanPlanDays, planUnit, productNameOverride) {37 // IMPORTANT: Keep the admin/API duration name exactly as entered.38 // The product-specific day ranges below are used only when the stored plan39 // contains a plain numeric Day duration; this lets 1-30 Day plans target40 // the exact website/API names requested by the admin without changing any41 // other product data or purchase logic.42 var raw = String((plan && (plan.api_duration || plan.name_on_website || plan.durationDisplay || plan.name || plan.title)) || "").replace(/\s+/g, " ").trim();43 44 // Already-custom API labels (including casing/suffixes) must pass through unchanged.45 if (raw && !/^[0-9]+(?:\.[0-9]+)?\s*(day|days)$/i.test(raw)) {46 return raw;47 }48 49 var dayMatch = raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(day|days)$/i);50 var n = dayMatch ? dayMatch[1] : String(cleanPlanDays || "1");51 var productName = String(productNameOverride || (plan && (plan.product_name || plan.productName || plan.product || plan.category)) || "").trim().toLowerCase();52 53 // If product name is not stored on the plan, the caller's raw API label is54 // still preserved above. Generic numeric Day plans remain "N Days".55 if (/pc\s*aim\s*silent/.test(productName)) return n + " Day Pc Aim Silent";56 if (/pc\s*modmenu\s*x86/.test(productName)) return n + " Day Pc Modmenu x86";57 if (/pc\s*bypass\s*\+\s*silent/.test(productName) || /bypass\s*\+\s*silent/.test(productName)) return n + " Days Pc Bypass + Silent";58 if (/nonroot/.test(productName) && !/root\s*\+\s*nonroot/.test(productName)) return n + " DaYS NONROOT";59 if (/pc\s*aimkill/.test(productName) || /aimkill/.test(productName)) return n + " DaYS PC AIMKILL";60 if (/root\s*\+\s*nonroot/.test(productName)) return n + " DaYs Root + Nonroot";61 if (/fluo?rite\s*ff/.test(productName)) return n + " DAYs FluoRite FF";62 if (/\broot\b/.test(productName)) return n + " DaYs ROOT";63 if (/all\s*colou?rs\s*mix/.test(productName)) return n + " DaYs All Colours Mix";64 if (/\bbasic\b/.test(productName)) return n + " DaYs Basic";65 if (/\bpro\b/.test(productName)) return n + " DaYs PRO";66 if (/\bsafe\b/.test(productName)) return n + " DaYs SAFE";67 if (/\bbrutal\b/.test(productName)) return n + " DaYs BRUTAL";68 if (/\bbrutal\b/.test(productName)) return n + " DaYs";69 70 // Hours/minutes are preserved exactly; no existing API duration is removed.71 var gh = raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(hour|hours)$/i);72 if (gh) return gh[1] + " Hours";73 var gm = raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(minute|minutes)$/i);74 if (gm) return gm[1] + (Number(gm[1]) === 1 ? " Minute" : " Minutes");75 76 return raw || n + " Days";77}78 79 80try {81 var userId = user.telegramid;82 var buyQrMessageId = (request && request.message && request.message.message_id) ||83 Bot.getProperty("buy_qr_msg_id_" + userId) || User.getProperty("buy_qr_msg_id_" + userId) || null;84 85 // โ
CRITICAL FIX: Proper atomic duplicate-payment prevention86 var utrFromContent = null;87 88 // Parse content to get UTR early89 if (content) {90 var res = (typeof content === "object") ? content : JSON.parse(content);91 92 // Gram UPI Gateway confirms payment with status:true and data.status="PAID".93 if (res && res.data && res.data.utr) {94 utrFromContent = res.data.utr;95 }96 }97 98 // ๐ STEP 1: Check if payment already processed using UTR (most reliable identifier)99 if (utrFromContent && Bot.getProperty("paid_" + utrFromContent)) {100 // โ
FIX: Vanish the QR completely instead of leaving a stale "already used" caption behind101 try {102 Api.deleteMessage({ chat_id: chat.chatid, message_id: buyQrMessageId });103 } catch (e) {}104 105 try {106 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");107 User.setProperty("buy_qr_msg_id_" + userId, null, "string");108 } catch (e) {}109 110 if (request && request.id) {111 try {112 Api.answerCallbackQuery({113 callback_query_id: String(request.id),114 text: "โ
ALREADY CLAIMED โ
\nYe order pehle hi deliver ho chuka hai.",115 show_alert: true116 });117 } catch (e) {}118 }119 120 Api.sendMessage({121 chat_id: chat.chatid,122 text: "<blockquote><tg-emoji emoji-id='5330237710655306682'>โ
</tg-emoji> <b>ORDER ALREADY CLAIMED</b>\n<i>Ye payment pehle hi verify ho kar item deliver ho chuka hai. Apni keys 'All History' me check karein.</i></blockquote>",123 parse_mode: "HTML",124 reply_markup: JSON.stringify({125 inline_keyboard: [[126 { text: "๐ My Keys", callback_data: "/mykey", style: "primary" },127 { text: "๐ Shop Menu", callback_data: "/buy_hack", style: "success" }128 ]]129 })130 });131 return;132 }133 134 // ๐ STEP 2: Duplicate-click lock check135 var isChecking = User.getProperty("buy_verifying_lock_" + userId);136 if (isChecking) {137 if (request && request.id) {138 Api.answerCallbackQuery({139 callback_query_id: String(request.id),140 text: "โณ ALREADY CHECKING โ PLEASE WAIT...",141 show_alert: true142 });143 }144 return;145 }146 147 // ๐ STEP 3: SET LOCK IMMEDIATELY before any async operations148 User.setProperty("buy_verifying_lock_" + userId, true, "boolean");149 150 if (!content) {151 if (buyQrMessageId && !(typeof options !== "undefined" && options && options.is_background)) {152 try { Api.editMessageCaption({153 chat_id: chat.chatid, message_id: buyQrMessageId,154 caption: "<blockquote>โ ๏ธ <b>Payment status is not available yet.</b>\nAutomatic verification will retry shortly.</blockquote>", parse_mode: "HTML"155 }); } catch (editErr) {}156 }157 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");158 return;159 }160 161 var res = (typeof content === "object") ? content : JSON.parse(content);162 163 if (res.status === true && res.data && String(res.data.status || "").toUpperCase() === "PAID") {164 var expectedOrderId = String(User.getProperty("buy_pending_order_id") || "").trim();165 var reportedOrderId = String(res.data.order_id || "").trim();166 if (!expectedOrderId || !reportedOrderId || reportedOrderId !== expectedOrderId) {167 Api.editMessageCaption({168 chat_id: chat.chatid, message_id: buyQrMessageId,169 caption: "โ <b>Payment Order ID mismatch.</b> Ye payment is order ke saath match nahi karti.",170 parse_mode: "HTML"171 });172 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");173 return;174 }175 var utr = res.data.utr || res.data.transaction_id || res.data.txn_id;176 var expectedBuyAmount = Number(User.getProperty("buy_expected_amount") || User.getProperty("buy_needpay") || 0);177 var reportedBuyAmount = Number(res.data.amount || res.data.payable_amount || 0);178 if (expectedBuyAmount > 0 && (!reportedBuyAmount || Math.abs(reportedBuyAmount - expectedBuyAmount) > 0.01)) {179 Api.editMessageCaption({180 chat_id: chat.chatid, message_id: buyQrMessageId,181 caption: "โ <b>Amount mismatch.</b> Expected โน" + expectedBuyAmount.toFixed(2) + ", Gram UPI Gateway reported โน" + reportedBuyAmount.toFixed(2) + ".",182 parse_mode: "HTML"183 });184 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");185 return;186 }187 188 // Gateway success + UTR/transaction ID is required before any delivery.189 if (!utr) {190 Api.sendMessage({ chat_id: chat.chatid, text: "โ Payment response me valid UTR/transaction ID nahi mila.", parse_mode: "HTML" });191 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");192 return;193 }194 Bot.setProperty("verified_txn_" + utr, { order_id: expectedOrderId, amount: reportedBuyAmount, sender_name: res.data.payer || res.data.sender_name || "", payment_time_ist: res.data.payment_time || res.data.payment_time_ist || "N/A" }, "json");195 196 var isPaid = Bot.getProperty("paid_" + utr);197 198 if (isPaid) {199 // โ
FIX: Vanish the QR completely instead of leaving a stale "already used" caption behind200 try {201 Api.deleteMessage({ chat_id: chat.chatid, message_id: buyQrMessageId });202 } catch (e) {}203 204 try {205 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");206 User.setProperty("buy_qr_msg_id_" + userId, null, "string");207 } catch (e) {}208 209 if (request && request.id) {210 try {211 Api.answerCallbackQuery({212 callback_query_id: String(request.id),213 text: "โ
ALREADY CLAIMED โ
\nYe order pehle hi deliver ho chuka hai.",214 show_alert: true215 });216 } catch (e) {}217 }218 219 Api.sendMessage({220 chat_id: chat.chatid,221 text: "<blockquote><tg-emoji emoji-id='5330237710655306682'>โ
</tg-emoji> <b>ORDER ALREADY CLAIMED</b>\n<i>Ye payment pehle hi verify ho kar item deliver ho chuka hai. Apni keys 'All History' me check karein.</i></blockquote>",222 parse_mode: "HTML",223 reply_markup: JSON.stringify({224 inline_keyboard: [[225 { text: "๐ My Keys", callback_data: "/mykey", style: "primary" },226 { text: "๐ Shop Menu", callback_data: "/buy_hack", style: "success" }227 ]]228 })229 });230 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");231 return;232 }233 234 // โ
IMMEDIATELY mark as paid BEFORE any async API calls to prevent race condition235 Bot.setProperty("paid_" + utr, true, "boolean");236 Bot.setProperty("paid_order_" + expectedOrderId, true, "boolean");237 try { Bot.clearRunAfter({ label: "gram_buy_verify_" + expectedOrderId }); } catch (clearVerifyErr) {}238 239 if (buyQrMessageId) Api.editMessageCaption({240 chat_id: chat.chatid, message_id: buyQrMessageId,241 caption: "<tg-emoji emoji-id='6192822213486321961'>๐</tg-emoji> <b>Payment verified! Delivering your key...</b>",242 parse_mode: "HTML"243 });244 245 // โ
FIX: Detect which purchase pipeline this QR payment belongs to.246 // "ffid" = local stock-based FF ID item (set by /execute_id_buy on low balance)247 // default/"plan" = original plan-based product via external xyzcheats API248 var flowType = User.getProperty("buy_flow_type") || "plan";249 250 if (flowType === "ffid") {251 // =========================================================252 // ๐ฎ FF ID STOCK DELIVERY (after successful QR payment)253 // =========================================================254 try {255 var rawType = User.getProperty("buy_ffid_rawtype") || "";256 var isResellerFlow = User.getProperty("buy_ffid_is_reseller") === true;257 var finalCost = Number(User.getProperty("buy_price") || 0);258 var displayTypeName = User.getProperty("buy_prod_name") || rawType;259 260 var stockData = [];261 var isDynamicCategory = false;262 var isGeneralCategory = false;263 var selectedCat = null;264 265 var fbCategories = Bot.getProperty("fb_categories") || [];266 if (!Array.isArray(fbCategories)) { fbCategories = []; }267 268 if (rawType.indexOf("fb_") === 0) {269 isDynamicCategory = true;270 var targetCatId = rawType.replace("fb_", "").trim();271 for (var i = 0; i < fbCategories.length; i++) {272 if (fbCategories[i].id === targetCatId) { selectedCat = fbCategories[i]; break; }273 }274 if (selectedCat) { stockData = selectedCat.stock_list || []; }275 } else if (rawType === "fb" || rawType === "google") {276 stockData = Bot.getProperty("ff_stock_" + rawType) || [];277 } else {278 isGeneralCategory = true;279 var categoriesFF = Bot.getProperty("ff_categories") || {};280 selectedCat = categoriesFF[rawType];281 if (selectedCat) {282 var fallbackStock = Bot.getProperty("ff_stock_" + rawType) || [];283 stockData = (selectedCat.stock_list && selectedCat.stock_list.length > 0) ? selectedCat.stock_list : fallbackStock;284 }285 }286 287 if (!stockData || stockData.length === 0) {288 Api.editMessageCaption({289 chat_id: chat.chatid, message_id: buyQrMessageId,290 caption: "โ ๏ธ Payment received but item went out of stock. Contact admin with UTR: " + utr,291 parse_mode: "HTML"292 });293 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");294 return;295 }296 297 var accountExtracted = stockData.shift();298 299 if (isDynamicCategory && selectedCat) {300 selectedCat.stock_list = stockData;301 Bot.setProperty("fb_categories", fbCategories, "json");302 } else if (isGeneralCategory && selectedCat) {303 selectedCat.stock_list = stockData;304 var categoriesFF2 = Bot.getProperty("ff_categories") || {};305 categoriesFF2[rawType] = selectedCat;306 Bot.setProperty("ff_categories", categoriesFF2, "json");307 Bot.setProperty("ff_stock_" + rawType, stockData, "json");308 } else {309 Bot.setProperty("ff_stock_" + rawType, stockData, "json");310 }311 312 var fullRawString = String(accountExtracted || "").trim();313 var emailData = fullRawString;314 var passwordData = "No Password Found";315 316 if (fullRawString.indexOf("|") !== -1) {317 var lastPipeIndex = fullRawString.lastIndexOf("|");318 var firstPart = fullRawString.substring(0, lastPipeIndex).trim();319 var secondPart = fullRawString.substring(lastPipeIndex + 1).trim();320 321 if (firstPart.indexOf(" ") !== -1) {322 var spaceParts = firstPart.split(" ");323 emailData = spaceParts[spaceParts.length - 1].trim();324 } else {325 emailData = firstPart;326 }327 passwordData = secondPart;328 }329 330 var purchasedKeys = User.getProperty("my_purchased_keys") || [];331 if (!Array.isArray(purchasedKeys)) { purchasedKeys = []; }332 var currentDate = new Date().toLocaleDateString('en-IN', { timeZone: "Asia/Kolkata" });333 purchasedKeys.push({334 productName: displayTypeName,335 cost: finalCost.toString(),336 key: emailData + (passwordData !== "No Password Found" ? " | " + passwordData : ""),337 days: "Permanent",338 date: currentDate339 });340 User.setProperty("my_purchased_keys", purchasedKeys, "json");341 342 var deliveryText =343 "โโโโโโโโโโโโโโโโโโโโโโโโโโ\n" +344 "โ โค๏ธโ๐ฅ <b>PURCHASE SUCCESSFUL!</b> โค๏ธโ๐ฅ โ\n" +345 "โโโโโโโโโโโโโโโโโโโโโโโโโโ\n\n" +346 "๐ฆ <b>Item:</b> <code>" + displayTypeName + "</code>\n" +347 "๐ฐ <b>Paid:</b> <code>โน" + finalCost + "</code> " + (isResellerFlow ? "<b>(Reseller)</b>" : "") + "\n" +348 "โโโโโโโโโโโโโโโโโโโโโโโโโโ\n" +349 "๐ค <b>ACCOUNT DETAILS:</b>\n\n" +350 "๐ <b>Email:</b> <code>" + emailData + "</code>\n" +351 "๐ <b>Password:</b> <code>" + passwordData + "</code>\n" +352 "โโโโโโโโโโโโโโโโโโโโโโโโโโ\n" +353 "โ ๏ธ <i>Copy details instantly.</i>";354 355 Api.sendMessage({356 chat_id: chat.chatid,357 text: deliveryText,358 parse_mode: "HTML"359 });360 361 var adminLogChannel = "7839151435";362 var adminNotificationMsg =363 "<blockquote>โ ๏ธ <b>NEW ORDER ALERT (QR)</b>" + (isResellerFlow ? " [RESELLER]" : "") + "</blockquote>\n" +364 "๐ค <b>User:</b> <a href='tg://user?id=" + userId + "'>" + user.first_name + "</a> (<code>" + userId + "</code>)\n" +365 "๐ฆ <b>Item:</b> <code>" + displayTypeName + "</code>\n" +366 "๐ฐ <b>Revenue:</b> <code>โน" + finalCost + "</code>\n" +367 "โก <b>Stock Left:</b> <code>" + stockData.length + " units</code>\n\n" +368 "๐ฅ <b>ACCOUNT DETAILS:</b>\n" +369 "โ <b>Email:</b> <code>" + emailData + "</code>\n" +370 "โ <b>Password:</b> <code>" + passwordData + "</code>";371 372 Api.sendMessage({373 chat_id: adminLogChannel,374 text: adminNotificationMsg,375 parse_mode: "HTML"376 });377 378 // Cleanup all buy_ state for this order379 User.setProperty("buy_flow_type", null, "string");380 User.setProperty("buy_ffid_rawtype", null, "string");381 User.setProperty("buy_ffid_is_reseller", null, "boolean");382 User.setProperty("buy_price", null, "number");383 User.setProperty("buy_needpay", null, "number");384 User.setProperty("buy_prod_name", null, "string");385 User.setProperty("buy_plan_unit", null, "string");386 User.setProperty("buy_plan_name_on_website", null, "string");387 Bot.setProperty("pay_order_amount_" + expectedOrderId, null, "number");388 User.setProperty("pay_order_amount_" + expectedOrderId, null, "number");389 User.setProperty("buy_pending_order_id", null);390 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");391 User.setProperty("buy_qr_msg_id_" + userId, null, "string");392 Bot.setProperty("buy_qr_caption_" + userId, null, "string");393 User.setProperty("buy_qr_caption_" + userId, null, "string");394 Bot.setProperty("buy_qr_buttons_" + userId, null, "string");395 User.setProperty("buy_qr_buttons_" + userId, null, "string");396 397 } catch (ffErr) {398 Api.editMessageCaption({399 chat_id: chat.chatid, message_id: buyQrMessageId,400 caption: "โ ๏ธ Delivery error. Contact admin with UTR: " + utr + " | Error: " + ffErr.message,401 parse_mode: "HTML"402 });403 }404 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");405 return;406 }407 408 // =========================================================409 // ๐ฆ ORIGINAL PLAN-BASED DELIVERY (external xyzcheats API)410 // =========================================================411 var prodIdx = User.getProperty("buy_prod_idx");412 var planIdx = User.getProperty("buy_plan_idx");413 var productList = Bot.getProperty("stored_products") || [];414 var product = productList[prodIdx];415 var plan = product && product.plans ? product.plans[planIdx] : null;416 417 if (!product || !plan) {418 Api.editMessageCaption({419 chat_id: chat.chatid, message_id: buyQrMessageId,420 caption: "โ ๏ธ Payment received but product data missing. Contact admin with UTR: " + utr,421 parse_mode: "HTML"422 });423 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");424 return;425 }426 427 // =========================================================428 // ๐ฆ MANUAL STOCK FIRST FOR PAID PLAN ORDERS429 // If admin already added a key with /addstock, deliver that key here430 // instead of trying to generate/fetch another key from the website API.431 // The verified QR amount is first credited to the wallet temporarily;432 // /confirm_buyitem then performs the normal full-price deduction and433 // manual-stock delivery using the existing purchase path.434 // =========================================================435 try {436 var pDaysManual = String(User.getProperty("buy_plan_days") || plan.days || "").replace(/[^0-9.]/g, "").trim();437 var pUnitManual = User.getProperty("buy_plan_unit") || plan.unit || "day";438 var prodSlugManual = String(product.name || "").trim().toUpperCase().replace(/[^A-Z0-9_-]/g, "_");439 var manualStorageKey = "manual_keys_" + prodSlugManual + "_" + pDaysManual + "_" + pUnitManual;440 var legacyManualKey = "manual_keys_" + String(product.name || "").trim().toUpperCase() + "_" + pDaysManual;441 var backupManualKey = "stock_" + String(product.name || "").trim() + "_" + pDaysManual + "_Day";442 var manualCheckStock = Bot.getProperty(manualStorageKey);443 444 if ((!manualCheckStock || (Array.isArray(manualCheckStock) && manualCheckStock.length === 0)) &&445 pUnitManual === "day" && legacyManualKey !== manualStorageKey) {446 manualCheckStock = Bot.getProperty(legacyManualKey);447 }448 if (!manualCheckStock || (Array.isArray(manualCheckStock) && manualCheckStock.length === 0)) {449 manualCheckStock = Bot.getProperty(backupManualKey);450 }451 if (typeof manualCheckStock === "string" && manualCheckStock.trim() !== "") {452 try { manualCheckStock = JSON.parse(manualCheckStock); }453 catch (eStock) { manualCheckStock = manualCheckStock.split("\n").map(function(k){ return k.trim(); }).filter(Boolean); }454 }455 456 if (Array.isArray(manualCheckStock) && manualCheckStock.length > 0) {457 var verifiedCredit = Number(addedAmount || 0);458 if (!(verifiedCredit > 0)) throw new Error("Verified payment amount is invalid");459 460 // Credit only the verified QR payment; existing wallet balance stays intact.461 try { Libs.ResourcesLib.userRes("balance").add(verifiedCredit); } catch (eBal) {}462 463 User.setProperty("buy_manual_stock_paid", true, "boolean");464 Bot.run({465 command: "/confirm_buyitem",466 options: { params: String(prodIdx) + " " + String(planIdx) }467 });468 469 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");470 return;471 }472 } catch (manualFlowErr) {473 // If manual-stock handoff fails, continue with the existing website/API flow.474 }475 476 // โ
PID is plan-level: Add Plan stores the API PID on the selected plan.477 // Product itself no longer needs a PID.478 var webProductId = String((plan && (plan.pid || plan.product_id || plan.variant_id)) || "").trim();479 if (!webProductId) {480 Api.sendMessage({ chat_id: chat.chatid, text: "โ ๏ธ Is plan ka PID set nahi hai. Admin ko Add Plan me PID number add karna hoga.", parse_mode: "HTML" });481 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");482 return;483 }484 var cleanPlanDays = User.getProperty("buy_plan_days") || String(plan.days);485 var planUnit = User.getProperty("buy_plan_unit") || plan.unit || "day";486 var prodNameLower = String(product.name).toLowerCase();487 var durationParam = resolveApiDuration(plan, cleanPlanDays, planUnit, product && product.name);488 489 // ๐ Use configured multi-API system instead of a hardcoded API.490 var apiRegistry = Bot.getProperty("api_registry") || {};491 var activeApiId = Bot.getProperty("active_reseller_api") || "";492 var selectedApi = activeApiId ? apiRegistry[activeApiId] : null;493 if (!selectedApi) {494 selectedApi = null;495 }496 if (!selectedApi) {497 Bot.sendMessage("โ No reseller API configured. Admin ko /apiadd se apna online API add karke /apiset se active karna hoga.");498 return;499 }500 if (selectedApi.enabled === false) {501 Bot.sendMessage("โ Selected API is disabled. Admin ko /apiset se active API select karna hoga.");502 return;503 }504 var variantId = String((plan && (plan.pid || plan.product_id || plan.variant_id || plan.variantId)) || "").trim();505 if (!variantId) {506 Api.sendMessage({ chat_id: chat.chatid, text: "โ ๏ธ Is plan ka PID set nahi hai. Admin ko Add Plan me PID number add karna hoga.", parse_mode: "HTML" });507 return;508 }509 var postFields = { api_key:selectedApi.api_key || "", action:"buy", variant_id:variantId, quantity:1, product_id:webProductId, duration:durationParam };510 if (selectedApi.policy) postFields.policy = String(selectedApi.policy);511 if (selectedApi.side) postFields.side = String(selectedApi.side);512 if (selectedApi.user_number) postFields.user_number = String(selectedApi.user_number);513 var savedAndroidId = User.getProperty("android_id") || User.getProperty("android_id_" + userId) || Bot.getProperty("android_id_" + userId) || "";514 if (selectedApi.android_required && !savedAndroidId) {515 Bot.sendMessage("โ ๏ธ Android ID required for this API/product.");516 return;517 }518 if (savedAndroidId) postFields.android_id = String(savedAndroidId);519 var postFieldsString = Object.keys(postFields).map(function(k){ return encodeURIComponent(k) + "=" + encodeURIComponent(postFields[k]); }).join("&");520 User.setProperty("last_pending_api_id", String(selectedApi.id || activeApiId || ""), "string");521 522 User.setProperty("last_pending_price", User.getProperty("buy_price"), "number");523 User.setProperty("last_pending_prod_id", webProductId, "string");524 User.setProperty("last_pending_prod_name", String(product.name).trim(), "string");525 User.setProperty("last_pending_plan_days", cleanPlanDays, "string");526 User.setProperty("last_pending_plan_unit", planUnit, "string");527 528 HTTP.post({529 url: selectedApi.url,530 body: postFieldsString,531 headers: (function(){ var h={"Content-Type":"application/x-www-form-urlencoded"}; if(selectedApi.master_key) h["x-master-key"]=selectedApi.master_key; if(selectedApi.policy) h["x-policy"]=String(selectedApi.policy); if(selectedApi.side) h["x-side"]=String(selectedApi.side); if(selectedApi.user_number) h["x-user-number"]=String(selectedApi.user_number); return h; })(),532 success: "/onWebKeyReceive",533 error: "/onWebKeyError"534 });535 536 User.setProperty("buy_pending_order_id", null);537 User.setProperty("buy_prod_idx", null);538 User.setProperty("buy_plan_idx", null);539 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");540 User.setProperty("buy_qr_msg_id_" + userId, null, "string");541 Bot.setProperty("buy_qr_caption_" + userId, null, "string");542 User.setProperty("buy_qr_caption_" + userId, null, "string");543 Bot.setProperty("buy_qr_buttons_" + userId, null, "string");544 User.setProperty("buy_qr_buttons_" + userId, null, "string");545 546 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");547 548 } else {549 // โ Payment not found โ restore original QR caption/buttons, then show dismissible notice550 try {551 var origCaption = Bot.getProperty("buy_qr_caption_" + userId) || User.getProperty("buy_qr_caption_" + userId);552 var origButtons = Bot.getProperty("buy_qr_buttons_" + userId) || User.getProperty("buy_qr_buttons_" + userId);553 554 if (origCaption) {555 Api.editMessageCaption({556 chat_id: chat.chatid,557 message_id: buyQrMessageId,558 caption: origCaption,559 parse_mode: "HTML",560 reply_markup: origButtons ? origButtons : undefined561 });562 }563 } catch (e) {}564 565 if (request && request.id) {566 Api.answerCallbackQuery({567 callback_query_id: String(request.id),568 text: "โ PAYMENT NOT FOUND โ\nPlease complete the payment first, then tap again.",569 show_alert: true570 });571 }572 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");573 }574 575} catch (err) {576 try {577 User.setProperty("buy_verifying_lock_" + user.telegramid, false, "boolean");578 } catch (e) {}579 Bot.sendMessage("โ ๏ธ <b>Verification Exception:</b> " + err.message, { parse_mode: "HTML" });580}