Skip to content

[in_app_purchase_storekit] Make Storekit 2 the default #9178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
4 changes: 3 additions & 1 deletion packages/in_app_purchase/in_app_purchase/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## NEXT
## 3.2.2

* Updates `in_app_purchase_storekit` to 0.4.0
* Updates README with Storekit 2 examples.
* Updates README to indicate that Andoid SDK <21 is no longer supported.

## 3.2.1
Expand Down
19 changes: 18 additions & 1 deletion packages/in_app_purchase/in_app_purchase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,14 @@ if (productDetails is AppStoreProductDetails) {
SKProductWrapper skProduct = (productDetails as AppStoreProductDetails).skProduct;
print(skProduct.subscriptionGroupIdentifier);
}

// With StoreKit 2
import 'package:in_app_purchase_storekit/store_kit_2_wrappers.dart';

if (productDetails is AppStoreProduct2Details) {
SK2Product product = (productDetails as AppStoreProduct2Details).sk2Product;
print(product.subscription?.subscriptionGroupID);
}
```

The `purchaseStream` provides objects of type `PurchaseDetails`. PurchaseDetails' provides all
Expand All @@ -377,7 +385,7 @@ if (purchaseDetails is GooglePlayPurchaseDetails) {
}
```

How to get the `transactionState` of a purchase in iOS:
How to get the `transactionState` of a purchase in iOS, using the original StoreKit API:
```dart
//import for AppStorePurchaseDetails
import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';
Expand All @@ -390,6 +398,15 @@ if (purchaseDetails is AppStorePurchaseDetails) {
}
```

How to get the `jsonRepresentation` of a transaction in iOS, using Storekit 2:
```dart
//import for SK2TransactionWrapper
import 'package:in_app_purchase_storekit/store_kit_2_wrappers.dart';

List<SK2Transaction> transactions = await SK2Transaction.transactions();
print(transactions[0].jsonRepresentation);
```

Please note that it is required to import `in_app_purchase_android` and/or `in_app_purchase_storekit`.

### Presenting a code redemption sheet (iOS 14)
Expand Down
2 changes: 1 addition & 1 deletion packages/in_app_purchase/in_app_purchase/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: in_app_purchase
description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play.
repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
version: 3.2.1
version: 3.2.2

environment:
sdk: ^3.5.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.4.0

* **BREAKING CHANGE:** StoreKit 2 is now the default for all devices that support it.
Copy link
Contributor

@hellohuanlin hellohuanlin Apr 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be 0.4.0 instead? iirc breaking change should be major bump, but this is still 0. version, so a minor bump?
(cc @stuartmorgan-g for advice)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, breaking changes need a "major" (which for pre-1.0 is the second number, per Dart convention) version bump.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooh makes sense. Ive changed it.


## 0.3.22+1

* Fix a channel thread-safety issue when StoreKit2 is enabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import 'consumable_store.dart';
import 'example_payment_queue_delegate.dart';

void main() {
InAppPurchaseStoreKitPlatform.enableStoreKit2();
WidgetsFlutterBinding.ensureInitialized();
// When using the Android plugin directly it is mandatory to register
// the plugin as default instance as part of initializing the app.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform {

/// Registers this class as the default instance of [InAppPurchasePlatform].
static void registerPlatform() {
enableStoreKit2();
// Register the [InAppPurchaseStoreKitPlatformAddition] containing
// StoreKit-specific functionality.
InAppPurchasePlatformAddition.instance =
Expand Down Expand Up @@ -251,8 +252,8 @@ class InAppPurchaseStoreKitPlatform extends InAppPurchasePlatform {
@Deprecated('Use countryCode')
Future<String?> getCountryCode() => countryCode();

/// Turns on StoreKit2. You cannot disable this after it is enabled.
/// This can only be enabled if your device supports StoreKit 2.
/// StoreKit 2 is now the default.
@Deprecated('StoreKit 2 is now the default')
static Future<bool> enableStoreKit2() async {
_useStoreKit2 = await SKRequestMaker.supportsStoreKit2();
return _useStoreKit2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class SK2Transaction {
required this.appAccountToken,
this.subscriptionGroupID,
this.price,
this.error});
this.error,
this.jsonRepresentation});

/// The unique identifier for the transaction.
final String id;
Expand Down Expand Up @@ -62,6 +63,9 @@ class SK2Transaction {
/// Any error returned from StoreKit
final SKError? error;

/// The json representation of a transaction
final String? jsonRepresentation;

/// Wrapper around [Transaction.finish]
/// https://developer.apple.com/documentation/storekit/transaction/3749694-finish
/// Indicates to the App Store that the app delivered the purchased content
Expand Down Expand Up @@ -105,7 +109,8 @@ extension on SK2TransactionMessage {
productId: productId,
purchaseDate: purchaseDate,
expirationDate: expirationDate,
appAccountToken: appAccountToken);
appAccountToken: appAccountToken,
jsonRepresentation: jsonRepresentation);
}

PurchaseDetails convertToDetails() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: in_app_purchase_storekit
description: An implementation for the iOS and macOS platforms of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework.
repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase_storekit
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
version: 0.3.22+1
version: 0.4.0

environment:
sdk: ^3.4.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi {
bool isPaymentQueueDelegateRegistered = false;
String _countryCode = 'USA';
String _countryIdentifier = 'LL';
bool shouldStoreKit2BeEnabled = false;

void reset() {
transactionList = <SKPaymentTransactionWrapper>[];
Expand Down Expand Up @@ -283,7 +284,7 @@ class FakeStoreKitPlatform implements TestInAppPurchaseApi {

@override
bool supportsStoreKit2() {
return true;
return shouldStoreKit2BeEnabled;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ void main() {

final FakeStoreKit2Platform fakeStoreKit2Platform = FakeStoreKit2Platform();
final FakeStoreKitPlatform fakeStoreKitPlatform = FakeStoreKitPlatform();

late InAppPurchaseStoreKitPlatform iapStoreKitPlatform;

setUpAll(() {
Expand All @@ -37,10 +36,12 @@ void main() {
});

setUp(() {
InAppPurchaseStoreKitPlatform.enableStoreKit2();
InAppPurchaseStoreKitPlatform.registerPlatform();
iapStoreKitPlatform =
InAppPurchasePlatform.instance as InAppPurchaseStoreKitPlatform;
InAppPurchaseStoreKitPlatform.enableStoreKit2();
fakeStoreKitPlatform.shouldStoreKit2BeEnabled = true;
fakeStoreKitPlatform.supportsStoreKit2();
fakeStoreKit2Platform.reset();
});

Expand Down