/** * IAA插件SDK - 参考OceanOld实现模式 * 用于微信小游戏环境中的IAA功能接入 */ class IAA_SDK { constructor() { this.isInitialized = false; this.miniGameCommon = null; this.adDataCache = new Map(); // 缓存广告数据 this.recentScene = null; // 记录最近的广告场景 this.recentSceneTime = 0; // 记录最近场景的时间 this.config = { delayTime: 30000, // 延迟30秒请求预测 enableDebugLog: true }; this.callbacks = { onPredictionReceived: null, onError: null }; this.init(); } /** * 初始化IAA插件 */ init() { try { if (typeof requirePlugin !== 'undefined') { const createMiniGameCommon = requirePlugin('MiniGameCommon', { enableRequireHostModule: true, customEnv: { wx } }).default; this.miniGameCommon = createMiniGameCommon(); if (typeof this.miniGameCommon === 'undefined' || typeof this.miniGameCommon.canIUse === 'undefined') { this.log('IAA插件创建失败', 'error'); } else { this.isInitialized = true; this.log('IAA插件初始化成功'); } } else { this.log('requirePlugin不存在,可能不在微信环境', 'warn'); } } catch (e) { this.log('IAA插件初始化异常:', e, 'error'); } } /** * 设置配置参数 * @param {Object} config */ setConfig(config) { this.config = Object.assign(this.config, config); this.log('IAA配置更新:', this.config); } /** * 记录视频广告观看 * @param {string} scene 广告场景 * @param {Object} data 广告相关数据 */ videoAdd(data = {}) { let scene = 'default' try { this.log(`开始记录视频观看 - 场景: ${scene}, 数据:`, data); // 更新最近场景信息 this.recentScene = scene; this.recentSceneTime = Date.now(); // 持久化保存最近场景信息 this.saveRecentScene(); const today = this.getTodayKey(); const cacheKey = `${scene}_${today}`; // 获取或创建今日数据 let todayData = this.adDataCache.get(cacheKey) || { scene: scene, date: today, clickCount: 0, successCount: 0, lastAdTime: 0, data: data }; // 更新观看次数 todayData.successCount++; todayData.lastAdTime = Date.now(); todayData.data = data; // 更新数据 // 保存到缓存 this.adDataCache.set(cacheKey, todayData); this.log(`视频观看记录成功: ${scene}, 今日次数: ${todayData.successCount}, 今日点击: ${todayData.clickCount}`); // 每次观看完成后都延迟上报IAA setTimeout(() => { this.reportToIAA(scene, todayData); }, this.config.delayTime); // 持久化存储 this.saveToStorage(); } catch (e) { this.log('videoAdd异常:', e, 'error'); } } /** * 记录广告点击(在广告展示前调用) * @param {string} scene 广告场景 * @param {Object} data 广告相关数据 */ videoClick(data = {}) { var scene = 'default' try { const today = this.getTodayKey(); const cacheKey = `${scene}_${today}`; let todayData = this.adDataCache.get(cacheKey) || { scene: scene, date: today, clickCount: 0, successCount: 0, lastAdTime: 0, data: data }; todayData.clickCount++; this.adDataCache.set(cacheKey, todayData); this.log(`视频点击记录: ${scene}, 今日点击: ${todayData.clickCount}`); } catch (e) { this.log('videoClick异常:', e, 'error'); } } /** * 手动获取预测档位 * @param {string|null} scene 场景名称,如果不传或传null,则使用最近的场景 * @param {Function} callback 回调函数 */ getUserLabel(scene = null, callback = null) { if (!this.isInitialized) { this.log('IAA插件未初始化', 'error'); callback && callback({ success: false, error: 'IAA插件未初始化' }); return; } // 如果没有传scene,使用最近的场景 if (!scene || scene === 'default') { this.log(`没有指定场景,当前最近场景: ${this.recentScene}, 最近场景时间: ${this.recentSceneTime ? new Date(this.recentSceneTime).toLocaleString() : '无'}`); if (this.recentScene) { scene = this.recentScene; this.log(`使用最近的场景: ${scene}`); } else { // 如果没有最近场景,尝试从缓存中找一个有数据的场景 const availableScenes = this.getAllAvailableScenes(); this.log(`可用场景列表: ${availableScenes.join(', ')}`); if (availableScenes.length > 0) { scene = availableScenes[0]; this.log(`没有最近场景,使用第一个可用场景: ${scene}`); } else { scene = 'default'; this.log(`没有任何场景数据,使用默认场景: ${scene}`); } } } const today = this.getTodayKey(); const cacheKey = `${scene}_${today}`; let todayData = this.adDataCache.get(cacheKey); // 如果没有找到数据,创建一个基础的数据结构 if (!todayData) { this.log(`没有找到场景 ${scene} 的广告数据,创建基础数据结构`, 'warn'); todayData = { scene: scene, date: today, clickCount: 0, successCount: 0, lastAdTime: 0, data: {} }; // 保存到缓存 this.adDataCache.set(cacheKey, todayData); } this.log(`请求预测档位 - 场景: ${scene}, 点击次数: ${todayData.clickCount}, 成功次数: ${todayData.successCount}`); this.requestPrediction(scene, todayData, callback); } /** * 上报IAA数据(不获取预测结果) * @param {string} scene 场景 * @param {Object} adData 广告数据 */ reportToIAA(scene, adData) { if (!this.isInitialized) { this.log('IAA插件未初始化,跳过数据上报', 'warn'); return; } try { // 构建上报数据 const reportData = JSON.stringify({ "gift_scene": this.getGiftScene(scene), "gift_name": this.getGiftName(scene, adData.data), "gift_value": adData.clickCount, "gift_value_success": adData.successCount }); this.log('上报IAA数据:', { scene, reportData }); // 通过getUserLabel接口上报数据(但不处理返回结果) this.miniGameCommon.getUserLabel({ reportData: reportData, labelId: 'iaa_feature' }).then(() => { this.log('IAA数据上报成功:', scene); }).catch((error) => { this.log('IAA数据上报失败:', error, 'error'); }); } catch (e) { this.log('reportToIAA异常:', e, 'error'); } } /** * 请求IAA预测档位 * @param {string} scene 场景 * @param {Object} adData 广告数据 * @param {Function} callback 回调函数 */ requestPrediction(scene, adData, callback = null) { if (!this.isInitialized) { this.log('IAA插件未初始化,无法请求预测', 'error'); return; } try { // 构建上报数据 const reportData = JSON.stringify({ "gift_scene": this.getGiftScene(scene), "gift_name": this.getGiftName(scene, adData.data), "gift_value": adData.clickCount, "gift_value_success": adData.successCount }); this.log('开始请求IAA预测:', { scene, reportData }); // 调用IAA插件API this.miniGameCommon.getUserLabel({ reportData: reportData, labelId: 'iaa_feature' }).then((res) => { this.log('getUserLabel成功:', res); const result = { success: true, scene: scene, timestamp: Date.now(), encryptedData: res.encryptedData, iv: res.iv, cloudID: res.cloudID, rawData: res }; // 存储结果 this.savePredictionResult(scene, result); // 触发回调 if (callback) { callback(result); } else if (this.callbacks.onPredictionReceived) { this.callbacks.onPredictionReceived(result); } }).catch((error) => { this.log('getUserLabel失败:', error, 'error'); const errorResult = { success: false, scene: scene, error: error, timestamp: Date.now() }; if (callback) { callback(errorResult); } else if (this.callbacks.onError) { this.callbacks.onError(errorResult); } }); } catch (e) { this.log('requestPrediction异常:', e, 'error'); } } /** * 获取最新的预测结果 * @param {string} scene 场景名称 * @returns {Object|null} 预测结果 */ getLatestPrediction(scene = 'default') { try { const key = `iaa_prediction_${scene}`; const stored = wx.getStorageSync(key); return stored ? JSON.parse(stored) : null; } catch (e) { this.log('获取预测结果异常:', e, 'error'); return null; } } /** * 获取今日广告统计 * @param {string} scene 场景名称 * @returns {Object} 统计数据 */ getTodayAdStats(scene = 'default') { const today = this.getTodayKey(); const cacheKey = `${scene}_${today}`; return this.adDataCache.get(cacheKey) || { scene: scene, date: today, clickCount: 0, successCount: 0, lastAdTime: 0 }; } /** * 设置回调函数 * @param {string} type 回调类型:'prediction' 或 'error' * @param {Function} callback 回调函数 */ setCallback(type, callback) { if (type === 'prediction') { this.callbacks.onPredictionReceived = callback; } else if (type === 'error') { this.callbacks.onError = callback; } } /** * 获取最近的广告场景 * @returns {string|null} 最近的场景名称 */ getRecentScene() { return this.recentScene; } /** * 获取所有有数据的场景列表 * @returns {Array} 场景名称数组 */ getAllAvailableScenes() { const today = this.getTodayKey(); const scenes = []; this.adDataCache.forEach((value, key) => { if (key.endsWith(`_${today}`)) { const scene = key.replace(`_${today}`, ''); scenes.push(scene); } }); return scenes; } /** * 获取今日所有场景的统计信息 * @returns {Object} 所有场景的统计数据 */ getAllTodayStats() { const today = this.getTodayKey(); const stats = {}; this.adDataCache.forEach((value, key) => { if (key.endsWith(`_${today}`)) { const scene = key.replace(`_${today}`, ''); stats[scene] = { scene: scene, clickCount: value.clickCount, successCount: value.successCount, lastAdTime: value.lastAdTime }; } }); return stats; } /** * 调试方法:显示所有缓存的数据 */ debugShowAllData() { this.log('=== IAA SDK 缓存数据调试信息 ==='); this.log('插件初始化状态:', this.isInitialized); this.log('最近场景:', this.recentScene); this.log('最近场景时间:', this.recentSceneTime ? new Date(this.recentSceneTime).toLocaleString() : '无'); this.log('缓存数据数量:', this.adDataCache.size); this.log('可用场景:', this.getAllAvailableScenes()); this.log('今日统计:', this.getAllTodayStats()); if (this.adDataCache.size === 0) { this.log('缓存中没有任何数据'); } else { this.adDataCache.forEach((value, key) => { this.log(`缓存键: ${key}`, value); }); } this.log('=== 调试信息结束 ==='); } /** * 快速状态检查 */ quickStatus() { const status = { initialized: this.isInitialized, recentScene: this.recentScene, recentSceneTime: this.recentSceneTime, availableScenes: this.getAllAvailableScenes(), todayStats: this.getAllTodayStats() }; this.log('IAA SDK 快速状态:', status); return status; } // ============ 工具方法 ============ getTodayKey() { const now = new Date(); return `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; } getGiftScene(scene) { const sceneMap = { 'game_revive': '复活场景', 'get_power': '获取体力', 'game_use_prop': '游戏道具', 'unlock_theme': '解锁主题', 'signin_reward': '签到奖励', 'level_reward': '通关奖励', 'daily_reward': '每日奖励' }; return sceneMap[scene] || '其他场景'; } getGiftName(scene, data) { if (scene === 'game_revive') { return '复活道具'; } else if (scene === 'get_power') { return '体力道具'; } else if (scene === 'game_use_prop') { return data && data.propType ? `${data.propType}道具` : '通用道具'; } else if (scene === 'default'){ return data && data.type ? `${data.type}` : '其他视频'; } return '游戏道具'; } savePredictionResult(scene, result) { try { const key = `iaa_prediction_${scene}`; wx.setStorageSync(key, JSON.stringify(result)); } catch (e) { this.log('保存预测结果异常:', e, 'error'); } } saveToStorage() { try { const dataToSave = {}; this.adDataCache.forEach((value, key) => { dataToSave[key] = value; }); wx.setStorageSync('iaa_ad_cache', JSON.stringify(dataToSave)); } catch (e) { this.log('保存广告缓存异常:', e, 'warn'); } } loadFromStorage() { try { const stored = wx.getStorageSync('iaa_ad_cache'); if (stored) { const data = JSON.parse(stored); Object.keys(data).forEach(key => { this.adDataCache.set(key, data[key]); }); } } catch (e) { this.log('加载广告缓存异常:', e, 'warn'); } // 加载最近场景信息 this.loadRecentScene(); } saveRecentScene() { try { const recentSceneData = { scene: this.recentScene, time: this.recentSceneTime }; wx.setStorageSync('iaa_recent_scene', JSON.stringify(recentSceneData)); this.log(`保存最近场景: ${this.recentScene}`); } catch (e) { this.log('保存最近场景异常:', e, 'warn'); } } loadRecentScene() { try { const stored = wx.getStorageSync('iaa_recent_scene'); if (stored) { const recentSceneData = JSON.parse(stored); this.recentScene = recentSceneData.scene; this.recentSceneTime = recentSceneData.time; this.log(`加载最近场景: ${this.recentScene}, 时间: ${new Date(this.recentSceneTime).toLocaleString()}`); } } catch (e) { this.log('加载最近场景异常:', e, 'warn'); } } log(message, data = '', level = 'info') { if (!this.config.enableDebugLog) return; const prefix = '[IAA-SDK]'; if (level === 'error') { console.error(prefix, message, data); } else if (level === 'warn') { console.warn(prefix, message, data); } else { console.log(prefix, message, data); } } } // 创建全局实例 const iaaSDK = new IAA_SDK(); // 加载存储的数据 iaaSDK.loadFromStorage(); // 导出方式1:模块导出 module.exports = { default: iaaSDK, IAA_SDK: IAA_SDK }; // 导出方式2:挂载到全局(类似OceanOld) if (typeof window !== 'undefined') { window.IAASDK = { default: iaaSDK }; }