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

Commit b709f7e

Browse files
authored
[in_app_purchase] presentCodeRedemptionSheet (#3274)
1 parent eb86dfc commit b709f7e

13 files changed

+95
-1
lines changed

packages/in_app_purchase/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.5.1
2+
3+
* [iOS] Introduce `SKPaymentQueueWrapper.presentCodeRedemptionSheet`
4+
15
## 0.5.0
26

37
* Migrate to Google Billing Library 3.0

packages/in_app_purchase/ios/Classes/FIAPaymentQueueHandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef void (^UpdatedDownloads)(NSArray<SKDownload *> *downloads);
2929
// Can throw exceptions if the transaction type is purchasing, should always used in a @try block.
3030
- (void)finishTransaction:(nonnull SKPaymentTransaction *)transaction;
3131
- (void)restoreTransactions:(nullable NSString *)applicationName;
32+
- (void)presentCodeRedemptionSheet;
3233
- (NSArray<SKPaymentTransaction *> *)getUnfinishedTransactions;
3334

3435
// This method needs to be called before any other methods.

packages/in_app_purchase/ios/Classes/FIAPaymentQueueHandler.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ - (void)restoreTransactions:(nullable NSString *)applicationName {
6666
}
6767
}
6868

69+
- (void)presentCodeRedemptionSheet {
70+
if (@available(iOS 14, *)) {
71+
[self.queue presentCodeRedemptionSheet];
72+
} else {
73+
NSLog(@"presentCodeRedemptionSheet is only available on iOS 14 or newer");
74+
}
75+
}
76+
6977
#pragma mark - observing
7078

7179
// Sent when the transaction array has changed (additions or state changes). Client should check

packages/in_app_purchase/ios/Classes/InAppPurchasePlugin.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
9393
[self finishTransaction:call result:result];
9494
} else if ([@"-[InAppPurchasePlugin restoreTransactions:result:]" isEqualToString:call.method]) {
9595
[self restoreTransactions:call result:result];
96+
} else if ([@"-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]"
97+
isEqualToString:call.method]) {
98+
[self presentCodeRedemptionSheet:call result:result];
9699
} else if ([@"-[InAppPurchasePlugin retrieveReceiptData:result:]" isEqualToString:call.method]) {
97100
[self retrieveReceiptData:call result:result];
98101
} else if ([@"-[InAppPurchasePlugin refreshReceipt:result:]" isEqualToString:call.method]) {
@@ -246,6 +249,11 @@ - (void)restoreTransactions:(FlutterMethodCall *)call result:(FlutterResult)resu
246249
result(nil);
247250
}
248251

252+
- (void)presentCodeRedemptionSheet:(FlutterMethodCall *)call result:(FlutterResult)result {
253+
[self.paymentQueueHandler presentCodeRedemptionSheet];
254+
result(nil);
255+
}
256+
249257
- (void)retrieveReceiptData:(FlutterMethodCall *)call result:(FlutterResult)result {
250258
FlutterError *error = nil;
251259
NSString *receiptData = [self.receiptManager retrieveReceiptWithError:&error];

packages/in_app_purchase/ios/Tests/InAppPurchasePluginTest.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,22 @@ - (void)testRefreshReceiptRequest {
250250
XCTAssertTrue(result);
251251
}
252252

253+
- (void)testPresentCodeRedemptionSheet {
254+
XCTestExpectation* expectation =
255+
[self expectationWithDescription:@"expect successfully present Code Redemption Sheet"];
256+
FlutterMethodCall* call = [FlutterMethodCall
257+
methodCallWithMethodName:@"-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]"
258+
arguments:nil];
259+
__block BOOL callbackInvoked = NO;
260+
[self.plugin handleMethodCall:call
261+
result:^(id r) {
262+
callbackInvoked = YES;
263+
[expectation fulfill];
264+
}];
265+
[self waitForExpectations:@[ expectation ] timeout:5];
266+
XCTAssertTrue(callbackInvoked);
267+
}
268+
253269
- (void)testGetPendingTransactions {
254270
XCTestExpectation* expectation = [self expectationWithDescription:@"expect success"];
255271
FlutterMethodCall* call =

packages/in_app_purchase/lib/src/in_app_purchase/app_store_connection.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ class AppStoreConnection implements InAppPurchaseConnection {
201201
);
202202
return productDetailsResponse;
203203
}
204+
205+
@override
206+
Future presentCodeRedemptionSheet() {
207+
return _skPaymentQueueWrapper.presentCodeRedemptionSheet();
208+
}
204209
}
205210

206211
class _TransactionObserver implements SKTransactionObserverWrapper {

packages/in_app_purchase/lib/src/in_app_purchase/google_play_connection.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ class GooglePlayConnection
179179
'The method <refreshPurchaseVerificationData> only works on iOS.');
180180
}
181181

182+
@override
183+
Future presentCodeRedemptionSheet() async {
184+
throw UnsupportedError(
185+
'The method <presentCodeRedemptionSheet> only works on iOS.');
186+
}
187+
182188
/// Resets the connection instance.
183189
///
184190
/// The next call to [instance] will create a new instance. Should only be

packages/in_app_purchase/lib/src/in_app_purchase/in_app_purchase_connection.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ abstract class InAppPurchaseConnection {
239239
/// Throws an [UnsupportedError] on Android.
240240
Future<PurchaseVerificationData?> refreshPurchaseVerificationData();
241241

242+
/// (App Store only) present Code Redemption Sheet.
243+
/// Available on devices running iOS 14 and iPadOS 14 and later.
244+
///
245+
/// Throws an [UnsupportedError] on Android.
246+
Future<void> presentCodeRedemptionSheet();
247+
242248
/// The [InAppPurchaseConnection] implemented for this platform.
243249
///
244250
/// Throws an [UnsupportedError] when accessed on a platform other than

packages/in_app_purchase/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,17 @@ class SKPaymentQueueWrapper {
137137
applicationUserName);
138138
}
139139

140+
/// Present Code Redemption Sheet
141+
///
142+
/// Use this to allow Users to enter and redeem Codes
143+
///
144+
/// This method triggers [`-[SKPayment
145+
/// presentCodeRedemptionSheet]`](https://developer.apple.com/documentation/storekit/skpaymentqueue/3566726-presentcoderedemptionsheet?language=objc)
146+
Future<void> presentCodeRedemptionSheet() async {
147+
await channel.invokeMethod<void>(
148+
'-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]');
149+
}
150+
140151
// Triage a method channel call from the platform and triggers the correct observer method.
141152
Future<void> _handleObserverCallbacks(MethodCall call) async {
142153
assert(_observer != null,

packages/in_app_purchase/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: in_app_purchase
22
description: A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store and Google Play.
33
homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase
4-
version: 0.5.0
4+
version: 0.5.1
55

66
dependencies:
77
flutter:

packages/in_app_purchase/test/in_app_purchase_connection/app_store_connection_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ void main() {
300300
throwsUnsupportedError);
301301
});
302302
});
303+
304+
group('present code redemption sheet', () {
305+
test('null', () async {
306+
expect(
307+
await AppStoreConnection.instance.presentCodeRedemptionSheet(), null);
308+
});
309+
});
303310
}
304311

305312
class FakeIOSPlatform {

packages/in_app_purchase/test/in_app_purchase_connection/google_play_connection_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,13 @@ void main() {
238238
});
239239
});
240240

241+
group('present code redemption sheet', () {
242+
test('should throw on android', () {
243+
expect(GooglePlayConnection.instance.presentCodeRedemptionSheet(),
244+
throwsUnsupportedError);
245+
});
246+
});
247+
241248
group('make payment', () {
242249
final String launchMethodName =
243250
'BillingClient#launchBillingFlow(Activity, BillingFlowParams)';

packages/in_app_purchase/test/store_kit_wrappers/sk_methodchannel_apis_test.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ void main() {
133133
expect(fakeIOSPlatform.applicationNameHasTransactionRestored, 'aUserID');
134134
});
135135
});
136+
137+
group('Code Redemption Sheet', () {
138+
test('presentCodeRedemptionSheet should not throw', () async {
139+
expect(fakeIOSPlatform.presentCodeRedemption, false);
140+
await SKPaymentQueueWrapper().presentCodeRedemptionSheet();
141+
expect(fakeIOSPlatform.presentCodeRedemption, true);
142+
fakeIOSPlatform.presentCodeRedemption = false;
143+
});
144+
});
136145
}
137146

138147
class FakeIOSPlatform {
@@ -153,6 +162,9 @@ class FakeIOSPlatform {
153162
List<Map<String, String>> transactionsFinished = [];
154163
String applicationNameHasTransactionRestored = '';
155164

165+
// present Code Redemption
166+
bool presentCodeRedemption = false;
167+
156168
Future<dynamic> onMethodCall(MethodCall call) {
157169
switch (call.method) {
158170
// request makers
@@ -193,6 +205,9 @@ class FakeIOSPlatform {
193205
case '-[InAppPurchasePlugin restoreTransactions:result:]':
194206
applicationNameHasTransactionRestored = call.arguments;
195207
return Future<void>.sync(() {});
208+
case '-[InAppPurchasePlugin presentCodeRedemptionSheet:result:]':
209+
presentCodeRedemption = true;
210+
return Future<void>.sync(() {});
196211
}
197212
return Future<void>.sync(() {});
198213
}

0 commit comments

Comments
 (0)