Skip to content

Commit 5646e26

Browse files
authored
Support Purchasing Packages as Add-Ons (#1545)
This PR allows developers using the Flutter SDK to purchase a Play Store subscription with `Package` add-ons by adding `addOnPackages` to the `PurchaseParams` constructors. It also updates the purchase tester's add-ons screen to allow you to select whether each add-on item is purchased as a `Package` This PR is marked to go into the `addOns-dev` branch. Once approved and merged, we'll create a second add-ons beta release from the `addOns-dev` branch.
1 parent d23acf3 commit 5646e26

File tree

6 files changed

+469
-26
lines changed

6 files changed

+469
-26
lines changed

android/src/main/java/com/revenuecat/purchases_flutter/PurchasesFlutterPlugin.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
155155
Map<String, Object> presentedOfferingContext = call.argument("presentedOfferingContext");
156156
List<Map<String, Object>> addOnStoreProducts = call.argument("addOnStoreProducts");
157157
List<Map<String, Object>> addOnSubscriptionOptions = call.argument("addOnSubscriptionOptions");
158+
List<Map<String, Object>> addOnPackages = call.argument("addOnPackages");
158159
purchaseProduct(productIdentifier, type, googleOldProductIdentifer, googleProrationMode,
159160
googleIsPersonalizedPrice, presentedOfferingContext, addOnStoreProducts,
160-
addOnSubscriptionOptions, result);
161+
addOnSubscriptionOptions, addOnPackages, result);
161162
break;
162163
case "purchasePackage":
163164
String packageIdentifier = call.argument("packageIdentifier");
@@ -167,9 +168,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
167168
googleIsPersonalizedPrice = call.argument("googleIsPersonalizedPrice");
168169
addOnStoreProducts = call.argument("addOnStoreProducts");
169170
addOnSubscriptionOptions = call.argument("addOnSubscriptionOptions");
171+
addOnPackages = call.argument("addOnPackages");
170172
purchasePackage(packageIdentifier, presentedOfferingContext, googleOldProductIdentifer,
171173
googleProrationMode, googleIsPersonalizedPrice, addOnStoreProducts,
172-
addOnSubscriptionOptions, result);
174+
addOnSubscriptionOptions, addOnPackages, result);
173175
break;
174176
case "purchaseSubscriptionOption":
175177
productIdentifier = call.argument("productIdentifier");
@@ -180,9 +182,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
180182
presentedOfferingContext = call.argument("presentedOfferingContext");
181183
addOnStoreProducts = call.argument("addOnStoreProducts");
182184
addOnSubscriptionOptions = call.argument("addOnSubscriptionOptions");
185+
addOnPackages = call.argument("addOnPackages");
183186
purchaseSubscriptionOption(productIdentifier, optionIdentifier, googleOldProductIdentifer,
184187
googleProrationMode, googleIsPersonalizedPrice, presentedOfferingContext,
185-
addOnStoreProducts, addOnSubscriptionOptions, result);
188+
addOnStoreProducts, addOnSubscriptionOptions, addOnPackages, result);
186189
break;
187190
case "getAppUserID":
188191
getAppUserID(result);
@@ -475,6 +478,7 @@ private void purchaseProduct(final String productIdentifier,
475478
@Nullable final Map<String, Object> presentedOfferingContext,
476479
@Nullable final List<Map<String, Object>> addOnStoreProducts,
477480
@Nullable final List<Map<String, Object>> addOnSubscriptionOptions,
481+
@Nullable final List<Map<String, Object>> addOnPackages,
478482
final Result result) {
479483
CommonKt.purchaseProduct(
480484
activity,
@@ -487,7 +491,8 @@ private void purchaseProduct(final String productIdentifier,
487491
presentedOfferingContext,
488492
getOnResult(result),
489493
addOnStoreProducts,
490-
addOnSubscriptionOptions);
494+
addOnSubscriptionOptions,
495+
addOnPackages);
491496
}
492497

