Mobile & Cross-Platform
Flutter (Dart) Multi-Platform Integration
Resolve localized purchasing power parity pricing policies across Flutter apps on iOS, Android, Web, macOS, and Windows with offline caching.
Production Flutter Service with SharedPreferences Caching
Create a thread-safe singleton service that caches resolved PPP models in SharedPreferences for instant offline rendering:
// lib/services/parity_edge_service.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class ParityModel {
final bool eligible;
final int discountPercentage;
final String couponCode;
final String countryName;
final String countryCode;
final String currency;
final int tier;
ParityModel({
required this.eligible,
required this.discountPercentage,
required this.couponCode,
required this.countryName,
required this.countryCode,
required this.currency,
required this.tier,
});
factory ParityModel.fromJson(Map<String, dynamic> json) {
return ParityModel(
eligible: json['eligible'] ?? false,
discountPercentage: json['discountPercentage'] ?? 0,
couponCode: json['couponCode'] ?? '',
countryName: json['countryName'] ?? 'United States',
countryCode: json['countryCode'] ?? 'US',
currency: json['currency'] ?? 'USD',
tier: json['tier'] ?? 1,
);
}
Map<String, dynamic> toJson() => {
'eligible': eligible,
'discountPercentage': discountPercentage,
'couponCode': couponCode,
'countryName': countryName,
'countryCode': countryCode,
'currency': currency,
'tier': tier,
};
}
class ParityEdgeService {
static const String _endpoint =
'https://api.parityedge.app/v1/lookup?pid=prj_live_YOUR_KEY';
static const String _cacheKey = 'parity_edge_cached_model';
static Future<ParityModel?> resolveParity() async {
final prefs = await SharedPreferences.getInstance();
try {
final response = await http.get(Uri.parse(_endpoint)).timeout(
const Duration(milliseconds: 1200),
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
final model = ParityModel.fromJson(data);
await prefs.setString(_cacheKey, json.encode(model.toJson()));
return model;
}
} catch (_) {
// Network timeout: Load from offline cache
final cachedJson = prefs.getString(_cacheKey);
if (cachedJson != null) {
return ParityModel.fromJson(json.decode(cachedJson));
}
}
return null;
}
}Flutter Pricing Banner & Checkout Widget
// lib/widgets/pricing_card.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import '../services/parity_edge_service.dart';
class PricingCardWidget extends StatelessWidget {
final ParityModel? parity;
final double basePrice = 49.00;
const PricingCardWidget({super.key, required this.parity});
Future<void> _launchCheckout() async {
String url = 'https://buy.stripe.com/your_checkout_id';
if (parity != null && parity!.eligible && parity!.couponCode.isNotEmpty) {
url = '$url?prefilled_promo_code=${parity!.couponCode}';
}
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
}
@override
Widget build(BuildContext context) {
final hasDiscount = parity != null && parity!.eligible && parity!.discountPercentage > 0;
final finalPrice = hasDiscount
? basePrice * (1.0 - (parity!.discountPercentage / 100.0))
: basePrice;
return Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: const Color(0xFF0F172A),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: const Color(0xFF1E293B)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (hasDiscount)
Container(
margin: const EdgeInsets.bottom(16),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: const Color(0xFF064E3B),
borderRadius: BorderRadius.circular(10),
border: Border.all(color: const Color(0xFF059669)),
),
child: Text(
'🎉 Special ${parity!.discountPercentage}% purchasing power discount for ${parity!.countryName}!',
style: const TextStyle(color: Color(0xFF34D399), fontSize: 12, fontWeight: FontWeight.w600),
),
),
Text(
'\$${finalPrice.toStringAsFixed(2)} / year',
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _launchCheckout,
style: ElevatedButton.styleFrom(backgroundColor: const Color(0xFF10B981)),
child: const Text('Subscribe with Local Discount'),
),
],
),
);
}
}Flutter Multi-Platform Best Practices
Zero Permission Dialogs
ParityEdge determines country and PPP tier at the Anycast edge with zero location permissions required in your AndroidManifest.xml or Info.plist.
Anti-VPN Security Shield
Datacenter proxies and commercial VPN tunnels are flagged at the edge layer, protecting mobile checkouts from geographic arbitrage.