Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
|
|
@ -0,0 +1,59 @@
|
|||
final class BillingPendingTransaction: NSObject, IBillingPendingTransaction {
|
||||
private var pendingTransaction: SKPaymentTransaction?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
SKPaymentQueue.default().add(self)
|
||||
}
|
||||
|
||||
deinit {
|
||||
SKPaymentQueue.default().remove(self)
|
||||
}
|
||||
|
||||
var status: TransactionStatus {
|
||||
let routeTransactions = SKPaymentQueue.default().transactions.filter {
|
||||
var isOk = !Subscription.legacyProductIds.contains($0.payment.productIdentifier) &&
|
||||
!Subscription.productIds.contains($0.payment.productIdentifier)
|
||||
if isOk && $0.transactionState == .purchasing {
|
||||
isOk = false
|
||||
Statistics.logEvent("Pending_purchasing_transaction",
|
||||
withParameters: ["productId" : $0.payment.productIdentifier])
|
||||
}
|
||||
return isOk
|
||||
}
|
||||
|
||||
if routeTransactions.count > 1 {
|
||||
pendingTransaction = routeTransactions.last
|
||||
routeTransactions.prefix(routeTransactions.count - 1).forEach {
|
||||
SKPaymentQueue.default().finishTransaction($0)
|
||||
}
|
||||
} else if routeTransactions.count == 1 {
|
||||
pendingTransaction = routeTransactions[0]
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
|
||||
switch pendingTransaction!.transactionState {
|
||||
case .purchasing, .failed:
|
||||
return .failed
|
||||
case .purchased, .restored, .deferred:
|
||||
return .paid
|
||||
}
|
||||
}
|
||||
|
||||
func finishTransaction() {
|
||||
guard let transaction = pendingTransaction else {
|
||||
assert(false, "There is no pending transactions")
|
||||
return
|
||||
}
|
||||
|
||||
SKPaymentQueue.default().finishTransaction(transaction)
|
||||
pendingTransaction = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension BillingPendingTransaction: SKPaymentTransactionObserver {
|
||||
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||
// Do nothing. Only for SKPaymentQueue.default().transactions to work
|
||||
}
|
||||
}
|
||||
121
iphone/Maps/Core/InappPurchase/Impl/InAppBilling.swift
Normal file
121
iphone/Maps/Core/InappPurchase/Impl/InAppBilling.swift
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
fileprivate struct BillingProduct: IBillingProduct {
|
||||
var productId: String {
|
||||
return product.productIdentifier
|
||||
}
|
||||
|
||||
var localizedName: String {
|
||||
return product.localizedTitle
|
||||
}
|
||||
|
||||
var price: NSDecimalNumber {
|
||||
return product.price
|
||||
}
|
||||
|
||||
var priceLocale: Locale {
|
||||
return product.priceLocale
|
||||
}
|
||||
|
||||
let product: SKProduct
|
||||
|
||||
init(_ product: SKProduct) {
|
||||
self.product = product
|
||||
}
|
||||
}
|
||||
|
||||
final class InAppBilling: NSObject, IInAppBilling {
|
||||
private var productsCompletion: ProductsCompletion?
|
||||
private var paymentCompletion: PaymentCompletion?
|
||||
private var productRequest: SKProductsRequest?
|
||||
private var billingProduct: BillingProduct?
|
||||
private var pendingTransaction: SKPaymentTransaction?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
SKPaymentQueue.default().add(self)
|
||||
}
|
||||
|
||||
deinit {
|
||||
productRequest?.cancel()
|
||||
productRequest?.delegate = nil
|
||||
SKPaymentQueue.default().remove(self)
|
||||
}
|
||||
|
||||
func requestProducts(_ productIds: Set<String>, completion: @escaping ProductsCompletion) {
|
||||
productsCompletion = completion
|
||||
productRequest = SKProductsRequest(productIdentifiers: productIds)
|
||||
productRequest!.delegate = self
|
||||
productRequest!.start()
|
||||
}
|
||||
|
||||
func makePayment(_ product: IBillingProduct, completion: @escaping PaymentCompletion) {
|
||||
guard let billingProduct = product as? BillingProduct else {
|
||||
assert(false, "Wrong product type")
|
||||
return
|
||||
}
|
||||
|
||||
paymentCompletion = completion
|
||||
self.billingProduct = billingProduct
|
||||
SKPaymentQueue.default().add(SKPayment(product: billingProduct.product))
|
||||
}
|
||||
|
||||
func finishTransaction() {
|
||||
guard let transaction = pendingTransaction else {
|
||||
assert(false, "You must call makePayment() first")
|
||||
return
|
||||
}
|
||||
|
||||
SKPaymentQueue.default().finishTransaction(transaction)
|
||||
billingProduct = nil
|
||||
pendingTransaction = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension InAppBilling: SKProductsRequestDelegate {
|
||||
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
let products = response.products.map { BillingProduct($0) }
|
||||
self?.productsCompletion?(products, nil)
|
||||
self?.productsCompletion = nil
|
||||
self?.productRequest = nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func request(_ request: SKRequest, didFailWithError error: Error) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.productsCompletion?(nil, error)
|
||||
self?.productsCompletion = nil
|
||||
self?.productRequest = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension InAppBilling: SKPaymentTransactionObserver {
|
||||
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||
guard let productId = billingProduct?.productId else { return }
|
||||
transactions.forEach {
|
||||
if ($0.payment.productIdentifier != productId) { return }
|
||||
self.pendingTransaction = $0
|
||||
|
||||
switch $0.transactionState {
|
||||
case .purchasing:
|
||||
break
|
||||
case .purchased:
|
||||
paymentCompletion?(.success, nil)
|
||||
break
|
||||
case .failed:
|
||||
if ($0.error?._code == SKError.paymentCancelled.rawValue) {
|
||||
paymentCompletion?(.userCancelled, $0.error)
|
||||
} else {
|
||||
paymentCompletion?(.failed, $0.error)
|
||||
}
|
||||
break
|
||||
case .restored:
|
||||
break
|
||||
case .deferred:
|
||||
paymentCompletion?(.deferred, nil)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue