extractPurchases function

List<Purchase> extractPurchases(
  1. dynamic result, {
  2. required bool platformIsAndroid,
  3. required bool platformIsIOS,
  4. required Map<String, bool> acknowledgedAndroidPurchaseTokens,
  5. bool rejectMalformed = false,
})

Implementation

List<gentype.Purchase> extractPurchases(
  dynamic result, {
  required bool platformIsAndroid,
  required bool platformIsIOS,
  required Map<String, bool> acknowledgedAndroidPurchaseTokens,
  bool rejectMalformed = false,
}) {
  List<dynamic> list;
  try {
    if (result is String) {
      list = json.decode(result) as List<dynamic>;
    } else if (result is List) {
      list = result;
    } else {
      list = json.decode(result.toString()) as List<dynamic>;
    }
  } catch (_) {
    if (rejectMalformed) {
      throw const FormatException(
        'Native bridge returned a malformed purchase list',
      );
    }
    return const <gentype.Purchase>[];
  }

  final purchases = <gentype.Purchase>[];
  for (var index = 0; index < list.length; index += 1) {
    final dynamic product = list[index];
    try {
      if (product is! Map) {
        if (rejectMalformed) {
          throw FormatException(
            'Native bridge returned a malformed purchase at index $index',
          );
        }
        debugPrint(
          '[flutter_inapp_purchase] Skipping purchase with unexpected type: ${product.runtimeType}',
        );
        continue;
      }
      // Safely convert map keys to strings to handle cases where platform channels
      // return maps with non-string keys (e.g., Map<Object?, Object?>)
      final map = normalizeDynamicMap(product);
      if (map == null) {
        if (rejectMalformed) {
          throw FormatException(
            'Native bridge returned a malformed purchase at index $index',
          );
        }
        debugPrint(
          '[flutter_inapp_purchase] Skipping purchase: failed to normalize map',
        );
        continue;
      }
      final original = map; // Use normalized data to access additional fields
      if (rejectMalformed &&
          !_isValidAuthoritativePurchaseMap(
            map,
            platformIsAndroid: platformIsAndroid,
            platformIsIOS: platformIsIOS,
          )) {
        throw FormatException(
          'Native bridge returned a purchase with invalid fields at index $index',
        );
      }
      purchases.add(
        convertToPurchase(
          map,
          originalJson: original,
          platformIsAndroid: platformIsAndroid,
          platformIsIOS: platformIsIOS,
          acknowledgedAndroidPurchaseTokens: acknowledgedAndroidPurchaseTokens,
        ),
      );
    } catch (error) {
      if (rejectMalformed) {
        if (error is FormatException) rethrow;
        throw FormatException(
          'Failed to decode native purchase at index $index',
        );
      }
      debugPrint(
        '[flutter_inapp_purchase] Skipping purchase due to parse error: $error',
      );
    }
  }

  return purchases;
}