diff --git a/android/src/main/kotlin/com/usercentrics/sdk/flutter/serializer/CMPDataSerializer.kt b/android/src/main/kotlin/com/usercentrics/sdk/flutter/serializer/CMPDataSerializer.kt index 75ccb32..5d55e72 100644 --- a/android/src/main/kotlin/com/usercentrics/sdk/flutter/serializer/CMPDataSerializer.kt +++ b/android/src/main/kotlin/com/usercentrics/sdk/flutter/serializer/CMPDataSerializer.kt @@ -8,6 +8,7 @@ import com.usercentrics.sdk.v2.settings.data.CustomizationFont import com.usercentrics.sdk.v2.settings.data.FirstLayer import com.usercentrics.sdk.v2.settings.data.PublishedApp import com.usercentrics.sdk.v2.settings.data.SecondLayer +import com.usercentrics.sdk.v2.settings.data.ConsentOrPayRestriction import com.usercentrics.sdk.v2.settings.data.ConsentOrPaySettings import com.usercentrics.sdk.v2.settings.data.TCF2ChangedPurposes import com.usercentrics.sdk.v2.settings.data.TCF2Settings @@ -228,7 +229,8 @@ private fun TCF2Settings.serialize(): Any { "acmV2Enabled" to acmV2Enabled, "selectedATPIds" to selectedATPIds, "consentOrPay" to consentOrPay?.serialize(), - "mandatoryLabel" to mandatoryLabel + "mandatoryLabel" to mandatoryLabel, + "specialFeaturesConsentOrPay" to specialFeaturesConsentOrPay?.map { it.serialize() }, ) } @@ -428,6 +430,12 @@ private fun TCF2ChangedPurposes?.serialize(): Any? { } return mapOf( "purposes" to purposes, - "legIntPurposes" to legIntPurposes + "legIntPurposes" to legIntPurposes, + "consentOrPay" to consentOrPay?.map { it.serialize() }, ) } + +private fun ConsentOrPayRestriction.serialize(): Map = mapOf( + "id" to id, + "value" to value, +) diff --git a/ios/Classes/Serializer/CMPDataSerializer.swift b/ios/Classes/Serializer/CMPDataSerializer.swift index e8d8f48..efd277b 100644 --- a/ios/Classes/Serializer/CMPDataSerializer.swift +++ b/ios/Classes/Serializer/CMPDataSerializer.swift @@ -218,7 +218,8 @@ extension TCF2Settings { "acmV2Enabled" : self.acmV2Enabled, "selectedATPIds" : self.selectedATPIds, "consentOrPay": self.consentOrPay?.serialize() as Any, - "mandatoryLabel": self.mandatoryLabel + "mandatoryLabel": self.mandatoryLabel, + "specialFeaturesConsentOrPay": self.specialFeaturesConsentOrPay?.map { $0.serialize() } as Any, ] } } @@ -409,7 +410,17 @@ extension TCF2ChangedPurposes { func serialize() -> Any { return [ "purposes": purposes, - "legIntPurposes": legIntPurposes + "legIntPurposes": legIntPurposes, + "consentOrPay": consentOrPay?.map { $0.serialize() } as Any, + ] + } +} + +extension ConsentOrPayRestriction { + func serialize() -> [String: Any] { + return [ + "id": self.id, + "value": self.value, ] } } diff --git a/lib/src/internal/serializer/tcf2_settings_serializer.dart b/lib/src/internal/serializer/tcf2_settings_serializer.dart index 59a2c76..c2edd5a 100644 --- a/lib/src/internal/serializer/tcf2_settings_serializer.dart +++ b/lib/src/internal/serializer/tcf2_settings_serializer.dart @@ -71,7 +71,10 @@ class TCF2SettingsSerializer { selectedATPIds: value['selectedATPIds']?.cast() ?? [], consentOrPay: TCF2ConsentOrPaySettingsSerializer.deserialize( value['consentOrPay']), - mandatoryLabel: value['mandatoryLabel'] ?? "Mandatory"); + mandatoryLabel: value['mandatoryLabel'] ?? "Mandatory", + specialFeaturesConsentOrPay: + ConsentOrPayRestrictionSerializer.deserializeList( + value['specialFeaturesConsentOrPay'])); } } @@ -107,7 +110,19 @@ class TCF2ChangedPurposesSerializer { static TCF2ChangedPurposes deserialize(value) { return TCF2ChangedPurposes( purposes: value['purposes']?.cast() ?? [], - legIntPurposes: value['legIntPurposes']?.cast() ?? []); + legIntPurposes: value['legIntPurposes']?.cast() ?? [], + consentOrPay: ConsentOrPayRestrictionSerializer.deserializeList( + value['consentOrPay'])); + } +} + +class ConsentOrPayRestrictionSerializer { + static List? deserializeList(value) { + if (value == null) return null; + return (value as List) + .map((e) => ConsentOrPayRestriction( + id: e['id'] as int, value: e['value'] as String)) + .toList(); } } diff --git a/lib/src/model/tcf2_settings.dart b/lib/src/model/tcf2_settings.dart index 9346e63..63138cb 100644 --- a/lib/src/model/tcf2_settings.dart +++ b/lib/src/model/tcf2_settings.dart @@ -62,7 +62,8 @@ class TCF2Settings { required this.acmV2Enabled, required this.selectedATPIds, this.consentOrPay, - this.mandatoryLabel = "Mandatory"}); + this.mandatoryLabel = "Mandatory", + this.specialFeaturesConsentOrPay}); final String firstLayerTitle; final String secondLayerTitle; @@ -125,6 +126,7 @@ class TCF2Settings { final List selectedATPIds; final TCF2ConsentOrPaySettings? consentOrPay; final String mandatoryLabel; + final List? specialFeaturesConsentOrPay; @override bool operator ==(Object other) => @@ -271,10 +273,13 @@ enum TCF2Scope { global, service } class TCF2ChangedPurposes { const TCF2ChangedPurposes( - {required this.purposes, required this.legIntPurposes}); + {required this.purposes, + required this.legIntPurposes, + this.consentOrPay}); final List purposes; final List legIntPurposes; + final List? consentOrPay; @override bool operator ==(Object other) => @@ -282,10 +287,32 @@ class TCF2ChangedPurposes { other is TCF2ChangedPurposes && runtimeType == other.runtimeType && listEquals(purposes, other.purposes) && - listEquals(legIntPurposes, other.legIntPurposes); + listEquals(legIntPurposes, other.legIntPurposes) && + listEquals(consentOrPay, other.consentOrPay); @override - int get hashCode => purposes.hashCode ^ legIntPurposes.hashCode; + int get hashCode => + purposes.hashCode ^ legIntPurposes.hashCode ^ consentOrPay.hashCode; +} + +class ConsentOrPayRestriction { + const ConsentOrPayRestriction({required this.id, required this.value}); + + final int id; + final String value; + + bool isFlexible() => value.toUpperCase() == 'FLEXIBLE'; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ConsentOrPayRestriction && + runtimeType == other.runtimeType && + id == other.id && + value == other.value; + + @override + int get hashCode => id.hashCode ^ value.hashCode; } class TCF2ConsentOrPaySettings {