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

Commit 108cb53

Browse files
committed
Improved testing on illegal values
1 parent 87fc1fd commit 108cb53

File tree

5 files changed

+160
-56
lines changed

5 files changed

+160
-56
lines changed

packages/in_app_purchase/in_app_purchase_ios/example/ios/RunnerTests/InAppPurchasePluginTests.m

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,37 @@ - (void)testAddPaymentSuccessWithPaymentDiscount {
203203
XCTAssertEqual(transactionForUpdateBlock.transactionState, SKPaymentTransactionStatePurchased);
204204
}
205205

206+
- (void)testAddPaymentFailureWithInvalidPaymentDiscount {
207+
XCTestExpectation* expectation =
208+
[self expectationWithDescription:@"result should return success state"];
209+
FlutterMethodCall* call =
210+
[FlutterMethodCall methodCallWithMethodName:@"-[InAppPurchasePlugin addPayment:result:]"
211+
arguments:@{
212+
@"productIdentifier" : @"123",
213+
@"quantity" : @(1),
214+
@"simulatesAskToBuyInSandbox" : @YES,
215+
@"paymentDiscount" : @{
216+
@"keyIdentifier" : @"test_key_identifier",
217+
@"nonce" : @"4a11a9cc-3bc3-11ec-8d3d-0242ac130003",
218+
@"signature" : @"test_signature",
219+
@"timestamp" : @(1635847102),
220+
}
221+
}];
222+
223+
[self.plugin
224+
handleMethodCall:call
225+
result:^(id r){
226+
XCTAssertTrue([r isKindOfClass:FlutterError.class]);
227+
FlutterError *result = r;
228+
XCTAssertEqualObjects(result.code, @"storekit_invalid_payment_discount_object");
229+
XCTAssertEqualObjects(result.message, @"You have requested a payment and specified a payment discount with invalid properties. When specifying a payment discount the 'identifier' field is mandatory.");
230+
XCTAssertEqualObjects(result.details, call.arguments);
231+
[expectation fulfill];
232+
}];
233+
234+
[self waitForExpectations:@[ expectation ] timeout:5];
235+
}
236+
206237
- (void)testAddPaymentWithNullSandboxArgument {
207238
XCTestExpectation* expectation =
208239
[self expectationWithDescription:@"result should return success state"];

packages/in_app_purchase/in_app_purchase_ios/example/ios/RunnerTests/TranslatorTests.m

Lines changed: 87 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ - (void)testSKStorefrontAndSKPaymentTransactionToMap {
188188

189189
- (void)testSKPaymentDiscountFromMap {
190190
if (@available(iOS 12.2, *)) {
191+
NSString *error = nil;
191192
SKPaymentDiscount *paymentDiscount =
192-
[FIAObjectTranslator getSKPaymentDiscountFromMap:self.paymentDiscountMap];
193+
[FIAObjectTranslator getSKPaymentDiscountFromMap:self.paymentDiscountMap withError: &error];
193194

194195
XCTAssertEqual(paymentDiscount.identifier, self.paymentDiscountMap[@"identifier"]);
195196
XCTAssertEqual(paymentDiscount.keyIdentifier, self.paymentDiscountMap[@"keyIdentifier"]);
@@ -202,66 +203,111 @@ - (void)testSKPaymentDiscountFromMap {
202203

203204
- (void)testSKPaymentDiscountFromMapMissingIdentifier {
204205
if (@available(iOS 12.2, *)) {
205-
NSDictionary *discountMap = @{
206-
@"keyIdentifier" : @"payment_discount_key_identifier",
207-
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
208-
@"signature" : @"this is a encrypted signature",
209-
@"timestamp" : @([NSDate date].timeIntervalSince1970),
210-
};
211-
212-
XCTAssertThrows([FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap]);
206+
NSArray * invalidValues = @[[NSNull null], @(1), @""];
207+
208+
for (id value in invalidValues) {
209+
NSDictionary *discountMap = @{
210+
@"identifier" : value,
211+
@"keyIdentifier" : @"payment_discount_key_identifier",
212+
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
213+
@"signature" : @"this is a encrypted signature",
214+
@"timestamp" : @([NSDate date].timeIntervalSince1970),
215+
};
216+
217+
NSString *error = nil;
218+
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
219+
220+
XCTAssertNotNil(error);
221+
XCTAssertEqualObjects(error, @"When specifying a payment discount the 'identifier' field is mandatory.");
222+
}
213223
}
214224
}
215225

216226
- (void)testSKPaymentDiscountFromMapMissingKeyIdentifier {
217227
if (@available(iOS 12.2, *)) {
218-
NSDictionary *discountMap = @{
219-
@"identifier" : @"payment_discount_identifier",
220-
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
221-
@"signature" : @"this is a encrypted signature",
222-
@"timestamp" : @([NSDate date].timeIntervalSince1970),
223-
};
224-
225-
XCTAssertThrows([FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap]);
228+
NSArray * invalidValues = @[[NSNull null], @(1), @""];
229+
230+
for (id value in invalidValues) {
231+
NSDictionary *discountMap = @{
232+
@"identifier" : @"payment_discount_identifier",
233+
@"keyIdentifier" : value,
234+
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
235+
@"signature" : @"this is a encrypted signature",
236+
@"timestamp" : @([NSDate date].timeIntervalSince1970),
237+
};
238+
239+
NSString *error = nil;
240+
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
241+
242+
XCTAssertNotNil(error);
243+
XCTAssertEqualObjects(error, @"When specifying a payment discount the 'keyIdentifier' field is mandatory.");
244+
}
226245
}
227246
}
228247

229248
- (void)testSKPaymentDiscountFromMapMissingNonce {
230249
if (@available(iOS 12.2, *)) {
231-
NSDictionary *discountMap = @{
232-
@"identifier" : @"payment_discount_identifier",
233-
@"keyIdentifier" : @"payment_discount_key_identifier",
234-
@"signature" : @"this is a encrypted signature",
235-
@"timestamp" : @([NSDate date].timeIntervalSince1970),
236-
};
237-
238-
XCTAssertThrows([FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap]);
250+
NSArray * invalidValues = @[[NSNull null], @(1), @""];
251+
252+
for (id value in invalidValues) {
253+
NSDictionary *discountMap = @{
254+
@"identifier" : @"payment_discount_identifier",
255+
@"keyIdentifier" : @"payment_discount_key_identifier",
256+
@"nonce" : value,
257+
@"signature" : @"this is a encrypted signature",
258+
@"timestamp" : @([NSDate date].timeIntervalSince1970),
259+
};
260+
261+
NSString *error = nil;
262+
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
263+
264+
XCTAssertNotNil(error);
265+
XCTAssertEqualObjects(error, @"When specifying a payment discount the 'nonce' field is mandatory.");
266+
}
239267
}
240268
}
241269

242270
- (void)testSKPaymentDiscountFromMapMissingSignature {
243271
if (@available(iOS 12.2, *)) {
244-
NSDictionary *discountMap = @{
245-
@"identifier" : @"payment_discount_identifier",
246-
@"keyIdentifier" : @"payment_discount_key_identifier",
247-
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
248-
@"timestamp" : @([NSDate date].timeIntervalSince1970),
249-
};
250-
251-
XCTAssertThrows([FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap]);
272+
NSArray * invalidValues = @[[NSNull null], @(1), @""];
273+
274+
for (id value in invalidValues) {
275+
NSDictionary *discountMap = @{
276+
@"identifier" : @"payment_discount_identifier",
277+
@"keyIdentifier" : @"payment_discount_key_identifier",
278+
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
279+
@"signature" : value,
280+
@"timestamp" : @([NSDate date].timeIntervalSince1970),
281+
};
282+
283+
NSString *error = nil;
284+
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
285+
286+
XCTAssertNotNil(error);
287+
XCTAssertEqualObjects(error, @"When specifying a payment discount the 'signature' field is mandatory.");
288+
}
252289
}
253290
}
254291

255292
- (void)testSKPaymentDiscountFromMapMissingTimestamp {
256293
if (@available(iOS 12.2, *)) {
257-
NSDictionary *discountMap = @{
258-
@"identifier" : @"payment_discount_identifier",
259-
@"keyIdentifier" : @"payment_discount_key_identifier",
260-
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
261-
@"signature" : @"this is a encrypted signature",
262-
};
263-
264-
XCTAssertThrows([FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap]);
294+
NSArray * invalidValues = @[[NSNull null], @"", @(-1)];
295+
296+
for (id value in invalidValues) {
297+
NSDictionary *discountMap = @{
298+
@"identifier" : @"payment_discount_identifier",
299+
@"keyIdentifier" : @"payment_discount_key_identifier",
300+
@"nonce" : @"d18981e0-9003-4365-98a2-4b90e3b62c52",
301+
@"signature" : @"this is a encrypted signature",
302+
@"timestamp" : value,
303+
};
304+
305+
NSString *error = nil;
306+
[FIAObjectTranslator getSKPaymentDiscountFromMap:discountMap withError:&error];
307+
308+
XCTAssertNotNil(error);
309+
XCTAssertEqualObjects(error, @"When specifying a payment discount the 'timestamp' field is mandatory.");
310+
}
265311
}
266312
}
267313

packages/in_app_purchase/in_app_purchase_ios/ios/Classes/FIAObjectTranslator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
5252
API_AVAILABLE(ios(13), macos(10.15), watchos(6.2));
5353

5454
// Creates an instance of the SKPaymentDiscount class based on the supplied dictionary.
55-
+ (SKPaymentDiscount *)getSKPaymentDiscountFromMap:(NSDictionary *)map API_AVAILABLE(ios(12.2));
55+
+ (SKPaymentDiscount *)getSKPaymentDiscountFromMap:(NSDictionary *)map withError:(NSString **)error API_AVAILABLE(ios(12.2));
5656

5757
@end
5858
;

packages/in_app_purchase/in_app_purchase_ios/ios/Classes/FIAObjectTranslator.m

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -208,30 +208,45 @@ + (NSDictionary *)getMapFromSKStorefront:(SKStorefront *)storefront
208208
return map;
209209
}
210210

211-
+ (SKPaymentDiscount *)getSKPaymentDiscountFromMap:(NSDictionary *)map {
211+
+ (SKPaymentDiscount *)getSKPaymentDiscountFromMap:(NSDictionary *)map withError:(NSString **)error{
212212
if (!map || map.count <= 0) {
213213
return nil;
214214
}
215215

216-
NSAssert(map[@"identifier"],
217-
@"When specifying a payment discount the 'identifier' field is mandatory.");
218-
NSAssert(map[@"keyIdentifier"],
219-
@"When specifying a payment discount the 'keyIdentifier' field is mandatory.");
220-
NSAssert(map[@"nonce"], @"When specifying a payment discount the 'nonce' field is mandatory.");
221-
NSAssert(map[@"signature"],
222-
@"When specifying a payment discount the 'signature' field is mandatory.");
223-
NSAssert(map[@"timestamp"],
224-
@"When specifying a payment discount the 'timestamp' field is mandatory.");
225-
226216
NSString *identifier = map[@"identifier"];
227217
NSString *keyIdentifier = map[@"keyIdentifier"];
228-
NSUUID *nonce = [[NSUUID alloc] initWithUUIDString:map[@"nonce"]];
218+
NSString *nonce = map[@"nonce"];
229219
NSString *signature = map[@"signature"];
230220
NSNumber *timestamp = map[@"timestamp"];
221+
222+
if (!identifier || ![identifier isKindOfClass:NSString.class] || [identifier isEqualToString:@""]) {
223+
*error = @"When specifying a payment discount the 'identifier' field is mandatory.";
224+
return nil;
225+
}
226+
227+
if (!keyIdentifier || ![keyIdentifier isKindOfClass:NSString.class] || [keyIdentifier isEqualToString:@""]) {
228+
*error = @"When specifying a payment discount the 'keyIdentifier' field is mandatory.";
229+
return nil;
230+
}
231+
232+
if (!nonce || ![nonce isKindOfClass:NSString.class] || [nonce isEqualToString:@""]) {
233+
*error = @"When specifying a payment discount the 'nonce' field is mandatory.";
234+
return nil;
235+
}
236+
237+
if (!signature || ![signature isKindOfClass:NSString.class] || [signature isEqualToString:@""]) {
238+
*error = @"When specifying a payment discount the 'signature' field is mandatory.";
239+
return nil;
240+
}
241+
242+
if (!timestamp || ![timestamp isKindOfClass:NSNumber.class] || [timestamp intValue] <= 0) {
243+
*error = @"When specifying a payment discount the 'timestamp' field is mandatory.";
244+
return nil;
245+
}
231246

232247
SKPaymentDiscount *discount = [[SKPaymentDiscount alloc] initWithIdentifier:identifier
233248
keyIdentifier:keyIdentifier
234-
nonce:nonce
249+
nonce:[[NSUUID alloc] initWithUUIDString:nonce]
235250
signature:signature
236251
timestamp:timestamp];
237252

packages/in_app_purchase/in_app_purchase_ios/ios/Classes/InAppPurchasePlugin.m

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,20 @@ - (void)addPayment:(FlutterMethodCall *)call result:(FlutterResult)result {
204204
: [simulatesAskToBuyInSandbox boolValue];
205205

206206
if (@available(iOS 12.2, *)) {
207+
NSString *error = nil;
207208
SKPaymentDiscount *paymentDiscount = [FIAObjectTranslator
208-
getSKPaymentDiscountFromMap:[paymentMap objectForKey:@"paymentDiscount"]];
209+
getSKPaymentDiscountFromMap:[paymentMap objectForKey:@"paymentDiscount"] withError:&error];
210+
211+
if (error) {
212+
result([FlutterError
213+
errorWithCode:@"storekit_invalid_payment_discount_object"
214+
message: [NSString stringWithFormat:
215+
@"You have requested a payment and specified a payment discount with invalid properties. %@",
216+
error]
217+
details:call.arguments]);
218+
return;
219+
}
220+
209221
payment.paymentDiscount = paymentDiscount;
210222
}
211223

0 commit comments

Comments
 (0)