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

[in_app_purchase] presentCodeRedemptionSheet #3274

Merged
merged 25 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d509a3e
Merge remote-tracking branch 'upstream/master'
May 8, 2020
22eeb98
Merge remote-tracking branch 'upstream/master'
ABausG May 11, 2020
ec8a602
Merge remote-tracking branch 'upstream/master'
ABausG Nov 18, 2020
7fff7e5
Add Plugin Implementation
ABausG Nov 18, 2020
3a9e84c
Adjust for Tests
ABausG Nov 18, 2020
8f3682b
Add Tests
ABausG Nov 18, 2020
1d02f54
Add XCTest
ABausG Nov 18, 2020
9df88c6
Update CHANGELOG and pubspec
ABausG Nov 18, 2020
792d091
Formatting
ABausG Nov 20, 2020
43b6bbc
Merge remote-tracking branch 'upstream/master' into present-code-rede…
ABausG Nov 20, 2020
86a46d8
Update Xcode
ABausG Nov 20, 2020
06b1973
Merge remote-tracking branch 'parent/master'
Jan 13, 2021
f40e252
Merge remote-tracking branch 'parent/master'
Jan 18, 2021
262f341
Merge remote-tracking branch 'parent/master' into present-code-redemp…
Jan 25, 2021
50a74f6
Merge remote-tracking branch 'parent/master' into present-code-redemp…
Mar 1, 2021
193c351
Remove empty line
Mar 1, 2021
b3280da
Change Version to 0.4.2
ABausG Mar 2, 2021
b76aeab
Use respondToSelector to check for xcode version
ABausG Mar 2, 2021
de6f090
Add Unit Test in sk_methodchannel_apis_test.dart
ABausG Mar 2, 2021
cff62bb
Merge remote-tracking branch 'origin/master' into present-code-redemp…
ABausG Mar 2, 2021
3b2d056
Merge remote-tracking branch 'parent/master' into present-code-redemp…
ABausG Mar 2, 2021
8858147
Clean up fakeIOSPlatform.presentCodeRedemption
ABausG Mar 3, 2021
4a761a0
Formatting
ABausG Mar 3, 2021
535cc46
Merge remote-tracking branch 'parent/master' into present-code-redemp…
ABausG Mar 4, 2021
47f9016
Remove respondsToSelector check
ABausG Mar 4, 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/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.1

* [iOS] Introduce `SKPaymentQueueWrapper.presentCodeRedemptionSheet`

## 0.5.0

* Migrate to Google Billing Library 3.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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 Down
9 changes: 9 additions & 0 deletions packages/in_app_purchase/ios/Classes/FIAPaymentQueueHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ - (void)restoreTransactions:(nullable NSString *)applicationName {
}
}

- (void)presentCodeRedemptionSheet {
if (@available(iOS 14, *) &&
[self.queue respondsToSelector:@selector(presentCodeRedemptionSheet)]) {
[self.queue presentCodeRedemptionSheet];
ABausG marked this conversation as resolved.
Show resolved Hide resolved
} else {
NSLog(@"presentCodeRedemptionSheet is only available on iOS 14 and Xcode 12 or newer");
}
}

#pragma mark - observing

// Sent when the transaction array has changed (additions or state changes). Client should check
Expand Down
8 changes: 8 additions & 0 deletions packages/in_app_purchase/ios/Classes/InAppPurchasePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
[self finishTransaction:call result:result];
} else if ([@"-[InAppPurchasePlugin restoreTransactions:result:]" isEqualToString:call.method]) {
[self restoreTransactions:call result:result];
} else if ([@"-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]"
isEqualToString:call.method]) {
[self presentCodeRedemptionSheet:call result:result];
} else if ([@"-[InAppPurchasePlugin retrieveReceiptData:result:]" isEqualToString:call.method]) {
[self retrieveReceiptData:call result:result];
} else if ([@"-[InAppPurchasePlugin refreshReceipt:result:]" isEqualToString:call.method]) {
Expand Down Expand Up @@ -246,6 +249,11 @@ - (void)restoreTransactions:(FlutterMethodCall *)call result:(FlutterResult)resu
result(nil);
}

- (void)presentCodeRedemptionSheet:(FlutterMethodCall *)call result:(FlutterResult)result {
[self.paymentQueueHandler presentCodeRedemptionSheet];
result(nil);
}

