import 'dart:async'; import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_event.dart'; import 'package:facebook_app_events/facebook_app_events.dart'; import 'package:logger/logger.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../config/facebook_config.dart'; /// 事件埋点:Adjust + Facebook App Events 双通道上报 /// Adjust 识别码见 docs/adjuest.md abstract final class AdjustEvents { static final _fb = FacebookAppEvents(); static final _fbLog = Logger( printer: PrettyPrinter(methodCount: 0, lineLength: 120), level: FacebookConfig.debugLogs ? Level.trace : Level.off, ); // 购买档位(充值页选择档位时上报) static const String tier1999 = 'm0r9u9'; // 19.99 static const String tier4999 = 'aht1ve'; // 49.99 static const String tier599 = '47hhx9'; // 5.99 static const String tier999 = 'w775gd'; // 9.99 static const String tier9999 = 'y7994m'; // 99.99 // 首日充值 static const String firstPurchase = 'r6w4bi'; // 支付失败 static const String orderAbnormal = '4txlo1'; // 支付成功 static const String purchase = 'ek780r'; // 注册(首次调用 fast_login 成功时) static const String register = '2z3dm4'; // 其他 static const String monthlyVip = '96o5ez'; // PetsHero AI Monthly VIP static const String weeklyVip = '95yg4o'; // PetsHero AI Weekly VIP /// 根据金额(如 19.99, 9.99)返回档位事件 token,无法匹配时返回 purchase static String? tierTokenFromPrice(num price) { final p = price.toStringAsFixed(2); switch (p) { case '5.99': return tier599; case '9.99': return tier999; case '19.99': return tier1999; case '49.99': return tier4999; case '99.99': return tier9999; default: return purchase; } } /// 从金额字符串解析数字(如 "¥19.99" / "\$19.99") static num? parsePrice(String amount) { final match = RegExp(r'[\d.]+').firstMatch(amount); if (match == null) return null; return num.tryParse(match.group(0)!); } static void _track(String eventToken) { Adjust.trackEvent(AdjustEvent(eventToken)); } /// 上报 Facebook(fire-and-forget,不阻塞主流程) static void _trackFb(String eventDesc, Future Function() fn) { if (FacebookConfig.debugLogs) _fbLog.w('FB ↑ $eventDesc'); unawaited(fn()); } /// 购买档位(用户点击某档位购买时) static void trackTier(String eventToken) { _track(eventToken); } /// 首日充值 static void trackFirstPurchase(double amount) { _track(firstPurchase); _trackFb( 'FirstRecharge amount=$amount', () => _fb .logEvent(name: 'FirstRecharge', parameters: {'amount': amount})); } /// 支付失败 static void trackOrderAbnormal() { _track(orderAbnormal); _trackFb('payment_failed', () => _fb.logEvent(name: 'payment_failed')); } /// 注册(fast_login 返回 equip=true / firstRegister 时) static void trackRegister() { _track(register); _trackFb('CompletedRegistration', () => _fb.logCompletedRegistration(registrationMethod: 'device')); } /// PetsHero AI Monthly VIP static void trackMonthlyVip() { _track(monthlyVip); _trackFb('Subscribe monthly_vip', () => _fb.logSubscribe(orderId: 'monthly_vip')); } /// PetsHero AI Weekly VIP static void trackWeeklyVip() { _track(weeklyVip); _trackFb( 'Subscribe weekly_vip', () => _fb.logSubscribe(orderId: 'weekly_vip')); } static const String _keyRegisterDate = 'adjust_register_date'; /// 支付成功时调用:上报 Purchase,若为首日充值则同时上报 first purchase static Future trackPurchaseSuccess(double amount) async { _track(purchase); final prefs = await SharedPreferences.getInstance(); final registerDate = prefs.getString(_keyRegisterDate); final isFirstPurchase = registerDate != null && registerDate == DateTime.now().toIso8601String().substring(0, 10); if (isFirstPurchase) { trackFirstPurchase(amount); } _trackFb( 'Purchase', () => _fb.logPurchase( amount: amount, currency: 'USD', )); } /// 支付失败时调用 static void trackPaymentFailed() { trackOrderAbnormal(); } }