Skip to content

Commit 832ab83

Browse files
author
Chris Yang
authored
Iap add payment objc translators (flutter#1172)
1 parent d0e615c commit 832ab83

File tree

5 files changed

+305
-0
lines changed

5 files changed

+305
-0
lines changed

packages/in_app_purchase/example/ios/in_app_purchase_pluginTests/Stubs.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,21 @@ NS_ASSUME_NONNULL_BEGIN
3131

3232
@interface InAppPurchasePluginStub : InAppPurchasePlugin
3333
@end
34+
35+
@interface SKPaymentTransactionStub : SKPaymentTransaction
36+
- (instancetype)initWithMap:(NSDictionary *)map;
37+
@end
38+
39+
@interface SKDownloadStub : SKDownload
40+
- (instancetype)initWithMap:(NSDictionary *)map;
41+
@end
42+
43+
@interface SKMutablePaymentStub : SKMutablePayment
44+
- (instancetype)initWithMap:(NSDictionary *)map;
45+
@end
46+
47+
@interface NSErrorStub : NSError
48+
- (instancetype)initWithMap:(NSDictionary *)map;
49+
@end
50+
3451
NS_ASSUME_NONNULL_END

packages/in_app_purchase/example/ios/in_app_purchase_pluginTests/Stubs.m

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,70 @@ - (SKProductRequestStub *)getProductRequestWithIdentifiers:(NSSet *)identifiers
129129
}
130130

131131
@end
132+
133+
@implementation SKPaymentTransactionStub
134+
135+
- (instancetype)initWithID:(NSString *)identifier {
136+
self = [super init];
137+
if (self) {
138+
[self setValue:identifier forKey:@"transactionIdentifier"];
139+
}
140+
return self;
141+
}
142+
143+
- (instancetype)initWithMap:(NSDictionary *)map {
144+
self = [super init];
145+
if (self) {
146+
[self setValue:map[@"transactionIdentifier"] forKey:@"transactionIdentifier"];
147+
[self setValue:map[@"transactionState"] forKey:@"transactionState"];
148+
if (map[@"originalTransaction"] && !
149+
[map[@"originalTransaction"] isKindOfClass:[NSNull class]]) {
150+
[self setValue:[[SKPaymentTransactionStub alloc] initWithMap:map[@"originalTransaction"]]
151+
forKey:@"originalTransaction"];
152+
}
153+
[self setValue:map[@"error"] ? [[NSErrorStub alloc] initWithMap:map[@"error"]] : [NSNull null]
154+
forKey:@"error"];
155+
[self setValue:[NSDate dateWithTimeIntervalSince1970:[map[@"transactionTimeStamp"] doubleValue]]
156+
forKey:@"transactionDate"];
157+
NSMutableArray *downloads = [NSMutableArray new];
158+
for (NSDictionary *downloadMap in map[@"downloads"]) {
159+
[downloads addObject:[[SKDownloadStub alloc] initWithMap:downloadMap]];
160+
}
161+
[self setValue:downloads forKey:@"downloads"];
162+
}
163+
return self;
164+
}
165+
166+
@end
167+
168+
@implementation SKDownloadStub
169+
170+
- (instancetype)initWithMap:(NSDictionary *)map {
171+
self = [super init];
172+
if (self) {
173+
[self setValue:map[@"state"] forKey:@"downloadState"];
174+
[self setValue:map[@"contentIdentifier"] ?: [NSNull null] forKey:@"contentIdentifier"];
175+
[self setValue:map[@"contentLength"] ?: [NSNull null] forKey:@"contentLength"];
176+
[self setValue:[NSURL URLWithString:map[@"contentURL"]] ?: [NSNull null] forKey:@"contentURL"];
177+
[self setValue:map[@"error"] ? [[NSErrorStub alloc] initWithMap:map[@"error"]] : [NSNull null]
178+
forKey:@"error"];
179+
[self setValue:map[@"progress"] ?: [NSNull null] forKey:@"progress"];
180+
[self setValue:map[@"timeRemaining"] ?: [NSNull null] forKey:@"timeRemaining"];
181+
[self setValue:[[SKPaymentTransactionStub alloc] initWithID:map[@"transactionID"]]
182+
?: [NSNull null]
183+
forKey:@"transaction"];
184+
}
185+
return self;
186+
}
187+
188+
@end
189+
190+
@implementation NSErrorStub
191+
192+
- (instancetype)initWithMap:(NSDictionary *)map {
193+
return [self initWithDomain:[map objectForKey:@"domain"]
194+
code:[[map objectForKey:@"code"] integerValue]
195+
userInfo:[map objectForKey:@"userInfo"]];
196+
}
197+
198+
@end

