[in_app_purchase] Added userIds to google play purchase (#4020)
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 949fe90..6175462 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 @@
+## 0.1.2
+
+* Added support for the obfuscatedAccountId and obfuscatedProfileId in the PurchaseWrapper.
+
## 0.1.1
* Added support to request a list of active subscriptions and non-consumed one-time purchases on Android, through the `InAppPurchaseAndroidPlatformAddition.queryPastPurchases` method.
diff --git a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Translator.java b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Translator.java
index 37e30cb..079c18a 100644
--- a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Translator.java
+++ b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Translator.java
@@ -5,6 +5,7 @@
package io.flutter.plugins.inapppurchase;
import androidx.annotation.Nullable;
+import com.android.billingclient.api.AccountIdentifiers;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.Purchase.PurchasesResult;
@@ -63,6 +64,11 @@
info.put("developerPayload", purchase.getDeveloperPayload());
info.put("isAcknowledged", purchase.isAcknowledged());
info.put("purchaseState", purchase.getPurchaseState());
+ AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
+ if (accountIdentifiers != null) {
+ info.put("obfuscatedAccountId", accountIdentifiers.getObfuscatedAccountId());
+ info.put("obfuscatedProfileId", accountIdentifiers.getObfuscatedProfileId());
+ }
return info;
}
diff --git a/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/TranslatorTest.java b/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/TranslatorTest.java
index 47147e7..e65afcf 100644
--- a/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/TranslatorTest.java
+++ b/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/TranslatorTest.java
@@ -5,9 +5,13 @@
package io.flutter.plugins.inapppurchase;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import androidx.annotation.NonNull;
+import com.android.billingclient.api.AccountIdentifiers;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
@@ -26,7 +30,7 @@
private static final String SKU_DETAIL_EXAMPLE_JSON =
"{\"productId\":\"example\",\"type\":\"inapp\",\"price\":\"$0.99\",\"price_amount_micros\":990000,\"price_currency_code\":\"USD\",\"title\":\"Example title\",\"description\":\"Example description.\",\"original_price\":\"$0.99\",\"original_price_micros\":990000}";
private static final String PURCHASE_EXAMPLE_JSON =
- "{\"orderId\":\"foo\",\"packageName\":\"bar\",\"productId\":\"consumable\",\"purchaseTime\":11111111,\"purchaseState\":0,\"purchaseToken\":\"baz\",\"developerPayload\":\"dummy payload\",\"isAcknowledged\":\"true\"}";
+ "{\"orderId\":\"foo\",\"packageName\":\"bar\",\"productId\":\"consumable\",\"purchaseTime\":11111111,\"purchaseState\":0,\"purchaseToken\":\"baz\",\"developerPayload\":\"dummy payload\",\"isAcknowledged\":\"true\", \"obfuscatedAccountId\":\"Account101\", \"obfuscatedProfileId\": \"Profile105\"}";
@Test
public void fromSkuDetail() throws JSONException {
@@ -64,6 +68,16 @@
}
@Test
+ public void fromPurchaseWithoutAccountIds() throws JSONException {
+ final Purchase expected =
+ new PurchaseWithoutAccountIdentifiers(PURCHASE_EXAMPLE_JSON, "signature");
+ Map<String, Object> serialized = Translator.fromPurchase(expected);
+ assertNotNull(serialized.get("orderId"));
+ assertNull(serialized.get("obfuscatedProfileId"));
+ assertNull(serialized.get("obfuscatedAccountId"));
+ }
+
+ @Test
public void fromPurchaseHistoryRecord() throws JSONException {
final PurchaseHistoryRecord expected =
new PurchaseHistoryRecord(PURCHASE_EXAMPLE_JSON, "signature");
@@ -200,6 +214,14 @@
assertEquals(expected.getDeveloperPayload(), serialized.get("developerPayload"));
assertEquals(expected.isAcknowledged(), serialized.get("isAcknowledged"));
assertEquals(expected.getPurchaseState(), serialized.get("purchaseState"));
+ assertNotNull(expected.getAccountIdentifiers().getObfuscatedAccountId());
+ assertEquals(
+ expected.getAccountIdentifiers().getObfuscatedAccountId(),
+ serialized.get("obfuscatedAccountId"));
+ assertNotNull(expected.getAccountIdentifiers().getObfuscatedProfileId());
+ assertEquals(
+ expected.getAccountIdentifiers().getObfuscatedProfileId(),
+ serialized.get("obfuscatedProfileId"));
}
private void assertSerialized(PurchaseHistoryRecord expected, Map<String, Object> serialized) {
@@ -211,3 +233,15 @@
assertEquals(expected.getDeveloperPayload(), serialized.get("developerPayload"));
}
}
+
+class PurchaseWithoutAccountIdentifiers extends Purchase {
+ public PurchaseWithoutAccountIdentifiers(@NonNull String s, @NonNull String s1)
+ throws JSONException {
+ super(s, s1);
+ }
+
+ @Override
+ public AccountIdentifiers getAccountIdentifiers() {
+ return null;
+ }
+}
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart
index 7ef089f..374c26a 100644
--- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart
+++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart
@@ -4,6 +4,7 @@
import 'dart:ui' show hashValues;
import 'package:flutter/foundation.dart';
+import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart';
import 'package:json_annotation/json_annotation.dart';
import 'enum_converters.dart';
import 'billing_client_wrapper.dart';
@@ -26,18 +27,21 @@
class PurchaseWrapper {
/// Creates a purchase wrapper with the given purchase details.
@visibleForTesting
- PurchaseWrapper(
- {required this.orderId,
- required this.packageName,
- required this.purchaseTime,
- required this.purchaseToken,
- required this.signature,
- required this.sku,
- required this.isAutoRenewing,
- required this.originalJson,
- this.developerPayload,
- required this.isAcknowledged,
- required this.purchaseState});
+ PurchaseWrapper({
+ required this.orderId,
+ required this.packageName,
+ required this.purchaseTime,
+ required this.purchaseToken,
+ required this.signature,
+ required this.sku,
+ required this.isAutoRenewing,
+ required this.originalJson,
+ this.developerPayload,
+ required this.isAcknowledged,
+ required this.purchaseState,
+ this.obfuscatedAccountId,
+ this.obfuscatedProfileId,
+ });
/// Factory for creating a [PurchaseWrapper] from a [Map] with the purchase details.
factory PurchaseWrapper.fromJson(Map<String, dynamic> map) =>
@@ -136,6 +140,20 @@
/// [BillingClient.acknowledgePurchase] should only be called when the `purchaseState` is [PurchaseStateWrapper.purchased].
/// * See also [BillingClient.acknowledgePurchase] for more details on acknowledging purchases.
final PurchaseStateWrapper purchaseState;
+
+ /// The obfuscatedAccountId specified when making a purchase.
+ ///
+ /// The [obfuscatedAccountId] can either be set in
+ /// [PurchaseParam.applicationUserName] when using the [InAppPurchasePlatform]
+ /// or by setting the [accountId] in [BillingClient.launchBillingFlow].
+ final String? obfuscatedAccountId;
+
+ /// The obfuscatedProfileId can be used when there are multiple profiles
+ /// withing one account. The obfuscatedProfileId should be specified when
+ /// making a purchase. This property can only be set on a purchase by
+ /// directly calling [BillingClient.launchBillingFlow] and is not available
+ /// on the generic [InAppPurchasePlatform].
+ final String? obfuscatedProfileId;
}
/// Data structure representing a purchase history record.
diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart
index 5f0d936..5607dbd 100644
--- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart
+++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart
@@ -20,6 +20,8 @@
isAcknowledged: json['isAcknowledged'] as bool? ?? false,
purchaseState:
const PurchaseStateConverter().fromJson(json['purchaseState'] as int?),
+ obfuscatedAccountId: json['obfuscatedAccountId'] as String?,
+ obfuscatedProfileId: json['obfuscatedProfileId'] as String?,
);
}
@@ -37,6 +39,8 @@
'isAcknowledged': instance.isAcknowledged,
'purchaseState':
const PurchaseStateConverter().toJson(instance.purchaseState),
+ 'obfuscatedAccountId': instance.obfuscatedAccountId,
+ 'obfuscatedProfileId': instance.obfuscatedProfileId,
};
PurchaseHistoryRecordWrapper _$PurchaseHistoryRecordWrapperFromJson(Map json) {
diff --git a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
index 4e78874..900fa43 100644
--- a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
+++ b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml
@@ -2,7 +2,7 @@
description: An implementation for the Android platform of the Flutter `in_app_purchase` plugin. This uses the Android BillingClient APIs.
repository: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/in_app_purchase_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
-version: 0.1.1
+version: 0.1.2
environment:
sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart
index a3e80a8..bb7ff85 100644
--- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart
+++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart
@@ -19,6 +19,8 @@
developerPayload: 'dummy payload',
isAcknowledged: true,
purchaseState: PurchaseStateWrapper.purchased,
+ obfuscatedAccountId: 'Account101',
+ obfuscatedProfileId: 'Profile103',
);
final PurchaseWrapper dummyUnacknowledgedPurchase = PurchaseWrapper(
@@ -191,6 +193,8 @@
'developerPayload': original.developerPayload,
'purchaseState': PurchaseStateConverter().toJson(original.purchaseState),
'isAcknowledged': original.isAcknowledged,
+ 'obfuscatedAccountId': original.obfuscatedAccountId,
+ 'obfuscatedProfileId': original.obfuscatedProfileId,
};
}