parseProductFromNative function

ProductCommon parseProductFromNative(
  1. Map<String, dynamic> json,
  2. String type, {
  3. required bool fallbackIsIOS,
})

Implementation

gentype.ProductCommon parseProductFromNative(
  Map<String, dynamic> json,
  String type, {
  required bool fallbackIsIOS,
}) {
  // Determine platform from JSON data if available, otherwise use heuristics, then runtime
  gentype.IapPlatform platform;
  final dynamic platformRaw = json['platform'];
  if (platformRaw is String) {
    final v = platformRaw.toLowerCase();
    platform = (v == 'android')
        ? gentype.IapPlatform.Android
        : gentype.IapPlatform.IOS;
  } else if (platformRaw is gentype.IapPlatform) {
    platform = platformRaw;
  } else {
    // Heuristics based on well-known platform-specific fields
    final looksAndroid =
        json.containsKey('oneTimePurchaseOfferDetailsAndroid') ||
            json.containsKey('subscriptionOfferDetailsAndroid') ||
            json.containsKey('nameAndroid');
    final looksIOS = json.containsKey('subscriptionGroupIdIOS') ||
        json.containsKey('jsonRepresentationIOS') ||
        json.containsKey('environmentIOS');
    if (looksAndroid && !looksIOS) {
      platform = gentype.IapPlatform.Android;
    } else if (looksIOS && !looksAndroid) {
      platform = gentype.IapPlatform.IOS;
    } else {
      platform =
          fallbackIsIOS ? gentype.IapPlatform.IOS : gentype.IapPlatform.Android;
    }
  }

  double? parsePrice(dynamic value) {
    if (value is num) return value.toDouble();
    if (value is String) return double.tryParse(value);
    return null;
  }

  final productId = (json['id']?.toString() ??
          json['productId']?.toString() ??
          json['sku']?.toString() ??
          json['productIdentifier']?.toString() ??
          '')
      .trim();
  final title = json['title']?.toString() ?? productId;
  final description = json['description']?.toString() ?? '';
  final currency = json['currency']?.toString() ?? '';
  final displayPrice = json['displayPrice']?.toString() ??
      json['localizedPrice']?.toString() ??
      '0';
  final priceValue = parsePrice(json['price']);
  final productType = _parseProductType(type);

  if (productType == gentype.ProductType.Subs) {
    if (platform == gentype.IapPlatform.IOS) {
      return gentype.ProductSubscriptionIOS(
        currency: currency,
        description: description,
        displayNameIOS: json['displayNameIOS']?.toString() ?? title,
        displayPrice: displayPrice,
        id: productId,
        isFamilyShareableIOS: json['isFamilyShareableIOS'] as bool? ?? false,
        jsonRepresentationIOS:
            json['jsonRepresentationIOS']?.toString() ?? '{}',
        platform: platform,
        title: title,
        type: productType,
        typeIOS: _parseProductTypeIOS(json['typeIOS']?.toString()),
        debugDescription: json['debugDescription']?.toString(),
        discountsIOS:
            _parseDiscountsIOS(json['discountsIOS'] ?? json['discounts']),
        displayName: json['displayName']?.toString(),
        introductoryPriceAsAmountIOS:
            json['introductoryPriceAsAmountIOS']?.toString(),
        introductoryPriceIOS: json['introductoryPriceIOS']?.toString(),
        introductoryPriceNumberOfPeriodsIOS:
            json['introductoryPriceNumberOfPeriodsIOS']?.toString(),
        introductoryPricePaymentModeIOS:
            _parsePaymentMode(json['introductoryPricePaymentModeIOS']),
        introductoryPriceSubscriptionPeriodIOS: _parseSubscriptionPeriod(
          json['introductoryPriceSubscriptionPeriodIOS'],
        ),
        price: priceValue,
        subscriptionInfoIOS: _parseSubscriptionInfoIOS(
          json['subscriptionInfoIOS'] ?? json['subscription'],
        ),
        subscriptionPeriodNumberIOS:
            json['subscriptionPeriodNumberIOS']?.toString(),
        subscriptionPeriodUnitIOS:
            _parseSubscriptionPeriod(json['subscriptionPeriodUnitIOS']),
      );
    }

    final subscriptionOffers = _parseOfferDetails(
      json['subscriptionOfferDetailsAndroid'],
    );

    return gentype.ProductSubscriptionAndroid(
      currency: currency,
      description: description,
      displayPrice: displayPrice,
      id: productId,
      nameAndroid: json['nameAndroid']?.toString() ?? productId,
      platform: platform,
      subscriptionOfferDetailsAndroid: subscriptionOffers,
      title: title,
      type: productType,
      debugDescription: json['debugDescription']?.toString(),
      displayName: json['displayName']?.toString(),
      oneTimePurchaseOfferDetailsAndroid: _parseOneTimePurchaseOfferDetail(
        json['oneTimePurchaseOfferDetailsAndroid'],
      ),
      price: priceValue,
    );
  }

  if (platform == gentype.IapPlatform.IOS) {
    return gentype.ProductIOS(
      currency: currency,
      description: description,
      displayNameIOS: json['displayNameIOS']?.toString() ?? title,
      displayPrice: displayPrice,
      id: productId,
      isFamilyShareableIOS: json['isFamilyShareableIOS'] as bool? ?? false,
      jsonRepresentationIOS: json['jsonRepresentationIOS']?.toString() ?? '{}',
      platform: platform,
      title: title,
      type: productType,
      typeIOS: _parseProductTypeIOS(json['typeIOS']?.toString()),
      debugDescription: json['debugDescription']?.toString(),
      displayName: json['displayName']?.toString(),
      price: priceValue,
      subscriptionInfoIOS: _parseSubscriptionInfoIOS(
        json['subscriptionInfoIOS'] ?? json['subscription'],
      ),
    );
  }

  final androidOffers = _parseOfferDetails(
    json['subscriptionOfferDetailsAndroid'],
  );

  return gentype.ProductAndroid(
    currency: currency,
    description: description,
    displayPrice: displayPrice,
    id: productId,
    nameAndroid: json['nameAndroid']?.toString() ?? productId,
    platform: platform,
    title: title,
    type: productType,
    debugDescription: json['debugDescription']?.toString(),
    displayName: json['displayName']?.toString(),
    oneTimePurchaseOfferDetailsAndroid: _parseOneTimePurchaseOfferDetail(
      json['oneTimePurchaseOfferDetailsAndroid'],
    ),
    price: priceValue,
    subscriptionOfferDetailsAndroid:
        androidOffers.isEmpty ? null : androidOffers,
  );
}