diff --git a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md index 5c39773bae6d..2632236fbf36 100644 --- a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Adds support for passing an obfuscated profile ID in GooglePlayPurchaseParam. + ## 0.5.1 * Adds support to overlay billing related messages. See `InAppPurchaseAndroidPlatformAddition.showInAppMessages`. diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart index d865e328edbe..7a6e73048159 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/in_app_purchase_android_platform.dart @@ -152,10 +152,12 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { Future buyNonConsumable({required PurchaseParam purchaseParam}) async { ChangeSubscriptionParam? changeSubscriptionParam; String? offerToken; + String? obfuscatedProfileId; if (purchaseParam is GooglePlayPurchaseParam) { changeSubscriptionParam = purchaseParam.changeSubscriptionParam; offerToken = purchaseParam.offerToken; + obfuscatedProfileId = purchaseParam.obfuscatedProfileId; } if (offerToken == null && purchaseParam.productDetails is GooglePlayProductDetails) { @@ -167,6 +169,7 @@ class InAppPurchaseAndroidPlatform extends InAppPurchasePlatform { product: purchaseParam.productDetails.id, offerToken: offerToken, accountId: purchaseParam.applicationUserName, + obfuscatedProfileId: obfuscatedProfileId, oldProduct: changeSubscriptionParam?.oldPurchaseDetails.productID, purchaseToken: changeSubscriptionParam?.oldPurchaseDetails.verificationData.serverVerificationData, diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_param.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_param.dart index 0e5f91701153..5a02e4833f83 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_param.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_param.dart @@ -14,6 +14,7 @@ class GooglePlayPurchaseParam extends PurchaseParam { super.applicationUserName, this.changeSubscriptionParam, this.offerToken, + this.obfuscatedProfileId, }); /// The 'changeSubscriptionParam' containing information for upgrading or @@ -25,4 +26,10 @@ class GooglePlayPurchaseParam extends PurchaseParam { /// For subscriptions, to get the offer token corresponding to the selected /// offer call productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken final String? offerToken; + + /// An optional obfuscated profile ID associated with the user's profile. + /// + /// Setting this field requires [applicationUserName], which maps to the + /// obfuscated account ID, to be specified as well. + final String? obfuscatedProfileId; } diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart index c0b6260167d4..6ed7349164a5 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart @@ -415,6 +415,34 @@ void main() { expect(result.productID, productDetails.productId); }); + test('buyNonConsumable passes obfuscatedProfileId', () async { + const profileId = 'hashedProfileId'; + const accountId = 'hashedAccountId'; + const expectedBillingResult = BillingResultWrapper( + responseCode: BillingResponse.ok, + debugMessage: 'dummy message', + ); + when( + mockApi.launchBillingFlow(any), + ).thenAnswer((_) async => convertToPigeonResult(expectedBillingResult)); + + final bool launchResult = await iapAndroidPlatform.buyNonConsumable( + purchaseParam: GooglePlayPurchaseParam( + productDetails: GooglePlayProductDetails.fromProductDetails( + dummyOneTimeProductDetails, + ).first, + applicationUserName: accountId, + obfuscatedProfileId: profileId, + ), + ); + + final VerificationResult result = verify(mockApi.launchBillingFlow(captureAny)); + final params = result.captured.single as PlatformBillingFlowParams; + expect(launchResult, isTrue); + expect(params.accountId, accountId); + expect(params.obfuscatedProfileId, profileId); + }); + test('handles an error with an empty purchases list', () async { const ProductDetailsWrapper productDetails = dummyOneTimeProductDetails; const accountId = 'hashedAccountId';