-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[in_app_purchase] Convert storefront(), transactions(), canMakePayment(), and addPayment() to pigeon #5910
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[in_app_purchase] Convert storefront(), transactions(), canMakePayment(), and addPayment() to pigeon #5910
Changes from 7 commits
451365d
942a623
90ff466
020e024
82670b1
0b110d7
2c9c545
9a085ba
5ddd517
7a47ab8
d434931
427181a
1585d3a
c5610c7
4c0672c
7c68126
56b8bc8
020623e
8fba660
bc666b8
3279b2b
fb7f98c
208844e
eb3320c
91554c6
8f8e242
0442eb5
d2f96fc
b3a8314
4629236
b4e1a5f
082ad70
3e53e09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
|
|
||
| #import <Foundation/Foundation.h> | ||
| #import <StoreKit/StoreKit.h> | ||
| #import "messages.g.h" | ||
|
|
||
| NS_ASSUME_NONNULL_BEGIN | ||
|
|
||
|
|
@@ -56,6 +57,9 @@ NS_ASSUME_NONNULL_BEGIN | |
| withError:(NSString *_Nullable *_Nullable)error | ||
| API_AVAILABLE(ios(12.2)); | ||
|
|
||
| + (nullable SKPaymentTransactionMessage *) convertTransactionToPigeon:(SKPaymentTransaction *) transaction; | ||
|
||
|
|
||
| + (nullable SKStorefrontMessage *) convertStorefrontToPigeon:(SKStorefront *)storefront API_AVAILABLE(ios(13.0)); | ||
| @end | ||
| ; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| // found in the LICENSE file. | ||
|
|
||
| #import "FIAObjectTranslator.h" | ||
| #import "messages.g.h" | ||
LouiseHsu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #pragma mark - SKProduct Coders | ||
|
|
||
|
|
@@ -294,4 +295,59 @@ + (SKPaymentDiscount *)getSKPaymentDiscountFromMap:(NSDictionary *)map | |
| return discount; | ||
| } | ||
|
|
||
| + (nullable SKPaymentTransactionMessage *) convertTransactionToPigeon:(SKPaymentTransaction *) transaction { | ||
| SKPaymentTransactionMessage *msg = [SKPaymentTransactionMessage makeWithPayment:[self convertPaymentToPigeon:transaction.payment] transactionState:[self convertTransactionStateToPigeon:transaction.transactionState] originalTransaction:transaction.originalTransaction ? [self convertTransactionToPigeon:transaction.originalTransaction] : nil transactionTimeStamp:[NSNumber numberWithDouble:[transaction.transactionDate timeIntervalSince1970]] transactionIdentifier:transaction.transactionIdentifier | ||
|
||
| error:[self convertSKErrorToPigeon:transaction.error]]; | ||
| return msg; | ||
| } | ||
|
|
||
| + (nullable SKErrorMessage *) convertSKErrorToPigeon:(NSError *) error { | ||
| SKErrorMessage *msg = [SKErrorMessage makeWithCode:@(error.code) domain:error.domain userInfo:error.userInfo]; | ||
| return msg; | ||
| } | ||
|
|
||
| + (SKPaymentTransactionStateMessage) convertTransactionStateToPigeon:(SKPaymentTransactionState) state { | ||
| switch (state) { | ||
| case SKPaymentTransactionStatePurchasing: | ||
| return SKPaymentTransactionStateMessagePurchasing; | ||
| break; | ||
|
||
| case SKPaymentTransactionStatePurchased: | ||
| return SKPaymentTransactionStateMessagePurchased; | ||
| break; | ||
| case SKPaymentTransactionStateFailed: | ||
| return SKPaymentTransactionStateMessageFailed; | ||
| break; | ||
| case SKPaymentTransactionStateRestored: | ||
| return SKPaymentTransactionStateMessageRestored; | ||
| break; | ||
| case SKPaymentTransactionStateDeferred: | ||
| return SKPaymentTransactionStateMessageDeferred; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| + (nullable SKPaymentMessage *) convertPaymentToPigeon:(SKPayment *) payment { | ||
| if (@available(iOS 12.2, *)) { | ||
| SKPaymentMessage *msg = [SKPaymentMessage makeWithProductIdentifier:payment.productIdentifier applicationUsername:payment.applicationUsername | ||
| requestData:[[NSString alloc] initWithData:payment.requestData encoding:NSUTF8StringEncoding] | ||
| quantity:@(payment.quantity) | ||
| simulatesAskToBuyInSandbox:@(payment.simulatesAskToBuyInSandbox) | ||
| paymentDiscount:[self convertPaymentDiscountToPigeon: payment.paymentDiscount]]; | ||
| return msg; | ||
| } | ||
| return nil; | ||
|
||
| } | ||
|
|
||
| + (nullable SKPaymentDiscountMessage *) convertPaymentDiscountToPigeon:(SKPaymentDiscount *) discount API_AVAILABLE(ios(12.2)){ | ||
| SKPaymentDiscountMessage *msg = [SKPaymentDiscountMessage makeWithIdentifier:discount.identifier keyIdentifier:discount.keyIdentifier nonce:[discount.nonce UUIDString] signature:discount.signature timestamp:discount.timestamp]; | ||
|
|
||
| return msg; | ||
| } | ||
|
|
||
| + (nullable SKStorefrontMessage *) convertStorefrontToPigeon:(SKStorefront *)storefront API_AVAILABLE(ios(13.0)){ | ||
| SKStorefrontMessage *msg = [SKStorefrontMessage makeWithCountryCode:storefront.countryCode | ||
| identifier:storefront.identifier]; | ||
| return msg; | ||
| } | ||
|
|
||
| @end | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |||||
| #import "FIAPReceiptManager.h" | ||||||
| #import "FIAPRequestHandler.h" | ||||||
| #import "FIAPaymentQueueHandler.h" | ||||||
| #import "messages.g.h" | ||||||
LouiseHsu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| @interface InAppPurchasePlugin () | ||||||
|
|
||||||
|
|
@@ -40,8 +41,13 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar { | |||||
| FlutterMethodChannel *channel = | ||||||
| [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/in_app_purchase" | ||||||
| binaryMessenger:[registrar messenger]]; | ||||||
| InAppPurchasePlugin *instance = [[InAppPurchasePlugin alloc] initWithRegistrar:registrar]; | ||||||
| [registrar addMethodCallDelegate:instance channel:channel]; | ||||||
| // InAppPurchasePlugin *instance = [[InAppPurchasePlugin alloc] initWithRegistrar:registrar]; | ||||||
| // SetUpInAppPurchaseAPI([registrar messenger], instance); | ||||||
|
|
||||||
| InAppPurchasePlugin *instance = [[InAppPurchasePlugin alloc] initWithRegistrar:registrar]; | ||||||
| [registrar addMethodCallDelegate:instance channel:channel]; | ||||||
| [registrar addApplicationDelegate:instance]; | ||||||
| InAppPurchaseAPISetup([registrar messenger], instance); | ||||||
|
||||||
| } | ||||||
|
|
||||||
| - (instancetype)initWithReceiptManager:(FIAPReceiptManager *)receiptManager { | ||||||
|
|
@@ -85,16 +91,8 @@ - (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar | |||||
| } | ||||||
|
|
||||||
| - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { | ||||||
| if ([@"-[SKPaymentQueue canMakePayments:]" isEqualToString:call.method]) { | ||||||
| [self canMakePayments:result]; | ||||||
| } else if ([@"-[SKPaymentQueue transactions]" isEqualToString:call.method]) { | ||||||
| [self getPendingTransactions:result]; | ||||||
| } else if ([@"-[SKPaymentQueue storefront]" isEqualToString:call.method]) { | ||||||
| [self getStorefront:result]; | ||||||
| } else if ([@"-[InAppPurchasePlugin startProductRequest:result:]" isEqualToString:call.method]) { | ||||||
|
Comment on lines
-90
to
-94
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! |
||||||
| if ([@"-[InAppPurchasePlugin startProductRequest:result:]" isEqualToString:call.method]) { | ||||||
| [self handleProductRequestMethodCall:call result:result]; | ||||||
| } else if ([@"-[InAppPurchasePlugin addPayment:result:]" isEqualToString:call.method]) { | ||||||
| [self addPayment:call result:result]; | ||||||
| } else if ([@"-[InAppPurchasePlugin finishTransaction:result:]" isEqualToString:call.method]) { | ||||||
| [self finishTransaction:call result:result]; | ||||||
| } else if ([@"-[InAppPurchasePlugin restoreTransactions:result:]" isEqualToString:call.method]) { | ||||||
|
|
@@ -193,70 +191,6 @@ - (void)handleProductRequestMethodCall:(FlutterMethodCall *)call result:(Flutter | |||||
| }]; | ||||||
| } | ||||||
|
|
||||||
| - (void)addPayment:(FlutterMethodCall *)call result:(FlutterResult)result { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be better for your sanity if you keep these methods around in the same place, but just change the signatures. That's going to be easier for you and the reviewer to verify the changes. Maybe something like - (void)addPayment:(SKProductMessage*)message withError:(NSError**)error;It's not mandatory, just a suggestion. Maybe something to consider next time. |
||||||
| if (![call.arguments isKindOfClass:[NSDictionary class]]) { | ||||||
| result([FlutterError errorWithCode:@"storekit_invalid_argument" | ||||||
| message:@"Argument type of addPayment is not a Dictionary" | ||||||
| details:call.arguments]); | ||||||
| return; | ||||||
| } | ||||||
| NSDictionary *paymentMap = (NSDictionary *)call.arguments; | ||||||
| NSString *productID = [paymentMap objectForKey:@"productIdentifier"]; | ||||||
| // When a product is already fetched, we create a payment object with | ||||||
| // the product to process the payment. | ||||||
| SKProduct *product = [self getProduct:productID]; | ||||||
| if (!product) { | ||||||
| result([FlutterError | ||||||
| errorWithCode:@"storekit_invalid_payment_object" | ||||||
| message: | ||||||
| @"You have requested a payment for an invalid product. Either the " | ||||||
| @"`productIdentifier` of the payment is not valid or the product has not been " | ||||||
| @"fetched before adding the payment to the payment queue." | ||||||
| details:call.arguments]); | ||||||
| return; | ||||||
| } | ||||||
| SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product]; | ||||||
| payment.applicationUsername = [paymentMap objectForKey:@"applicationUsername"]; | ||||||
| NSNumber *quantity = [paymentMap objectForKey:@"quantity"]; | ||||||
| payment.quantity = (quantity != nil) ? quantity.integerValue : 1; | ||||||
| NSNumber *simulatesAskToBuyInSandbox = [paymentMap objectForKey:@"simulatesAskToBuyInSandbox"]; | ||||||
| payment.simulatesAskToBuyInSandbox = (id)simulatesAskToBuyInSandbox == (id)[NSNull null] | ||||||
| ? NO | ||||||
| : [simulatesAskToBuyInSandbox boolValue]; | ||||||
|
|
||||||
| if (@available(iOS 12.2, *)) { | ||||||
| NSDictionary *paymentDiscountMap = [self getNonNullValueFromDictionary:paymentMap | ||||||
| forKey:@"paymentDiscount"]; | ||||||
| NSString *error = nil; | ||||||
| SKPaymentDiscount *paymentDiscount = | ||||||
| [FIAObjectTranslator getSKPaymentDiscountFromMap:paymentDiscountMap withError:&error]; | ||||||
|
|
||||||
| if (error) { | ||||||
| result([FlutterError | ||||||
| errorWithCode:@"storekit_invalid_payment_discount_object" | ||||||
| message:[NSString stringWithFormat:@"You have requested a payment and specified a " | ||||||
| @"payment discount with invalid properties. %@", | ||||||
| error] | ||||||
| details:call.arguments]); | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| payment.paymentDiscount = paymentDiscount; | ||||||
| } | ||||||
|
|
||||||
| if (![self.paymentQueueHandler addPayment:payment]) { | ||||||
| result([FlutterError | ||||||
| errorWithCode:@"storekit_duplicate_product_object" | ||||||
| message:@"There is a pending transaction for the same product identifier. Please " | ||||||
| @"either wait for it to be finished or finish it manually using " | ||||||
| @"`completePurchase` to avoid edge cases." | ||||||
|
|
||||||
| details:call.arguments]); | ||||||
| return; | ||||||
| } | ||||||
| result(nil); | ||||||
| } | ||||||
|
|
||||||
| - (void)finishTransaction:(FlutterMethodCall *)call result:(FlutterResult)result { | ||||||
| if (![call.arguments isKindOfClass:[NSDictionary class]]) { | ||||||
| result([FlutterError errorWithCode:@"storekit_invalid_argument" | ||||||
|
|
@@ -466,4 +400,87 @@ - (SKReceiptRefreshRequest *)getRefreshReceiptRequest:(NSDictionary *)properties | |||||
| return [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:properties]; | ||||||
| } | ||||||
|
|
||||||
| - (nullable NSNumber *)canMakePaymentsWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { | ||||||
| return @([SKPaymentQueue canMakePayments]); | ||||||
| } | ||||||
|
|
||||||
| - (nullable SKStorefrontMessage *)storefrontWithError:(FlutterError *_Nullable *_Nonnull)error { | ||||||
| if (@available(iOS 13.0, macOS 10.15, *)) { | ||||||
| SKStorefront *storefront = self.paymentQueueHandler.storefront; | ||||||
| if (!storefront) { | ||||||
| return nil; | ||||||
|
||||||
| } | ||||||
| return[FIAObjectTranslator convertStorefrontToPigeon:storefront]; | ||||||
|
||||||
| return[FIAObjectTranslator convertStorefrontToPigeon:storefront]; | |
| return [FIAObjectTranslator convertStorefrontToPigeon:storefront]; |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, should be a reported error.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/transactionMaps/transactions?
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should have a nil check here since addObject will crash if you try to send it a nil.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is working with a dictionary argument. Did we plan on moving this over to a class at some point? Maybe a class pigeon generates?
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please revert these. xcode does this automatically, it's annoying