493498
private void purchasePackage(final String packageIdentifier,
@@ -497,6 +502,7 @@ private void purchasePackage(final String packageIdentifier,
497502
@Nullable final Boolean googleIsPersonalizedPrice,
498503
@Nullable final List<Map<String, Object>> addOnStoreProducts,
499504
@Nullable final List<Map<String, Object>> addOnSubscriptionOptions,
505+
@Nullable final List<Map<String, Object>> addOnPackages,
500506
final Result result) {
501507
CommonKt.purchasePackage(
502508
activity,
@@ -507,7 +513,8 @@ private void purchasePackage(final String packageIdentifier,
507513
googleIsPersonalizedPrice,
508514
getOnResult(result),
509515
addOnStoreProducts,
510-
addOnSubscriptionOptions);
516+
addOnSubscriptionOptions,
517+
addOnPackages);
511518
}
512519

513520
private void purchaseSubscriptionOption(final String productIdentifier,
@@ -518,6 +525,7 @@ private void purchaseSubscriptionOption(final String productIdentifier,
518525
@Nullable final Map<String, Object> presentedOfferingContext,
519526
@Nullable final List<Map<String, Object>> addOnStoreProducts,
520527
@Nullable final List<Map<String, Object>> addOnSubscriptionOptions,
528+
@Nullable final List<Map<String, Object>> addOnPackages,
521529
final Result result) {
522530
CommonKt.purchaseSubscriptionOption(
523531
activity,
@@ -529,7 +537,8 @@ private void purchaseSubscriptionOption(final String productIdentifier,
529537
presentedOfferingContext,
530538
getOnResult(result),
531539
addOnStoreProducts,
532-
addOnSubscriptionOptions);
540+
addOnSubscriptionOptions,
541+
addOnPackages);
533542
}
534543

535544
private void getAppUserID(final Result result) {

api_tester/lib/api_tests/models/purchase_params_api_test.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class _PurchaseParamsApiTest {
1313
String? customerEmail,
1414
List<StoreProduct>? addOnStoreProducts,
1515
List<SubscriptionOption>? addOnSubscriptionOptions,
16+
List<Package>? addOnPackages,
1617
) {
1718
PurchaseParams purchaseParams = PurchaseParams.package(
1819
package,
@@ -56,6 +57,24 @@ class _PurchaseParamsApiTest {
5657
customerEmail: customerEmail,
5758
addOnStoreProducts: addOnStoreProducts,
5859
);
60+
purchaseParams = PurchaseParams.package(
61+
package,
62+
googleProductChangeInfo: googleProductChangeInfo,
63+
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
64+
promotionalOffer: promotionalOffer,
65+
winBackOffer: winBackOffer,
66+
customerEmail: customerEmail,
67+
addOnPackages: addOnPackages,
68+
);
69+
purchaseParams = PurchaseParams.package(
70+
package,
71+
googleProductChangeInfo: googleProductChangeInfo,
72+
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
73+
promotionalOffer: promotionalOffer,
74+
winBackOffer: winBackOffer,
75+
customerEmail: customerEmail,
76+
addOnSubscriptionOptions: addOnSubscriptionOptions,
77+
);
5978
purchaseParams = PurchaseParams.package(
6079
package,
6180
googleProductChangeInfo: googleProductChangeInfo,
@@ -65,6 +84,7 @@ class _PurchaseParamsApiTest {
6584
customerEmail: customerEmail,
6685
addOnStoreProducts: addOnStoreProducts,
6786
addOnSubscriptionOptions: addOnSubscriptionOptions,
87+
addOnPackages: addOnPackages,
6888
);
6989
}
7090

@@ -77,6 +97,7 @@ class _PurchaseParamsApiTest {
7797
String? customerEmail,
7898
List<StoreProduct>? addOnStoreProducts,
7999
List<SubscriptionOption>? addOnSubscriptionOptions,
100+
List<Package>? addOnPackages,
80101
) {
81102
PurchaseParams purchaseParams = PurchaseParams.storeProduct(
82103
storeProduct,
@@ -120,6 +141,24 @@ class _PurchaseParamsApiTest {
120141
customerEmail: customerEmail,
121142
addOnStoreProducts: addOnStoreProducts,
122143
);
144+
purchaseParams = PurchaseParams.storeProduct(
145+
storeProduct,
146+
googleProductChangeInfo: googleProductChangeInfo,
147+
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
148+
promotionalOffer: promotionalOffer,
149+
winBackOffer: winBackOffer,
150+
customerEmail: customerEmail,
151+
addOnPackages: addOnPackages,
152+
);
153+
purchaseParams = PurchaseParams.storeProduct(
154+
storeProduct,
155+
googleProductChangeInfo: googleProductChangeInfo,
156+
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
157+
promotionalOffer: promotionalOffer,
158+
winBackOffer: winBackOffer,
159+
customerEmail: customerEmail,
160+
addOnSubscriptionOptions: addOnSubscriptionOptions,
161+
);
123162
purchaseParams = PurchaseParams.storeProduct(
124163
storeProduct,
125164
googleProductChangeInfo: googleProductChangeInfo,
@@ -129,6 +168,7 @@ class _PurchaseParamsApiTest {
129168
customerEmail: customerEmail,
130169
addOnStoreProducts: addOnStoreProducts,
131170
addOnSubscriptionOptions: addOnSubscriptionOptions,
171+
addOnPackages: addOnPackages,
132172
);
133173
}
134174

@@ -139,6 +179,7 @@ class _PurchaseParamsApiTest {
139179
String? customerEmail,
140180
List<StoreProduct>? addOnStoreProducts,
141181
List<SubscriptionOption>? addOnSubscriptionOptions,
182+
List<Package>? addOnPackages,
142183
) {
143184
PurchaseParams purchaseParams = PurchaseParams.subscriptionOption(
144185
subscriptionOption,
@@ -165,13 +206,28 @@ class _PurchaseParamsApiTest {
165206
customerEmail: customerEmail,
166207
addOnStoreProducts: addOnStoreProducts,
167208
);
209+
purchaseParams = PurchaseParams.subscriptionOption(
210+
subscriptionOption,
211+
googleProductChangeInfo: googleProductChangeInfo,
212+
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
213+
customerEmail: customerEmail,
214+
addOnPackages: addOnPackages,
215+
);
216+
purchaseParams = PurchaseParams.subscriptionOption(
217+
subscriptionOption,
218+
googleProductChangeInfo: googleProductChangeInfo,
219+
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
220+
customerEmail: customerEmail,
221+
addOnSubscriptionOptions: addOnSubscriptionOptions,
222+
);
168223
purchaseParams = PurchaseParams.subscriptionOption(
169224
subscriptionOption,
170225
googleProductChangeInfo: googleProductChangeInfo,
171226
googleIsPersonalizedPrice: googleIsPersonalizedPrice,
172227
customerEmail: customerEmail,
173228
addOnStoreProducts: addOnStoreProducts,
174229
addOnSubscriptionOptions: addOnSubscriptionOptions,
230+
addOnPackages: addOnPackages,
175231
);
176232
}
177233

@@ -186,5 +242,6 @@ class _PurchaseParamsApiTest {
186242
String? customerEmail = purchaseParams.customerEmail;
187243
List<StoreProduct>? addOnStoreProducts = purchaseParams.addOnStoreProducts;
188244
List<SubscriptionOption>? addOnSubscriptionOptions = purchaseParams.addOnSubscriptionOptions;
245+
List<Package>? addOnPackages = purchaseParams.addOnPackages;
189246
}
190247
}

lib/models/purchase_params.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class PurchaseParams {
1717
final String? customerEmail;
1818
final List<StoreProduct>? addOnStoreProducts;
1919
final List<SubscriptionOption>? addOnSubscriptionOptions;
20+
final List<Package>? addOnPackages;
2021

2122
const PurchaseParams._(
2223
this.package,
@@ -29,6 +30,7 @@ class PurchaseParams {
2930
this.customerEmail,
3031
this.addOnStoreProducts,
3132
this.addOnSubscriptionOptions,
33+
this.addOnPackages,
3234
);
3335

3436
/// Creates purchase parameters for a package.
@@ -60,6 +62,8 @@ class PurchaseParams {
6062
///
6163
/// [addOnSubscriptionOptions] Play Store only. Add-on subscription options to be purchased with the base item.
6264
///
65+
/// [addOnPackages] Play Store only. Add-on packages to be purchased with the base item.
66+
///
6367
const PurchaseParams.package(
6468
Package package, {
6569
GoogleProductChangeInfo? googleProductChangeInfo,
@@ -69,6 +73,7 @@ class PurchaseParams {
6973
String? customerEmail,
7074
List<StoreProduct>? addOnStoreProducts,
7175
List<SubscriptionOption>? addOnSubscriptionOptions,
76+
List<Package>? addOnPackages,
7277
}) : this._(
7378
package,
7479
null,
@@ -80,6 +85,7 @@ class PurchaseParams {
8085
customerEmail,
8186
addOnStoreProducts,
8287
addOnSubscriptionOptions,
88+
addOnPackages,
8389
);
8490

8591
/// Creates purchase parameters for a store product.
@@ -111,6 +117,8 @@ class PurchaseParams {
111117
/// [addOnStoreProducts] Play Store only. Add-on products to be purchased with the base item.
112118
///
113119
/// [addOnSubscriptionOptions] Play Store only. Add-on subscription options to be purchased with the base item.
120+
///
121+
/// [addOnPackages] Play Store only. Add-on packages to be purchased with the base item.
114122
///
115123
const PurchaseParams.storeProduct(
116124
StoreProduct storeProduct, {
@@ -121,6 +129,7 @@ class PurchaseParams {
121129
String? customerEmail,
122130
List<StoreProduct>? addOnStoreProducts,
123131
List<SubscriptionOption>? addOnSubscriptionOptions,
132+
List<Package>? addOnPackages,
124133
}) : this._(
125134
null,
126135
storeProduct,
@@ -132,6 +141,7 @@ class PurchaseParams {
132141
customerEmail,
133142
addOnStoreProducts,
134143
addOnSubscriptionOptions,
144+
addOnPackages,
135145
);
136146

137147
/// Creates purchase parameters for a subscription option. Google Play-only.
@@ -154,6 +164,8 @@ class PurchaseParams {
154164
/// [addOnStoreProducts] Play Store only. Add-on products to be purchased with the base item.
155165
///
156166
/// [addOnSubscriptionOptions] Play Store only. Add-on subscription options to be purchased with the base item.
167+
///
168+
/// [addOnPackages] Play Store only. Add-on packages to be purchased with the base item.
157169
///
158170
const PurchaseParams.subscriptionOption(
159171
SubscriptionOption subscriptionOption, {
@@ -162,6 +174,7 @@ class PurchaseParams {
162174
String? customerEmail,
163175
List<StoreProduct>? addOnStoreProducts,
164176
List<SubscriptionOption>? addOnSubscriptionOptions,
177+
List<Package>? addOnPackages,
165178
}) : this._(
166179
null,
167180
null,
@@ -173,5 +186,6 @@ class PurchaseParams {
173186
customerEmail,
174187
addOnStoreProducts,
175188
addOnSubscriptionOptions,
189+
addOnPackages,
176190
);
177191
}

lib/purchases_flutter.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,15 @@ class Purchases {
588588
'optionIdentifier': subscriptionOption.id,
589589
},)
590590
.toList();
591+
final addOnPackages = purchaseParams.addOnPackages
592+
?.map(
593+
(package) => <String, dynamic>{
594+
'packageIdentifier': package.identifier,
595+
'presentedOfferingContext':
596+
package.presentedOfferingContext.toJson(),
597+
},
598+
)
599+
.toList();
591600
final purchaseArgs = <String, dynamic>{
592601
'googleOldProductIdentifier': googleProductChangeInfo?.oldProductIdentifier,
593602
'googleProrationMode': prorationMode,
@@ -598,6 +607,7 @@ class Purchases {
598607
'winBackOfferIdentifier': winBackOffer?.identifier,
599608
'addOnStoreProducts': addOnStoreProducts,
600609
'addOnSubscriptionOptions': addOnSubscriptionOptions,
610+
'addOnPackages': addOnPackages,
601611
};
602612
final isWinBackOfferPurchase = (defaultTargetPlatform == TargetPlatform.iOS
603613
|| defaultTargetPlatform == TargetPlatform.macOS)

0 commit comments

Comments
 (0)