devbro468/Dev_x_store_botPublic · Bot Template
AIThis bot operates a digital storefront (DEV X STORE) selling subscription-based products — likely game hacks, accounts, or access keys — categorized by platform (Android Root, Non-Root, iPhone). It features a reseller program with discounted pricing, a dual-currency wallet (INR balance + Telegram Stars/XTR), and a full admin/co-admin panel for managing products, plans, per-plan pricing, stock (keys/accounts), coupons, and API endpoints. Purchases flow through a plan selection screen offering wallet payment, Stars invoices (sendInvoice with XTR currency), and coupon application. Successful Stars payments are handled via successful_payment webhook, crediting wallet or delivering keys directly. Admin tools include user listing with chunked messaging, stock viewing/deletion with inline keyboards, co-admin management, and API registry updates. The bot registers users on first interaction and
commands/_onBuyCheck.js
javascript · 419 lines
1/**#command2name: /onBuyCheck3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12function resolveApiDuration(plan, cleanPlanDays, planUnit) {13 var raw = String((plan && (plan.api_duration || plan.name_on_website || plan.durationDisplay || plan.name || plan.title)) || "").replace(/\s+/g, " ").trim();14 var canonical = ["1 DaYS NONROOT","House","1 DaYs","15 DaYs All Colours Mix","30 DaYs PRO","1 DaYs Basic","1 Year Ios Esign Gbox Certificate","1 DaYs Root + Nonroot","7 DaYS PC AIMKILL","30 Day Pc Modmenu x86","3 DaYs SAFE","3 DaYs BRUTAL"];15 for (var i=0;i<canonical.length;i++) if (raw.toLowerCase() === canonical[i].toLowerCase()) return canonical[i];16 var gd=raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(day|days)$/i);17 if(gd) return Number(gd[1])===1 ? "1 DaYs" : gd[1]+" Days";18 // HOURS: preserve the exact duration entered by admin/API.19 // Examples: "1 Hours", "2 Hours", "12 Hours" all remain unchanged.20 var gh=raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(hour|hours)$/i);21 if(gh) return raw;22 var gm=raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(minute|minutes)$/i);23 if(gm) return gm[1]+(Number(gm[1])===1?" Minute":" Minutes");24 return raw || (Number(cleanPlanDays||"1")===1 ? "1 DaYs" : String(cleanPlanDays)+" Days");25}26 27 28try {29 var userId = user.telegramid;30 31 // ✅ CRITICAL FIX: Proper atomic duplicate-payment prevention32 var utrFromContent = null;33 34 // Parse content to get UTR early35 if (content) {36 var res = (typeof content === "object") ? content : JSON.parse(content);37 if (res && res.data && res.data.utr) {38 utrFromContent = res.data.utr;39 }40 }41 42 // 🛑 STEP 1: Check if payment already processed using UTR (most reliable identifier)43 if (utrFromContent && Bot.getProperty("paid_" + utrFromContent)) {44 // ✅ FIX: Vanish the QR completely instead of leaving a stale "already used" caption behind45 try {46 Api.deleteMessage({ chat_id: chat.chatid, message_id: request.message.message_id });47 } catch (e) {}48 49 try {50 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");51 User.setProperty("buy_qr_msg_id_" + userId, null, "string");52 } catch (e) {}53 54 if (request && request.id) {55 try {56 Api.answerCallbackQuery({57 callback_query_id: String(request.id),58 text: "✅ ALREADY CLAIMED ✅\nYe order pehle hi deliver ho chuka hai.",59 show_alert: true60 });61 } catch (e) {}62 }63 64 Api.sendMessage({65 chat_id: chat.chatid,66 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>",67 parse_mode: "HTML",68 reply_markup: JSON.stringify({69 inline_keyboard: [[70 { text: "📜 My Keys", callback_data: "/mykey", style: "primary" },71 { text: "🛒 Shop Menu", callback_data: "/buy_hack", style: "success" }72 ]]73 })74 });75 return;76 }77 78 // 🛑 STEP 2: Duplicate-click lock check79 var isChecking = User.getProperty("buy_verifying_lock_" + userId);80 if (isChecking) {81 if (request && request.id) {82 Api.answerCallbackQuery({83 callback_query_id: String(request.id),84 text: "⏳ ALREADY CHECKING — PLEASE WAIT...",85 show_alert: true86 });87 }88 return;89 }90 91 // 🛑 STEP 3: SET LOCK IMMEDIATELY before any async operations92 User.setProperty("buy_verifying_lock_" + userId, true, "boolean");93 94 if (!content) {95 Api.editMessageCaption({96 chat_id: chat.chatid, message_id: request.message.message_id,97 caption: "<blockquote>⚠️ <b>Server didn't respond.</b>\nClick 'I have paid' again.</blockquote>", parse_mode: "HTML"98 });99 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");100 return;101 }102 103 var res = (typeof content === "object") ? content : JSON.parse(content);104 105 if (res.status === "success" && res.data) {106 var utr = res.data.utr;107 var isPaid = Bot.getProperty("paid_" + utr);108 109 if (isPaid) {110 // ✅ FIX: Vanish the QR completely instead of leaving a stale "already used" caption behind111 try {112 Api.deleteMessage({ chat_id: chat.chatid, message_id: request.message.message_id });113 } catch (e) {}114 115 try {116 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");117 User.setProperty("buy_qr_msg_id_" + userId, null, "string");118 } catch (e) {}119 120 if (request && request.id) {121 try {122 Api.answerCallbackQuery({123 callback_query_id: String(request.id),124 text: "✅ ALREADY CLAIMED ✅\nYe order pehle hi deliver ho chuka hai.",125 show_alert: true126 });127 } catch (e) {}128 }129 130 Api.sendMessage({131 chat_id: chat.chatid,132 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>",133 parse_mode: "HTML",134 reply_markup: JSON.stringify({135 inline_keyboard: [[136 { text: "📜 My Keys", callback_data: "/mykey", style: "primary" },137 { text: "🛒 Shop Menu", callback_data: "/buy_hack", style: "success" }138 ]]139 })140 });141 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");142 return;143 }144 145 // ✅ IMMEDIATELY mark as paid BEFORE any async API calls to prevent race condition146 Bot.setProperty("paid_" + utr, true, "boolean");147 148 Api.editMessageCaption({149 chat_id: chat.chatid, message_id: request.message.message_id,150 caption: "<tg-emoji emoji-id='6192822213486321961'>🔄</tg-emoji> <b>Payment verified! Delivering your key...</b>",151 parse_mode: "HTML"152 });153 154 // ✅ FIX: Detect which purchase pipeline this QR payment belongs to.155 // "ffid" = local stock-based FF ID item (set by /execute_id_buy on low balance)156 // default/"plan" = original plan-based product via external xyzcheats API157 var flowType = User.getProperty("buy_flow_type") || "plan";158 159 if (flowType === "ffid") {160 // =========================================================161 // 🎮 FF ID STOCK DELIVERY (after successful QR payment)162 // =========================================================163 try {164 var rawType = User.getProperty("buy_ffid_rawtype") || "";165 var isResellerFlow = User.getProperty("buy_ffid_is_reseller") === true;166 var finalCost = Number(User.getProperty("buy_price") || 0);167 var displayTypeName = User.getProperty("buy_prod_name") || rawType;168 169 var stockData = [];170 var isDynamicCategory = false;171 var isGeneralCategory = false;172 var selectedCat = null;173 174 var fbCategories = Bot.getProperty("fb_categories") || [];175 if (!Array.isArray(fbCategories)) { fbCategories = []; }176 177 if (rawType.indexOf("fb_") === 0) {178 isDynamicCategory = true;179 var targetCatId = rawType.replace("fb_", "").trim();180 for (var i = 0; i < fbCategories.length; i++) {181 if (fbCategories[i].id === targetCatId) { selectedCat = fbCategories[i]; break; }182 }183 if (selectedCat) { stockData = selectedCat.stock_list || []; }184 } else if (rawType === "fb" || rawType === "google") {185 stockData = Bot.getProperty("ff_stock_" + rawType) || [];186 } else {187 isGeneralCategory = true;188 var categoriesFF = Bot.getProperty("ff_categories") || {};189 selectedCat = categoriesFF[rawType];190 if (selectedCat) {191 var fallbackStock = Bot.getProperty("ff_stock_" + rawType) || [];192 stockData = (selectedCat.stock_list && selectedCat.stock_list.length > 0) ? selectedCat.stock_list : fallbackStock;193 }194 }195 196 if (!stockData || stockData.length === 0) {197 Api.editMessageCaption({198 chat_id: chat.chatid, message_id: request.message.message_id,199 caption: "⚠️ Payment received but item went out of stock. Contact admin with UTR: " + utr,200 parse_mode: "HTML"201 });202 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");203 return;204 }205 206 var accountExtracted = stockData.shift();207 208 if (isDynamicCategory && selectedCat) {209 selectedCat.stock_list = stockData;210 Bot.setProperty("fb_categories", fbCategories, "json");211 } else if (isGeneralCategory && selectedCat) {212 selectedCat.stock_list = stockData;213 var categoriesFF2 = Bot.getProperty("ff_categories") || {};214 categoriesFF2[rawType] = selectedCat;215 Bot.setProperty("ff_categories", categoriesFF2, "json");216 Bot.setProperty("ff_stock_" + rawType, stockData, "json");217 } else {218 Bot.setProperty("ff_stock_" + rawType, stockData, "json");219 }220 221 var fullRawString = String(accountExtracted || "").trim();222 var emailData = fullRawString;223 var passwordData = "No Password Found";224 225 if (fullRawString.indexOf("|") !== -1) {226 var lastPipeIndex = fullRawString.lastIndexOf("|");227 var firstPart = fullRawString.substring(0, lastPipeIndex).trim();228 var secondPart = fullRawString.substring(lastPipeIndex + 1).trim();229 230 if (firstPart.indexOf(" ") !== -1) {231 var spaceParts = firstPart.split(" ");232 emailData = spaceParts[spaceParts.length - 1].trim();233 } else {234 emailData = firstPart;235 }236 passwordData = secondPart;237 }238 239 var purchasedKeys = User.getProperty("my_purchased_keys") || [];240 if (!Array.isArray(purchasedKeys)) { purchasedKeys = []; }241 var currentDate = new Date().toLocaleDateString('en-IN', { timeZone: "Asia/Kolkata" });242 purchasedKeys.push({243 productName: displayTypeName,244 cost: finalCost.toString(),245 key: emailData + (passwordData !== "No Password Found" ? " | " + passwordData : ""),246 days: "Permanent",247 date: currentDate248 });249 User.setProperty("my_purchased_keys", purchasedKeys, "json");250 251 var deliveryText =252 "┏━━━━━━━━━━━━━━━━━━━━━━━━┓\n" +253 "┃ ❤️🔥 <b>PURCHASE SUCCESSFUL!</b> ❤️🔥 ┃\n" +254 "┗━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n" +255 "📦 <b>Item:</b> <code>" + displayTypeName + "</code>\n" +256 "💰 <b>Paid:</b> <code>₹" + finalCost + "</code> " + (isResellerFlow ? "<b>(Reseller)</b>" : "") + "\n" +257 "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +258 "👤 <b>ACCOUNT DETAILS:</b>\n\n" +259 "🚀 <b>Email:</b> <code>" + emailData + "</code>\n" +260 "🔒 <b>Password:</b> <code>" + passwordData + "</code>\n" +261 "━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +262 "⚠️ <i>Copy details instantly.</i>";263 264 Api.sendMessage({265 chat_id: chat.chatid,266 text: deliveryText,267 parse_mode: "HTML"268 });269 270 var adminLogChannel = "8875810358";271 var adminNotificationMsg =272 "<blockquote>⚠️ <b>NEW ORDER ALERT (QR)</b>" + (isResellerFlow ? " [RESELLER]" : "") + "</blockquote>\n" +273 "👤 <b>User:</b> <a href='tg://user?id=" + userId + "'>" + user.first_name + "</a> (<code>" + userId + "</code>)\n" +274 "📦 <b>Item:</b> <code>" + displayTypeName + "</code>\n" +275 "💰 <b>Revenue:</b> <code>₹" + finalCost + "</code>\n" +276 "⚡ <b>Stock Left:</b> <code>" + stockData.length + " units</code>\n\n" +277 "🖥 <b>ACCOUNT DETAILS:</b>\n" +278 "➔ <b>Email:</b> <code>" + emailData + "</code>\n" +279 "➔ <b>Password:</b> <code>" + passwordData + "</code>";280 281 Api.sendMessage({282 chat_id: adminLogChannel,283 text: adminNotificationMsg,284 parse_mode: "HTML"285 });286 287 // Cleanup all buy_ state for this order288 User.setProperty("buy_flow_type", null, "string");289 User.setProperty("buy_ffid_rawtype", null, "string");290 User.setProperty("buy_ffid_is_reseller", null, "boolean");291 User.setProperty("buy_price", null, "number");292 User.setProperty("buy_needpay", null, "number");293 User.setProperty("buy_prod_name", null, "string");294 User.setProperty("buy_plan_unit", null, "string");295 User.setProperty("buy_plan_name_on_website", null, "string");296 User.setProperty("buy_pending_order_id", null);297 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");298 User.setProperty("buy_qr_msg_id_" + userId, null, "string");299 Bot.setProperty("buy_qr_caption_" + userId, null, "string");300 User.setProperty("buy_qr_caption_" + userId, null, "string");301 Bot.setProperty("buy_qr_buttons_" + userId, null, "string");302 User.setProperty("buy_qr_buttons_" + userId, null, "string");303 304 } catch (ffErr) {305 Api.editMessageCaption({306 chat_id: chat.chatid, message_id: request.message.message_id,307 caption: "⚠️ Delivery error. Contact admin with UTR: " + utr + " | Error: " + ffErr.message,308 parse_mode: "HTML"309 });310 }311 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");312 return;313 }314 315 // =========================================================316 // 📦 ORIGINAL PLAN-BASED DELIVERY (external xyzcheats API)317 // =========================================================318 var prodIdx = User.getProperty("buy_prod_idx");319 var planIdx = User.getProperty("buy_plan_idx");320 var productList = Bot.getProperty("stored_products") || [];321 var product = productList[prodIdx];322 var plan = product && product.plans ? product.plans[planIdx] : null;323 324 if (!product || !plan) {325 Api.editMessageCaption({326 chat_id: chat.chatid, message_id: request.message.message_id,327 caption: "⚠️ Payment received but product data missing. Contact admin with UTR: " + utr,328 parse_mode: "HTML"329 });330 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");331 return;332 }333 334 var webProductId = String(product.id || "PID_ID").trim();335 var cleanPlanDays = User.getProperty("buy_plan_days") || String(plan.days);336 var planUnit = User.getProperty("buy_plan_unit") || plan.unit || "day";337 var prodNameLower = String(product.name).toLowerCase();338 var durationParam = resolveApiDuration(plan, cleanPlanDays, planUnit);339 340 // 🔌 Use configured multi-API system instead of a hardcoded API.341 var apiRegistry = Bot.getProperty("api_registry") || {};342 var activeApiId = Bot.getProperty("active_reseller_api") || "";343 var selectedApi = activeApiId ? apiRegistry[activeApiId] : null;344 if (!selectedApi) {345 selectedApi = { id:"default", url:"https://xyzcheats.com/api/reseller_v1.php", api_key:"a9b26aa6439ff7cd495d64cb47916cb2", master_key:"a7f3e8b2c9d1f4a6b8c2d5e9f1a3b6c8", android_required:false, enabled:true };346 }347 if (selectedApi.enabled === false) {348 Bot.sendMessage("❌ Selected API is disabled. Admin ko /apiset se active API select karna hoga.");349 return;350 }351 var postFields = { api_key:selectedApi.api_key || "", action:"buy", product_id:webProductId, duration:durationParam };352 var savedAndroidId = User.getProperty("android_id") || User.getProperty("android_id_" + userId) || Bot.getProperty("android_id_" + userId) || "";353 if (selectedApi.android_required && !savedAndroidId) {354 Bot.sendMessage("⚠️ Android ID required for this API/product.");355 return;356 }357 if (savedAndroidId) postFields.android_id = String(savedAndroidId);358 var postFieldsString = Object.keys(postFields).map(function(k){ return encodeURIComponent(k) + "=" + encodeURIComponent(postFields[k]); }).join("&");359 User.setProperty("last_pending_api_id", String(selectedApi.id || activeApiId || ""), "string");360 361 User.setProperty("last_pending_price", User.getProperty("buy_price"), "number");362 User.setProperty("last_pending_prod_id", webProductId, "string");363 User.setProperty("last_pending_prod_name", String(product.name).trim(), "string");364 User.setProperty("last_pending_plan_days", cleanPlanDays, "string");365 User.setProperty("last_pending_plan_unit", planUnit, "string");366 367 HTTP.post({368 url: selectedApi.url,369 body: postFieldsString,370 headers: (function(){ var h={"Content-Type":"application/x-www-form-urlencoded"}; if(selectedApi.master_key) h["x-master-key"]=selectedApi.master_key; return h; })(),371 success: "/onWebKeyReceive",372 error: "/onWebKeyError"373 });374 375 User.setProperty("buy_pending_order_id", null);376 User.setProperty("buy_prod_idx", null);377 User.setProperty("buy_plan_idx", null);378 Bot.setProperty("buy_qr_msg_id_" + userId, null, "string");379 User.setProperty("buy_qr_msg_id_" + userId, null, "string");380 Bot.setProperty("buy_qr_caption_" + userId, null, "string");381 User.setProperty("buy_qr_caption_" + userId, null, "string");382 Bot.setProperty("buy_qr_buttons_" + userId, null, "string");383 User.setProperty("buy_qr_buttons_" + userId, null, "string");384 385 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");386 387 } else {388 // ❌ Payment not found — restore original QR caption/buttons, then show dismissible notice389 try {390 var origCaption = Bot.getProperty("buy_qr_caption_" + userId) || User.getProperty("buy_qr_caption_" + userId);391 var origButtons = Bot.getProperty("buy_qr_buttons_" + userId) || User.getProperty("buy_qr_buttons_" + userId);392 393 if (origCaption) {394 Api.editMessageCaption({395 chat_id: chat.chatid,396 message_id: request.message.message_id,397 caption: origCaption,398 parse_mode: "HTML",399 reply_markup: origButtons ? origButtons : undefined400 });401 }402 } catch (e) {}403 404 if (request && request.id) {405 Api.answerCallbackQuery({406 callback_query_id: String(request.id),407 text: "❌ PAYMENT NOT FOUND ❌\nPlease complete the payment first, then tap again.",408 show_alert: true409 });410 }411 User.setProperty("buy_verifying_lock_" + userId, false, "boolean");412 }413 414} catch (err) {415 try {416 User.setProperty("buy_verifying_lock_" + user.telegramid, false, "boolean");417 } catch (e) {}418 Bot.sendMessage("⚠️ <b>Verification Exception:</b> " + err.message, { parse_mode: "HTML" });419}