Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[in_app_purchase]: Add macOS Support #4313

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5c3e8cd
Add macOS Support
rebarah Sep 5, 2021
50423fc
fix "FIAP" misspelling in symolic link
rebarah Sep 5, 2021
bc4742d
Add Target check for ReceiptManager
rebarah Sep 5, 2021
d3bab94
Migrate main dart interfaces
rebarah Sep 5, 2021
75a68e9
migrate types
rebarah Sep 5, 2021
396bd22
migrate store kit wrappers
rebarah Sep 5, 2021
f517312
Add checks for iOS specific apis
rebarah Sep 5, 2021
9c1b8ca
add instancer in main interface
rebarah Sep 5, 2021
dd31d7a
Check iOS Interfaces for QueueHandler
rebarah Sep 5, 2021
f7d540d
Migrate Tests
rebarah Sep 5, 2021
4bf1e47
Adjust changelog for macOS
rebarah Sep 5, 2021
22a2364
Adjust readme
rebarah Sep 5, 2021
9859ed9
fix description in pubspec.yaml
Ahmadre Sep 5, 2021
b0e89c3
Add macOS Support
Ahmadre Sep 5, 2021
71e97e6
Merge commit 'b0e89c3d'
Ahmadre Sep 5, 2021
d2b0069
Merge commit 'b0e89c3d'
Ahmadre Sep 5, 2021
f626439
Merge branch 'master' of https://github.com/Ahmadre/plugins
Ahmadre Sep 5, 2021
90893bf
Merge branch 'master' of https://github.com/Ahmadre/plugins
Ahmadre Sep 5, 2021
30f34a9
Merge branch 'master' of https://github.com/Ahmadre/plugins
Ahmadre Sep 5, 2021
18692b0
clean rebase
Ahmadre Sep 5, 2021
2487b12
format
Ahmadre Sep 5, 2021
2949fcb
format other repos
Ahmadre Sep 5, 2021
19a269b
format objective-c
Ahmadre Sep 5, 2021
035bee9
Migrate example project
Ahmadre Sep 5, 2021
7d204b6
clean macOS platform instances
Ahmadre Sep 5, 2021
12ff934
add git repo to macos dependecy
Ahmadre Sep 5, 2021
875b7ab
First migration to federated plugin for macOS
Ahmadre Sep 5, 2021
ed9d8f1
Remove PaymentQueueDelegate | remove iOS checks
Ahmadre Sep 5, 2021
dc95edd
remove dart interfaces to QueueDelegate
Ahmadre Sep 5, 2021
af61a0e
remove dart apis
Ahmadre Sep 5, 2021
e528027
Update FIAPaymentQueueHandler.m
Ahmadre Sep 5, 2021
6f6cb75
merge ios and macos to storekit
Ahmadre Sep 6, 2021
0c3bdac
fix name
Ahmadre Sep 6, 2021
4640a53
fix default package name
Ahmadre Sep 6, 2021
a90d1f8
fix naming
Ahmadre Sep 6, 2021
1e056de
correct podspec
Ahmadre Sep 6, 2021
685c777
migrate imports
Ahmadre Sep 6, 2021
2e57cf0
merge podspec
Ahmadre Sep 6, 2021
917a367
update platform
Ahmadre Sep 6, 2021
6598b28
add symbolic links
Ahmadre Sep 6, 2021
7d87ac3
Add platform specific podspecs
Ahmadre Sep 6, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/in_app_purchase/in_app_purchase/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.1.0

* Merge Apple speficic implementation to new shared package: `in_app_purchase_storekit`

## 1.0.8

* Fix repository link in pubspec.yaml.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart';
import 'package:in_app_purchase_android/in_app_purchase_android.dart';
import 'package:in_app_purchase_ios/in_app_purchase_ios.dart';
import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';