- (void)retrieveReceiptData:(FlutterMethodCall *)call result:(FlutterResult)result {
FlutterError *error = nil;
NSString *receiptData = [self.receiptManager retrieveReceiptWithError:&error];
Expand Down
16 changes: 16 additions & 0 deletions packages/in_app_purchase/ios/Tests/InAppPurchasePluginTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,22 @@ - (void)testRefreshReceiptRequest {
XCTAssertTrue(result);
}

- (void)testPresentCodeRedemptionSheet {
XCTestExpectation* expectation =
[self expectationWithDescription:@"expect successfully present Code Redemption Sheet"];
FlutterMethodCall* call = [FlutterMethodCall
methodCallWithMethodName:@"-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]"
arguments:nil];
__block BOOL callbackInvoked = NO;
[self.plugin handleMethodCall:call
result:^(id r) {
callbackInvoked = YES;
[expectation fulfill];
}];
[self waitForExpectations:@[ expectation ] timeout:5];
XCTAssertTrue(callbackInvoked);
}

- (void)testGetPendingTransactions {
XCTestExpectation* expectation = [self expectationWithDescription:@"expect success"];
FlutterMethodCall* call =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ class AppStoreConnection implements InAppPurchaseConnection {
);
return productDetailsResponse;
}

@override
Future presentCodeRedemptionSheet() {
return _skPaymentQueueWrapper.presentCodeRedemptionSheet();
}
}

class _TransactionObserver implements SKTransactionObserverWrapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ class GooglePlayConnection
'The method <refreshPurchaseVerificationData> only works on iOS.');
}

@override
Future presentCodeRedemptionSheet() async {
throw UnsupportedError(
'The method <presentCodeRedemptionSheet> only works on iOS.');
}

/// Resets the connection instance.
///
/// The next call to [instance] will create a new instance. Should only be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ abstract class InAppPurchaseConnection {
/// Throws an [UnsupportedError] on Android.
Future<PurchaseVerificationData?> refreshPurchaseVerificationData();

/// (App Store only) present Code Redemption Sheet.
/// Available on devices running iOS 14 and iPadOS 14 and later.
///
/// Throws an [UnsupportedError] on Android.
Future<void> presentCodeRedemptionSheet();

/// The [InAppPurchaseConnection] implemented for this platform.
///
/// Throws an [UnsupportedError] when accessed on a platform other than
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ class SKPaymentQueueWrapper {
applicationUserName);
}

/// Present Code Redemption Sheet
///
/// Use this to allow Users to enter and redeem Codes
///
/// This method triggers [`-[SKPayment
/// presentCodeRedemptionSheet]`](https://developer.apple.com/documentation/storekit/skpaymentqueue/3566726-presentcoderedemptionsheet?language=objc)
Future<void> presentCodeRedemptionSheet() async {
ABausG marked this conversation as resolved.
Show resolved Hide resolved
await channel.invokeMethod<void>(
'-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]');
}

// Triage a method channel call from the platform and triggers the correct observer method.
Future<void> _handleObserverCallbacks(MethodCall call) async {
assert(_observer != null,
Expand Down
2 changes: 1 addition & 1 deletion packages/in_app_purchase/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,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.
homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase
version: 0.5.0
version: 0.5.1

dependencies:
flutter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ void main() {
throwsUnsupportedError);
});
});

group('present code redemption sheet', () {
test('null', () async {
expect(
await AppStoreConnection.instance.presentCodeRedemptionSheet(), null);
});
});
}

class FakeIOSPlatform {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ void main() {
});
});

group('present code redemption sheet', () {
test('should throw on android', () {
expect(GooglePlayConnection.instance.presentCodeRedemptionSheet(),
throwsUnsupportedError);
});
});

group('make payment', () {
final String launchMethodName =
'BillingClient#launchBillingFlow(Activity, BillingFlowParams)';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ void main() {
expect(fakeIOSPlatform.applicationNameHasTransactionRestored, 'aUserID');
});
});

group('Code Redemption Sheet', () {
test('presentCodeRedemptionSheet should not throw', () async {
expect(fakeIOSPlatform.presentCodeRedemption, false);
await SKPaymentQueueWrapper().presentCodeRedemptionSheet();
expect(fakeIOSPlatform.presentCodeRedemption, true);
fakeIOSPlatform.presentCodeRedemption = false;
});
ABausG marked this conversation as resolved.
Show resolved Hide resolved
});
}

class FakeIOSPlatform {
Expand All @@ -153,6 +162,9 @@ class FakeIOSPlatform {
List<Map<String, String>> transactionsFinished = [];
String applicationNameHasTransactionRestored = '';

// present Code Redemption
bool presentCodeRedemption = false;

Future<dynamic> onMethodCall(MethodCall call) {
switch (call.method) {
// request makers
Expand Down Expand Up @@ -193,6 +205,9 @@ class FakeIOSPlatform {
case '-[InAppPurchasePlugin restoreTransactions:result:]':
applicationNameHasTransactionRestored = call.arguments;
return Future<void>.sync(() {});
case '-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]':
presentCodeRedemption = true;
return Future<void>.sync(() {});
}
return Future<void>.sync(() {});
Comment on lines +210 to 212
Copy link
Member

Choose a reason for hiding this comment

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

nit: @cyanglaz i wonder why all over the plugins

Future<void>.sync(() {});

is used instead of

Future<void>.value();

}
Expand Down