packages/in_app_purchase/example/ios/in_app_purchase_pluginTests/TranslatorTest.m

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ @interface TranslatorTest : XCTestCase
1212
@property(strong, nonatomic) NSDictionary *discountMap;
1313
@property(strong, nonatomic) NSDictionary *productMap;
1414
@property(strong, nonatomic) NSDictionary *productResponseMap;
15+
@property(strong, nonatomic) NSDictionary *downloadMap;
16+
@property(strong, nonatomic) NSDictionary *paymentMap;
17+
@property(strong, nonatomic) NSDictionary *transactionMap;
18+
@property(strong, nonatomic) NSDictionary *errorMap;
1519
@property(strong, nonatomic) NSDictionary *localeMap;
1620

1721
@end
@@ -42,6 +46,72 @@ - (void)setUp {
4246
};
4347
self.productResponseMap =
4448
@{@"products" : @[ self.productMap ], @"invalidProductIdentifiers" : @[]};
49+
self.downloadMap = @{
50+
@"state" : @(0),
51+
@"contentIdentifier" : [NSNull null],
52+
@"contentLength" : @(2),
53+
@"contentURL" : @"https://flutter.io",
54+
@"contentVersion" : [NSNull null],
55+
@"error" : [[NSError errorWithDomain:@"test_stub" code:123 userInfo:@{}] toMap],
56+
@"progress" : @(0.5),
57+
@"timeRemaining" : @(100),
58+
@"downloadTimeUnKnown" : @(NO),
59+
@"transactionID" : [NSNull null],
60+
};
61+
self.paymentMap = @{
62+
@"productIdentifier" : @"123",
63+
@"requestData" : @"abcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefghabcdefgh",
64+
@"quantity" : @(2),
65+
@"applicationUsername" : @"app user name",
66+
@"simulatesAskToBuyInSandbox" : @(NO)
67+
};
68+
NSDictionary *originalTransactionMap = @{
69+
@"transactionIdentifier" : @"567",
70+
@"transactionState" : @(SKPaymentTransactionStatePurchasing),
71+
@"payment" : [NSNull null],
72+
@"error" : [[NSError errorWithDomain:@"test_stub" code:123 userInfo:@{}] toMap],
73+
@"transactionTimeStamp" : @([NSDate date].timeIntervalSince1970),
74+
@"originalTransaction" : [NSNull null],
75+
@"downloads" : @[ @{
76+
@"state" : @(0),
77+
@"contentIdentifier" : [NSNull null],
78+
@"contentLength" : @(2),
79+
@"contentURL" : @"https://flutter.io",
80+
@"contentVersion" : [NSNull null],
81+
@"error" : [[NSError errorWithDomain:@"test_stub" code:123 userInfo:@{}] toMap],
82+
@"progress" : @(0.5),
83+
@"timeRemaining" : @(100),
84+
@"downloadTimeUnKnown" : @(NO),
85+
@"transactionID" : @"567",
86+
} ]
87+
};
88+
self.transactionMap = @{
89+
@"transactionIdentifier" : @"567",
90+
@"transactionState" : @(SKPaymentTransactionStatePurchasing),
91+
@"payment" : [NSNull null],
92+
@"error" : [[NSError errorWithDomain:@"test_stub" code:123 userInfo:@{}] toMap],
93+
@"transactionTimeStamp" : @([NSDate date].timeIntervalSince1970),
94+
@"originalTransaction" : originalTransactionMap,
95+
@"downloads" : @[ @{
96+
@"state" : @(0),
97+
@"contentIdentifier" : [NSNull null],
98+
@"contentLength" : @(2),
99+
@"contentURL" : @"https://flutter.io",
100+
@"contentVersion" : [NSNull null],
101+
@"error" : [[NSError errorWithDomain:@"test_stub" code:123 userInfo:@{}] toMap],
102+
@"progress" : @(0.5),
103+
@"timeRemaining" : @(100),
104+
@"downloadTimeUnKnown" : @(NO),
105+
@"transactionID" : @"567",
106+
} ]
107+
};
108+
self.errorMap = @{
109+
@"code" : @(123),
110+
@"domain" : @"test_domain",
111+
@"userInfo" : @{
112+
@"key" : @"value",
113+
}
114+
};
45115
}
46116

