Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public class InAppPurchasePlugin: NSObject, FlutterPlugin, InAppPurchaseAPI {
registrar.addMethodCallDelegate(instance, channel: channel)
registrar.addApplicationDelegate(instance)
SetUpInAppPurchaseAPI(messenger, instance)
if #available(iOS 15.0, *) {
InAppPurchase2APISetup.setUp(binaryMessenger: messenger, api: instance)
Copy link
Contributor

Choose a reason for hiding this comment

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

InAppPurchaseStoreKit2APISetup

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

}
}

// This init is used for tests
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@available(iOS 15.0, macOS 12.0, *)
extension InAppPurchasePlugin: InAppPurchase2API {
// MARK: - Pigeon Functions

// Wrapper method around StoreKit2's canMakePayments() method
// https://developer.apple.com/documentation/storekit/appstore/3822277-canmakepayments
func canMakePayments() throws -> Bool {
return AppStore.canMakePayments
}

// Wrapper method around StoreKit2's products() method
// https://developer.apple.com/documentation/storekit/product/3851116-products
func products(
identifiers: [String], completion: @escaping (Result<[SK2ProductMessage], any Error>) -> Void
) {
Task {
do {
let products = try await Product.products(for: identifiers)
let productMessages = products.map { product in
product.convertToPigeon()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

products.map { $0.convertToPigeon() }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

completion(.success(productMessages))
} catch {
completion(
.failure(
PigeonError(
code: "storekit2_products_error",
message: error.localizedDescription,
details: error.localizedDescription)))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import Foundation
import StoreKit

@available(iOS 15.0, macOS 12.0, *)
extension Product {
func convertToPigeon() -> SK2ProductMessage {
Copy link
Contributor

Choose a reason for hiding this comment

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

var pigeonMessage: SK2ProductMessage {
  return ...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done


return SK2ProductMessage(
id: id,
displayName: displayName,
description: description,
price: NSDecimalNumber(decimal: price).doubleValue,
displayPrice: displayPrice,
type: type.convertToPigeon(),
subscription: subscription?.convertToPigeon(),
priceLocale: priceFormatStyle.locale.convertToPigeon()
)
}
}

extension SK2ProductMessage: Equatable {
static func == (lhs: SK2ProductMessage, rhs: SK2ProductMessage) -> Bool {
return lhs.id == rhs.id && lhs.displayName == rhs.displayName
&& lhs.description == rhs.description && lhs.price == rhs.price
&& lhs.displayPrice == rhs.displayPrice && lhs.type == rhs.type
&& lhs.subscription == rhs.subscription && lhs.priceLocale == rhs.priceLocale
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.ProductType {
func convertToPigeon() -> SK2ProductTypeMessage {
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

switch self {
case Product.ProductType.autoRenewable:
return SK2ProductTypeMessage.autoRenewable
case Product.ProductType.consumable:
return SK2ProductTypeMessage.consumable
case Product.ProductType.nonConsumable:
return SK2ProductTypeMessage.nonConsumable
case Product.ProductType.nonRenewable:
return SK2ProductTypeMessage.nonRenewable
default:
fatalError("An unknown ProductType was passed in")
}
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.SubscriptionInfo {
func convertToPigeon() -> SK2SubscriptionInfoMessage {
return SK2SubscriptionInfoMessage(
promotionalOffers: promotionalOffers.map({ $0.convertToPigeon() }),
subscriptionGroupID: subscriptionGroupID,
subscriptionPeriod: subscriptionPeriod.convertToPigeon())
}
}

extension SK2SubscriptionInfoMessage: Equatable {
static func == (lhs: SK2SubscriptionInfoMessage, rhs: SK2SubscriptionInfoMessage) -> Bool {
return lhs.promotionalOffers == rhs.promotionalOffers
&& lhs.subscriptionGroupID == rhs.subscriptionGroupID
&& lhs.subscriptionPeriod == rhs.subscriptionPeriod
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.SubscriptionOffer {
func convertToPigeon() -> SK2SubscriptionOfferMessage {
return SK2SubscriptionOfferMessage(
/// ID is always `nil` for introductory offers and never `nil` for other offer types.
id: id,
price: NSDecimalNumber(decimal: price).doubleValue,
type: type.convertToPigeon(),
period: period.convertToPigeon(),
periodCount: Int64(periodCount),
paymentMode: paymentMode.convertToPigeon()
)
}
}

extension SK2SubscriptionOfferMessage: Equatable {
static func == (lhs: SK2SubscriptionOfferMessage, rhs: SK2SubscriptionOfferMessage) -> Bool {
return lhs.id == rhs.id && lhs.price == rhs.price && lhs.type == rhs.type
&& lhs.period == rhs.period && lhs.periodCount == rhs.periodCount
&& lhs.paymentMode == rhs.paymentMode
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.SubscriptionOffer.OfferType {
func convertToPigeon() -> SK2SubscriptionOfferTypeMessage {
switch self {
case .introductory:
return SK2SubscriptionOfferTypeMessage.introductory
case .promotional:
return SK2SubscriptionOfferTypeMessage.promotional
default:
fatalError("An unknown OfferType was passed in")
}
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.SubscriptionPeriod {
func convertToPigeon() -> SK2SubscriptionPeriodMessage {
return SK2SubscriptionPeriodMessage(
value: Int64(value),
unit: unit.convertToPigeon())
}
}

extension SK2SubscriptionPeriodMessage: Equatable {
static func == (lhs: SK2SubscriptionPeriodMessage, rhs: SK2SubscriptionPeriodMessage) -> Bool {
return lhs.value == rhs.value && lhs.unit == rhs.unit
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.SubscriptionPeriod.Unit {
func convertToPigeon() -> SK2SubscriptionPeriodUnitMessage {
switch self {
case .day:
return SK2SubscriptionPeriodUnitMessage.day
case .week:
return SK2SubscriptionPeriodUnitMessage.week
case .month:
return SK2SubscriptionPeriodUnitMessage.month
case .year:
return SK2SubscriptionPeriodUnitMessage.year
@unknown default:
fatalError("unknown SubscriptionPeriodUnit encountered")
}
}
}

@available(iOS 15.0, macOS 12.0, *)
extension Product.SubscriptionOffer.PaymentMode {
func convertToPigeon() -> SK2SubscriptionOfferPaymentModeMessage {
switch self {
case .freeTrial:
return SK2SubscriptionOfferPaymentModeMessage.freeTrial
case .payUpFront:
return SK2SubscriptionOfferPaymentModeMessage.payUpFront
case .payAsYouGo:
return SK2SubscriptionOfferPaymentModeMessage.payAsYouGo
default:
fatalError("Encountered an unknown PaymentMode")
}
}
}

extension Locale {
func convertToPigeon() -> SK2PriceLocaleMessage {
return SK2PriceLocaleMessage(
currencyCode: currencyCode ?? "",
currencySymbol: currencySymbol ?? ""
)
}
}

extension SK2PriceLocaleMessage: Equatable {
static func == (lhs: SK2PriceLocaleMessage, rhs: SK2PriceLocaleMessage) -> Bool {
return lhs.currencyCode == rhs.currencyCode && lhs.currencySymbol == rhs.currencySymbol
}
}
Loading