export 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'
show
Expand Down Expand Up @@ -35,8 +35,9 @@ class InAppPurchase implements InAppPurchasePlatformAdditionProvider {

if (defaultTargetPlatform == TargetPlatform.android) {
InAppPurchaseAndroidPlatform.registerPlatform();
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
InAppPurchaseIosPlatform.registerPlatform();
} else if (defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.macOS) {
InAppPurchaseStoreKitPlatform.registerPlatform();
}

_instance = InAppPurchase._();
Expand Down Expand Up @@ -77,7 +78,7 @@ class InAppPurchase implements InAppPurchasePlatformAdditionProvider {
/// Query product details for the given set of IDs.
///
/// Identifiers in the underlying payment platform, for example, [App Store
/// Connect](https://appstoreconnect.apple.com/) for iOS and [Google Play
/// Connect](https://appstoreconnect.apple.com/) for iOS/macOS and [Google Play
/// Console](https://play.google.com/) for Android.
Future<ProductDetailsResponse> queryProductDetails(Set<String> identifiers) =>
InAppPurchasePlatform.instance.queryProductDetails(identifiers);
Expand Down
8 changes: 7 additions & 1 deletion packages/in_app_purchase/in_app_purchase/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,20 @@ flutter:
android:
default_package: in_app_purchase_android
ios:
default_package: in_app_purchase_ios
default_package: in_app_purchase_storekit
macos:
default_package: in_app_purchase_storekit

dependencies:
flutter:
sdk: flutter
in_app_purchase_platform_interface: ^1.0.0
in_app_purchase_android: ^0.1.4
in_app_purchase_ios: ^0.1.1
in_app_purchase_storekit:
git:
url: git://github.com/Ahmadre/plugins
path: packages/in_app_purchase/in_app_purchase_storekit

dev_dependencies:
flutter_driver:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ const String _kOnBillingServiceDisconnected =
///
/// Wraps a
/// [`PurchasesUpdatedListener`](https://developer.android.com/reference/com/android/billingclient/api/PurchasesUpdatedListener.html).
typedef void PurchasesUpdatedListener(PurchasesResultWrapper purchasesResult);
typedef PurchasesUpdatedListener = void Function(
PurchasesResultWrapper purchasesResult);

/// This class can be used directly instead of [InAppPurchaseConnection] to call
/// Play-specific billing APIs.
Expand Down Expand Up @@ -356,7 +357,7 @@ class BillingClient {
/// Wraps
/// [`com.android.billingclient.api.BillingClientStateListener.onServiceDisconnected()`](https://developer.android.com/reference/com/android/billingclient/api/BillingClientStateListener.html#onBillingServiceDisconnected())
/// to call back on `BillingClient` disconnect.
typedef void OnBillingServiceDisconnected();
typedef OnBillingServiceDisconnected = void Function();

/// Possible `BillingClient` response statuses.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'dart:async';
import 'package:flutter/services.dart';

typedef void AdditionalSteps(dynamic args);
typedef AdditionalSteps = void Function(dynamic args);

class StubInAppPurchasePlatform {
Map<String, dynamic> _expectedCalls = <String, dynamic>{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ NS_ASSUME_NONNULL_BEGIN

// Converts an instance of SKProductSubscriptionPeriod into a dictionary.
+ (NSDictionary *)getMapFromSKProductSubscriptionPeriod:(SKProductSubscriptionPeriod *)period
API_AVAILABLE(ios(11.2));
API_AVAILABLE(ios(11.2), macos(10.13.2));

// Converts an instance of SKProductDiscount into a dictionary.
+ (NSDictionary *)getMapFromSKProductDiscount:(SKProductDiscount *)discount
API_AVAILABLE(ios(11.2));
API_AVAILABLE(ios(11.2), macos(10.13.2));

// Converts an instance of SKProductsResponse into a dictionary.
+ (NSDictionary *)getMapFromSKProductsResponse:(SKProductsResponse *)productResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if TARGET_OS_OSX
#import <FlutterMacOS/FlutterMacOS.h>
#else
#import <Flutter/Flutter.h>
#endif
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>

Expand All @@ -11,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
API_AVAILABLE(ios(13))
@interface FIAPPaymentQueueDelegate : NSObject <SKPaymentQueueDelegate>
- (id)initWithMethodChannel:(FlutterMethodChannel *)methodChannel;

- (BOOL)paymentQueueShouldShowPriceConsent:(SKPaymentQueue *)paymentQueue API_AVAILABLE(ios(13.4));
@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
// found in the LICENSE file.

#import "FIAPReceiptManager.h"
#if TARGET_OS_OSX
#import <FlutterMacOS/FlutterMacOS.h>
#else
#import <Flutter/Flutter.h>
#endif
#import "FIAObjectTranslator.h"

@interface FIAPReceiptManager ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ typedef void (^UpdatedDownloads)(NSArray<SKDownload *> *downloads);
// Can throw exceptions if the transaction type is purchasing, should always used in a @try block.
- (void)finishTransaction:(nonnull SKPaymentTransaction *)transaction;
- (void)restoreTransactions:(nullable NSString *)applicationName;
- (void)presentCodeRedemptionSheet;
- (NSArray<SKPaymentTransaction *> *)getUnfinishedTransactions;

// This method needs to be called before any other methods.
Expand All @@ -46,6 +45,10 @@ typedef void (^UpdatedDownloads)(NSArray<SKDownload *> *downloads);
// @return whether "addPayment" was successful.
- (BOOL)addPayment:(SKPayment *)payment;

#if TARGET_OS_IPHONE
// Can throw exceptions if the transaction type is purchasing, should always used in a @try block.
- (void)presentCodeRedemptionSheet API_AVAILABLE(ios(14.0));

// Displays the price consent sheet.
//
// The price consent sheet is only displayed when the following
Expand All @@ -54,6 +57,7 @@ typedef void (^UpdatedDownloads)(NSArray<SKDownload *> *downloads);
// - The subscriber has not yet responded to a price consent query.
// Otherwise the method has no effect.
- (void)showPriceConsentIfNeeded API_AVAILABLE(ios(13.4));
#endif

@end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ - (void)restoreTransactions:(nullable NSString *)applicationName {
}
}

#if TARGET_OS_IPHONE
- (void)presentCodeRedemptionSheet {
if (@available(iOS 14, *)) {
[self.queue presentCodeRedemptionSheet];
Expand All @@ -84,8 +85,13 @@ - (void)presentCodeRedemptionSheet {
}

- (void)showPriceConsentIfNeeded {
[self.queue showPriceConsentIfNeeded];
if (@available(iOS 13.4, *)) {
[self.queue showPriceConsentIfNeeded];
} else {
NSLog(@"showPriceConsentIfNeeded is only available on iOS 13.4 or newer");
}
}
#endif

#pragma mark - observing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if TARGET_OS_OSX
#import <FlutterMacOS/FlutterMacOS.h>
#else
#import <Flutter/Flutter.h>
#endif
@class FIAPaymentQueueHandler;
@class FIAPReceiptManager;

Expand All @@ -14,4 +18,9 @@
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;

#if TARGET_OS_IPHONE
- (void)presentCodeRedemptionSheet API_AVAILABLE(ios(14));
- (void)showPriceConsentIfNeeded API_AVAILABLE(ios(13.4));
#endif

@end
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
[self restoreTransactions:call result:result];
} else if ([@"-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]"
isEqualToString:call.method]) {
#if TARGET_OS_IPHONE
[self presentCodeRedemptionSheet:call result:result];
#endif
} else if ([@"-[InAppPurchasePlugin retrieveReceiptData:result:]" isEqualToString:call.method]) {
[self retrieveReceiptData:call result:result];
} else if ([@"-[InAppPurchasePlugin refreshReceipt:result:]" isEqualToString:call.method]) {
Expand All @@ -116,7 +118,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
} else if ([@"-[SKPaymentQueue removeDelegate]" isEqualToString:call.method]) {
[self removePaymentQueueDelegate:result];
} else if ([@"-[SKPaymentQueue showPriceConsentIfNeeded]" isEqualToString:call.method]) {
#if TARGET_OS_IPHONE
[self showPriceConsentIfNeeded:result];
#endif
} else {
result(FlutterMethodNotImplemented);
}
Expand Down Expand Up @@ -265,11 +269,16 @@ - (void)restoreTransactions:(FlutterMethodCall *)call result:(FlutterResult)resu
[self.paymentQueueHandler restoreTransactions:call.arguments];
result(nil);
}

#if TARGET_OS_IPHONE
- (void)presentCodeRedemptionSheet:(FlutterMethodCall *)call result:(FlutterResult)result {
[self.paymentQueueHandler presentCodeRedemptionSheet];
if (@available(iOS 14, *)) {
[self.paymentQueueHandler presentCodeRedemptionSheet];
} else {
NSLog(@"presentCodeRedemptionSheet is only available on iOS 14 or newer");
}
result(nil);
}
#endif

- (void)retrieveReceiptData:(FlutterMethodCall *)call result:(FlutterResult)result {
FlutterError *error = nil;
Expand Down Expand Up @@ -347,12 +356,14 @@ - (void)removePaymentQueueDelegate:(FlutterResult)result {
result(nil);
}

#if TARGET_OS_IPHONE
- (void)showPriceConsentIfNeeded:(FlutterResult)result {
if (@available(iOS 13.4, *)) {
[_paymentQueueHandler showPriceConsentIfNeeded];
}
result(nil);
}
#endif

#pragma mark - transaction observer:

Expand Down
52 changes: 52 additions & 0 deletions packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
## 0.1.4

* Merge Apple speficic implementation to new shared package: `in_app_purchase_storekit`

## 0.1.3+3

* Add `implements` to pubspec.

# 0.1.3+2

* Removed dependency on the `test` package.

# 0.1.3+1

- Updated installation instructions in README.

## 0.1.3

* Add price symbol to platform interface object ProductDetail.

## 0.1.2+2

* Fix crash when retrieveReceiptWithError gives an error.

## 0.1.2+1

* Fix wrong data type when cancelling user credentials dialog.

## 0.1.2

* Added countryCode to the SKPriceLocaleWrapper.

## 0.1.1+1

* iOS: Fix treating missing App Store receipt as an exception.

## 0.1.1

* Added support to register a `SKPaymentQueueDelegateWrapper` and handle changes to active subscriptions accordingly (see also Store Kit's [SKPaymentQueueDelegate](https://developer.apple.com/documentation/storekit/skpaymentqueuedelegate?language=objc)).

## 0.1.0+2

* Changed the iOS payment queue handler in such a way that it only adds a listener to the `SKPaymentQueue` when there
is a listener to the Dart `purchaseStream`.

## 0.1.0+1

* Added a "Restore purchases" button to conform to Apple's StoreKit guidelines on [restoring products](https://developer.apple.com/documentation/storekit/in-app_purchase/restoring_purchased_products?language=objc);

## 0.1.0

* Initial open-source release.
25 changes: 25 additions & 0 deletions packages/in_app_purchase/in_app_purchase_storekit/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Copyright 2013 The Flutter Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 changes: 29 additions & 0 deletions packages/in_app_purchase/in_app_purchase_storekit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# in\_app\_purchase\_ios

The iOS implementation of [`in_app_purchase`][1].

## Usage

This package has been [endorsed][2], meaning that you only need to add `in_app_purchase`
as a dependency in your `pubspec.yaml`. This package will be automatically included in your app
when you do.

If you wish to use the iOS package only, you can [add `in_app_purchase_ios` directly][3].

## Contributing

This plugin uses
[json_serializable](https://pub.dev/packages/json_serializable) for the
many data structs passed between the underlying platform layers and Dart. After
editing any of the serialized data structs, rebuild the serializers by running
`flutter packages pub run build_runner build --delete-conflicting-outputs`.
`flutter packages pub run build_runner watch --delete-conflicting-outputs` will
watch the filesystem for changes.

If you would like to contribute to the plugin, check out our
[contribution guide](https://github.com/flutter/plugins/blob/master/CONTRIBUTING.md).


[1]: ../in_app_purchase/in_app_purchase
[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
[3]: https://pub.dev/packages/in_app_purchase_ios/install
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include: ../../../analysis_options_legacy.yaml
7 changes: 7 additions & 0 deletions packages/in_app_purchase/in_app_purchase_storekit/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
targets:
$default:
builders:
json_serializable:
options:
any_map: true
create_to_json: true
Loading