convertToPurchase function
Implementation
gentype.Purchase convertToPurchase(
Map<String, dynamic> itemJson, {
required bool platformIsAndroid,
required bool platformIsIOS,
required Map<String, bool> acknowledgedAndroidPurchaseTokens,
Map<String, dynamic>? originalJson,
}) {
final productId = itemJson['productId']?.toString() ?? '';
final transactionId =
itemJson['transactionId']?.toString() ?? itemJson['id']?.toString();
final dynamic quantityValue = itemJson['quantity'];
int quantity = 1;
if (quantityValue is num) {
quantity = quantityValue.toInt();
} else if (quantityValue is String) {
final parsedQuantity = int.tryParse(quantityValue.trim());
if (parsedQuantity != null) {
quantity = parsedQuantity;
}
}
final String? purchaseId = (transactionId?.isNotEmpty ?? false)
? transactionId
: (productId.isNotEmpty ? productId : null);
if (purchaseId == null || purchaseId.isEmpty) {
debugPrint(
'[flutter_inapp_purchase] Skipping purchase with missing identifiers: $itemJson',
);
throw const FormatException('Missing purchase identifier');
}
double transactionDate = 0;
final transactionDateValue = itemJson['transactionDate'];
if (transactionDateValue is num) {
transactionDate = transactionDateValue.toDouble();
} else if (transactionDateValue is String) {
final parsedDate = DateTime.tryParse(transactionDateValue);
if (parsedDate != null) {
transactionDate = parsedDate.millisecondsSinceEpoch.toDouble();
}
}
if (platformIsAndroid) {
final stateValue = _coerceAndroidPurchaseState(
itemJson['purchaseStateAndroid'] ?? itemJson['purchaseState'],
);
final purchaseState = _mapAndroidPurchaseState(stateValue).toJson();
final map = <String, dynamic>{
'id': purchaseId,
'productId': productId,
'platform': gentype.IapPlatform.Android.toJson(),
'isAutoRenewing': itemJson['isAutoRenewing'] as bool? ??
itemJson['autoRenewingAndroid'] as bool? ??
false,
'purchaseState': purchaseState,
'quantity': quantity,
'transactionDate': transactionDate,
'purchaseToken': itemJson['purchaseToken']?.toString(),
'autoRenewingAndroid': itemJson['autoRenewingAndroid'] as bool?,
'dataAndroid': itemJson['originalJsonAndroid']?.toString(),
'developerPayloadAndroid':
itemJson['developerPayloadAndroid']?.toString(),
'ids': (itemJson['ids'] as List<dynamic>?)
?.map((e) => e.toString())
.toList(),
'isAcknowledgedAndroid': itemJson['isAcknowledgedAndroid'] as bool?,
'obfuscatedAccountIdAndroid':
itemJson['obfuscatedAccountIdAndroid']?.toString() ??
originalJson?['obfuscatedAccountIdAndroid']?.toString(),
'obfuscatedProfileIdAndroid':
itemJson['obfuscatedProfileIdAndroid']?.toString() ??
originalJson?['obfuscatedProfileIdAndroid']?.toString(),
'packageNameAndroid': itemJson['packageNameAndroid']?.toString(),
'signatureAndroid': itemJson['signatureAndroid']?.toString(),
'transactionId': transactionId,
};
final purchaseToken = itemJson['purchaseToken']?.toString();
if (purchaseToken != null && purchaseToken.isNotEmpty) {
acknowledgedAndroidPurchaseTokens[purchaseToken] =
itemJson['isAcknowledgedAndroid'] as bool? ?? false;
}
return gentype.PurchaseAndroid.fromJson(map);
}
if (platformIsIOS) {
final stateIOS = _parsePurchaseStateIOS(
itemJson['purchaseState'] ?? itemJson['transactionStateIOS'],
).toJson();
double? originalTransactionDateIOS;
final originalTransactionDateValue =
itemJson['originalTransactionDateIOS'] ??
originalJson?['originalTransactionDateIOS'];
if (originalTransactionDateValue is num) {
originalTransactionDateIOS = originalTransactionDateValue.toDouble();
} else if (originalTransactionDateValue is String) {
final parsed = DateTime.tryParse(originalTransactionDateValue);
if (parsed != null) {
originalTransactionDateIOS = parsed.millisecondsSinceEpoch.toDouble();
}
}
final map = <String, dynamic>{
'id': purchaseId,
'productId': productId,
'platform': gentype.IapPlatform.IOS.toJson(),
'isAutoRenewing': itemJson['isAutoRenewing'] as bool? ?? false,
'purchaseState': stateIOS,
'quantity': quantity,
'transactionDate': transactionDate,
'purchaseToken': itemJson['transactionReceipt']?.toString() ??
itemJson['purchaseToken']?.toString(),
'ids': (itemJson['ids'] as List<dynamic>?)
?.map((e) => e.toString())
.toList(),
'appAccountToken': itemJson['appAccountToken']?.toString(),
'appBundleIdIOS': itemJson['appBundleIdIOS']?.toString(),
'countryCodeIOS': itemJson['countryCodeIOS']?.toString(),
'currencyCodeIOS': itemJson['currencyCodeIOS']?.toString(),
'currencySymbolIOS': itemJson['currencySymbolIOS']?.toString(),
'environmentIOS': itemJson['environmentIOS']?.toString(),
'expirationDateIOS':
(originalJson?['expirationDateIOS'] as num?)?.toDouble(),
'originalTransactionIdentifierIOS':
itemJson['originalTransactionIdentifierIOS']?.toString(),
'originalTransactionDateIOS': originalTransactionDateIOS,
'subscriptionGroupIdIOS': itemJson['subscriptionGroupIdIOS']?.toString(),
'transactionReasonIOS': itemJson['transactionReasonIOS']?.toString(),
'webOrderLineItemIdIOS': itemJson['webOrderLineItemIdIOS']?.toString(),
'offerIOS': originalJson?['offerIOS'],
'priceIOS': (originalJson?['priceIOS'] as num?)?.toDouble(),
'revocationDateIOS':
(originalJson?['revocationDateIOS'] as num?)?.toDouble(),
'revocationReasonIOS': originalJson?['revocationReasonIOS']?.toString(),
'transactionId': transactionId ?? purchaseId,
};
return gentype.PurchaseIOS.fromJson(map);
}
throw const FormatException('Unsupported platform for legacy purchase');
}