47117
- (void)testSKProductSubscriptionPeriodStubToMap {
@@ -70,6 +140,33 @@ - (void)testProductResponseToMap {
70140
XCTAssertEqualObjects(map, self.productResponseMap);
71141
}
72142

143+
- (void)testDownloadToMap {
144+
// bug with state, downloadTimeUnKnown, transaction and contentIdentifer in KVC, cannot test these
145+
// fields.
146+
SKDownloadStub *download = [[SKDownloadStub alloc] initWithMap:self.downloadMap];
147+
NSDictionary *map = [download toMap];
148+
XCTAssertEqualObjects(map, self.downloadMap);
149+
}
150+
151+
- (void)testPaymentToMap {
152+
SKMutablePayment *payment = [[SKMutablePayment alloc] initWithMap:self.paymentMap];
153+
NSDictionary *map = [payment toMap];
154+
XCTAssertEqualObjects(map, self.paymentMap);
155+
}
156+
157+
- (void)testPaymentTransactionToMap {
158+
// payment is not KVC, cannot test payment field.
159+
SKPaymentTransactionStub *paymentTransaction =
160+
[[SKPaymentTransactionStub alloc] initWithMap:self.transactionMap];
161+
NSDictionary *map = [paymentTransaction toMap];
162+
XCTAssertEqualObjects(map, self.transactionMap);
163+
}
164+
165+
- (void)testError {
166+
NSErrorStub *error = [[NSErrorStub alloc] initWithMap:self.errorMap];
167+
NSDictionary *map = [error toMap];
168+
XCTAssertEqualObjects(map, self.errorMap);
169+
}
73170
- (void)testLocaleToMap {
74171
NSLocale *system = NSLocale.systemLocale;
75172
NSDictionary *map = [system toMap];

packages/in_app_purchase/ios/Classes/FIAObjectTranslator.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,36 @@ NS_ASSUME_NONNULL_BEGIN
3131

3232
@end
3333

34+
@interface SKPayment (Coder)
35+
36+
- (NSDictionary *)toMap;
37+
38+
@end
39+
40+
@interface SKMutablePayment (Coder)
41+
42+
- (instancetype)initWithMap:(NSDictionary *)map;
43+
44+
@end
45+
46+
@interface SKPaymentTransaction (Coder)
47+
48+
- (NSDictionary *)toMap;
49+
50+
@end
51+
52+
@interface SKDownload (Coder)
53+
54+
- (NSDictionary *)toMap;
55+
56+
@end
57+
58+
@interface NSError (Coder)
59+
60+
- (NSDictionary *)toMap;
61+
62+
@end
63+
3464
@interface NSLocale (Coder)
3565

3666
- (nullable NSDictionary *)toMap;

packages/in_app_purchase/ios/Classes/FIAObjectTranslator.m

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ - (NSDictionary *)toMap {
8080

8181
@end
8282

83+
@implementation SKPayment (Coder)
84+
85+
- (NSDictionary *)toMap {
86+
NSMutableDictionary *map = [[NSMutableDictionary alloc] initWithDictionary:@{
87+
@"productIdentifier" : self.productIdentifier ?: [NSNull null],
88+
@"requestData" : self.requestData ? [[NSString alloc] initWithData:self.requestData
89+
encoding:NSUTF8StringEncoding]
90+
: [NSNull null],
91+
@"quantity" : @(self.quantity),
92+
@"applicationUsername" : self.applicationUsername ?: [NSNull null]
93+
}];
94+
if (@available(iOS 8.3, *)) {
95+
[map setObject:@(self.simulatesAskToBuyInSandbox) forKey:@"simulatesAskToBuyInSandbox"];
96+
}
97+
return map;
98+
}
99+
100+
@end
101+
83102
@implementation NSLocale (Coder)
84103

85104
- (nullable NSDictionary *)toMap {
@@ -90,3 +109,78 @@ - (nullable NSDictionary *)toMap {
90109
}
91110

92111
@end
112+
113+
@implementation SKMutablePayment (Coder)
114+
115+
- (instancetype)initWithMap:(NSDictionary *)map {
116+
self = [self init];
117+
if (self) {
118+
self.productIdentifier = map[@"productIdentifier"];
119+
NSString *utf8String = map[@"requestData"];
120+
self.requestData = [utf8String dataUsingEncoding:NSUTF8StringEncoding];
121+
self.quantity = [map[@"quantity"] integerValue];
122+
self.applicationUsername = map[@"applicationUsername"];
123+
if (@available(iOS 8.3, *)) {
124+
self.simulatesAskToBuyInSandbox = [map[@"simulatesAskToBuyInSandbox"] boolValue];
125+
}
126+
}
127+
return self;
128+
}
129+
130+
@end
131+
132+
@implementation SKPaymentTransaction (Coder)
133+
134+
- (NSDictionary *)toMap {
135+
NSMutableDictionary *map = [[NSMutableDictionary alloc] initWithDictionary:@{
136+
@"error" : [self.error toMap] ?: [NSNull null],
137+
@"payment" : self.payment ? [self.payment toMap] : [NSNull null],
138+
@"originalTransaction" : self.originalTransaction ? [self.originalTransaction toMap]
139+
: [NSNull null],
140+
@"transactionTimeStamp" : self.transactionDate ? @(self.transactionDate.timeIntervalSince1970)
141+
: [NSNull null],
142+
@"transactionIdentifier" : self.transactionIdentifier ?: [NSNull null],
143+
@"transactionState" : @(self.transactionState)
144+
}];
145+
NSMutableArray *downloads = [NSMutableArray new];
146+
for (SKDownload *download in self.downloads) {
147+
[downloads addObject:[download toMap]];
148+
}
149+
[map setObject:downloads forKey:@"downloads"];
150+
return map;
151+
}
152+
153+
@end
154+
155+
@implementation SKDownload (Coder)
156+
157+
- (NSDictionary *)toMap {
158+
NSMutableDictionary *map = [[NSMutableDictionary alloc] initWithDictionary:@{
159+
@"contentLength" : @(self.contentLength),
160+
@"contentIdentifier" : self.contentIdentifier ?: [NSNull null],
161+
@"contentURL" : self.contentURL.absoluteString ?: [NSNull null],
162+
@"contentVersion" : self.contentVersion ?: [NSNull null],
163+
@"error" : [self.error toMap] ?: @{},
164+
@"progress" : @(self.progress),
165+
@"timeRemaining" : @(self.timeRemaining),
166+
@"downloadTimeUnKnown" : @(self.timeRemaining == SKDownloadTimeRemainingUnknown),
167+
@"transactionID" : self.transaction.transactionIdentifier ?: [NSNull null]
168+
}];
169+
if (@available(iOS 12.0, *)) {
170+
[map setObject:@(self.state) forKey:@"state"];
171+
} else {
172+
[map setObject:@(self.downloadState) forKey:@"state"];
173+
}
174+
return map;
175+
}
176+
177+
@end
178+
179+
@implementation NSError (Coder)
180+
181+
- (NSDictionary *)toMap {
182+
return
183+
@{@"code" : @(self.code), @"domain" : self.domain ?: @"", @"userInfo" : self.userInfo ?: @{}};
184+
}
185+
186+
@end

0 commit comments

Comments
 (0)