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 4b7329ca448..b1115c133fa 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,9 @@ +## 0.3.3 + +* Converts data objects in internal platform communication to Pigeon. +* Deprecates JSON serialization and deserialization for Billing Client wrapper + objects. + ## 0.3.2+1 * Converts internal platform communication to Pigeon. diff --git a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Messages.java b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Messages.java index 09701660aa9..6a465b4bb2c 100644 --- a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Messages.java +++ b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/Messages.java @@ -103,12 +103,38 @@ private PlatformBillingChoiceMode(final int index) { } } + /** Pigeon version of Java Purchase.PurchaseState. */ + public enum PlatformPurchaseState { + UNSPECIFIED(0), + PURCHASED(1), + PENDING(2); + + final int index; + + private PlatformPurchaseState(final int index) { + this.index = index; + } + } + + /** Pigeon version of Java ProductDetails.RecurrenceMode. */ + public enum PlatformRecurrenceMode { + FINITE_RECURRING(0), + INFINITE_RECURRING(1), + NON_RECURRING(2); + + final int index; + + private PlatformRecurrenceMode(final int index) { + this.index = index; + } + } + /** - * Pigeon version of Java Product. + * Pigeon version of Java QueryProductDetailsParams.Product. * *

Generated class from Pigeon that represents data sent in messages. */ - public static final class PlatformProduct { + public static final class PlatformQueryProduct { private @NonNull String productId; public @NonNull String getProductId() { @@ -136,7 +162,7 @@ public void setProductType(@NonNull PlatformProductType setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PlatformProduct() {} + PlatformQueryProduct() {} public static final class Builder { @@ -156,8 +182,8 @@ public static final class Builder { return this; } - public @NonNull PlatformProduct build() { - PlatformProduct pigeonReturn = new PlatformProduct(); + public @NonNull PlatformQueryProduct build() { + PlatformQueryProduct pigeonReturn = new PlatformQueryProduct(); pigeonReturn.setProductId(productId); pigeonReturn.setProductType(productType); return pigeonReturn; @@ -172,8 +198,8 @@ ArrayList toList() { return toListResult; } - static @NonNull PlatformProduct fromList(@NonNull ArrayList list) { - PlatformProduct pigeonResult = new PlatformProduct(); + static @NonNull PlatformQueryProduct fromList(@NonNull ArrayList list) { + PlatformQueryProduct pigeonResult = new PlatformQueryProduct(); Object productId = list.get(0); pigeonResult.setProductId((String) productId); Object productType = list.get(1); @@ -182,6 +208,76 @@ ArrayList toList() { } } + /** + * Pigeon version of Java AccountIdentifiers. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformAccountIdentifiers { + private @Nullable String obfuscatedAccountId; + + public @Nullable String getObfuscatedAccountId() { + return obfuscatedAccountId; + } + + public void setObfuscatedAccountId(@Nullable String setterArg) { + this.obfuscatedAccountId = setterArg; + } + + private @Nullable String obfuscatedProfileId; + + public @Nullable String getObfuscatedProfileId() { + return obfuscatedProfileId; + } + + public void setObfuscatedProfileId(@Nullable String setterArg) { + this.obfuscatedProfileId = setterArg; + } + + public static final class Builder { + + private @Nullable String obfuscatedAccountId; + + @CanIgnoreReturnValue + public @NonNull Builder setObfuscatedAccountId(@Nullable String setterArg) { + this.obfuscatedAccountId = setterArg; + return this; + } + + private @Nullable String obfuscatedProfileId; + + @CanIgnoreReturnValue + public @NonNull Builder setObfuscatedProfileId(@Nullable String setterArg) { + this.obfuscatedProfileId = setterArg; + return this; + } + + public @NonNull PlatformAccountIdentifiers build() { + PlatformAccountIdentifiers pigeonReturn = new PlatformAccountIdentifiers(); + pigeonReturn.setObfuscatedAccountId(obfuscatedAccountId); + pigeonReturn.setObfuscatedProfileId(obfuscatedProfileId); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(obfuscatedAccountId); + toListResult.add(obfuscatedProfileId); + return toListResult; + } + + static @NonNull PlatformAccountIdentifiers fromList(@NonNull ArrayList list) { + PlatformAccountIdentifiers pigeonResult = new PlatformAccountIdentifiers(); + Object obfuscatedAccountId = list.get(0); + pigeonResult.setObfuscatedAccountId((String) obfuscatedAccountId); + Object obfuscatedProfileId = list.get(1); + pigeonResult.setObfuscatedProfileId((String) obfuscatedProfileId); + return pigeonResult; + } + } + /** * Pigeon version of Java BillingResult. * @@ -264,6 +360,324 @@ ArrayList toList() { } } + /** + * Pigeon version of Java ProductDetails.OneTimePurchaseOfferDetails. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformOneTimePurchaseOfferDetails { + private @NonNull Long priceAmountMicros; + + public @NonNull Long getPriceAmountMicros() { + return priceAmountMicros; + } + + public void setPriceAmountMicros(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"priceAmountMicros\" is null."); + } + this.priceAmountMicros = setterArg; + } + + private @NonNull String formattedPrice; + + public @NonNull String getFormattedPrice() { + return formattedPrice; + } + + public void setFormattedPrice(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"formattedPrice\" is null."); + } + this.formattedPrice = setterArg; + } + + private @NonNull String priceCurrencyCode; + + public @NonNull String getPriceCurrencyCode() { + return priceCurrencyCode; + } + + public void setPriceCurrencyCode(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"priceCurrencyCode\" is null."); + } + this.priceCurrencyCode = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformOneTimePurchaseOfferDetails() {} + + public static final class Builder { + + private @Nullable Long priceAmountMicros; + + @CanIgnoreReturnValue + public @NonNull Builder setPriceAmountMicros(@NonNull Long setterArg) { + this.priceAmountMicros = setterArg; + return this; + } + + private @Nullable String formattedPrice; + + @CanIgnoreReturnValue + public @NonNull Builder setFormattedPrice(@NonNull String setterArg) { + this.formattedPrice = setterArg; + return this; + } + + private @Nullable String priceCurrencyCode; + + @CanIgnoreReturnValue + public @NonNull Builder setPriceCurrencyCode(@NonNull String setterArg) { + this.priceCurrencyCode = setterArg; + return this; + } + + public @NonNull PlatformOneTimePurchaseOfferDetails build() { + PlatformOneTimePurchaseOfferDetails pigeonReturn = + new PlatformOneTimePurchaseOfferDetails(); + pigeonReturn.setPriceAmountMicros(priceAmountMicros); + pigeonReturn.setFormattedPrice(formattedPrice); + pigeonReturn.setPriceCurrencyCode(priceCurrencyCode); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(3); + toListResult.add(priceAmountMicros); + toListResult.add(formattedPrice); + toListResult.add(priceCurrencyCode); + return toListResult; + } + + static @NonNull PlatformOneTimePurchaseOfferDetails fromList(@NonNull ArrayList list) { + PlatformOneTimePurchaseOfferDetails pigeonResult = new PlatformOneTimePurchaseOfferDetails(); + Object priceAmountMicros = list.get(0); + pigeonResult.setPriceAmountMicros( + (priceAmountMicros == null) + ? null + : ((priceAmountMicros instanceof Integer) + ? (Integer) priceAmountMicros + : (Long) priceAmountMicros)); + Object formattedPrice = list.get(1); + pigeonResult.setFormattedPrice((String) formattedPrice); + Object priceCurrencyCode = list.get(2); + pigeonResult.setPriceCurrencyCode((String) priceCurrencyCode); + return pigeonResult; + } + } + + /** + * Pigeon version of Java ProductDetails. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformProductDetails { + private @NonNull String description; + + public @NonNull String getDescription() { + return description; + } + + public void setDescription(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"description\" is null."); + } + this.description = setterArg; + } + + private @NonNull String name; + + public @NonNull String getName() { + return name; + } + + public void setName(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"name\" is null."); + } + this.name = setterArg; + } + + private @NonNull String productId; + + public @NonNull String getProductId() { + return productId; + } + + public void setProductId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"productId\" is null."); + } + this.productId = setterArg; + } + + private @NonNull PlatformProductType productType; + + public @NonNull PlatformProductType getProductType() { + return productType; + } + + public void setProductType(@NonNull PlatformProductType setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"productType\" is null."); + } + this.productType = setterArg; + } + + private @NonNull String title; + + public @NonNull String getTitle() { + return title; + } + + public void setTitle(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"title\" is null."); + } + this.title = setterArg; + } + + private @Nullable PlatformOneTimePurchaseOfferDetails oneTimePurchaseOfferDetails; + + public @Nullable PlatformOneTimePurchaseOfferDetails getOneTimePurchaseOfferDetails() { + return oneTimePurchaseOfferDetails; + } + + public void setOneTimePurchaseOfferDetails( + @Nullable PlatformOneTimePurchaseOfferDetails setterArg) { + this.oneTimePurchaseOfferDetails = setterArg; + } + + private @Nullable List subscriptionOfferDetails; + + public @Nullable List getSubscriptionOfferDetails() { + return subscriptionOfferDetails; + } + + public void setSubscriptionOfferDetails( + @Nullable List setterArg) { + this.subscriptionOfferDetails = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformProductDetails() {} + + public static final class Builder { + + private @Nullable String description; + + @CanIgnoreReturnValue + public @NonNull Builder setDescription(@NonNull String setterArg) { + this.description = setterArg; + return this; + } + + private @Nullable String name; + + @CanIgnoreReturnValue + public @NonNull Builder setName(@NonNull String setterArg) { + this.name = setterArg; + return this; + } + + private @Nullable String productId; + + @CanIgnoreReturnValue + public @NonNull Builder setProductId(@NonNull String setterArg) { + this.productId = setterArg; + return this; + } + + private @Nullable PlatformProductType productType; + + @CanIgnoreReturnValue + public @NonNull Builder setProductType(@NonNull PlatformProductType setterArg) { + this.productType = setterArg; + return this; + } + + private @Nullable String title; + + @CanIgnoreReturnValue + public @NonNull Builder setTitle(@NonNull String setterArg) { + this.title = setterArg; + return this; + } + + private @Nullable PlatformOneTimePurchaseOfferDetails oneTimePurchaseOfferDetails; + + @CanIgnoreReturnValue + public @NonNull Builder setOneTimePurchaseOfferDetails( + @Nullable PlatformOneTimePurchaseOfferDetails setterArg) { + this.oneTimePurchaseOfferDetails = setterArg; + return this; + } + + private @Nullable List subscriptionOfferDetails; + + @CanIgnoreReturnValue + public @NonNull Builder setSubscriptionOfferDetails( + @Nullable List setterArg) { + this.subscriptionOfferDetails = setterArg; + return this; + } + + public @NonNull PlatformProductDetails build() { + PlatformProductDetails pigeonReturn = new PlatformProductDetails(); + pigeonReturn.setDescription(description); + pigeonReturn.setName(name); + pigeonReturn.setProductId(productId); + pigeonReturn.setProductType(productType); + pigeonReturn.setTitle(title); + pigeonReturn.setOneTimePurchaseOfferDetails(oneTimePurchaseOfferDetails); + pigeonReturn.setSubscriptionOfferDetails(subscriptionOfferDetails); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(7); + toListResult.add(description); + toListResult.add(name); + toListResult.add(productId); + toListResult.add(productType == null ? null : productType.index); + toListResult.add(title); + toListResult.add( + (oneTimePurchaseOfferDetails == null) ? null : oneTimePurchaseOfferDetails.toList()); + toListResult.add(subscriptionOfferDetails); + return toListResult; + } + + static @NonNull PlatformProductDetails fromList(@NonNull ArrayList list) { + PlatformProductDetails pigeonResult = new PlatformProductDetails(); + Object description = list.get(0); + pigeonResult.setDescription((String) description); + Object name = list.get(1); + pigeonResult.setName((String) name); + Object productId = list.get(2); + pigeonResult.setProductId((String) productId); + Object productType = list.get(3); + pigeonResult.setProductType(PlatformProductType.values()[(int) productType]); + Object title = list.get(4); + pigeonResult.setTitle((String) title); + Object oneTimePurchaseOfferDetails = list.get(5); + pigeonResult.setOneTimePurchaseOfferDetails( + (oneTimePurchaseOfferDetails == null) + ? null + : PlatformOneTimePurchaseOfferDetails.fromList( + (ArrayList) oneTimePurchaseOfferDetails)); + Object subscriptionOfferDetails = list.get(6); + pigeonResult.setSubscriptionOfferDetails( + (List) subscriptionOfferDetails); + return pigeonResult; + } + } + /** * Pigeon version of ProductDetailsResponseWrapper, which contains the components of the Java * ProductDetailsResponseListener callback. @@ -284,21 +698,17 @@ public void setBillingResult(@NonNull PlatformBillingResult setterArg) { this.billingResult = setterArg; } - /** - * A JSON-compatible list of details, where each entry in the list is a Map - * JSON encoding of the product details. - */ - private @NonNull List productDetailsJsonList; + private @NonNull List productDetails; - public @NonNull List getProductDetailsJsonList() { - return productDetailsJsonList; + public @NonNull List getProductDetails() { + return productDetails; } - public void setProductDetailsJsonList(@NonNull List setterArg) { + public void setProductDetails(@NonNull List setterArg) { if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"productDetailsJsonList\" is null."); + throw new IllegalStateException("Nonnull field \"productDetails\" is null."); } - this.productDetailsJsonList = setterArg; + this.productDetails = setterArg; } /** Constructor is non-public to enforce null safety; use Builder. */ @@ -314,18 +724,18 @@ public static final class Builder { return this; } - private @Nullable List productDetailsJsonList; + private @Nullable List productDetails; @CanIgnoreReturnValue - public @NonNull Builder setProductDetailsJsonList(@NonNull List setterArg) { - this.productDetailsJsonList = setterArg; + public @NonNull Builder setProductDetails(@NonNull List setterArg) { + this.productDetails = setterArg; return this; } public @NonNull PlatformProductDetailsResponse build() { PlatformProductDetailsResponse pigeonReturn = new PlatformProductDetailsResponse(); pigeonReturn.setBillingResult(billingResult); - pigeonReturn.setProductDetailsJsonList(productDetailsJsonList); + pigeonReturn.setProductDetails(productDetails); return pigeonReturn; } } @@ -334,7 +744,7 @@ public static final class Builder { ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add((billingResult == null) ? null : billingResult.toList()); - toListResult.add(productDetailsJsonList); + toListResult.add(productDetails); return toListResult; } @@ -345,8 +755,8 @@ ArrayList toList() { (billingResult == null) ? null : PlatformBillingResult.fromList((ArrayList) billingResult)); - Object productDetailsJsonList = list.get(1); - pigeonResult.setProductDetailsJsonList((List) productDetailsJsonList); + Object productDetails = list.get(1); + pigeonResult.setProductDetails((List) productDetails); return pigeonResult; } } @@ -615,63 +1025,820 @@ public static final class Builder { return this; } - private @Nullable Long prorationMode; + private @Nullable Long prorationMode; + + @CanIgnoreReturnValue + public @NonNull Builder setProrationMode(@NonNull Long setterArg) { + this.prorationMode = setterArg; + return this; + } + + private @Nullable String offerToken; + + @CanIgnoreReturnValue + public @NonNull Builder setOfferToken(@Nullable String setterArg) { + this.offerToken = setterArg; + return this; + } + + private @Nullable String accountId; + + @CanIgnoreReturnValue + public @NonNull Builder setAccountId(@Nullable String setterArg) { + this.accountId = setterArg; + return this; + } + + private @Nullable String obfuscatedProfileId; + + @CanIgnoreReturnValue + public @NonNull Builder setObfuscatedProfileId(@Nullable String setterArg) { + this.obfuscatedProfileId = setterArg; + return this; + } + + private @Nullable String oldProduct; + + @CanIgnoreReturnValue + public @NonNull Builder setOldProduct(@Nullable String setterArg) { + this.oldProduct = setterArg; + return this; + } + + private @Nullable String purchaseToken; + + @CanIgnoreReturnValue + public @NonNull Builder setPurchaseToken(@Nullable String setterArg) { + this.purchaseToken = setterArg; + return this; + } + + public @NonNull PlatformBillingFlowParams build() { + PlatformBillingFlowParams pigeonReturn = new PlatformBillingFlowParams(); + pigeonReturn.setProduct(product); + pigeonReturn.setProrationMode(prorationMode); + pigeonReturn.setOfferToken(offerToken); + pigeonReturn.setAccountId(accountId); + pigeonReturn.setObfuscatedProfileId(obfuscatedProfileId); + pigeonReturn.setOldProduct(oldProduct); + pigeonReturn.setPurchaseToken(purchaseToken); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(7); + toListResult.add(product); + toListResult.add(prorationMode); + toListResult.add(offerToken); + toListResult.add(accountId); + toListResult.add(obfuscatedProfileId); + toListResult.add(oldProduct); + toListResult.add(purchaseToken); + return toListResult; + } + + static @NonNull PlatformBillingFlowParams fromList(@NonNull ArrayList list) { + PlatformBillingFlowParams pigeonResult = new PlatformBillingFlowParams(); + Object product = list.get(0); + pigeonResult.setProduct((String) product); + Object prorationMode = list.get(1); + pigeonResult.setProrationMode( + (prorationMode == null) + ? null + : ((prorationMode instanceof Integer) + ? (Integer) prorationMode + : (Long) prorationMode)); + Object offerToken = list.get(2); + pigeonResult.setOfferToken((String) offerToken); + Object accountId = list.get(3); + pigeonResult.setAccountId((String) accountId); + Object obfuscatedProfileId = list.get(4); + pigeonResult.setObfuscatedProfileId((String) obfuscatedProfileId); + Object oldProduct = list.get(5); + pigeonResult.setOldProduct((String) oldProduct); + Object purchaseToken = list.get(6); + pigeonResult.setPurchaseToken((String) purchaseToken); + return pigeonResult; + } + } + + /** + * Pigeon version of Java ProductDetails.PricingPhase. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformPricingPhase { + private @NonNull Long billingCycleCount; + + public @NonNull Long getBillingCycleCount() { + return billingCycleCount; + } + + public void setBillingCycleCount(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"billingCycleCount\" is null."); + } + this.billingCycleCount = setterArg; + } + + private @NonNull PlatformRecurrenceMode recurrenceMode; + + public @NonNull PlatformRecurrenceMode getRecurrenceMode() { + return recurrenceMode; + } + + public void setRecurrenceMode(@NonNull PlatformRecurrenceMode setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"recurrenceMode\" is null."); + } + this.recurrenceMode = setterArg; + } + + private @NonNull Long priceAmountMicros; + + public @NonNull Long getPriceAmountMicros() { + return priceAmountMicros; + } + + public void setPriceAmountMicros(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"priceAmountMicros\" is null."); + } + this.priceAmountMicros = setterArg; + } + + private @NonNull String billingPeriod; + + public @NonNull String getBillingPeriod() { + return billingPeriod; + } + + public void setBillingPeriod(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"billingPeriod\" is null."); + } + this.billingPeriod = setterArg; + } + + private @NonNull String formattedPrice; + + public @NonNull String getFormattedPrice() { + return formattedPrice; + } + + public void setFormattedPrice(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"formattedPrice\" is null."); + } + this.formattedPrice = setterArg; + } + + private @NonNull String priceCurrencyCode; + + public @NonNull String getPriceCurrencyCode() { + return priceCurrencyCode; + } + + public void setPriceCurrencyCode(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"priceCurrencyCode\" is null."); + } + this.priceCurrencyCode = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformPricingPhase() {} + + public static final class Builder { + + private @Nullable Long billingCycleCount; + + @CanIgnoreReturnValue + public @NonNull Builder setBillingCycleCount(@NonNull Long setterArg) { + this.billingCycleCount = setterArg; + return this; + } + + private @Nullable PlatformRecurrenceMode recurrenceMode; + + @CanIgnoreReturnValue + public @NonNull Builder setRecurrenceMode(@NonNull PlatformRecurrenceMode setterArg) { + this.recurrenceMode = setterArg; + return this; + } + + private @Nullable Long priceAmountMicros; + + @CanIgnoreReturnValue + public @NonNull Builder setPriceAmountMicros(@NonNull Long setterArg) { + this.priceAmountMicros = setterArg; + return this; + } + + private @Nullable String billingPeriod; + + @CanIgnoreReturnValue + public @NonNull Builder setBillingPeriod(@NonNull String setterArg) { + this.billingPeriod = setterArg; + return this; + } + + private @Nullable String formattedPrice; + + @CanIgnoreReturnValue + public @NonNull Builder setFormattedPrice(@NonNull String setterArg) { + this.formattedPrice = setterArg; + return this; + } + + private @Nullable String priceCurrencyCode; + + @CanIgnoreReturnValue + public @NonNull Builder setPriceCurrencyCode(@NonNull String setterArg) { + this.priceCurrencyCode = setterArg; + return this; + } + + public @NonNull PlatformPricingPhase build() { + PlatformPricingPhase pigeonReturn = new PlatformPricingPhase(); + pigeonReturn.setBillingCycleCount(billingCycleCount); + pigeonReturn.setRecurrenceMode(recurrenceMode); + pigeonReturn.setPriceAmountMicros(priceAmountMicros); + pigeonReturn.setBillingPeriod(billingPeriod); + pigeonReturn.setFormattedPrice(formattedPrice); + pigeonReturn.setPriceCurrencyCode(priceCurrencyCode); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(6); + toListResult.add(billingCycleCount); + toListResult.add(recurrenceMode == null ? null : recurrenceMode.index); + toListResult.add(priceAmountMicros); + toListResult.add(billingPeriod); + toListResult.add(formattedPrice); + toListResult.add(priceCurrencyCode); + return toListResult; + } + + static @NonNull PlatformPricingPhase fromList(@NonNull ArrayList list) { + PlatformPricingPhase pigeonResult = new PlatformPricingPhase(); + Object billingCycleCount = list.get(0); + pigeonResult.setBillingCycleCount( + (billingCycleCount == null) + ? null + : ((billingCycleCount instanceof Integer) + ? (Integer) billingCycleCount + : (Long) billingCycleCount)); + Object recurrenceMode = list.get(1); + pigeonResult.setRecurrenceMode(PlatformRecurrenceMode.values()[(int) recurrenceMode]); + Object priceAmountMicros = list.get(2); + pigeonResult.setPriceAmountMicros( + (priceAmountMicros == null) + ? null + : ((priceAmountMicros instanceof Integer) + ? (Integer) priceAmountMicros + : (Long) priceAmountMicros)); + Object billingPeriod = list.get(3); + pigeonResult.setBillingPeriod((String) billingPeriod); + Object formattedPrice = list.get(4); + pigeonResult.setFormattedPrice((String) formattedPrice); + Object priceCurrencyCode = list.get(5); + pigeonResult.setPriceCurrencyCode((String) priceCurrencyCode); + return pigeonResult; + } + } + + /** + * Pigeon version of Java Purchase. + * + *

See also PurchaseWrapper on the Dart side. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformPurchase { + private @Nullable String orderId; + + public @Nullable String getOrderId() { + return orderId; + } + + public void setOrderId(@Nullable String setterArg) { + this.orderId = setterArg; + } + + private @NonNull String packageName; + + public @NonNull String getPackageName() { + return packageName; + } + + public void setPackageName(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"packageName\" is null."); + } + this.packageName = setterArg; + } + + private @NonNull Long purchaseTime; + + public @NonNull Long getPurchaseTime() { + return purchaseTime; + } + + public void setPurchaseTime(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"purchaseTime\" is null."); + } + this.purchaseTime = setterArg; + } + + private @NonNull String purchaseToken; + + public @NonNull String getPurchaseToken() { + return purchaseToken; + } + + public void setPurchaseToken(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"purchaseToken\" is null."); + } + this.purchaseToken = setterArg; + } + + private @NonNull String signature; + + public @NonNull String getSignature() { + return signature; + } + + public void setSignature(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"signature\" is null."); + } + this.signature = setterArg; + } + + private @NonNull List products; + + public @NonNull List getProducts() { + return products; + } + + public void setProducts(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"products\" is null."); + } + this.products = setterArg; + } + + private @NonNull Boolean isAutoRenewing; + + public @NonNull Boolean getIsAutoRenewing() { + return isAutoRenewing; + } + + public void setIsAutoRenewing(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"isAutoRenewing\" is null."); + } + this.isAutoRenewing = setterArg; + } + + private @NonNull String originalJson; + + public @NonNull String getOriginalJson() { + return originalJson; + } + + public void setOriginalJson(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"originalJson\" is null."); + } + this.originalJson = setterArg; + } + + private @NonNull String developerPayload; + + public @NonNull String getDeveloperPayload() { + return developerPayload; + } + + public void setDeveloperPayload(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"developerPayload\" is null."); + } + this.developerPayload = setterArg; + } + + private @NonNull Boolean isAcknowledged; + + public @NonNull Boolean getIsAcknowledged() { + return isAcknowledged; + } + + public void setIsAcknowledged(@NonNull Boolean setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"isAcknowledged\" is null."); + } + this.isAcknowledged = setterArg; + } + + private @NonNull Long quantity; + + public @NonNull Long getQuantity() { + return quantity; + } + + public void setQuantity(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"quantity\" is null."); + } + this.quantity = setterArg; + } + + private @NonNull PlatformPurchaseState purchaseState; + + public @NonNull PlatformPurchaseState getPurchaseState() { + return purchaseState; + } + + public void setPurchaseState(@NonNull PlatformPurchaseState setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"purchaseState\" is null."); + } + this.purchaseState = setterArg; + } + + private @Nullable PlatformAccountIdentifiers accountIdentifiers; + + public @Nullable PlatformAccountIdentifiers getAccountIdentifiers() { + return accountIdentifiers; + } + + public void setAccountIdentifiers(@Nullable PlatformAccountIdentifiers setterArg) { + this.accountIdentifiers = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformPurchase() {} + + public static final class Builder { + + private @Nullable String orderId; + + @CanIgnoreReturnValue + public @NonNull Builder setOrderId(@Nullable String setterArg) { + this.orderId = setterArg; + return this; + } + + private @Nullable String packageName; + + @CanIgnoreReturnValue + public @NonNull Builder setPackageName(@NonNull String setterArg) { + this.packageName = setterArg; + return this; + } + + private @Nullable Long purchaseTime; + + @CanIgnoreReturnValue + public @NonNull Builder setPurchaseTime(@NonNull Long setterArg) { + this.purchaseTime = setterArg; + return this; + } + + private @Nullable String purchaseToken; + + @CanIgnoreReturnValue + public @NonNull Builder setPurchaseToken(@NonNull String setterArg) { + this.purchaseToken = setterArg; + return this; + } + + private @Nullable String signature; + + @CanIgnoreReturnValue + public @NonNull Builder setSignature(@NonNull String setterArg) { + this.signature = setterArg; + return this; + } + + private @Nullable List products; + + @CanIgnoreReturnValue + public @NonNull Builder setProducts(@NonNull List setterArg) { + this.products = setterArg; + return this; + } + + private @Nullable Boolean isAutoRenewing; + + @CanIgnoreReturnValue + public @NonNull Builder setIsAutoRenewing(@NonNull Boolean setterArg) { + this.isAutoRenewing = setterArg; + return this; + } + + private @Nullable String originalJson; + + @CanIgnoreReturnValue + public @NonNull Builder setOriginalJson(@NonNull String setterArg) { + this.originalJson = setterArg; + return this; + } + + private @Nullable String developerPayload; + + @CanIgnoreReturnValue + public @NonNull Builder setDeveloperPayload(@NonNull String setterArg) { + this.developerPayload = setterArg; + return this; + } + + private @Nullable Boolean isAcknowledged; + + @CanIgnoreReturnValue + public @NonNull Builder setIsAcknowledged(@NonNull Boolean setterArg) { + this.isAcknowledged = setterArg; + return this; + } + + private @Nullable Long quantity; + + @CanIgnoreReturnValue + public @NonNull Builder setQuantity(@NonNull Long setterArg) { + this.quantity = setterArg; + return this; + } + + private @Nullable PlatformPurchaseState purchaseState; + + @CanIgnoreReturnValue + public @NonNull Builder setPurchaseState(@NonNull PlatformPurchaseState setterArg) { + this.purchaseState = setterArg; + return this; + } + + private @Nullable PlatformAccountIdentifiers accountIdentifiers; + + @CanIgnoreReturnValue + public @NonNull Builder setAccountIdentifiers( + @Nullable PlatformAccountIdentifiers setterArg) { + this.accountIdentifiers = setterArg; + return this; + } + + public @NonNull PlatformPurchase build() { + PlatformPurchase pigeonReturn = new PlatformPurchase(); + pigeonReturn.setOrderId(orderId); + pigeonReturn.setPackageName(packageName); + pigeonReturn.setPurchaseTime(purchaseTime); + pigeonReturn.setPurchaseToken(purchaseToken); + pigeonReturn.setSignature(signature); + pigeonReturn.setProducts(products); + pigeonReturn.setIsAutoRenewing(isAutoRenewing); + pigeonReturn.setOriginalJson(originalJson); + pigeonReturn.setDeveloperPayload(developerPayload); + pigeonReturn.setIsAcknowledged(isAcknowledged); + pigeonReturn.setQuantity(quantity); + pigeonReturn.setPurchaseState(purchaseState); + pigeonReturn.setAccountIdentifiers(accountIdentifiers); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(13); + toListResult.add(orderId); + toListResult.add(packageName); + toListResult.add(purchaseTime); + toListResult.add(purchaseToken); + toListResult.add(signature); + toListResult.add(products); + toListResult.add(isAutoRenewing); + toListResult.add(originalJson); + toListResult.add(developerPayload); + toListResult.add(isAcknowledged); + toListResult.add(quantity); + toListResult.add(purchaseState == null ? null : purchaseState.index); + toListResult.add((accountIdentifiers == null) ? null : accountIdentifiers.toList()); + return toListResult; + } + + static @NonNull PlatformPurchase fromList(@NonNull ArrayList list) { + PlatformPurchase pigeonResult = new PlatformPurchase(); + Object orderId = list.get(0); + pigeonResult.setOrderId((String) orderId); + Object packageName = list.get(1); + pigeonResult.setPackageName((String) packageName); + Object purchaseTime = list.get(2); + pigeonResult.setPurchaseTime( + (purchaseTime == null) + ? null + : ((purchaseTime instanceof Integer) ? (Integer) purchaseTime : (Long) purchaseTime)); + Object purchaseToken = list.get(3); + pigeonResult.setPurchaseToken((String) purchaseToken); + Object signature = list.get(4); + pigeonResult.setSignature((String) signature); + Object products = list.get(5); + pigeonResult.setProducts((List) products); + Object isAutoRenewing = list.get(6); + pigeonResult.setIsAutoRenewing((Boolean) isAutoRenewing); + Object originalJson = list.get(7); + pigeonResult.setOriginalJson((String) originalJson); + Object developerPayload = list.get(8); + pigeonResult.setDeveloperPayload((String) developerPayload); + Object isAcknowledged = list.get(9); + pigeonResult.setIsAcknowledged((Boolean) isAcknowledged); + Object quantity = list.get(10); + pigeonResult.setQuantity( + (quantity == null) + ? null + : ((quantity instanceof Integer) ? (Integer) quantity : (Long) quantity)); + Object purchaseState = list.get(11); + pigeonResult.setPurchaseState(PlatformPurchaseState.values()[(int) purchaseState]); + Object accountIdentifiers = list.get(12); + pigeonResult.setAccountIdentifiers( + (accountIdentifiers == null) + ? null + : PlatformAccountIdentifiers.fromList((ArrayList) accountIdentifiers)); + return pigeonResult; + } + } + + /** + * Pigeon version of PurchaseHistoryRecord. + * + *

See also PurchaseHistoryRecordWrapper on the Dart side. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformPurchaseHistoryRecord { + private @NonNull Long quantity; + + public @NonNull Long getQuantity() { + return quantity; + } + + public void setQuantity(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"quantity\" is null."); + } + this.quantity = setterArg; + } + + private @NonNull Long purchaseTime; + + public @NonNull Long getPurchaseTime() { + return purchaseTime; + } + + public void setPurchaseTime(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"purchaseTime\" is null."); + } + this.purchaseTime = setterArg; + } + + private @Nullable String developerPayload; + + public @Nullable String getDeveloperPayload() { + return developerPayload; + } + + public void setDeveloperPayload(@Nullable String setterArg) { + this.developerPayload = setterArg; + } + + private @NonNull String originalJson; + + public @NonNull String getOriginalJson() { + return originalJson; + } + + public void setOriginalJson(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"originalJson\" is null."); + } + this.originalJson = setterArg; + } + + private @NonNull String purchaseToken; + + public @NonNull String getPurchaseToken() { + return purchaseToken; + } + + public void setPurchaseToken(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"purchaseToken\" is null."); + } + this.purchaseToken = setterArg; + } + + private @NonNull String signature; + + public @NonNull String getSignature() { + return signature; + } + + public void setSignature(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"signature\" is null."); + } + this.signature = setterArg; + } + + private @NonNull List products; + + public @NonNull List getProducts() { + return products; + } + + public void setProducts(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"products\" is null."); + } + this.products = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformPurchaseHistoryRecord() {} + + public static final class Builder { + + private @Nullable Long quantity; + + @CanIgnoreReturnValue + public @NonNull Builder setQuantity(@NonNull Long setterArg) { + this.quantity = setterArg; + return this; + } + + private @Nullable Long purchaseTime; @CanIgnoreReturnValue - public @NonNull Builder setProrationMode(@NonNull Long setterArg) { - this.prorationMode = setterArg; + public @NonNull Builder setPurchaseTime(@NonNull Long setterArg) { + this.purchaseTime = setterArg; return this; } - private @Nullable String offerToken; + private @Nullable String developerPayload; @CanIgnoreReturnValue - public @NonNull Builder setOfferToken(@Nullable String setterArg) { - this.offerToken = setterArg; + public @NonNull Builder setDeveloperPayload(@Nullable String setterArg) { + this.developerPayload = setterArg; return this; } - private @Nullable String accountId; + private @Nullable String originalJson; @CanIgnoreReturnValue - public @NonNull Builder setAccountId(@Nullable String setterArg) { - this.accountId = setterArg; + public @NonNull Builder setOriginalJson(@NonNull String setterArg) { + this.originalJson = setterArg; return this; } - private @Nullable String obfuscatedProfileId; + private @Nullable String purchaseToken; @CanIgnoreReturnValue - public @NonNull Builder setObfuscatedProfileId(@Nullable String setterArg) { - this.obfuscatedProfileId = setterArg; + public @NonNull Builder setPurchaseToken(@NonNull String setterArg) { + this.purchaseToken = setterArg; return this; } - private @Nullable String oldProduct; + private @Nullable String signature; @CanIgnoreReturnValue - public @NonNull Builder setOldProduct(@Nullable String setterArg) { - this.oldProduct = setterArg; + public @NonNull Builder setSignature(@NonNull String setterArg) { + this.signature = setterArg; return this; } - private @Nullable String purchaseToken; + private @Nullable List products; @CanIgnoreReturnValue - public @NonNull Builder setPurchaseToken(@Nullable String setterArg) { - this.purchaseToken = setterArg; + public @NonNull Builder setProducts(@NonNull List setterArg) { + this.products = setterArg; return this; } - public @NonNull PlatformBillingFlowParams build() { - PlatformBillingFlowParams pigeonReturn = new PlatformBillingFlowParams(); - pigeonReturn.setProduct(product); - pigeonReturn.setProrationMode(prorationMode); - pigeonReturn.setOfferToken(offerToken); - pigeonReturn.setAccountId(accountId); - pigeonReturn.setObfuscatedProfileId(obfuscatedProfileId); - pigeonReturn.setOldProduct(oldProduct); + public @NonNull PlatformPurchaseHistoryRecord build() { + PlatformPurchaseHistoryRecord pigeonReturn = new PlatformPurchaseHistoryRecord(); + pigeonReturn.setQuantity(quantity); + pigeonReturn.setPurchaseTime(purchaseTime); + pigeonReturn.setDeveloperPayload(developerPayload); + pigeonReturn.setOriginalJson(originalJson); pigeonReturn.setPurchaseToken(purchaseToken); + pigeonReturn.setSignature(signature); + pigeonReturn.setProducts(products); return pigeonReturn; } } @@ -679,37 +1846,38 @@ public static final class Builder { @NonNull ArrayList toList() { ArrayList toListResult = new ArrayList(7); - toListResult.add(product); - toListResult.add(prorationMode); - toListResult.add(offerToken); - toListResult.add(accountId); - toListResult.add(obfuscatedProfileId); - toListResult.add(oldProduct); + toListResult.add(quantity); + toListResult.add(purchaseTime); + toListResult.add(developerPayload); + toListResult.add(originalJson); toListResult.add(purchaseToken); + toListResult.add(signature); + toListResult.add(products); return toListResult; } - static @NonNull PlatformBillingFlowParams fromList(@NonNull ArrayList list) { - PlatformBillingFlowParams pigeonResult = new PlatformBillingFlowParams(); - Object product = list.get(0); - pigeonResult.setProduct((String) product); - Object prorationMode = list.get(1); - pigeonResult.setProrationMode( - (prorationMode == null) + static @NonNull PlatformPurchaseHistoryRecord fromList(@NonNull ArrayList list) { + PlatformPurchaseHistoryRecord pigeonResult = new PlatformPurchaseHistoryRecord(); + Object quantity = list.get(0); + pigeonResult.setQuantity( + (quantity == null) ? null - : ((prorationMode instanceof Integer) - ? (Integer) prorationMode - : (Long) prorationMode)); - Object offerToken = list.get(2); - pigeonResult.setOfferToken((String) offerToken); - Object accountId = list.get(3); - pigeonResult.setAccountId((String) accountId); - Object obfuscatedProfileId = list.get(4); - pigeonResult.setObfuscatedProfileId((String) obfuscatedProfileId); - Object oldProduct = list.get(5); - pigeonResult.setOldProduct((String) oldProduct); - Object purchaseToken = list.get(6); + : ((quantity instanceof Integer) ? (Integer) quantity : (Long) quantity)); + Object purchaseTime = list.get(1); + pigeonResult.setPurchaseTime( + (purchaseTime == null) + ? null + : ((purchaseTime instanceof Integer) ? (Integer) purchaseTime : (Long) purchaseTime)); + Object developerPayload = list.get(2); + pigeonResult.setDeveloperPayload((String) developerPayload); + Object originalJson = list.get(3); + pigeonResult.setOriginalJson((String) originalJson); + Object purchaseToken = list.get(4); pigeonResult.setPurchaseToken((String) purchaseToken); + Object signature = list.get(5); + pigeonResult.setSignature((String) signature); + Object products = list.get(6); + pigeonResult.setProducts((List) products); return pigeonResult; } } @@ -734,21 +1902,17 @@ public void setBillingResult(@NonNull PlatformBillingResult setterArg) { this.billingResult = setterArg; } - /** - * A JSON-compatible list of purchase history records, where each entry in the list is a - * Map JSON encoding of the record. - */ - private @NonNull List purchaseHistoryRecordJsonList; + private @NonNull List purchases; - public @NonNull List getPurchaseHistoryRecordJsonList() { - return purchaseHistoryRecordJsonList; + public @NonNull List getPurchases() { + return purchases; } - public void setPurchaseHistoryRecordJsonList(@NonNull List setterArg) { + public void setPurchases(@NonNull List setterArg) { if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"purchaseHistoryRecordJsonList\" is null."); + throw new IllegalStateException("Nonnull field \"purchases\" is null."); } - this.purchaseHistoryRecordJsonList = setterArg; + this.purchases = setterArg; } /** Constructor is non-public to enforce null safety; use Builder. */ @@ -764,18 +1928,18 @@ public static final class Builder { return this; } - private @Nullable List purchaseHistoryRecordJsonList; + private @Nullable List purchases; @CanIgnoreReturnValue - public @NonNull Builder setPurchaseHistoryRecordJsonList(@NonNull List setterArg) { - this.purchaseHistoryRecordJsonList = setterArg; + public @NonNull Builder setPurchases(@NonNull List setterArg) { + this.purchases = setterArg; return this; } public @NonNull PlatformPurchaseHistoryResponse build() { PlatformPurchaseHistoryResponse pigeonReturn = new PlatformPurchaseHistoryResponse(); pigeonReturn.setBillingResult(billingResult); - pigeonReturn.setPurchaseHistoryRecordJsonList(purchaseHistoryRecordJsonList); + pigeonReturn.setPurchases(purchases); return pigeonReturn; } } @@ -784,7 +1948,7 @@ public static final class Builder { ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add((billingResult == null) ? null : billingResult.toList()); - toListResult.add(purchaseHistoryRecordJsonList); + toListResult.add(purchases); return toListResult; } @@ -795,8 +1959,8 @@ ArrayList toList() { (billingResult == null) ? null : PlatformBillingResult.fromList((ArrayList) billingResult)); - Object purchaseHistoryRecordJsonList = list.get(1); - pigeonResult.setPurchaseHistoryRecordJsonList((List) purchaseHistoryRecordJsonList); + Object purchases = list.get(1); + pigeonResult.setPurchases((List) purchases); return pigeonResult; } } @@ -821,21 +1985,17 @@ public void setBillingResult(@NonNull PlatformBillingResult setterArg) { this.billingResult = setterArg; } - /** - * A JSON-compatible list of purchases, where each entry in the list is a Map - * JSON encoding of the product details. - */ - private @NonNull List purchasesJsonList; + private @NonNull List purchases; - public @NonNull List getPurchasesJsonList() { - return purchasesJsonList; + public @NonNull List getPurchases() { + return purchases; } - public void setPurchasesJsonList(@NonNull List setterArg) { + public void setPurchases(@NonNull List setterArg) { if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"purchasesJsonList\" is null."); + throw new IllegalStateException("Nonnull field \"purchases\" is null."); } - this.purchasesJsonList = setterArg; + this.purchases = setterArg; } /** Constructor is non-public to enforce null safety; use Builder. */ @@ -851,18 +2011,18 @@ public static final class Builder { return this; } - private @Nullable List purchasesJsonList; + private @Nullable List purchases; @CanIgnoreReturnValue - public @NonNull Builder setPurchasesJsonList(@NonNull List setterArg) { - this.purchasesJsonList = setterArg; + public @NonNull Builder setPurchases(@NonNull List setterArg) { + this.purchases = setterArg; return this; } public @NonNull PlatformPurchasesResponse build() { PlatformPurchasesResponse pigeonReturn = new PlatformPurchasesResponse(); pigeonReturn.setBillingResult(billingResult); - pigeonReturn.setPurchasesJsonList(purchasesJsonList); + pigeonReturn.setPurchases(purchases); return pigeonReturn; } } @@ -871,7 +2031,7 @@ public static final class Builder { ArrayList toList() { ArrayList toListResult = new ArrayList(2); toListResult.add((billingResult == null) ? null : billingResult.toList()); - toListResult.add(purchasesJsonList); + toListResult.add(purchases); return toListResult; } @@ -882,8 +2042,159 @@ ArrayList toList() { (billingResult == null) ? null : PlatformBillingResult.fromList((ArrayList) billingResult)); - Object purchasesJsonList = list.get(1); - pigeonResult.setPurchasesJsonList((List) purchasesJsonList); + Object purchases = list.get(1); + pigeonResult.setPurchases((List) purchases); + return pigeonResult; + } + } + + /** + * Pigeon version of Java ProductDetails.SubscriptionOfferDetails. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformSubscriptionOfferDetails { + private @NonNull String basePlanId; + + public @NonNull String getBasePlanId() { + return basePlanId; + } + + public void setBasePlanId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"basePlanId\" is null."); + } + this.basePlanId = setterArg; + } + + private @Nullable String offerId; + + public @Nullable String getOfferId() { + return offerId; + } + + public void setOfferId(@Nullable String setterArg) { + this.offerId = setterArg; + } + + private @NonNull String offerToken; + + public @NonNull String getOfferToken() { + return offerToken; + } + + public void setOfferToken(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"offerToken\" is null."); + } + this.offerToken = setterArg; + } + + private @NonNull List offerTags; + + public @NonNull List getOfferTags() { + return offerTags; + } + + public void setOfferTags(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"offerTags\" is null."); + } + this.offerTags = setterArg; + } + + private @NonNull List pricingPhases; + + public @NonNull List getPricingPhases() { + return pricingPhases; + } + + public void setPricingPhases(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"pricingPhases\" is null."); + } + this.pricingPhases = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformSubscriptionOfferDetails() {} + + public static final class Builder { + + private @Nullable String basePlanId; + + @CanIgnoreReturnValue + public @NonNull Builder setBasePlanId(@NonNull String setterArg) { + this.basePlanId = setterArg; + return this; + } + + private @Nullable String offerId; + + @CanIgnoreReturnValue + public @NonNull Builder setOfferId(@Nullable String setterArg) { + this.offerId = setterArg; + return this; + } + + private @Nullable String offerToken; + + @CanIgnoreReturnValue + public @NonNull Builder setOfferToken(@NonNull String setterArg) { + this.offerToken = setterArg; + return this; + } + + private @Nullable List offerTags; + + @CanIgnoreReturnValue + public @NonNull Builder setOfferTags(@NonNull List setterArg) { + this.offerTags = setterArg; + return this; + } + + private @Nullable List pricingPhases; + + @CanIgnoreReturnValue + public @NonNull Builder setPricingPhases(@NonNull List setterArg) { + this.pricingPhases = setterArg; + return this; + } + + public @NonNull PlatformSubscriptionOfferDetails build() { + PlatformSubscriptionOfferDetails pigeonReturn = new PlatformSubscriptionOfferDetails(); + pigeonReturn.setBasePlanId(basePlanId); + pigeonReturn.setOfferId(offerId); + pigeonReturn.setOfferToken(offerToken); + pigeonReturn.setOfferTags(offerTags); + pigeonReturn.setPricingPhases(pricingPhases); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(5); + toListResult.add(basePlanId); + toListResult.add(offerId); + toListResult.add(offerToken); + toListResult.add(offerTags); + toListResult.add(pricingPhases); + return toListResult; + } + + static @NonNull PlatformSubscriptionOfferDetails fromList(@NonNull ArrayList list) { + PlatformSubscriptionOfferDetails pigeonResult = new PlatformSubscriptionOfferDetails(); + Object basePlanId = list.get(0); + pigeonResult.setBasePlanId((String) basePlanId); + Object offerId = list.get(1); + pigeonResult.setOfferId((String) offerId); + Object offerToken = list.get(2); + pigeonResult.setOfferToken((String) offerToken); + Object offerTags = list.get(3); + pigeonResult.setOfferTags((List) offerTags); + Object pricingPhases = list.get(4); + pigeonResult.setPricingPhases((List) pricingPhases); return pigeonResult; } } @@ -917,21 +2228,17 @@ public void setExternalTransactionToken(@NonNull String setterArg) { this.externalTransactionToken = setterArg; } - /** - * A JSON-compatible list of products, where each entry in the list is a Map - * JSON encoding of the product. - */ - private @NonNull List productsJsonList; + private @NonNull List products; - public @NonNull List getProductsJsonList() { - return productsJsonList; + public @NonNull List getProducts() { + return products; } - public void setProductsJsonList(@NonNull List setterArg) { + public void setProducts(@NonNull List setterArg) { if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"productsJsonList\" is null."); + throw new IllegalStateException("Nonnull field \"products\" is null."); } - this.productsJsonList = setterArg; + this.products = setterArg; } /** Constructor is non-public to enforce null safety; use Builder. */ @@ -955,11 +2262,11 @@ public static final class Builder { return this; } - private @Nullable List productsJsonList; + private @Nullable List products; @CanIgnoreReturnValue - public @NonNull Builder setProductsJsonList(@NonNull List setterArg) { - this.productsJsonList = setterArg; + public @NonNull Builder setProducts(@NonNull List setterArg) { + this.products = setterArg; return this; } @@ -967,7 +2274,7 @@ public static final class Builder { PlatformUserChoiceDetails pigeonReturn = new PlatformUserChoiceDetails(); pigeonReturn.setOriginalExternalTransactionId(originalExternalTransactionId); pigeonReturn.setExternalTransactionToken(externalTransactionToken); - pigeonReturn.setProductsJsonList(productsJsonList); + pigeonReturn.setProducts(products); return pigeonReturn; } } @@ -977,7 +2284,7 @@ ArrayList toList() { ArrayList toListResult = new ArrayList(3); toListResult.add(originalExternalTransactionId); toListResult.add(externalTransactionToken); - toListResult.add(productsJsonList); + toListResult.add(products); return toListResult; } @@ -987,8 +2294,109 @@ ArrayList toList() { pigeonResult.setOriginalExternalTransactionId((String) originalExternalTransactionId); Object externalTransactionToken = list.get(1); pigeonResult.setExternalTransactionToken((String) externalTransactionToken); - Object productsJsonList = list.get(2); - pigeonResult.setProductsJsonList((List) productsJsonList); + Object products = list.get(2); + pigeonResult.setProducts((List) products); + return pigeonResult; + } + } + + /** + * Pigeon version of UserChoiseDetails.Product. + * + *

Generated class from Pigeon that represents data sent in messages. + */ + public static final class PlatformUserChoiceProduct { + private @NonNull String id; + + public @NonNull String getId() { + return id; + } + + public void setId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"id\" is null."); + } + this.id = setterArg; + } + + private @Nullable String offerToken; + + public @Nullable String getOfferToken() { + return offerToken; + } + + public void setOfferToken(@Nullable String setterArg) { + this.offerToken = setterArg; + } + + private @NonNull PlatformProductType type; + + public @NonNull PlatformProductType getType() { + return type; + } + + public void setType(@NonNull PlatformProductType setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"type\" is null."); + } + this.type = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PlatformUserChoiceProduct() {} + + public static final class Builder { + + private @Nullable String id; + + @CanIgnoreReturnValue + public @NonNull Builder setId(@NonNull String setterArg) { + this.id = setterArg; + return this; + } + + private @Nullable String offerToken; + + @CanIgnoreReturnValue + public @NonNull Builder setOfferToken(@Nullable String setterArg) { + this.offerToken = setterArg; + return this; + } + + private @Nullable PlatformProductType type; + + @CanIgnoreReturnValue + public @NonNull Builder setType(@NonNull PlatformProductType setterArg) { + this.type = setterArg; + return this; + } + + public @NonNull PlatformUserChoiceProduct build() { + PlatformUserChoiceProduct pigeonReturn = new PlatformUserChoiceProduct(); + pigeonReturn.setId(id); + pigeonReturn.setOfferToken(offerToken); + pigeonReturn.setType(type); + return pigeonReturn; + } + } + + @NonNull + ArrayList toList() { + ArrayList toListResult = new ArrayList(3); + toListResult.add(id); + toListResult.add(offerToken); + toListResult.add(type == null ? null : type.index); + return toListResult; + } + + static @NonNull PlatformUserChoiceProduct fromList(@NonNull ArrayList list) { + PlatformUserChoiceProduct pigeonResult = new PlatformUserChoiceProduct(); + Object id = list.get(0); + pigeonResult.setId((String) id); + Object offerToken = list.get(1); + pigeonResult.setOfferToken((String) offerToken); + Object type = list.get(2); + pigeonResult.setType(PlatformProductType.values()[(int) type]); return pigeonResult; } } @@ -1027,22 +2435,37 @@ private InAppPurchaseApiCodec() {} protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { switch (type) { case (byte) 128: + return PlatformAccountIdentifiers.fromList((ArrayList) readValue(buffer)); + case (byte) 129: return PlatformAlternativeBillingOnlyReportingDetailsResponse.fromList( (ArrayList) readValue(buffer)); - case (byte) 129: - return PlatformBillingConfigResponse.fromList((ArrayList) readValue(buffer)); case (byte) 130: - return PlatformBillingFlowParams.fromList((ArrayList) readValue(buffer)); + return PlatformBillingConfigResponse.fromList((ArrayList) readValue(buffer)); case (byte) 131: - return PlatformBillingResult.fromList((ArrayList) readValue(buffer)); + return PlatformBillingFlowParams.fromList((ArrayList) readValue(buffer)); case (byte) 132: - return PlatformProduct.fromList((ArrayList) readValue(buffer)); + return PlatformBillingResult.fromList((ArrayList) readValue(buffer)); case (byte) 133: - return PlatformProductDetailsResponse.fromList((ArrayList) readValue(buffer)); + return PlatformOneTimePurchaseOfferDetails.fromList( + (ArrayList) readValue(buffer)); case (byte) 134: - return PlatformPurchaseHistoryResponse.fromList((ArrayList) readValue(buffer)); + return PlatformPricingPhase.fromList((ArrayList) readValue(buffer)); case (byte) 135: + return PlatformProductDetails.fromList((ArrayList) readValue(buffer)); + case (byte) 136: + return PlatformProductDetailsResponse.fromList((ArrayList) readValue(buffer)); + case (byte) 137: + return PlatformPurchase.fromList((ArrayList) readValue(buffer)); + case (byte) 138: + return PlatformPurchaseHistoryRecord.fromList((ArrayList) readValue(buffer)); + case (byte) 139: + return PlatformPurchaseHistoryResponse.fromList((ArrayList) readValue(buffer)); + case (byte) 140: return PlatformPurchasesResponse.fromList((ArrayList) readValue(buffer)); + case (byte) 141: + return PlatformQueryProduct.fromList((ArrayList) readValue(buffer)); + case (byte) 142: + return PlatformSubscriptionOfferDetails.fromList((ArrayList) readValue(buffer)); default: return super.readValueOfType(type, buffer); } @@ -1050,31 +2473,52 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { @Override protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof PlatformAlternativeBillingOnlyReportingDetailsResponse) { + if (value instanceof PlatformAccountIdentifiers) { stream.write(128); + writeValue(stream, ((PlatformAccountIdentifiers) value).toList()); + } else if (value instanceof PlatformAlternativeBillingOnlyReportingDetailsResponse) { + stream.write(129); writeValue( stream, ((PlatformAlternativeBillingOnlyReportingDetailsResponse) value).toList()); } else if (value instanceof PlatformBillingConfigResponse) { - stream.write(129); + stream.write(130); writeValue(stream, ((PlatformBillingConfigResponse) value).toList()); } else if (value instanceof PlatformBillingFlowParams) { - stream.write(130); + stream.write(131); writeValue(stream, ((PlatformBillingFlowParams) value).toList()); } else if (value instanceof PlatformBillingResult) { - stream.write(131); - writeValue(stream, ((PlatformBillingResult) value).toList()); - } else if (value instanceof PlatformProduct) { stream.write(132); - writeValue(stream, ((PlatformProduct) value).toList()); - } else if (value instanceof PlatformProductDetailsResponse) { + writeValue(stream, ((PlatformBillingResult) value).toList()); + } else if (value instanceof PlatformOneTimePurchaseOfferDetails) { stream.write(133); + writeValue(stream, ((PlatformOneTimePurchaseOfferDetails) value).toList()); + } else if (value instanceof PlatformPricingPhase) { + stream.write(134); + writeValue(stream, ((PlatformPricingPhase) value).toList()); + } else if (value instanceof PlatformProductDetails) { + stream.write(135); + writeValue(stream, ((PlatformProductDetails) value).toList()); + } else if (value instanceof PlatformProductDetailsResponse) { + stream.write(136); writeValue(stream, ((PlatformProductDetailsResponse) value).toList()); + } else if (value instanceof PlatformPurchase) { + stream.write(137); + writeValue(stream, ((PlatformPurchase) value).toList()); + } else if (value instanceof PlatformPurchaseHistoryRecord) { + stream.write(138); + writeValue(stream, ((PlatformPurchaseHistoryRecord) value).toList()); } else if (value instanceof PlatformPurchaseHistoryResponse) { - stream.write(134); + stream.write(139); writeValue(stream, ((PlatformPurchaseHistoryResponse) value).toList()); } else if (value instanceof PlatformPurchasesResponse) { - stream.write(135); + stream.write(140); writeValue(stream, ((PlatformPurchasesResponse) value).toList()); + } else if (value instanceof PlatformQueryProduct) { + stream.write(141); + writeValue(stream, ((PlatformQueryProduct) value).toList()); + } else if (value instanceof PlatformSubscriptionOfferDetails) { + stream.write(142); + writeValue(stream, ((PlatformSubscriptionOfferDetails) value).toList()); } else { super.writeValue(stream, value); } @@ -1125,7 +2569,7 @@ void queryPurchaseHistoryAsync( * ProductDetailsResponseListener). */ void queryProductDetailsAsync( - @NonNull List products, + @NonNull List products, @NonNull Result result); /** Wraps BillingClient#isFeatureSupported(String). */ @NonNull @@ -1422,7 +2866,7 @@ public void error(Throwable error) { (message, reply) -> { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; - List productsArg = (List) args.get(0); + List productsArg = (List) args.get(0); Result resultCallback = new Result() { public void success(PlatformProductDetailsResponse result) { @@ -1568,11 +3012,17 @@ private InAppPurchaseCallbackApiCodec() {} protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { switch (type) { case (byte) 128: - return PlatformBillingResult.fromList((ArrayList) readValue(buffer)); + return PlatformAccountIdentifiers.fromList((ArrayList) readValue(buffer)); case (byte) 129: - return PlatformPurchasesResponse.fromList((ArrayList) readValue(buffer)); + return PlatformBillingResult.fromList((ArrayList) readValue(buffer)); case (byte) 130: + return PlatformPurchase.fromList((ArrayList) readValue(buffer)); + case (byte) 131: + return PlatformPurchasesResponse.fromList((ArrayList) readValue(buffer)); + case (byte) 132: return PlatformUserChoiceDetails.fromList((ArrayList) readValue(buffer)); + case (byte) 133: + return PlatformUserChoiceProduct.fromList((ArrayList) readValue(buffer)); default: return super.readValueOfType(type, buffer); } @@ -1580,15 +3030,24 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { @Override protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof PlatformBillingResult) { + if (value instanceof PlatformAccountIdentifiers) { stream.write(128); + writeValue(stream, ((PlatformAccountIdentifiers) value).toList()); + } else if (value instanceof PlatformBillingResult) { + stream.write(129); writeValue(stream, ((PlatformBillingResult) value).toList()); + } else if (value instanceof PlatformPurchase) { + stream.write(130); + writeValue(stream, ((PlatformPurchase) value).toList()); } else if (value instanceof PlatformPurchasesResponse) { - stream.write(129); + stream.write(131); writeValue(stream, ((PlatformPurchasesResponse) value).toList()); } else if (value instanceof PlatformUserChoiceDetails) { - stream.write(130); + stream.write(132); writeValue(stream, ((PlatformUserChoiceDetails) value).toList()); + } else if (value instanceof PlatformUserChoiceProduct) { + stream.write(133); + writeValue(stream, ((PlatformUserChoiceProduct) value).toList()); } else { super.writeValue(stream, value); } diff --git a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/MethodCallHandlerImpl.java b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/MethodCallHandlerImpl.java index c9543f13286..849337e21fb 100644 --- a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/MethodCallHandlerImpl.java +++ b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/MethodCallHandlerImpl.java @@ -41,11 +41,11 @@ import io.flutter.plugins.inapppurchase.Messages.PlatformBillingChoiceMode; import io.flutter.plugins.inapppurchase.Messages.PlatformBillingFlowParams; import io.flutter.plugins.inapppurchase.Messages.PlatformBillingResult; -import io.flutter.plugins.inapppurchase.Messages.PlatformProduct; import io.flutter.plugins.inapppurchase.Messages.PlatformProductDetailsResponse; import io.flutter.plugins.inapppurchase.Messages.PlatformProductType; import io.flutter.plugins.inapppurchase.Messages.PlatformPurchaseHistoryResponse; import io.flutter.plugins.inapppurchase.Messages.PlatformPurchasesResponse; +import io.flutter.plugins.inapppurchase.Messages.PlatformQueryProduct; import io.flutter.plugins.inapppurchase.Messages.Result; import java.util.ArrayList; import java.util.HashMap; @@ -218,7 +218,7 @@ public Boolean isReady() { @Override public void queryProductDetailsAsync( - @NonNull List products, + @NonNull List products, @NonNull Result result) { if (billingClient == null) { result.error(getNullBillingClientError()); @@ -235,7 +235,7 @@ public void queryProductDetailsAsync( final PlatformProductDetailsResponse.Builder responseBuilder = new PlatformProductDetailsResponse.Builder() .setBillingResult(fromBillingResult(billingResult)) - .setProductDetailsJsonList(fromProductDetailsList(productDetailsList)); + .setProductDetails(fromProductDetailsList(productDetailsList)); result.success(responseBuilder.build()); }); } catch (RuntimeException e) { @@ -397,7 +397,7 @@ public void queryPurchasesAsync( PlatformPurchasesResponse.Builder builder = new PlatformPurchasesResponse.Builder() .setBillingResult(fromBillingResult(billingResult)) - .setPurchasesJsonList(fromPurchasesList(purchasesList)); + .setPurchases(fromPurchasesList(purchasesList)); result.success(builder.build()); }); } catch (RuntimeException e) { @@ -423,7 +423,7 @@ public void queryPurchaseHistoryAsync( PlatformPurchaseHistoryResponse.Builder builder = new PlatformPurchaseHistoryResponse.Builder() .setBillingResult(fromBillingResult(billingResult)) - .setPurchaseHistoryRecordJsonList(fromPurchaseHistoryRecordList(purchasesList)); + .setPurchases(fromPurchaseHistoryRecordList(purchasesList)); result.success(builder.build()); }); } catch (RuntimeException e) { diff --git a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/PluginPurchaseListener.java b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/PluginPurchaseListener.java index e8f1b40aeb5..2dc99e73c23 100644 --- a/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/PluginPurchaseListener.java +++ b/packages/in_app_purchase/in_app_purchase_android/android/src/main/java/io/flutter/plugins/inapppurchase/PluginPurchaseListener.java @@ -28,7 +28,7 @@ public void onPurchasesUpdated( Messages.PlatformPurchasesResponse.Builder builder = new Messages.PlatformPurchasesResponse.Builder() .setBillingResult(fromBillingResult(billingResult)) - .setPurchasesJsonList(fromPurchasesList(purchases)); + .setPurchases(fromPurchasesList(purchases)); callbackApi.onPurchasesUpdated( builder.build(), new Messages.VoidResult() { 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 195cc7335ac..c06b3acfb50 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 @@ -16,11 +16,26 @@ import com.android.billingclient.api.PurchaseHistoryRecord; import com.android.billingclient.api.QueryProductDetailsParams; import com.android.billingclient.api.UserChoiceDetails; -import com.android.billingclient.api.UserChoiceDetails.Product; +import io.flutter.plugins.inapppurchase.Messages.FlutterError; +import io.flutter.plugins.inapppurchase.Messages.PlatformAccountIdentifiers; +import io.flutter.plugins.inapppurchase.Messages.PlatformAlternativeBillingOnlyReportingDetailsResponse; +import io.flutter.plugins.inapppurchase.Messages.PlatformBillingConfigResponse; +import io.flutter.plugins.inapppurchase.Messages.PlatformBillingResult; +import io.flutter.plugins.inapppurchase.Messages.PlatformOneTimePurchaseOfferDetails; +import io.flutter.plugins.inapppurchase.Messages.PlatformPricingPhase; +import io.flutter.plugins.inapppurchase.Messages.PlatformProductDetails; +import io.flutter.plugins.inapppurchase.Messages.PlatformProductType; +import io.flutter.plugins.inapppurchase.Messages.PlatformPurchase; +import io.flutter.plugins.inapppurchase.Messages.PlatformPurchaseHistoryRecord; +import io.flutter.plugins.inapppurchase.Messages.PlatformPurchaseState; +import io.flutter.plugins.inapppurchase.Messages.PlatformQueryProduct; +import io.flutter.plugins.inapppurchase.Messages.PlatformRecurrenceMode; +import io.flutter.plugins.inapppurchase.Messages.PlatformSubscriptionOfferDetails; +import io.flutter.plugins.inapppurchase.Messages.PlatformUserChoiceDetails; +import io.flutter.plugins.inapppurchase.Messages.PlatformUserChoiceProduct; import java.util.ArrayList; import java.util.Collections; import java.util.Currency; -import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -29,45 +44,31 @@ * related objects. */ /*package*/ class Translator { - static HashMap fromProductDetail(ProductDetails detail) { - HashMap info = new HashMap<>(); - info.put("title", detail.getTitle()); - info.put("description", detail.getDescription()); - info.put("productId", detail.getProductId()); - info.put("productType", detail.getProductType()); - info.put("name", detail.getName()); - - @Nullable - ProductDetails.OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails = - detail.getOneTimePurchaseOfferDetails(); - if (oneTimePurchaseOfferDetails != null) { - info.put( - "oneTimePurchaseOfferDetails", - fromOneTimePurchaseOfferDetails(oneTimePurchaseOfferDetails)); - } - - @Nullable - List subscriptionOfferDetailsList = - detail.getSubscriptionOfferDetails(); - if (subscriptionOfferDetailsList != null) { - info.put( - "subscriptionOfferDetails", - fromSubscriptionOfferDetailsList(subscriptionOfferDetailsList)); - } - - return info; + static @NonNull PlatformProductDetails fromProductDetail(@NonNull ProductDetails detail) { + return new PlatformProductDetails.Builder() + .setTitle(detail.getTitle()) + .setDescription(detail.getDescription()) + .setProductId(detail.getProductId()) + .setProductType(toPlatformProductType(detail.getProductType())) + .setName(detail.getName()) + .setOneTimePurchaseOfferDetails( + fromOneTimePurchaseOfferDetails(detail.getOneTimePurchaseOfferDetails())) + .setSubscriptionOfferDetails( + fromSubscriptionOfferDetailsList(detail.getSubscriptionOfferDetails())) + .build(); } - static List toProductList( - List platformProducts) { + static @NonNull List toProductList( + @NonNull List platformProducts) { List products = new ArrayList<>(); - for (Messages.PlatformProduct platformProduct : platformProducts) { + for (PlatformQueryProduct platformProduct : platformProducts) { products.add(toProduct(platformProduct)); } return products; } - static QueryProductDetailsParams.Product toProduct(Messages.PlatformProduct platformProduct) { + static @NonNull QueryProductDetailsParams.Product toProduct( + @NonNull PlatformQueryProduct platformProduct) { return QueryProductDetailsParams.Product.newBuilder() .setProductId(platformProduct.getProductId()) @@ -75,52 +76,60 @@ static QueryProductDetailsParams.Product toProduct(Messages.PlatformProduct plat .build(); } - static String toProductTypeString(Messages.PlatformProductType type) { + static @NonNull String toProductTypeString(PlatformProductType type) { switch (type) { case INAPP: return BillingClient.ProductType.INAPP; case SUBS: return BillingClient.ProductType.SUBS; } - throw new Messages.FlutterError("UNKNOWN_TYPE", "Unknown product type: " + type, null); + throw new FlutterError("UNKNOWN_TYPE", "Unknown product type: " + type, null); + } + + static PlatformProductType toPlatformProductType(@NonNull String typeString) { + switch (typeString) { + case BillingClient.ProductType.INAPP: + // Fallback handling to avoid throwing an exception if a new type is added in the future. + default: + return PlatformProductType.INAPP; + case BillingClient.ProductType.SUBS: + return PlatformProductType.SUBS; + } } - static List fromProductDetailsList(@Nullable List productDetailsList) { + static @NonNull List fromProductDetailsList( + @Nullable List productDetailsList) { if (productDetailsList == null) { return Collections.emptyList(); } - // This and the method are generically typed due to Pigeon limitations; see - // https://github.com/flutter/flutter/issues/116117. - ArrayList output = new ArrayList<>(); + ArrayList output = new ArrayList<>(); for (ProductDetails detail : productDetailsList) { output.add(fromProductDetail(detail)); } return output; } - static HashMap fromOneTimePurchaseOfferDetails( + static @Nullable PlatformOneTimePurchaseOfferDetails fromOneTimePurchaseOfferDetails( @Nullable ProductDetails.OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails) { - HashMap serialized = new HashMap<>(); if (oneTimePurchaseOfferDetails == null) { - return serialized; + return null; } - serialized.put("priceAmountMicros", oneTimePurchaseOfferDetails.getPriceAmountMicros()); - serialized.put("priceCurrencyCode", oneTimePurchaseOfferDetails.getPriceCurrencyCode()); - serialized.put("formattedPrice", oneTimePurchaseOfferDetails.getFormattedPrice()); - - return serialized; + return new PlatformOneTimePurchaseOfferDetails.Builder() + .setPriceAmountMicros(oneTimePurchaseOfferDetails.getPriceAmountMicros()) + .setPriceCurrencyCode(oneTimePurchaseOfferDetails.getPriceCurrencyCode()) + .setFormattedPrice(oneTimePurchaseOfferDetails.getFormattedPrice()) + .build(); } - static List> fromSubscriptionOfferDetailsList( + static @Nullable List fromSubscriptionOfferDetailsList( @Nullable List subscriptionOfferDetailsList) { if (subscriptionOfferDetailsList == null) { - return Collections.emptyList(); + return null; } - ArrayList> serialized = new ArrayList<>(); - + ArrayList serialized = new ArrayList<>(); for (ProductDetails.SubscriptionOfferDetails subscriptionOfferDetails : subscriptionOfferDetailsList) { serialized.add(fromSubscriptionOfferDetails(subscriptionOfferDetails)); @@ -129,175 +138,182 @@ static List> fromSubscriptionOfferDetailsList( return serialized; } - static HashMap fromSubscriptionOfferDetails( - @Nullable ProductDetails.SubscriptionOfferDetails subscriptionOfferDetails) { - HashMap serialized = new HashMap<>(); - if (subscriptionOfferDetails == null) { - return serialized; - } - - serialized.put("offerId", subscriptionOfferDetails.getOfferId()); - serialized.put("basePlanId", subscriptionOfferDetails.getBasePlanId()); - serialized.put("offerTags", subscriptionOfferDetails.getOfferTags()); - serialized.put("offerIdToken", subscriptionOfferDetails.getOfferToken()); - - ProductDetails.PricingPhases pricingPhases = subscriptionOfferDetails.getPricingPhases(); - serialized.put("pricingPhases", fromPricingPhases(pricingPhases)); - - return serialized; + static @NonNull PlatformSubscriptionOfferDetails fromSubscriptionOfferDetails( + @NonNull ProductDetails.SubscriptionOfferDetails subscriptionOfferDetails) { + return new PlatformSubscriptionOfferDetails.Builder() + .setOfferId(subscriptionOfferDetails.getOfferId()) + .setBasePlanId(subscriptionOfferDetails.getBasePlanId()) + .setOfferTags(subscriptionOfferDetails.getOfferTags()) + .setOfferToken(subscriptionOfferDetails.getOfferToken()) + .setPricingPhases(fromPricingPhases(subscriptionOfferDetails.getPricingPhases())) + .build(); } - static List> fromPricingPhases( + static @NonNull List fromPricingPhases( @NonNull ProductDetails.PricingPhases pricingPhases) { - ArrayList> serialized = new ArrayList<>(); - + ArrayList serialized = new ArrayList<>(); for (ProductDetails.PricingPhase pricingPhase : pricingPhases.getPricingPhaseList()) { serialized.add(fromPricingPhase(pricingPhase)); } return serialized; } - static HashMap fromPricingPhase( - @Nullable ProductDetails.PricingPhase pricingPhase) { - HashMap serialized = new HashMap<>(); + static @NonNull PlatformPricingPhase fromPricingPhase( + @NonNull ProductDetails.PricingPhase pricingPhase) { + return new PlatformPricingPhase.Builder() + .setFormattedPrice(pricingPhase.getFormattedPrice()) + .setPriceCurrencyCode(pricingPhase.getPriceCurrencyCode()) + .setPriceAmountMicros(pricingPhase.getPriceAmountMicros()) + .setBillingCycleCount((long) pricingPhase.getBillingCycleCount()) + .setBillingPeriod(pricingPhase.getBillingPeriod()) + .setRecurrenceMode(toPlatformRecurrenceMode(pricingPhase.getRecurrenceMode())) + .build(); + } - if (pricingPhase == null) { - return serialized; + static PlatformRecurrenceMode toPlatformRecurrenceMode(int mode) { + switch (mode) { + case ProductDetails.RecurrenceMode.FINITE_RECURRING: + return PlatformRecurrenceMode.FINITE_RECURRING; + case ProductDetails.RecurrenceMode.INFINITE_RECURRING: + return PlatformRecurrenceMode.INFINITE_RECURRING; + case ProductDetails.RecurrenceMode.NON_RECURRING: + return PlatformRecurrenceMode.NON_RECURRING; } + return PlatformRecurrenceMode.NON_RECURRING; + } - serialized.put("formattedPrice", pricingPhase.getFormattedPrice()); - serialized.put("priceCurrencyCode", pricingPhase.getPriceCurrencyCode()); - serialized.put("priceAmountMicros", pricingPhase.getPriceAmountMicros()); - serialized.put("billingCycleCount", pricingPhase.getBillingCycleCount()); - serialized.put("billingPeriod", pricingPhase.getBillingPeriod()); - serialized.put("recurrenceMode", pricingPhase.getRecurrenceMode()); - - return serialized; + static PlatformPurchaseState toPlatformPurchaseState(int state) { + switch (state) { + case Purchase.PurchaseState.PURCHASED: + return PlatformPurchaseState.PURCHASED; + case Purchase.PurchaseState.PENDING: + return PlatformPurchaseState.PENDING; + case Purchase.PurchaseState.UNSPECIFIED_STATE: + return PlatformPurchaseState.UNSPECIFIED; + } + return PlatformPurchaseState.UNSPECIFIED; } - static HashMap fromPurchase(Purchase purchase) { - HashMap info = new HashMap<>(); - List products = purchase.getProducts(); - info.put("orderId", purchase.getOrderId()); - info.put("packageName", purchase.getPackageName()); - info.put("purchaseTime", purchase.getPurchaseTime()); - info.put("purchaseToken", purchase.getPurchaseToken()); - info.put("signature", purchase.getSignature()); - info.put("products", products); - info.put("isAutoRenewing", purchase.isAutoRenewing()); - info.put("originalJson", purchase.getOriginalJson()); - info.put("developerPayload", purchase.getDeveloperPayload()); - info.put("isAcknowledged", purchase.isAcknowledged()); - info.put("purchaseState", purchase.getPurchaseState()); - info.put("quantity", purchase.getQuantity()); + static @NonNull PlatformPurchase fromPurchase(@NonNull Purchase purchase) { + PlatformPurchase.Builder builder = + new PlatformPurchase.Builder() + .setOrderId(purchase.getOrderId()) + .setPackageName(purchase.getPackageName()) + .setPurchaseTime(purchase.getPurchaseTime()) + .setPurchaseToken(purchase.getPurchaseToken()) + .setSignature(purchase.getSignature()) + .setProducts(purchase.getProducts()) + .setIsAutoRenewing(purchase.isAutoRenewing()) + .setOriginalJson(purchase.getOriginalJson()) + .setDeveloperPayload(purchase.getDeveloperPayload()) + .setIsAcknowledged(purchase.isAcknowledged()) + .setPurchaseState(toPlatformPurchaseState(purchase.getPurchaseState())) + .setQuantity((long) purchase.getQuantity()); AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers(); if (accountIdentifiers != null) { - info.put("obfuscatedAccountId", accountIdentifiers.getObfuscatedAccountId()); - info.put("obfuscatedProfileId", accountIdentifiers.getObfuscatedProfileId()); + builder.setAccountIdentifiers( + new PlatformAccountIdentifiers.Builder() + .setObfuscatedAccountId(accountIdentifiers.getObfuscatedAccountId()) + .setObfuscatedProfileId(accountIdentifiers.getObfuscatedProfileId()) + .build()); } - return info; + return builder.build(); } - static HashMap fromPurchaseHistoryRecord( - PurchaseHistoryRecord purchaseHistoryRecord) { - HashMap info = new HashMap<>(); - List products = purchaseHistoryRecord.getProducts(); - info.put("purchaseTime", purchaseHistoryRecord.getPurchaseTime()); - info.put("purchaseToken", purchaseHistoryRecord.getPurchaseToken()); - info.put("signature", purchaseHistoryRecord.getSignature()); - info.put("products", products); - info.put("developerPayload", purchaseHistoryRecord.getDeveloperPayload()); - info.put("originalJson", purchaseHistoryRecord.getOriginalJson()); - info.put("quantity", purchaseHistoryRecord.getQuantity()); - return info; + static @NonNull PlatformPurchaseHistoryRecord fromPurchaseHistoryRecord( + @NonNull PurchaseHistoryRecord purchaseHistoryRecord) { + return new PlatformPurchaseHistoryRecord.Builder() + .setPurchaseTime(purchaseHistoryRecord.getPurchaseTime()) + .setPurchaseToken(purchaseHistoryRecord.getPurchaseToken()) + .setSignature(purchaseHistoryRecord.getSignature()) + .setProducts(purchaseHistoryRecord.getProducts()) + .setDeveloperPayload(purchaseHistoryRecord.getDeveloperPayload()) + .setOriginalJson(purchaseHistoryRecord.getOriginalJson()) + .setQuantity((long) purchaseHistoryRecord.getQuantity()) + .build(); } - static List fromPurchasesList(@Nullable List purchases) { + static @NonNull List fromPurchasesList(@Nullable List purchases) { if (purchases == null) { return Collections.emptyList(); } - // This and the method are generically typed due to Pigeon limitations; see - // https://github.com/flutter/flutter/issues/116117. - List serialized = new ArrayList<>(); + List serialized = new ArrayList<>(); for (Purchase purchase : purchases) { serialized.add(fromPurchase(purchase)); } return serialized; } - static List fromPurchaseHistoryRecordList( + static @NonNull List fromPurchaseHistoryRecordList( @Nullable List purchaseHistoryRecords) { if (purchaseHistoryRecords == null) { return Collections.emptyList(); } - // This and the method are generically typed due to Pigeon limitations; see - // https://github.com/flutter/flutter/issues/116117. - List serialized = new ArrayList<>(); + List serialized = new ArrayList<>(); for (PurchaseHistoryRecord purchaseHistoryRecord : purchaseHistoryRecords) { serialized.add(fromPurchaseHistoryRecord(purchaseHistoryRecord)); } return serialized; } - static Messages.PlatformBillingResult fromBillingResult(BillingResult billingResult) { - return new Messages.PlatformBillingResult.Builder() + static @NonNull PlatformBillingResult fromBillingResult(@NonNull BillingResult billingResult) { + return new PlatformBillingResult.Builder() .setResponseCode((long) billingResult.getResponseCode()) .setDebugMessage(billingResult.getDebugMessage()) .build(); } - static Messages.PlatformUserChoiceDetails fromUserChoiceDetails( - UserChoiceDetails userChoiceDetails) { - return new Messages.PlatformUserChoiceDetails.Builder() + static @NonNull PlatformUserChoiceDetails fromUserChoiceDetails( + @NonNull UserChoiceDetails userChoiceDetails) { + return new PlatformUserChoiceDetails.Builder() .setExternalTransactionToken(userChoiceDetails.getExternalTransactionToken()) .setOriginalExternalTransactionId(userChoiceDetails.getOriginalExternalTransactionId()) - .setProductsJsonList(fromProductsList(userChoiceDetails.getProducts())) + .setProducts(fromUserChoiceProductsList(userChoiceDetails.getProducts())) .build(); } - static List fromProductsList(List productsList) { + static @NonNull List fromUserChoiceProductsList( + @NonNull List productsList) { if (productsList.isEmpty()) { return Collections.emptyList(); } - // This and the method are generically typed due to Pigeon limitations; see - // https://github.com/flutter/flutter/issues/116117. - ArrayList output = new ArrayList<>(); - for (Product product : productsList) { - output.add(fromProduct(product)); + ArrayList output = new ArrayList<>(); + for (UserChoiceDetails.Product product : productsList) { + output.add(fromUserChoiceProduct(product)); } return output; } - static HashMap fromProduct(Product product) { - HashMap info = new HashMap<>(); - info.put("id", product.getId()); - info.put("offerToken", product.getOfferToken()); - info.put("productType", product.getType()); - - return info; + static @NonNull PlatformUserChoiceProduct fromUserChoiceProduct( + @NonNull UserChoiceDetails.Product product) { + return new PlatformUserChoiceProduct.Builder() + .setId(product.getId()) + .setOfferToken(product.getOfferToken()) + .setType(toPlatformProductType(product.getType())) + .build(); } /** Converter from {@link BillingResult} and {@link BillingConfig} to map. */ - static Messages.PlatformBillingConfigResponse fromBillingConfig( - BillingResult result, BillingConfig billingConfig) { - return new Messages.PlatformBillingConfigResponse.Builder() + static @NonNull PlatformBillingConfigResponse fromBillingConfig( + @NonNull BillingResult result, @Nullable BillingConfig billingConfig) { + return new PlatformBillingConfigResponse.Builder() .setBillingResult(fromBillingResult(result)) - .setCountryCode(billingConfig.getCountryCode()) + .setCountryCode(billingConfig == null ? "" : billingConfig.getCountryCode()) .build(); } /** * Converter from {@link BillingResult} and {@link AlternativeBillingOnlyReportingDetails} to map. */ - static Messages.PlatformAlternativeBillingOnlyReportingDetailsResponse + static @NonNull PlatformAlternativeBillingOnlyReportingDetailsResponse fromAlternativeBillingOnlyReportingDetails( - BillingResult result, AlternativeBillingOnlyReportingDetails details) { - return new Messages.PlatformAlternativeBillingOnlyReportingDetailsResponse.Builder() + @NonNull BillingResult result, @Nullable AlternativeBillingOnlyReportingDetails details) { + return new PlatformAlternativeBillingOnlyReportingDetailsResponse.Builder() .setBillingResult(fromBillingResult(result)) - .setExternalTransactionToken(details.getExternalTransactionToken()) + .setExternalTransactionToken(details == null ? "" : details.getExternalTransactionToken()) .build(); } diff --git a/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/MethodCallHandlerTest.java b/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/MethodCallHandlerTest.java index e3fdb6b4dfd..1c466cdea01 100644 --- a/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/MethodCallHandlerTest.java +++ b/packages/in_app_purchase/in_app_purchase_android/android/src/test/java/io/flutter/plugins/inapppurchase/MethodCallHandlerTest.java @@ -6,9 +6,6 @@ import static io.flutter.plugins.inapppurchase.MethodCallHandlerImpl.ACTIVITY_UNAVAILABLE; import static io.flutter.plugins.inapppurchase.MethodCallHandlerImpl.PRORATION_MODE_UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY; -import static io.flutter.plugins.inapppurchase.Translator.fromProductDetailsList; -import static io.flutter.plugins.inapppurchase.Translator.fromPurchaseHistoryRecordList; -import static io.flutter.plugins.inapppurchase.Translator.fromPurchasesList; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Collections.unmodifiableList; @@ -66,11 +63,11 @@ import io.flutter.plugins.inapppurchase.Messages.PlatformBillingConfigResponse; import io.flutter.plugins.inapppurchase.Messages.PlatformBillingFlowParams; import io.flutter.plugins.inapppurchase.Messages.PlatformBillingResult; -import io.flutter.plugins.inapppurchase.Messages.PlatformProduct; import io.flutter.plugins.inapppurchase.Messages.PlatformProductDetailsResponse; import io.flutter.plugins.inapppurchase.Messages.PlatformProductType; import io.flutter.plugins.inapppurchase.Messages.PlatformPurchaseHistoryResponse; import io.flutter.plugins.inapppurchase.Messages.PlatformPurchasesResponse; +import io.flutter.plugins.inapppurchase.Messages.PlatformQueryProduct; import io.flutter.plugins.inapppurchase.Messages.PlatformUserChoiceDetails; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -239,7 +236,7 @@ public void startConnectionUserChoiceBilling() { assertEquals(callbackCaptor.getValue().getExternalTransactionToken(), externalTransactionToken); assertEquals( callbackCaptor.getValue().getOriginalExternalTransactionId(), originalTransactionId); - assertTrue(callbackCaptor.getValue().getProductsJsonList().isEmpty()); + assertTrue(callbackCaptor.getValue().getProducts().isEmpty()); } @Test @@ -308,7 +305,7 @@ public void userChoiceBillingOnSecondConnection() { assertEquals(callbackCaptor.getValue().getExternalTransactionToken(), externalTransactionToken); assertEquals( callbackCaptor.getValue().getOriginalExternalTransactionId(), originalTransactionId); - assertTrue(callbackCaptor.getValue().getProductsJsonList().isEmpty()); + assertTrue(callbackCaptor.getValue().getProducts().isEmpty()); } @Test @@ -545,7 +542,7 @@ public void queryProductDetailsAsync() { // Connect a billing client and set up the product query listeners establishConnectedBillingClient(); List productsIds = asList("id1", "id2"); - final List productList = + final List productList = buildProductList(productsIds, PlatformProductType.INAPP); // Query for product details @@ -568,8 +565,7 @@ public void queryProductDetailsAsync() { verify(platformProductDetailsResult).success(resultCaptor.capture()); PlatformProductDetailsResponse resultData = resultCaptor.getValue(); assertResultsMatch(resultData.getBillingResult(), billingResult); - assertEquals( - resultData.getProductDetailsJsonList(), fromProductDetailsList(productDetailsResponse)); + assertDetailListsMatch(productDetailsResponse, resultData.getProductDetails()); } @Test @@ -577,7 +573,7 @@ public void queryProductDetailsAsync_clientDisconnected() { // Disconnect the Billing client and prepare a queryProductDetails call methodChannelHandler.endConnection(); List productsIds = asList("id1", "id2"); - final List productList = + final List productList = buildProductList(productsIds, PlatformProductType.INAPP); methodChannelHandler.queryProductDetailsAsync(productList, platformProductDetailsResult); @@ -941,7 +937,7 @@ public void queryPurchases_returns_success() { assertEquals( purchasesResponse.getBillingResult().getResponseCode().longValue(), BillingClient.BillingResponseCode.OK); - assertTrue(purchasesResponse.getPurchasesJsonList().isEmpty()); + assertTrue(purchasesResponse.getPurchases().isEmpty()); } @Test @@ -949,7 +945,9 @@ public void queryPurchaseHistoryAsync() { // Set up an established billing client and all our mocked responses establishConnectedBillingClient(); BillingResult billingResult = buildBillingResult(); - List purchasesList = singletonList(buildPurchaseHistoryRecord("foo")); + final String purchaseToken = "foo"; + List purchasesList = + singletonList(buildPurchaseHistoryRecord(purchaseToken)); ArgumentCaptor listenerCaptor = ArgumentCaptor.forClass(PurchaseHistoryResponseListener.class); @@ -965,8 +963,8 @@ public void queryPurchaseHistoryAsync() { verify(platformPurchaseHistoryResult).success(resultCaptor.capture()); PlatformPurchaseHistoryResponse result = resultCaptor.getValue(); assertResultsMatch(result.getBillingResult(), billingResult); - assertEquals( - fromPurchaseHistoryRecordList(purchasesList), result.getPurchaseHistoryRecordJsonList()); + assertEquals(1, result.getPurchases().size()); + assertEquals(purchaseToken, result.getPurchases().get(0).getPurchaseToken()); } @Test @@ -990,7 +988,8 @@ public void onPurchasesUpdatedListener() { PluginPurchaseListener listener = new PluginPurchaseListener(mockCallbackApi); BillingResult billingResult = buildBillingResult(); - List purchasesList = singletonList(buildPurchase("foo")); + final String orderId = "foo"; + List purchasesList = singletonList(buildPurchase(orderId)); ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(PlatformPurchasesResponse.class); doNothing().when(mockCallbackApi).onPurchasesUpdated(resultCaptor.capture(), any()); @@ -998,7 +997,8 @@ public void onPurchasesUpdatedListener() { PlatformPurchasesResponse response = resultCaptor.getValue(); assertResultsMatch(response.getBillingResult(), billingResult); - assertEquals(fromPurchasesList(purchasesList), response.getPurchasesJsonList()); + assertEquals(1, response.getPurchases().size()); + assertEquals(orderId, response.getPurchases().get(0).getOrderId()); } @Test @@ -1118,7 +1118,7 @@ private void queryForProducts(List productIdList) { // Set up the query method call establishConnectedBillingClient(); List productsIds = asList("id1", "id2"); - final List productList = + final List productList = buildProductList(productsIds, PlatformProductType.INAPP); // Call the method. @@ -1135,12 +1135,12 @@ private void queryForProducts(List productIdList) { listenerCaptor.getValue().onProductDetailsResponse(billingResult, productDetailsResponse); } - private List buildProductList( + private List buildProductList( List productIds, PlatformProductType productType) { - List productList = new ArrayList<>(); + List productList = new ArrayList<>(); for (String productId : productIds) { - PlatformProduct.Builder builder = - new PlatformProduct.Builder().setProductId(productId).setProductType(productType); + PlatformQueryProduct.Builder builder = + new PlatformQueryProduct.Builder().setProductId(productId).setProductType(productType); productList.add(builder.build()); } return productList; @@ -1172,12 +1172,27 @@ private ProductDetails buildProductDetails(String id) { private Purchase buildPurchase(String orderId) { Purchase purchase = mock(Purchase.class); when(purchase.getOrderId()).thenReturn(orderId); + when(purchase.getPurchaseState()).thenReturn(Purchase.PurchaseState.UNSPECIFIED_STATE); + when(purchase.getQuantity()).thenReturn(1); + when(purchase.getPurchaseTime()).thenReturn(0L); + when(purchase.getDeveloperPayload()).thenReturn(""); + when(purchase.getOriginalJson()).thenReturn(""); + when(purchase.getPackageName()).thenReturn(""); + when(purchase.getPurchaseToken()).thenReturn(""); + when(purchase.getSignature()).thenReturn(""); + when(purchase.getProducts()).thenReturn(Collections.emptyList()); return purchase; } private PurchaseHistoryRecord buildPurchaseHistoryRecord(String purchaseToken) { PurchaseHistoryRecord purchase = mock(PurchaseHistoryRecord.class); when(purchase.getPurchaseToken()).thenReturn(purchaseToken); + when(purchase.getQuantity()).thenReturn(1); + when(purchase.getPurchaseTime()).thenReturn(0L); + when(purchase.getDeveloperPayload()).thenReturn(""); + when(purchase.getOriginalJson()).thenReturn(""); + when(purchase.getSignature()).thenReturn(""); + when(purchase.getProducts()).thenReturn(Collections.emptyList()); return purchase; } @@ -1196,4 +1211,26 @@ private void assertResultsMatch(PlatformBillingResult pigeonResult, BillingResul assertEquals(pigeonResult.getResponseCode().longValue(), nativeResult.getResponseCode()); assertEquals(pigeonResult.getDebugMessage(), nativeResult.getDebugMessage()); } + + private void assertDetailListsMatch( + List expected, List actual) { + assertEquals(expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { + assertDetailsMatch(expected.get(i), actual.get(i)); + } + } + + private void assertDetailsMatch(ProductDetails expected, Messages.PlatformProductDetails actual) { + assertEquals(expected.getDescription(), actual.getDescription()); + assertEquals(expected.getName(), actual.getName()); + assertEquals(expected.getProductId(), actual.getProductId()); + assertEquals(expected.getTitle(), actual.getTitle()); + // This doesn't do a deep match; TranslatorTest covers that. This is just a sanity check. + assertEquals( + expected.getOneTimePurchaseOfferDetails() == null, + actual.getOneTimePurchaseOfferDetails() == null); + assertEquals( + expected.getSubscriptionOfferDetails() == null, + actual.getSubscriptionOfferDetails() == null); + } } 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 d76f4958940..fff2ef2ffbc 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 @@ -23,7 +23,6 @@ import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import org.json.JSONException; import org.junit.Before; @@ -35,7 +34,7 @@ public class TranslatorTest { private static final String IN_APP_PRODUCT_DETAIL_EXAMPLE_JSON = "{\"title\":\"Example title\",\"description\":\"Example description\",\"productId\":\"Example id\",\"type\":\"inapp\",\"name\":\"Example name\",\"oneTimePurchaseOfferDetails\":{\"priceAmountMicros\":990000,\"priceCurrencyCode\":\"USD\",\"formattedPrice\":\"$0.99\"}}"; private static final String SUBS_PRODUCT_DETAIL_EXAMPLE_JSON = - "{\"title\":\"Example title 2\",\"description\":\"Example description 2\",\"productId\":\"Example id 2\",\"type\":\"subs\",\"name\":\"Example name 2\",\"subscriptionOfferDetails\":[{\"offerId\":\"Example offer id\",\"basePlanId\":\"Example base plan id\",\"offerTags\":[\"Example offer tag\"],\"offerIdToken\":\"Example offer token\",\"pricingPhases\":[{\"formattedPrice\":\"$0.99\",\"priceCurrencyCode\":\"USD\",\"priceAmountMicros\":990000,\"billingCycleCount\":4,\"billingPeriod\":\"Example billing period\",\"recurrenceMode\":0}]}]}"; + "{\"title\":\"Example title 2\",\"description\":\"Example description 2\",\"productId\":\"Example id 2\",\"type\":\"subs\",\"name\":\"Example name 2\",\"subscriptionOfferDetails\":[{\"offerId\":\"Example offer id\",\"basePlanId\":\"Example base plan id\",\"offerTags\":[\"Example offer tag\"],\"offerIdToken\":\"Example offer token\",\"pricingPhases\":[{\"formattedPrice\":\"$0.99\",\"priceCurrencyCode\":\"USD\",\"priceAmountMicros\":990000,\"billingCycleCount\":4,\"billingPeriod\":\"Example billing period\",\"recurrenceMode\":1}]}]}"; Constructor productDetailsConstructor; @@ -54,7 +53,7 @@ public void fromInAppProductDetail() final ProductDetails expected = productDetailsConstructor.newInstance(IN_APP_PRODUCT_DETAIL_EXAMPLE_JSON); - Map serialized = Translator.fromProductDetail(expected); + Messages.PlatformProductDetails serialized = Translator.fromProductDetail(expected); assertSerialized(expected, serialized); } @@ -65,7 +64,7 @@ public void fromSubsProductDetail() final ProductDetails expected = productDetailsConstructor.newInstance(SUBS_PRODUCT_DETAIL_EXAMPLE_JSON); - Map serialized = Translator.fromProductDetail(expected); + Messages.PlatformProductDetails serialized = Translator.fromProductDetail(expected); assertSerialized(expected, serialized); } @@ -78,7 +77,8 @@ public void fromProductDetailsList() productDetailsConstructor.newInstance(IN_APP_PRODUCT_DETAIL_EXAMPLE_JSON), productDetailsConstructor.newInstance(SUBS_PRODUCT_DETAIL_EXAMPLE_JSON)); - final List serialized = Translator.fromProductDetailsList(expected); + final List serialized = + Translator.fromProductDetailsList(expected); assertEquals(expected.size(), serialized.size()); assertSerialized(expected.get(0), serialized.get(0)); @@ -100,10 +100,9 @@ public void fromPurchase() throws JSONException { public void fromPurchaseWithoutAccountIds() throws JSONException { final Purchase expected = new PurchaseWithoutAccountIdentifiers(PURCHASE_EXAMPLE_JSON, "signature"); - Map serialized = Translator.fromPurchase(expected); - assertNotNull(serialized.get("orderId")); - assertNull(serialized.get("obfuscatedProfileId")); - assertNull(serialized.get("obfuscatedAccountId")); + Messages.PlatformPurchase serialized = Translator.fromPurchase(expected); + assertNotNull(serialized.getOrderId()); + assertNull(serialized.getAccountIdentifiers()); } @Test @@ -123,7 +122,8 @@ public void fromPurchasesHistoryRecordList() throws JSONException { new PurchaseHistoryRecord(PURCHASE_EXAMPLE_JSON, signature), new PurchaseHistoryRecord(purchase2Json, signature)); - final List serialized = Translator.fromPurchaseHistoryRecordList(expected); + final List serialized = + Translator.fromPurchaseHistoryRecordList(expected); assertEquals(expected.size(), serialized.size()); assertSerialized(expected.get(0), serialized.get(0)); @@ -144,7 +144,7 @@ public void fromPurchasesList() throws JSONException { Arrays.asList( new Purchase(PURCHASE_EXAMPLE_JSON, signature), new Purchase(purchase2Json, signature)); - final List serialized = Translator.fromPurchasesList(expected); + final List serialized = Translator.fromPurchasesList(expected); assertEquals(expected.size(), serialized.size()); assertSerialized(expected.get(0), serialized.get(0)); @@ -190,124 +190,146 @@ public void currencyCodeFromSymbol() { } } - private void assertSerialized(ProductDetails expected, Object serializedGeneric) { - @SuppressWarnings("unchecked") - final Map serialized = (Map) serializedGeneric; - assertEquals(expected.getTitle(), serialized.get("title")); - assertEquals(expected.getName(), serialized.get("name")); - assertEquals(expected.getProductId(), serialized.get("productId")); - assertEquals(expected.getProductType(), serialized.get("productType")); + private void assertSerialized( + ProductDetails expected, Messages.PlatformProductDetails serialized) { + assertEquals(expected.getTitle(), serialized.getTitle()); + assertEquals(expected.getName(), serialized.getName()); + assertEquals(expected.getProductId(), serialized.getProductId()); + assertEquals(expected.getProductType(), productTypeFromPlatform(serialized.getProductType())); ProductDetails.OneTimePurchaseOfferDetails expectedOneTimePurchaseOfferDetails = expected.getOneTimePurchaseOfferDetails(); - Object oneTimePurchaseOfferDetailsObject = serialized.get("oneTimePurchaseOfferDetails"); - assertEquals( - expectedOneTimePurchaseOfferDetails == null, oneTimePurchaseOfferDetailsObject == null); - if (expectedOneTimePurchaseOfferDetails != null && oneTimePurchaseOfferDetailsObject != null) { - @SuppressWarnings(value = "unchecked") - Map oneTimePurchaseOfferDetailsMap = - (Map) oneTimePurchaseOfferDetailsObject; - assertSerialized(expectedOneTimePurchaseOfferDetails, oneTimePurchaseOfferDetailsMap); + Messages.PlatformOneTimePurchaseOfferDetails oneTimePurchaseOfferDetails = + serialized.getOneTimePurchaseOfferDetails(); + assertEquals(expectedOneTimePurchaseOfferDetails == null, oneTimePurchaseOfferDetails == null); + if (expectedOneTimePurchaseOfferDetails != null && oneTimePurchaseOfferDetails != null) { + assertSerialized(expectedOneTimePurchaseOfferDetails, oneTimePurchaseOfferDetails); } List expectedSubscriptionOfferDetailsList = expected.getSubscriptionOfferDetails(); - Object subscriptionOfferDetailsListObject = serialized.get("subscriptionOfferDetails"); + List subscriptionOfferDetailsList = + serialized.getSubscriptionOfferDetails(); assertEquals( - expectedSubscriptionOfferDetailsList == null, subscriptionOfferDetailsListObject == null); - if (expectedSubscriptionOfferDetailsList != null - && subscriptionOfferDetailsListObject != null) { - @SuppressWarnings(value = "unchecked") - List subscriptionOfferDetailsListList = - (List) subscriptionOfferDetailsListObject; - assertSerialized(expectedSubscriptionOfferDetailsList, subscriptionOfferDetailsListList); + expectedSubscriptionOfferDetailsList == null, subscriptionOfferDetailsList == null); + if (expectedSubscriptionOfferDetailsList != null && subscriptionOfferDetailsList != null) { + assertSerialized(expectedSubscriptionOfferDetailsList, subscriptionOfferDetailsList); } } private void assertSerialized( - ProductDetails.OneTimePurchaseOfferDetails expected, Map serialized) { - assertEquals(expected.getPriceAmountMicros(), serialized.get("priceAmountMicros")); - assertEquals(expected.getPriceCurrencyCode(), serialized.get("priceCurrencyCode")); - assertEquals(expected.getFormattedPrice(), serialized.get("formattedPrice")); + ProductDetails.OneTimePurchaseOfferDetails expected, + Messages.PlatformOneTimePurchaseOfferDetails serialized) { + assertEquals(expected.getPriceAmountMicros(), serialized.getPriceAmountMicros().longValue()); + assertEquals(expected.getPriceCurrencyCode(), serialized.getPriceCurrencyCode()); + assertEquals(expected.getFormattedPrice(), serialized.getFormattedPrice()); } private void assertSerialized( - List expected, List serialized) { + List expected, + List serialized) { assertEquals(expected.size(), serialized.size()); for (int i = 0; i < expected.size(); i++) { - @SuppressWarnings(value = "unchecked") - Map serializedMap = (Map) serialized.get(i); - assertSerialized(expected.get(i), serializedMap); + assertSerialized(expected.get(i), serialized.get(i)); } } private void assertSerialized( - ProductDetails.SubscriptionOfferDetails expected, Map serialized) { - assertEquals(expected.getBasePlanId(), serialized.get("basePlanId")); - assertEquals(expected.getOfferId(), serialized.get("offerId")); - assertEquals(expected.getOfferTags(), serialized.get("offerTags")); - assertEquals(expected.getOfferToken(), serialized.get("offerIdToken")); - - @SuppressWarnings(value = "unchecked") - List serializedPricingPhases = (List) serialized.get("pricingPhases"); - assertNotNull(serializedPricingPhases); - assertSerialized(expected.getPricingPhases(), serializedPricingPhases); + ProductDetails.SubscriptionOfferDetails expected, + Messages.PlatformSubscriptionOfferDetails serialized) { + assertEquals(expected.getBasePlanId(), serialized.getBasePlanId()); + assertEquals(expected.getOfferId(), serialized.getOfferId()); + assertEquals(expected.getOfferTags(), serialized.getOfferTags()); + assertEquals(expected.getOfferToken(), serialized.getOfferToken()); + assertSerialized(expected.getPricingPhases(), serialized.getPricingPhases()); } - private void assertSerialized(ProductDetails.PricingPhases expected, List serialized) { + private void assertSerialized( + ProductDetails.PricingPhases expected, List serialized) { List expectedPhases = expected.getPricingPhaseList(); assertEquals(expectedPhases.size(), serialized.size()); for (int i = 0; i < serialized.size(); i++) { - @SuppressWarnings(value = "unchecked") - Map pricingPhaseMap = (Map) serialized.get(i); - assertSerialized(expectedPhases.get(i), pricingPhaseMap); + assertSerialized(expectedPhases.get(i), serialized.get(i)); } expected.getPricingPhaseList(); } private void assertSerialized( - ProductDetails.PricingPhase expected, Map serialized) { - assertEquals(expected.getFormattedPrice(), serialized.get("formattedPrice")); - assertEquals(expected.getPriceCurrencyCode(), serialized.get("priceCurrencyCode")); - assertEquals(expected.getPriceAmountMicros(), serialized.get("priceAmountMicros")); - assertEquals(expected.getBillingCycleCount(), serialized.get("billingCycleCount")); - assertEquals(expected.getBillingPeriod(), serialized.get("billingPeriod")); - assertEquals(expected.getRecurrenceMode(), serialized.get("recurrenceMode")); + ProductDetails.PricingPhase expected, Messages.PlatformPricingPhase serialized) { + assertEquals(expected.getFormattedPrice(), serialized.getFormattedPrice()); + assertEquals(expected.getPriceCurrencyCode(), serialized.getPriceCurrencyCode()); + assertEquals(expected.getPriceAmountMicros(), serialized.getPriceAmountMicros().longValue()); + assertEquals(expected.getBillingCycleCount(), serialized.getBillingCycleCount().intValue()); + assertEquals(expected.getBillingPeriod(), serialized.getBillingPeriod()); + assertEquals( + expected.getRecurrenceMode(), recurrenceModeFromPlatform(serialized.getRecurrenceMode())); } - private void assertSerialized(Purchase expected, Object serializedGeneric) { - @SuppressWarnings("unchecked") - final Map serialized = (Map) serializedGeneric; - assertEquals(expected.getOrderId(), serialized.get("orderId")); - assertEquals(expected.getPackageName(), serialized.get("packageName")); - assertEquals(expected.getPurchaseTime(), serialized.get("purchaseTime")); - assertEquals(expected.getPurchaseToken(), serialized.get("purchaseToken")); - assertEquals(expected.getSignature(), serialized.get("signature")); - assertEquals(expected.getOriginalJson(), serialized.get("originalJson")); - assertEquals(expected.getProducts(), serialized.get("products")); - assertEquals(expected.getDeveloperPayload(), serialized.get("developerPayload")); - assertEquals(expected.isAcknowledged(), serialized.get("isAcknowledged")); - assertEquals(expected.getPurchaseState(), serialized.get("purchaseState")); + private void assertSerialized(Purchase expected, Messages.PlatformPurchase serialized) { + assertEquals(expected.getOrderId(), serialized.getOrderId()); + assertEquals(expected.getPackageName(), serialized.getPackageName()); + assertEquals(expected.getPurchaseTime(), serialized.getPurchaseTime().longValue()); + assertEquals(expected.getPurchaseToken(), serialized.getPurchaseToken()); + assertEquals(expected.getSignature(), serialized.getSignature()); + assertEquals(expected.getOriginalJson(), serialized.getOriginalJson()); + assertEquals(expected.getProducts(), serialized.getProducts()); + assertEquals(expected.getDeveloperPayload(), serialized.getDeveloperPayload()); + assertEquals(expected.isAcknowledged(), serialized.getIsAcknowledged()); + assertEquals(expected.getPurchaseState(), stateFromPlatform(serialized.getPurchaseState())); assertNotNull( Objects.requireNonNull(expected.getAccountIdentifiers()).getObfuscatedAccountId()); assertEquals( expected.getAccountIdentifiers().getObfuscatedAccountId(), - serialized.get("obfuscatedAccountId")); + Objects.requireNonNull(serialized.getAccountIdentifiers()).getObfuscatedAccountId()); assertNotNull(expected.getAccountIdentifiers().getObfuscatedProfileId()); assertEquals( expected.getAccountIdentifiers().getObfuscatedProfileId(), - serialized.get("obfuscatedProfileId")); + Objects.requireNonNull(serialized.getAccountIdentifiers()).getObfuscatedProfileId()); + } + + private String productTypeFromPlatform(Messages.PlatformProductType type) { + switch (type) { + case INAPP: + return BillingClient.ProductType.INAPP; + case SUBS: + return BillingClient.ProductType.SUBS; + } + throw new IllegalStateException("Unhandled type"); } - private void assertSerialized(PurchaseHistoryRecord expected, Object serializedGeneric) { - @SuppressWarnings("unchecked") - final Map serialized = (Map) serializedGeneric; - assertEquals(expected.getPurchaseTime(), serialized.get("purchaseTime")); - assertEquals(expected.getPurchaseToken(), serialized.get("purchaseToken")); - assertEquals(expected.getSignature(), serialized.get("signature")); - assertEquals(expected.getOriginalJson(), serialized.get("originalJson")); - assertEquals(expected.getProducts(), serialized.get("products")); - assertEquals(expected.getDeveloperPayload(), serialized.get("developerPayload")); + private int stateFromPlatform(Messages.PlatformPurchaseState state) { + switch (state) { + case UNSPECIFIED: + return Purchase.PurchaseState.UNSPECIFIED_STATE; + case PURCHASED: + return Purchase.PurchaseState.PURCHASED; + case PENDING: + return Purchase.PurchaseState.PENDING; + } + throw new IllegalStateException("Unhandled state"); + } + + private int recurrenceModeFromPlatform(Messages.PlatformRecurrenceMode mode) { + switch (mode) { + case FINITE_RECURRING: + return ProductDetails.RecurrenceMode.FINITE_RECURRING; + case INFINITE_RECURRING: + return ProductDetails.RecurrenceMode.INFINITE_RECURRING; + case NON_RECURRING: + return ProductDetails.RecurrenceMode.NON_RECURRING; + } + throw new IllegalStateException("Unhandled mode"); + } + + private void assertSerialized( + PurchaseHistoryRecord expected, Messages.PlatformPurchaseHistoryRecord serialized) { + assertEquals(expected.getPurchaseTime(), serialized.getPurchaseTime().longValue()); + assertEquals(expected.getPurchaseToken(), serialized.getPurchaseToken()); + assertEquals(expected.getSignature(), serialized.getSignature()); + assertEquals(expected.getOriginalJson(), serialized.getOriginalJson()); + assertEquals(expected.getProducts(), serialized.getProducts()); + assertEquals(expected.getDeveloperPayload(), serialized.getDeveloperPayload()); + assertEquals(expected.getQuantity(), serialized.getQuantity().intValue()); } } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart index 6e6dee97fb8..bbabd1477a2 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/alternative_billing_only_reporting_details_wrapper.dart @@ -35,6 +35,8 @@ class AlternativeBillingOnlyReportingDetailsWrapper /// /// The map needs to have named string keys with values matching the names and /// types of all of the members on this class. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory AlternativeBillingOnlyReportingDetailsWrapper.fromJson( Map? map) { if (map == null || map.isEmpty) { diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart index af6f4e8d09d..b9417c6b25e 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart @@ -139,8 +139,8 @@ class BillingClient { }) async { return productDetailsResponseWrapperFromPlatform( await _hostApi.queryProductDetailsAsync(productList - .map( - (ProductWrapper product) => platformProductFromWrapper(product)) + .map((ProductWrapper product) => + platformQueryProductFromWrapper(product)) .toList())); } @@ -473,6 +473,8 @@ class BillingChoiceModeConverter const BillingChoiceModeConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') BillingChoiceMode fromJson(int? json) { if (json == null) { return BillingChoiceMode.playBillingOnly; @@ -493,6 +495,8 @@ class BillingResponseConverter implements JsonConverter { const BillingResponseConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') BillingResponse fromJson(int? json) { if (json == null) { return BillingResponse.error; @@ -533,6 +537,8 @@ class ProductTypeConverter implements JsonConverter { const ProductTypeConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') ProductType fromJson(String? json) { if (json == null) { return ProductType.inapp; @@ -603,6 +609,8 @@ class ProrationModeConverter implements JsonConverter { const ProrationModeConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') ProrationMode fromJson(int? json) { if (json == null) { return ProrationMode.unknownSubscriptionUpgradeDowngradePolicy; @@ -658,6 +666,8 @@ class BillingClientFeatureConverter const BillingClientFeatureConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') BillingClientFeature fromJson(String json) { return $enumDecode( _$BillingClientFeatureEnumMap.cast(), diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart index 27601285bc1..3020a120e26 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_config_wrapper.dart @@ -32,6 +32,8 @@ class BillingConfigWrapper implements HasBillingResponse { /// /// The map needs to have named string keys with values matching the names and /// types of all of the members on this class. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory BillingConfigWrapper.fromJson(Map? map) { if (map == null || map.isEmpty) { return const BillingConfigWrapper( diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_response_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_response_wrapper.dart index 583dd4ef716..5faf19764f8 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_response_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_response_wrapper.dart @@ -31,6 +31,8 @@ class BillingResultWrapper implements HasBillingResponse { /// /// The map needs to have named string keys with values matching the names and /// types of all of the members on this class. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory BillingResultWrapper.fromJson(Map? map) { if (map == null || map.isEmpty) { return const BillingResultWrapper( diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/one_time_purchase_offer_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/one_time_purchase_offer_details_wrapper.dart index f5ceed22ebe..f2218495883 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/one_time_purchase_offer_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/one_time_purchase_offer_details_wrapper.dart @@ -17,7 +17,6 @@ part 'one_time_purchase_offer_details_wrapper.g.dart'; @immutable class OneTimePurchaseOfferDetailsWrapper { /// Creates a [OneTimePurchaseOfferDetailsWrapper]. - @visibleForTesting const OneTimePurchaseOfferDetailsWrapper({ required this.formattedPrice, required this.priceAmountMicros, @@ -26,6 +25,8 @@ class OneTimePurchaseOfferDetailsWrapper { /// Factory for creating a [OneTimePurchaseOfferDetailsWrapper] from a [Map] /// with the offer details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory OneTimePurchaseOfferDetailsWrapper.fromJson( Map map) => _$OneTimePurchaseOfferDetailsWrapperFromJson(map); diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_details_wrapper.dart index 2a7c279b3fc..43303d4d237 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/product_details_wrapper.dart @@ -21,7 +21,6 @@ part 'product_details_wrapper.g.dart'; @immutable class ProductDetailsWrapper { /// Creates a [ProductDetailsWrapper] with the given purchase details. - @visibleForTesting const ProductDetailsWrapper({ required this.description, required this.name, @@ -34,6 +33,8 @@ class ProductDetailsWrapper { /// Factory for creating a [ProductDetailsWrapper] from a [Map] with the /// product details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory ProductDetailsWrapper.fromJson(Map map) => _$ProductDetailsWrapperFromJson(map); @@ -123,6 +124,8 @@ class ProductDetailsResponseWrapper implements HasBillingResponse { /// /// The map needs to have named string keys with values matching the names and /// types of all of the members on this class. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory ProductDetailsResponseWrapper.fromJson(Map map) => _$ProductDetailsResponseWrapperFromJson(map); @@ -178,6 +181,8 @@ class RecurrenceModeConverter implements JsonConverter { const RecurrenceModeConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') RecurrenceMode fromJson(int? json) { if (json == null) { return RecurrenceMode.nonRecurring; 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 97fde8a8755..8d17d81c9a4 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 @@ -25,7 +25,6 @@ part 'purchase_wrapper.g.dart'; @immutable class PurchaseWrapper { /// Creates a purchase wrapper with the given purchase details. - @visibleForTesting const PurchaseWrapper({ required this.orderId, required this.packageName, @@ -43,6 +42,8 @@ class PurchaseWrapper { }); /// Factory for creating a [PurchaseWrapper] from a [Map] with the purchase details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory PurchaseWrapper.fromJson(Map map) => _$PurchaseWrapperFromJson(map); @@ -172,7 +173,6 @@ class PurchaseWrapper { @immutable class PurchaseHistoryRecordWrapper { /// Creates a [PurchaseHistoryRecordWrapper] with the given record details. - @visibleForTesting const PurchaseHistoryRecordWrapper({ required this.purchaseTime, required this.purchaseToken, @@ -183,6 +183,8 @@ class PurchaseHistoryRecordWrapper { }); /// Factory for creating a [PurchaseHistoryRecordWrapper] from a [Map] with the record details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory PurchaseHistoryRecordWrapper.fromJson(Map map) => _$PurchaseHistoryRecordWrapperFromJson(map); @@ -263,6 +265,8 @@ class PurchasesResultWrapper implements HasBillingResponse { required this.purchasesList}); /// Factory for creating a [PurchaseResultWrapper] from a [Map] with the result details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory PurchasesResultWrapper.fromJson(Map map) => _$PurchasesResultWrapperFromJson(map); @@ -313,6 +317,8 @@ class PurchasesHistoryResult implements HasBillingResponse { {required this.billingResult, required this.purchaseHistoryRecordList}); /// Factory for creating a [PurchasesHistoryResult] from a [Map] with the history result details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory PurchasesHistoryResult.fromJson(Map map) => _$PurchasesHistoryResultFromJson(map); @@ -387,6 +393,8 @@ class PurchaseStateConverter const PurchaseStateConverter(); @override + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') PurchaseStateWrapper fromJson(int? json) { if (json == null) { return PurchaseStateWrapper.unspecified_state; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart index aa5688eb60f..4b5642ed043 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/subscription_offer_details_wrapper.dart @@ -20,7 +20,6 @@ part 'subscription_offer_details_wrapper.g.dart'; @immutable class SubscriptionOfferDetailsWrapper { /// Creates a [SubscriptionOfferDetailsWrapper]. - @visibleForTesting const SubscriptionOfferDetailsWrapper({ required this.basePlanId, this.offerId, @@ -31,6 +30,8 @@ class SubscriptionOfferDetailsWrapper { /// Factory for creating a [SubscriptionOfferDetailsWrapper] from a [Map] /// with the offer details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory SubscriptionOfferDetailsWrapper.fromJson(Map map) => _$SubscriptionOfferDetailsWrapperFromJson(map); @@ -90,7 +91,6 @@ class SubscriptionOfferDetailsWrapper { @immutable class PricingPhaseWrapper { /// Creates a new [PricingPhaseWrapper] from the supplied info. - @visibleForTesting const PricingPhaseWrapper({ required this.billingCycleCount, required this.billingPeriod, @@ -101,6 +101,8 @@ class PricingPhaseWrapper { }); /// Factory for creating a [PricingPhaseWrapper] from a [Map] with the phase details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory PricingPhaseWrapper.fromJson(Map map) => _$PricingPhaseWrapperFromJson(map); diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart index 4c4307e9896..8b23058c195 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/user_choice_details_wrapper.dart @@ -27,6 +27,8 @@ class UserChoiceDetailsWrapper { /// Factory for creating a [UserChoiceDetailsWrapper] from a [Map] with /// the user choice details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory UserChoiceDetailsWrapper.fromJson(Map map) => _$UserChoiceDetailsWrapperFromJson(map); @@ -81,7 +83,6 @@ class UserChoiceDetailsWrapper { @immutable class UserChoiceDetailsProductWrapper { /// Creates a [UserChoiceDetailsProductWrapper] with the given record details. - @visibleForTesting const UserChoiceDetailsProductWrapper({ required this.id, required this.offerToken, @@ -89,6 +90,8 @@ class UserChoiceDetailsProductWrapper { }); /// Factory for creating a [UserChoiceDetailsProductWrapper] from a [Map] with the record details. + @Deprecated('JSON serialization is not intended for public use, and will ' + 'be removed in a future version.') factory UserChoiceDetailsProductWrapper.fromJson(Map map) => _$UserChoiceDetailsProductWrapperFromJson(map); diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart index 6f19a7b92a8..1b5753f8006 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/messages.g.dart @@ -49,9 +49,23 @@ enum PlatformBillingChoiceMode { userChoiceBilling, } -/// Pigeon version of Java Product. -class PlatformProduct { - PlatformProduct({ +/// Pigeon version of Java Purchase.PurchaseState. +enum PlatformPurchaseState { + unspecified, + purchased, + pending, +} + +/// Pigeon version of Java ProductDetails.RecurrenceMode. +enum PlatformRecurrenceMode { + finiteRecurring, + infiniteRecurring, + nonRecurring, +} + +/// Pigeon version of Java QueryProductDetailsParams.Product. +class PlatformQueryProduct { + PlatformQueryProduct({ required this.productId, required this.productType, }); @@ -67,15 +81,42 @@ class PlatformProduct { ]; } - static PlatformProduct decode(Object result) { + static PlatformQueryProduct decode(Object result) { result as List; - return PlatformProduct( + return PlatformQueryProduct( productId: result[0]! as String, productType: PlatformProductType.values[result[1]! as int], ); } } +/// Pigeon version of Java AccountIdentifiers. +class PlatformAccountIdentifiers { + PlatformAccountIdentifiers({ + this.obfuscatedAccountId, + this.obfuscatedProfileId, + }); + + String? obfuscatedAccountId; + + String? obfuscatedProfileId; + + Object encode() { + return [ + obfuscatedAccountId, + obfuscatedProfileId, + ]; + } + + static PlatformAccountIdentifiers decode(Object result) { + result as List; + return PlatformAccountIdentifiers( + obfuscatedAccountId: result[0] as String?, + obfuscatedProfileId: result[1] as String?, + ); + } +} + /// Pigeon version of Java BillingResult. class PlatformBillingResult { PlatformBillingResult({ @@ -103,24 +144,110 @@ class PlatformBillingResult { } } +/// Pigeon version of Java ProductDetails.OneTimePurchaseOfferDetails. +class PlatformOneTimePurchaseOfferDetails { + PlatformOneTimePurchaseOfferDetails({ + required this.priceAmountMicros, + required this.formattedPrice, + required this.priceCurrencyCode, + }); + + int priceAmountMicros; + + String formattedPrice; + + String priceCurrencyCode; + + Object encode() { + return [ + priceAmountMicros, + formattedPrice, + priceCurrencyCode, + ]; + } + + static PlatformOneTimePurchaseOfferDetails decode(Object result) { + result as List; + return PlatformOneTimePurchaseOfferDetails( + priceAmountMicros: result[0]! as int, + formattedPrice: result[1]! as String, + priceCurrencyCode: result[2]! as String, + ); + } +} + +/// Pigeon version of Java ProductDetails. +class PlatformProductDetails { + PlatformProductDetails({ + required this.description, + required this.name, + required this.productId, + required this.productType, + required this.title, + this.oneTimePurchaseOfferDetails, + this.subscriptionOfferDetails, + }); + + String description; + + String name; + + String productId; + + PlatformProductType productType; + + String title; + + PlatformOneTimePurchaseOfferDetails? oneTimePurchaseOfferDetails; + + List? subscriptionOfferDetails; + + Object encode() { + return [ + description, + name, + productId, + productType.index, + title, + oneTimePurchaseOfferDetails?.encode(), + subscriptionOfferDetails, + ]; + } + + static PlatformProductDetails decode(Object result) { + result as List; + return PlatformProductDetails( + description: result[0]! as String, + name: result[1]! as String, + productId: result[2]! as String, + productType: PlatformProductType.values[result[3]! as int], + title: result[4]! as String, + oneTimePurchaseOfferDetails: result[5] != null + ? PlatformOneTimePurchaseOfferDetails.decode( + result[5]! as List) + : null, + subscriptionOfferDetails: (result[6] as List?) + ?.cast(), + ); + } +} + /// Pigeon version of ProductDetailsResponseWrapper, which contains the /// components of the Java ProductDetailsResponseListener callback. class PlatformProductDetailsResponse { PlatformProductDetailsResponse({ required this.billingResult, - required this.productDetailsJsonList, + required this.productDetails, }); PlatformBillingResult billingResult; - /// A JSON-compatible list of details, where each entry in the list is a - /// Map JSON encoding of the product details. - List productDetailsJsonList; + List productDetails; Object encode() { return [ billingResult.encode(), - productDetailsJsonList, + productDetails, ]; } @@ -128,7 +255,8 @@ class PlatformProductDetailsResponse { result as List; return PlatformProductDetailsResponse( billingResult: PlatformBillingResult.decode(result[0]! as List), - productDetailsJsonList: (result[1] as List?)!.cast(), + productDetails: + (result[1] as List?)!.cast(), ); } } @@ -243,24 +371,209 @@ class PlatformBillingFlowParams { } } +/// Pigeon version of Java ProductDetails.PricingPhase. +class PlatformPricingPhase { + PlatformPricingPhase({ + required this.billingCycleCount, + required this.recurrenceMode, + required this.priceAmountMicros, + required this.billingPeriod, + required this.formattedPrice, + required this.priceCurrencyCode, + }); + + int billingCycleCount; + + PlatformRecurrenceMode recurrenceMode; + + int priceAmountMicros; + + String billingPeriod; + + String formattedPrice; + + String priceCurrencyCode; + + Object encode() { + return [ + billingCycleCount, + recurrenceMode.index, + priceAmountMicros, + billingPeriod, + formattedPrice, + priceCurrencyCode, + ]; + } + + static PlatformPricingPhase decode(Object result) { + result as List; + return PlatformPricingPhase( + billingCycleCount: result[0]! as int, + recurrenceMode: PlatformRecurrenceMode.values[result[1]! as int], + priceAmountMicros: result[2]! as int, + billingPeriod: result[3]! as String, + formattedPrice: result[4]! as String, + priceCurrencyCode: result[5]! as String, + ); + } +} + +/// Pigeon version of Java Purchase. +/// +/// See also PurchaseWrapper on the Dart side. +class PlatformPurchase { + PlatformPurchase({ + this.orderId, + required this.packageName, + required this.purchaseTime, + required this.purchaseToken, + required this.signature, + required this.products, + required this.isAutoRenewing, + required this.originalJson, + required this.developerPayload, + required this.isAcknowledged, + required this.quantity, + required this.purchaseState, + this.accountIdentifiers, + }); + + String? orderId; + + String packageName; + + int purchaseTime; + + String purchaseToken; + + String signature; + + List products; + + bool isAutoRenewing; + + String originalJson; + + String developerPayload; + + bool isAcknowledged; + + int quantity; + + PlatformPurchaseState purchaseState; + + PlatformAccountIdentifiers? accountIdentifiers; + + Object encode() { + return [ + orderId, + packageName, + purchaseTime, + purchaseToken, + signature, + products, + isAutoRenewing, + originalJson, + developerPayload, + isAcknowledged, + quantity, + purchaseState.index, + accountIdentifiers?.encode(), + ]; + } + + static PlatformPurchase decode(Object result) { + result as List; + return PlatformPurchase( + orderId: result[0] as String?, + packageName: result[1]! as String, + purchaseTime: result[2]! as int, + purchaseToken: result[3]! as String, + signature: result[4]! as String, + products: (result[5] as List?)!.cast(), + isAutoRenewing: result[6]! as bool, + originalJson: result[7]! as String, + developerPayload: result[8]! as String, + isAcknowledged: result[9]! as bool, + quantity: result[10]! as int, + purchaseState: PlatformPurchaseState.values[result[11]! as int], + accountIdentifiers: result[12] != null + ? PlatformAccountIdentifiers.decode(result[12]! as List) + : null, + ); + } +} + +/// Pigeon version of PurchaseHistoryRecord. +/// +/// See also PurchaseHistoryRecordWrapper on the Dart side. +class PlatformPurchaseHistoryRecord { + PlatformPurchaseHistoryRecord({ + required this.quantity, + required this.purchaseTime, + this.developerPayload, + required this.originalJson, + required this.purchaseToken, + required this.signature, + required this.products, + }); + + int quantity; + + int purchaseTime; + + String? developerPayload; + + String originalJson; + + String purchaseToken; + + String signature; + + List products; + + Object encode() { + return [ + quantity, + purchaseTime, + developerPayload, + originalJson, + purchaseToken, + signature, + products, + ]; + } + + static PlatformPurchaseHistoryRecord decode(Object result) { + result as List; + return PlatformPurchaseHistoryRecord( + quantity: result[0]! as int, + purchaseTime: result[1]! as int, + developerPayload: result[2] as String?, + originalJson: result[3]! as String, + purchaseToken: result[4]! as String, + signature: result[5]! as String, + products: (result[6] as List?)!.cast(), + ); + } +} + /// Pigeon version of PurchasesHistoryResult, which contains the components of /// the Java PurchaseHistoryResponseListener callback. class PlatformPurchaseHistoryResponse { PlatformPurchaseHistoryResponse({ required this.billingResult, - required this.purchaseHistoryRecordJsonList, + required this.purchases, }); PlatformBillingResult billingResult; - /// A JSON-compatible list of purchase history records, where each entry in - /// the list is a Map JSON encoding of the record. - List purchaseHistoryRecordJsonList; + List purchases; Object encode() { return [ billingResult.encode(), - purchaseHistoryRecordJsonList, + purchases, ]; } @@ -268,8 +581,8 @@ class PlatformPurchaseHistoryResponse { result as List; return PlatformPurchaseHistoryResponse( billingResult: PlatformBillingResult.decode(result[0]! as List), - purchaseHistoryRecordJsonList: - (result[1] as List?)!.cast(), + purchases: + (result[1] as List?)!.cast(), ); } } @@ -279,19 +592,17 @@ class PlatformPurchaseHistoryResponse { class PlatformPurchasesResponse { PlatformPurchasesResponse({ required this.billingResult, - required this.purchasesJsonList, + required this.purchases, }); PlatformBillingResult billingResult; - /// A JSON-compatible list of purchases, where each entry in the list is a - /// Map JSON encoding of the product details. - List purchasesJsonList; + List purchases; Object encode() { return [ billingResult.encode(), - purchasesJsonList, + purchases, ]; } @@ -299,7 +610,50 @@ class PlatformPurchasesResponse { result as List; return PlatformPurchasesResponse( billingResult: PlatformBillingResult.decode(result[0]! as List), - purchasesJsonList: (result[1] as List?)!.cast(), + purchases: (result[1] as List?)!.cast(), + ); + } +} + +/// Pigeon version of Java ProductDetails.SubscriptionOfferDetails. +class PlatformSubscriptionOfferDetails { + PlatformSubscriptionOfferDetails({ + required this.basePlanId, + this.offerId, + required this.offerToken, + required this.offerTags, + required this.pricingPhases, + }); + + String basePlanId; + + String? offerId; + + String offerToken; + + List offerTags; + + List pricingPhases; + + Object encode() { + return [ + basePlanId, + offerId, + offerToken, + offerTags, + pricingPhases, + ]; + } + + static PlatformSubscriptionOfferDetails decode(Object result) { + result as List; + return PlatformSubscriptionOfferDetails( + basePlanId: result[0]! as String, + offerId: result[1] as String?, + offerToken: result[2]! as String, + offerTags: (result[3] as List?)!.cast(), + pricingPhases: + (result[4] as List?)!.cast(), ); } } @@ -309,22 +663,20 @@ class PlatformUserChoiceDetails { PlatformUserChoiceDetails({ this.originalExternalTransactionId, required this.externalTransactionToken, - required this.productsJsonList, + required this.products, }); String? originalExternalTransactionId; String externalTransactionToken; - /// A JSON-compatible list of products, where each entry in the list is a - /// Map JSON encoding of the product. - List productsJsonList; + List products; Object encode() { return [ originalExternalTransactionId, externalTransactionToken, - productsJsonList, + products, ]; } @@ -333,7 +685,40 @@ class PlatformUserChoiceDetails { return PlatformUserChoiceDetails( originalExternalTransactionId: result[0] as String?, externalTransactionToken: result[1]! as String, - productsJsonList: (result[2] as List?)!.cast(), + products: + (result[2] as List?)!.cast(), + ); + } +} + +/// Pigeon version of UserChoiseDetails.Product. +class PlatformUserChoiceProduct { + PlatformUserChoiceProduct({ + required this.id, + this.offerToken, + required this.type, + }); + + String id; + + String? offerToken; + + PlatformProductType type; + + Object encode() { + return [ + id, + offerToken, + type.index, + ]; + } + + static PlatformUserChoiceProduct decode(Object result) { + result as List; + return PlatformUserChoiceProduct( + id: result[0]! as String, + offerToken: result[1] as String?, + type: PlatformProductType.values[result[2]! as int], ); } } @@ -342,30 +727,52 @@ class _InAppPurchaseApiCodec extends StandardMessageCodec { const _InAppPurchaseApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PlatformAlternativeBillingOnlyReportingDetailsResponse) { + if (value is PlatformAccountIdentifiers) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is PlatformBillingConfigResponse) { + } else if (value + is PlatformAlternativeBillingOnlyReportingDetailsResponse) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is PlatformBillingFlowParams) { + } else if (value is PlatformBillingConfigResponse) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is PlatformBillingResult) { + } else if (value is PlatformBillingFlowParams) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is PlatformProduct) { + } else if (value is PlatformBillingResult) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PlatformProductDetailsResponse) { + } else if (value is PlatformOneTimePurchaseOfferDetails) { buffer.putUint8(133); writeValue(buffer, value.encode()); - } else if (value is PlatformPurchaseHistoryResponse) { + } else if (value is PlatformPricingPhase) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is PlatformPurchasesResponse) { + } else if (value is PlatformProductDetails) { buffer.putUint8(135); writeValue(buffer, value.encode()); + } else if (value is PlatformProductDetailsResponse) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); + } else if (value is PlatformPurchase) { + buffer.putUint8(137); + writeValue(buffer, value.encode()); + } else if (value is PlatformPurchaseHistoryRecord) { + buffer.putUint8(138); + writeValue(buffer, value.encode()); + } else if (value is PlatformPurchaseHistoryResponse) { + buffer.putUint8(139); + writeValue(buffer, value.encode()); + } else if (value is PlatformPurchasesResponse) { + buffer.putUint8(140); + writeValue(buffer, value.encode()); + } else if (value is PlatformQueryProduct) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PlatformSubscriptionOfferDetails) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -375,22 +782,36 @@ class _InAppPurchaseApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: + return PlatformAccountIdentifiers.decode(readValue(buffer)!); + case 129: return PlatformAlternativeBillingOnlyReportingDetailsResponse.decode( readValue(buffer)!); - case 129: - return PlatformBillingConfigResponse.decode(readValue(buffer)!); case 130: - return PlatformBillingFlowParams.decode(readValue(buffer)!); + return PlatformBillingConfigResponse.decode(readValue(buffer)!); case 131: - return PlatformBillingResult.decode(readValue(buffer)!); + return PlatformBillingFlowParams.decode(readValue(buffer)!); case 132: - return PlatformProduct.decode(readValue(buffer)!); + return PlatformBillingResult.decode(readValue(buffer)!); case 133: - return PlatformProductDetailsResponse.decode(readValue(buffer)!); + return PlatformOneTimePurchaseOfferDetails.decode(readValue(buffer)!); case 134: - return PlatformPurchaseHistoryResponse.decode(readValue(buffer)!); + return PlatformPricingPhase.decode(readValue(buffer)!); case 135: + return PlatformProductDetails.decode(readValue(buffer)!); + case 136: + return PlatformProductDetailsResponse.decode(readValue(buffer)!); + case 137: + return PlatformPurchase.decode(readValue(buffer)!); + case 138: + return PlatformPurchaseHistoryRecord.decode(readValue(buffer)!); + case 139: + return PlatformPurchaseHistoryResponse.decode(readValue(buffer)!); + case 140: return PlatformPurchasesResponse.decode(readValue(buffer)!); + case 141: + return PlatformQueryProduct.decode(readValue(buffer)!); + case 142: + return PlatformSubscriptionOfferDetails.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -680,7 +1101,7 @@ class InAppPurchaseApi { /// Wraps BillingClient#queryProductDetailsAsync(QueryProductDetailsParams, ProductDetailsResponseListener). Future queryProductDetailsAsync( - List products) async { + List products) async { const String __pigeon_channelName = 'dev.flutter.pigeon.in_app_purchase_android.InAppPurchaseApi.queryProductDetailsAsync'; final BasicMessageChannel __pigeon_channel = @@ -837,15 +1258,24 @@ class _InAppPurchaseCallbackApiCodec extends StandardMessageCodec { const _InAppPurchaseCallbackApiCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PlatformBillingResult) { + if (value is PlatformAccountIdentifiers) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is PlatformPurchasesResponse) { + } else if (value is PlatformBillingResult) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is PlatformUserChoiceDetails) { + } else if (value is PlatformPurchase) { buffer.putUint8(130); writeValue(buffer, value.encode()); + } else if (value is PlatformPurchasesResponse) { + buffer.putUint8(131); + writeValue(buffer, value.encode()); + } else if (value is PlatformUserChoiceDetails) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); + } else if (value is PlatformUserChoiceProduct) { + buffer.putUint8(133); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -855,11 +1285,17 @@ class _InAppPurchaseCallbackApiCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return PlatformBillingResult.decode(readValue(buffer)!); + return PlatformAccountIdentifiers.decode(readValue(buffer)!); case 129: - return PlatformPurchasesResponse.decode(readValue(buffer)!); + return PlatformBillingResult.decode(readValue(buffer)!); case 130: + return PlatformPurchase.decode(readValue(buffer)!); + case 131: + return PlatformPurchasesResponse.decode(readValue(buffer)!); + case 132: return PlatformUserChoiceDetails.decode(readValue(buffer)!); + case 133: + return PlatformUserChoiceProduct.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart index 232302f3a5f..7fe8a3c92f2 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/pigeon_converters.dart @@ -30,38 +30,84 @@ BillingResultWrapper resultWrapperFromPlatform(PlatformBillingResult result) { ProductDetailsResponseWrapper productDetailsResponseWrapperFromPlatform( PlatformProductDetailsResponse response) { return ProductDetailsResponseWrapper( - billingResult: resultWrapperFromPlatform(response.billingResult), - // See TODOs in messages.dart for why this is currently JSON. - productDetailsList: response.productDetailsJsonList - .map((Object? json) => ProductDetailsWrapper.fromJson( - (json! as Map).cast())) + billingResult: resultWrapperFromPlatform(response.billingResult), + productDetailsList: response.productDetails + // See TODOs in messages.dart for why casting away nullability is safe. + .map((PlatformProductDetails? p) => p!) + .map(productDetailsWrapperFromPlatform) + .toList()); +} + +/// Creates a [ProductDetailsWrapper] from the Pigeon equivalent. +ProductDetailsWrapper productDetailsWrapperFromPlatform( + PlatformProductDetails product) { + return ProductDetailsWrapper( + description: product.description, + name: product.name, + productId: product.productId, + productType: productTypeFromPlatform(product.productType), + title: product.title, + oneTimePurchaseOfferDetails: oneTimePurchaseOfferDetailsWrapperFromPlatform( + product.oneTimePurchaseOfferDetails), + subscriptionOfferDetails: product.subscriptionOfferDetails + // See comment in messages.dart for why casting away nullability is safe. + ?.map((PlatformSubscriptionOfferDetails? o) => o!) + .map(subscriptionOfferDetailsWrapperFromPlatform) .toList(), ); } +/// Creates a [OneTimePurchaseOfferDetailsWrapper] from the Pigeon equivalent. +OneTimePurchaseOfferDetailsWrapper? + oneTimePurchaseOfferDetailsWrapperFromPlatform( + PlatformOneTimePurchaseOfferDetails? details) { + if (details == null) { + return null; + } + return OneTimePurchaseOfferDetailsWrapper( + formattedPrice: details.formattedPrice, + priceAmountMicros: details.priceAmountMicros, + priceCurrencyCode: details.priceCurrencyCode, + ); +} + /// Creates a [PurchaseHistoryResult] from the Pigeon equivalent. PurchasesHistoryResult purchaseHistoryResultFromPlatform( PlatformPurchaseHistoryResponse response) { return PurchasesHistoryResult( billingResult: resultWrapperFromPlatform(response.billingResult), - // See TODOs in messages.dart for why this is currently JSON. - purchaseHistoryRecordList: response.purchaseHistoryRecordJsonList - .map((Object? json) => PurchaseHistoryRecordWrapper.fromJson( - (json! as Map).cast())) + purchaseHistoryRecordList: response.purchases + // See comment in messages.dart for why casting away nullability is safe. + .map((PlatformPurchaseHistoryRecord? r) => r!) + .map(purchaseHistoryRecordWrapperFromPlatform) .toList(), ); } +/// Creates a [PurchaseHistoryRecordWrapper] from the Pigeon equivalent. +PurchaseHistoryRecordWrapper purchaseHistoryRecordWrapperFromPlatform( + PlatformPurchaseHistoryRecord record) { + return PurchaseHistoryRecordWrapper( + purchaseTime: record.purchaseTime, + purchaseToken: record.purchaseToken, + signature: record.signature, + // See comment in messages.dart for why casting away nullability is safe. + products: record.products.map((String? s) => s!).toList(), + originalJson: record.originalJson, + developerPayload: record.developerPayload, + ); +} + /// Creates a [PurchasesResultWrapper] from the Pigeon equivalent. PurchasesResultWrapper purchasesResultWrapperFromPlatform( PlatformPurchasesResponse response, {bool forceOkResponseCode = false}) { return PurchasesResultWrapper( billingResult: resultWrapperFromPlatform(response.billingResult), - // See TODOs in messages.dart for why this is currently JSON. - purchasesList: response.purchasesJsonList - .map((Object? json) => PurchaseWrapper.fromJson( - (json! as Map).cast())) + purchasesList: response.purchases + // See TODOs in messages.dart for why casting away nullability is safe. + .map((PlatformPurchase? p) => p!) + .map(purchaseWrapperFromPlatform) .toList(), responseCode: forceOkResponseCode ? BillingResponse.ok @@ -95,8 +141,8 @@ BillingConfigWrapper billingConfigWrapperFromPlatform( } /// Creates a Pigeon [PlatformProduct] from a [ProductWrapper]. -PlatformProduct platformProductFromWrapper(ProductWrapper product) { - return PlatformProduct( +PlatformQueryProduct platformQueryProductFromWrapper(ProductWrapper product) { + return PlatformQueryProduct( productId: product.productId, productType: platformProductTypeFromWrapper(product.productType), ); @@ -110,16 +156,104 @@ PlatformProductType platformProductTypeFromWrapper(ProductType type) { }; } +/// Creates a [PricingPhaseWrapper] from its Pigeon equivalent. +PricingPhaseWrapper pricingPhaseWrapperFromPlatform( + PlatformPricingPhase phase) { + return PricingPhaseWrapper( + billingCycleCount: phase.billingCycleCount, + billingPeriod: phase.billingPeriod, + formattedPrice: phase.formattedPrice, + priceAmountMicros: phase.priceAmountMicros, + priceCurrencyCode: phase.priceCurrencyCode, + recurrenceMode: recurrenceModeFromPlatform(phase.recurrenceMode), + ); +} + +/// Converts a Pigeon [PlatformProductType] to its public API equivalent. +ProductType productTypeFromPlatform(PlatformProductType type) { + return switch (type) { + PlatformProductType.inapp => ProductType.inapp, + PlatformProductType.subs => ProductType.subs, + }; +} + +/// Creates a [PurchaseWrapper] from the Pigeon equivalent. +PurchaseWrapper purchaseWrapperFromPlatform(PlatformPurchase purchase) { + return PurchaseWrapper( + orderId: purchase.orderId ?? '', + packageName: purchase.packageName, + purchaseTime: purchase.purchaseTime, + purchaseToken: purchase.purchaseToken, + signature: purchase.signature, + // See comment in messages.dart for why casting away nullability is safe. + products: purchase.products.map((String? s) => s!).toList(), + isAutoRenewing: purchase.isAutoRenewing, + originalJson: purchase.originalJson, + isAcknowledged: purchase.isAcknowledged, + purchaseState: purchaseStateWrapperFromPlatform(purchase.purchaseState), + developerPayload: purchase.developerPayload, + obfuscatedAccountId: purchase.accountIdentifiers?.obfuscatedAccountId, + obfuscatedProfileId: purchase.accountIdentifiers?.obfuscatedProfileId, + ); +} + +/// Creates a [PurchaseStateWrapper] from the Pigeon equivalent. +PurchaseStateWrapper purchaseStateWrapperFromPlatform( + PlatformPurchaseState state) { + return switch (state) { + PlatformPurchaseState.unspecified => PurchaseStateWrapper.unspecified_state, + PlatformPurchaseState.purchased => PurchaseStateWrapper.purchased, + PlatformPurchaseState.pending => PurchaseStateWrapper.pending, + }; +} + +/// Creates a [RecurrenceMode] from the Pigeon equivalent. +RecurrenceMode recurrenceModeFromPlatform(PlatformRecurrenceMode mode) { + return switch (mode) { + PlatformRecurrenceMode.finiteRecurring => RecurrenceMode.finiteRecurring, + PlatformRecurrenceMode.infiniteRecurring => + RecurrenceMode.infiniteRecurring, + PlatformRecurrenceMode.nonRecurring => RecurrenceMode.nonRecurring, + }; +} + +/// Creates a [SubscriptionOfferDetailsWrapper] from the Pigeon equivalent. +SubscriptionOfferDetailsWrapper subscriptionOfferDetailsWrapperFromPlatform( + PlatformSubscriptionOfferDetails offer) { + return SubscriptionOfferDetailsWrapper( + basePlanId: offer.basePlanId, + offerId: offer.offerId, + // See comment in messages.dart for why casting away nullability is safe. + offerTags: offer.offerTags.map((String? s) => s!).toList(), + offerIdToken: offer.offerToken, + pricingPhases: offer.pricingPhases + // See comment in messages.dart for why casting away nullability is safe. + .map((PlatformPricingPhase? p) => p!) + .map(pricingPhaseWrapperFromPlatform) + .toList(), + ); +} + /// Creates a [UserChoiceDetailsWrapper] from the Pigeon equivalent. UserChoiceDetailsWrapper userChoiceDetailsFromPlatform( PlatformUserChoiceDetails details) { return UserChoiceDetailsWrapper( originalExternalTransactionId: details.originalExternalTransactionId ?? '', externalTransactionToken: details.externalTransactionToken, - // See TODOs in messages.dart for why this is currently JSON. - products: details.productsJsonList - .map((Object? json) => UserChoiceDetailsProductWrapper.fromJson( - (json! as Map).cast())) + products: details.products + // See comment in messages.dart for why casting away nullability is safe. + .map((PlatformUserChoiceProduct? p) => p!) + .map(userChoiceDetailsProductFromPlatform) .toList(), ); } + +/// Creates a [UserChoiceDetailsProductWrapper] from the Pigeon equivalent. +UserChoiceDetailsProductWrapper userChoiceDetailsProductFromPlatform( + PlatformUserChoiceProduct product) { + return UserChoiceDetailsProductWrapper( + id: product.id, + offerToken: product.offerToken ?? '', + productType: productTypeFromPlatform(product.type), + ); +} diff --git a/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart b/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart index 7d66a8723d9..2921c0907ca 100644 --- a/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart +++ b/packages/in_app_purchase/in_app_purchase_android/pigeons/messages.dart @@ -12,14 +12,25 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', )) -/// Pigeon version of Java Product. -class PlatformProduct { - PlatformProduct({required this.productId, required this.productType}); +/// Pigeon version of Java QueryProductDetailsParams.Product. +class PlatformQueryProduct { + PlatformQueryProduct({required this.productId, required this.productType}); final String productId; final PlatformProductType productType; } +/// Pigeon version of Java AccountIdentifiers. +class PlatformAccountIdentifiers { + PlatformAccountIdentifiers({ + required this.obfuscatedAccountId, + required this.obfuscatedProfileId, + }); + + final String? obfuscatedAccountId; + final String? obfuscatedProfileId; +} + /// Pigeon version of Java BillingResult. class PlatformBillingResult { PlatformBillingResult( @@ -28,28 +39,57 @@ class PlatformBillingResult { final String debugMessage; } +/// Pigeon version of Java ProductDetails.OneTimePurchaseOfferDetails. +class PlatformOneTimePurchaseOfferDetails { + PlatformOneTimePurchaseOfferDetails({ + required this.priceAmountMicros, + required this.formattedPrice, + required this.priceCurrencyCode, + }); + + final int priceAmountMicros; + final String formattedPrice; + final String priceCurrencyCode; +} + +/// Pigeon version of Java ProductDetails. +class PlatformProductDetails { + PlatformProductDetails({ + required this.description, + required this.name, + required this.productId, + required this.productType, + required this.title, + required this.oneTimePurchaseOfferDetails, + required this.subscriptionOfferDetails, + }); + + final String description; + final String name; + final String productId; + final PlatformProductType productType; + final String title; + final PlatformOneTimePurchaseOfferDetails? oneTimePurchaseOfferDetails; + // TODO(stuartmorgan): Make the generic type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats it (the entries, not the list itself) as + // non-nullable. + final List? subscriptionOfferDetails; +} + /// Pigeon version of ProductDetailsResponseWrapper, which contains the /// components of the Java ProductDetailsResponseListener callback. class PlatformProductDetailsResponse { PlatformProductDetailsResponse({ required this.billingResult, - required this.productDetailsJsonList, + required this.productDetails, }); final PlatformBillingResult billingResult; - - /// A JSON-compatible list of details, where each entry in the list is a - /// Map JSON encoding of the product details. - // TODO(stuartmorgan): Finish converting to Pigeon. This is still using the - // old serialization system to allow conversion of all the method calls to - // Pigeon without converting the entire object graph all at once. See - // https://github.com/flutter/flutter/issues/117910. The list items are - // currently untyped due to https://github.com/flutter/flutter/issues/116117. - // // TODO(stuartmorgan): Make the generic type non-nullable once supported. // https://github.com/flutter/flutter/issues/97848 // The consuming code treats it as non-nullable. - final List productDetailsJsonList; + final List productDetails; } /// Pigeon version of AlternativeBillingOnlyReportingDetailsWrapper, which @@ -97,28 +137,102 @@ class PlatformBillingFlowParams { final String? purchaseToken; } +/// Pigeon version of Java ProductDetails.PricingPhase. +class PlatformPricingPhase { + PlatformPricingPhase({ + required this.billingCycleCount, + required this.recurrenceMode, + required this.priceAmountMicros, + required this.billingPeriod, + required this.formattedPrice, + required this.priceCurrencyCode, + }); + + final int billingCycleCount; + final PlatformRecurrenceMode recurrenceMode; + final int priceAmountMicros; + final String billingPeriod; + final String formattedPrice; + final String priceCurrencyCode; +} + +/// Pigeon version of Java Purchase. +/// +/// See also PurchaseWrapper on the Dart side. +class PlatformPurchase { + const PlatformPurchase({ + required this.orderId, + required this.packageName, + required this.purchaseTime, + required this.purchaseToken, + required this.signature, + required this.products, + required this.isAutoRenewing, + required this.originalJson, + required this.developerPayload, + required this.isAcknowledged, + required this.quantity, + required this.purchaseState, + required this.accountIdentifiers, + }); + + final String? orderId; + final String packageName; + final int purchaseTime; + final String purchaseToken; + final String signature; + // TODO(stuartmorgan): Make the type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats it as non-nullable. + final List products; + final bool isAutoRenewing; + final String originalJson; + final String developerPayload; + final bool isAcknowledged; + final int quantity; + final PlatformPurchaseState purchaseState; + final PlatformAccountIdentifiers? accountIdentifiers; +} + +/// Pigeon version of PurchaseHistoryRecord. +/// +/// See also PurchaseHistoryRecordWrapper on the Dart side. +class PlatformPurchaseHistoryRecord { + PlatformPurchaseHistoryRecord({ + required this.quantity, + required this.purchaseTime, + required this.developerPayload, + required this.originalJson, + required this.purchaseToken, + required this.signature, + required this.products, + }); + + final int quantity; + final int purchaseTime; + final String? developerPayload; + final String originalJson; + final String purchaseToken; + final String signature; + // TODO(stuartmorgan): Make the type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats it as non-nullable. + final List products; +} + /// Pigeon version of PurchasesHistoryResult, which contains the components of /// the Java PurchaseHistoryResponseListener callback. class PlatformPurchaseHistoryResponse { PlatformPurchaseHistoryResponse({ required this.billingResult, - required this.purchaseHistoryRecordJsonList, + required this.purchases, }); final PlatformBillingResult billingResult; - - /// A JSON-compatible list of purchase history records, where each entry in - /// the list is a Map JSON encoding of the record. - // TODO(stuartmorgan): Finish converting to Pigeon. This is still using the - // old serialization system to allow conversion of all the method calls to - // Pigeon without converting the entire object graph all at once. See - // https://github.com/flutter/flutter/issues/117910. The list items are - // currently untyped due to https://github.com/flutter/flutter/issues/116117. - // - // TODO(stuartmorgan): Make the generic type non-nullable once supported. + // TODO(stuartmorgan): Make the type non-nullable once supported. // https://github.com/flutter/flutter/issues/97848 // The consuming code treats it as non-nullable. - final List purchaseHistoryRecordJsonList; + final List purchases; } /// Pigeon version of PurchasesResultWrapper, which contains the components of @@ -126,23 +240,41 @@ class PlatformPurchaseHistoryResponse { class PlatformPurchasesResponse { PlatformPurchasesResponse({ required this.billingResult, - required this.purchasesJsonList, + required this.purchases, }); final PlatformBillingResult billingResult; + // TODO(stuartmorgan): Make the generic type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats it as non-nullable. + final List purchases; +} + +/// Pigeon version of Java ProductDetails.SubscriptionOfferDetails. +class PlatformSubscriptionOfferDetails { + PlatformSubscriptionOfferDetails({ + required this.basePlanId, + required this.offerId, + required this.offerToken, + required this.offerTags, + required this.pricingPhases, + }); - /// A JSON-compatible list of purchases, where each entry in the list is a - /// Map JSON encoding of the product details. - // TODO(stuartmorgan): Finish converting to Pigeon. This is still using the - // old serialization system to allow conversion of all the method calls to - // Pigeon without converting the entire object graph all at once. See - // https://github.com/flutter/flutter/issues/117910. The list items are - // currently untyped due to https://github.com/flutter/flutter/issues/116117. - // + final String basePlanId; + final String? offerId; + final String offerToken; + // TODO(stuartmorgan): Make the generic type non-nullable once supported. + // https://github.com/flutter/flutter/issues/97848 + // The consuming code treats it as non-nullable. + final List offerTags; + // On the native side this is actually a class called PricingPhases, + // which contains nothing but a List. Since this is an + // internal API, we can always add that indirection later if we need it, + // so for now this bypasses that unnecessary wrapper. // TODO(stuartmorgan): Make the generic type non-nullable once supported. // https://github.com/flutter/flutter/issues/97848 // The consuming code treats it as non-nullable. - final List purchasesJsonList; + final List pricingPhases; } /// Pigeon version of UserChoiceDetailsWrapper and Java UserChoiceDetails. @@ -150,24 +282,28 @@ class PlatformUserChoiceDetails { PlatformUserChoiceDetails({ required this.originalExternalTransactionId, required this.externalTransactionToken, - required this.productsJsonList, + required this.products, }); final String? originalExternalTransactionId; final String externalTransactionToken; - - /// A JSON-compatible list of products, where each entry in the list is a - /// Map JSON encoding of the product. - // TODO(stuartmorgan): Finish converting to Pigeon. This is still using the - // old serialization system to allow conversion of all the method calls to - // Pigeon without converting the entire object graph all at once. See - // https://github.com/flutter/flutter/issues/117910. The list items are - // currently untyped due to https://github.com/flutter/flutter/issues/116117. - // // TODO(stuartmorgan): Make the generic type non-nullable once supported. // https://github.com/flutter/flutter/issues/97848 // The consuming code treats it as non-nullable. - final List productsJsonList; + final List products; +} + +/// Pigeon version of UserChoiseDetails.Product. +class PlatformUserChoiceProduct { + PlatformUserChoiceProduct({ + required this.id, + required this.offerToken, + required this.type, + }); + + final String id; + final String? offerToken; + final PlatformProductType type; } /// Pigeon version of Java BillingClient.ProductType. @@ -190,6 +326,20 @@ enum PlatformBillingChoiceMode { userChoiceBilling, } +/// Pigeon version of Java Purchase.PurchaseState. +enum PlatformPurchaseState { + unspecified, + purchased, + pending, +} + +/// Pigeon version of Java ProductDetails.RecurrenceMode. +enum PlatformRecurrenceMode { + finiteRecurring, + infiniteRecurring, + nonRecurring, +} + @HostApi() abstract class InAppPurchaseApi { /// Wraps BillingClient#isReady. @@ -231,7 +381,7 @@ abstract class InAppPurchaseApi { /// Wraps BillingClient#queryProductDetailsAsync(QueryProductDetailsParams, ProductDetailsResponseListener). @async PlatformProductDetailsResponse queryProductDetailsAsync( - List products); + List products); /// Wraps BillingClient#isFeatureSupported(String). // TODO(stuartmorgan): Consider making this take a enum, and converting the 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 54da00c680f..125aede3ff7 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 @@ name: in_app_purchase_android 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/packages/tree/main/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.3.2+1 +version: 0.3.3 environment: sdk: ^3.1.0 diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart index 4bf15d878ba..0d94ddc7bf9 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart @@ -203,7 +203,7 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - productDetailsJsonList: >[], + productDetails: [], )); final ProductDetailsResponseWrapper response = await billingClient @@ -227,8 +227,8 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - productDetailsJsonList: >[ - buildProductMap(dummyOneTimeProductDetails) + productDetails: [ + convertToPigeonProductDetails(dummyOneTimeProductDetails) ], )); @@ -436,16 +436,17 @@ void main() { const String debugMessage = 'dummy message'; const BillingResultWrapper expectedBillingResult = BillingResultWrapper( responseCode: expectedCode, debugMessage: debugMessage); - when(mockApi.queryPurchasesAsync(any)).thenAnswer((_) async => - PlatformPurchasesResponse( - billingResult: PlatformBillingResult( - responseCode: - const BillingResponseConverter().toJson(expectedCode), - debugMessage: debugMessage), - purchasesJsonList: expectedList - .map((PurchaseWrapper purchase) => buildPurchaseMap(purchase)) - .toList(), - )); + when(mockApi.queryPurchasesAsync(any)) + .thenAnswer((_) async => PlatformPurchasesResponse( + billingResult: PlatformBillingResult( + responseCode: + const BillingResponseConverter().toJson(expectedCode), + debugMessage: debugMessage), + purchases: expectedList + .map((PurchaseWrapper purchase) => + convertToPigeonPurchase(purchase)) + .toList(), + )); final PurchasesResultWrapper response = await billingClient.queryPurchases(ProductType.inapp); @@ -466,7 +467,7 @@ void main() { responseCode: const BillingResponseConverter().toJson(expectedCode), debugMessage: debugMessage), - purchasesJsonList: >[], + purchases: [], )); final PurchasesResultWrapper response = @@ -496,9 +497,8 @@ void main() { responseCode: const BillingResponseConverter().toJson(expectedCode), debugMessage: debugMessage), - purchaseHistoryRecordJsonList: expectedList - .map((PurchaseHistoryRecordWrapper purchaseHistoryRecord) => - buildPurchaseHistoryRecordMap(purchaseHistoryRecord)) + purchases: expectedList + .map(platformPurchaseHistoryRecordFromWrapper) .toList(), )); @@ -519,7 +519,7 @@ void main() { responseCode: const BillingResponseConverter().toJson(expectedCode), debugMessage: debugMessage), - purchaseHistoryRecordJsonList: >[], + purchases: [], )); final PurchasesHistoryResult response = @@ -663,3 +663,18 @@ PlatformAlternativeBillingOnlyReportingDetailsResponse ), externalTransactionToken: original.externalTransactionToken); } + +PlatformPurchaseHistoryRecord platformPurchaseHistoryRecordFromWrapper( + PurchaseHistoryRecordWrapper wrapper) { + return PlatformPurchaseHistoryRecord( + // For some reason quantity is not currently exposed in + // PurchaseHistoryRecordWrapper. + quantity: 99, + purchaseTime: wrapper.purchaseTime, + originalJson: wrapper.originalJson, + purchaseToken: wrapper.purchaseToken, + signature: wrapper.signature, + products: wrapper.products, + developerPayload: wrapper.developerPayload, + ); +} diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart index 133c65445ba..1fd6c338245 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.mocks.dart @@ -308,7 +308,7 @@ class MockInAppPurchaseApi extends _i1.Mock implements _i2.InAppPurchaseApi { @override _i3.Future<_i2.PlatformProductDetailsResponse> queryProductDetailsAsync( - List<_i2.PlatformProduct?>? products) => + List<_i2.PlatformQueryProduct?>? products) => (super.noSuchMethod( Invocation.method( #queryProductDetailsAsync, diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart index 6040318103e..a9c76ab5afe 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart @@ -144,8 +144,8 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - purchasesJsonList: >[ - buildPurchaseMap(dummyPurchase), + purchases: [ + convertToPigeonPurchase(dummyPurchase), ], )); 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 71021331330..c4e92602d98 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 @@ -104,7 +104,7 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - productDetailsJsonList: >[], + productDetails: [], )); final ProductDetailsResponse response = @@ -121,8 +121,8 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - productDetailsJsonList: >[ - buildProductMap(dummyOneTimeProductDetails) + productDetails: [ + convertToPigeonProductDetails(dummyOneTimeProductDetails) ], )); // Since queryProductDetails makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead @@ -149,8 +149,8 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - productDetailsJsonList: >[ - buildProductMap(dummyOneTimeProductDetails) + productDetails: [ + convertToPigeonProductDetails(dummyOneTimeProductDetails) ], )); // Since queryProductDetails makes 2 platform method calls (one for each ProductType), the result will contain 2 dummyWrapper instead @@ -230,8 +230,8 @@ void main() { responseCode: const BillingResponseConverter().toJson(responseCode), debugMessage: debugMessage), - purchasesJsonList: >[ - buildPurchaseMap(dummyPurchase), + purchases: [ + convertToPigeonPurchase(dummyPurchase), ], )); @@ -274,20 +274,21 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [ - { - 'orderId': 'orderID1', - 'products': [productDetails.productId], - 'isAutoRenewing': false, - 'packageName': 'package', - 'purchaseTime': 1231231231, - 'purchaseToken': 'token', - 'signature': 'sign', - 'originalJson': 'json', - 'developerPayload': 'dummy payload', - 'isAcknowledged': true, - 'purchaseState': 1, - } + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ) ], )); @@ -330,7 +331,7 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [], + purchases: [], )); return convertToPigeonResult(expectedBillingResult); @@ -372,20 +373,21 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [ - { - 'orderId': 'orderID1', - 'products': [productDetails.productId], - 'isAutoRenewing': false, - 'packageName': 'package', - 'purchaseTime': 1231231231, - 'purchaseToken': 'token', - 'signature': 'sign', - 'originalJson': 'json', - 'developerPayload': 'dummy payload', - 'isAcknowledged': true, - 'purchaseState': 1, - } + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ) ], )); @@ -482,20 +484,21 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [ - { - 'orderId': 'orderID1', - 'products': [productDetails.productId], - 'isAutoRenewing': false, - 'packageName': 'package', - 'purchaseTime': 1231231231, - 'purchaseToken': 'token', - 'signature': 'sign', - 'originalJson': 'json', - 'developerPayload': 'dummy payload', - 'isAcknowledged': true, - 'purchaseState': 1, - } + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ) ], )); @@ -556,20 +559,21 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [ - { - 'orderId': 'orderID1', - 'products': [productDetails.productId], - 'isAutoRenewing': false, - 'packageName': 'package', - 'purchaseTime': 1231231231, - 'purchaseToken': 'token', - 'signature': 'sign', - 'originalJson': 'json', - 'developerPayload': 'dummy payload', - 'isAcknowledged': true, - 'purchaseState': 1, - } + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ) ], )); @@ -618,20 +622,21 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [ - { - 'orderId': 'orderID1', - 'products': [productDetails.productId], - 'isAutoRenewing': false, - 'packageName': 'package', - 'purchaseTime': 1231231231, - 'purchaseToken': 'token', - 'signature': 'sign', - 'originalJson': 'json', - 'developerPayload': 'dummy payload', - 'isAcknowledged': true, - 'purchaseState': 1, - } + purchases: [ + PlatformPurchase( + orderId: 'orderID1', + products: [productDetails.productId], + isAutoRenewing: false, + packageName: 'package', + purchaseTime: 1231231231, + purchaseToken: 'token', + signature: 'sign', + originalJson: 'json', + developerPayload: 'dummy payload', + isAcknowledged: true, + purchaseState: PlatformPurchaseState.purchased, + quantity: 1, + ) ], )); @@ -686,7 +691,7 @@ void main() { iapAndroidPlatform.billingClientManager.client.hostCallbackHandler .onPurchasesUpdated(PlatformPurchasesResponse( billingResult: convertToPigeonResult(expectedBillingResult), - purchasesJsonList: [], + purchases: [], )); return convertToPigeonResult(expectedBillingResult); diff --git a/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart b/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart index 827ce25d749..483c7ee257f 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/test_conversion_utils.dart @@ -4,6 +4,7 @@ import 'package:in_app_purchase_android/billing_client_wrappers.dart'; import 'package:in_app_purchase_android/src/messages.g.dart'; +import 'package:in_app_purchase_android/src/pigeon_converters.dart'; /// Creates the [PlatformBillingResult] to return from a mock to get /// [targetResult]. @@ -17,3 +18,96 @@ PlatformBillingResult convertToPigeonResult(BillingResultWrapper targetResult) { debugMessage: targetResult.debugMessage!, ); } + +/// Creates a [PlatformPurchase] from the corresponding [PurchaseWrapper]. +PlatformPurchase convertToPigeonPurchase(PurchaseWrapper purchase) { + return PlatformPurchase( + orderId: purchase.orderId, + packageName: purchase.packageName, + purchaseTime: purchase.purchaseTime, + purchaseToken: purchase.purchaseToken, + signature: purchase.signature, + products: purchase.products, + isAutoRenewing: purchase.isAutoRenewing, + originalJson: purchase.originalJson, + developerPayload: purchase.developerPayload ?? '', + isAcknowledged: purchase.isAcknowledged, + purchaseState: _convertToPigeonPurchaseState(purchase.purchaseState), + // For some reason quantity is not in PurchaseWrapper. + quantity: 99, + accountIdentifiers: purchase.obfuscatedAccountId != null || + purchase.obfuscatedProfileId != null + ? PlatformAccountIdentifiers( + obfuscatedAccountId: purchase.obfuscatedAccountId, + obfuscatedProfileId: purchase.obfuscatedProfileId, + ) + : null); +} + +/// Creates a [PlatformProductDetails] from the corresponding [ProductDetailsWrapper]. +PlatformProductDetails convertToPigeonProductDetails( + ProductDetailsWrapper details) { + return PlatformProductDetails( + description: details.description, + name: details.name, + productId: details.productId, + productType: platformProductTypeFromWrapper(details.productType), + title: details.title, + oneTimePurchaseOfferDetails: _convertToPigeonOneTimePurchaseOfferDetails( + details.oneTimePurchaseOfferDetails), + subscriptionOfferDetails: details.subscriptionOfferDetails + ?.map(convertToPigeonSubscriptionOfferDetails) + .toList()); +} + +PlatformSubscriptionOfferDetails convertToPigeonSubscriptionOfferDetails( + SubscriptionOfferDetailsWrapper details) { + return PlatformSubscriptionOfferDetails( + basePlanId: details.basePlanId, + offerId: details.offerId, + offerToken: details.offerIdToken, + offerTags: details.offerTags, + pricingPhases: + details.pricingPhases.map(convertToPigeonPricingPhase).toList()); +} + +PlatformPricingPhase convertToPigeonPricingPhase(PricingPhaseWrapper phase) { + return PlatformPricingPhase( + billingCycleCount: phase.billingCycleCount, + recurrenceMode: _convertToPigeonRecurrenceMode(phase.recurrenceMode), + priceAmountMicros: phase.priceAmountMicros, + billingPeriod: phase.billingPeriod, + formattedPrice: phase.formattedPrice, + priceCurrencyCode: phase.priceCurrencyCode); +} + +PlatformOneTimePurchaseOfferDetails? + _convertToPigeonOneTimePurchaseOfferDetails( + OneTimePurchaseOfferDetailsWrapper? offer) { + if (offer == null) { + return null; + } + return PlatformOneTimePurchaseOfferDetails( + priceAmountMicros: offer.priceAmountMicros, + formattedPrice: offer.formattedPrice, + priceCurrencyCode: offer.priceCurrencyCode); +} + +/// Creates a [PlatformPurchaseState] from the Dart wrapper equivalent. +PlatformPurchaseState _convertToPigeonPurchaseState( + PurchaseStateWrapper state) { + return switch (state) { + PurchaseStateWrapper.unspecified_state => PlatformPurchaseState.unspecified, + PurchaseStateWrapper.purchased => PlatformPurchaseState.purchased, + PurchaseStateWrapper.pending => PlatformPurchaseState.pending, + }; +} + +PlatformRecurrenceMode _convertToPigeonRecurrenceMode(RecurrenceMode mode) { + return switch (mode) { + RecurrenceMode.finiteRecurring => PlatformRecurrenceMode.finiteRecurring, + RecurrenceMode.infiniteRecurring => + PlatformRecurrenceMode.infiniteRecurring, + RecurrenceMode.nonRecurring => PlatformRecurrenceMode.nonRecurring, + }; +}