Music_Player3/relax.offline.mp3.music/MP/Common/Tool(工具封装)/MP_IAPManager.swift
2024-12-25 10:02:00 +08:00

255 lines
10 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// MP_IAPManager.swift
// relax.offline.mp3.music
//
// Created by Mr.Zhou on 2024/7/29.
//
import UIKit
import SwiftyStoreKit
import StoreKit
///
class MP_IAPManager: NSObject {
///
static let shared = MP_IAPManager()
///ID
var productIdentifiers:[String] = ["1weekvip","1yearvip","lifetimevip"]
///
private var transactions:[PaymentTransaction] = []
///(ID)
private var productsRequest:SKProductsRequest?
///
private var availableProducts:Set<SKProduct> = []
///
private var showHUD:Bool = false
///VIP
var isVIP:Bool {
if let purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String], !purchasedProducts.isEmpty {
//VIP
return true
}else {
//VIP
guard let lastDate = UserDefaults.standard.object(forKey: "PurchaseVIPDate") as? Date, lastDate.timeIntervalSince(Date()) > 0 else { return false }
return true
}
}
override init() {
super.init()
}
deinit {
}
///
func observeVIPStoreKit() {
//
transactions.removeAll()
//
SwiftyStoreKit.completeTransactions { [weak self] purchases in
guard let self = self else { return }
var productId = ""
//
print("检索交易")
purchases.forEach { item in
switch item.transaction.transactionState {
case .purchased, .restored:///
//
if item.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(item.transaction)
}
//ID
productId = item.productId
//
self.transactions.append(item.transaction)
case .failed://
//
if item.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(item.transaction)
}
default:
break
}
}
//
if !productId.isEmpty {
//
print("当前用户有VIP记录,进行验证")
self.showHUD = false
self.purchaseVerificationProductVIP(with: productId)
}else {
//
print("当前用户非VIP")
}
}
if let purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String], !purchasedProducts.isEmpty {
restorePurchases(true)
}
}
///
func getVIPAllProducts() {
let productIds:Set<String> = Set(productIdentifiers)
SwiftyStoreKit.retrieveProductsInfo(productIds) { [weak self] results in
guard let self = self else { return }
//
if !results.retrievedProducts.isEmpty {
self.availableProducts = results.retrievedProducts
}
}
}
///
func purchaseProduct(with productId:String) {
showHUD = true
MP_HUD.loading()
//
if SwiftyStoreKit.canMakePayments {
//
MP_AnalyticsManager.shared.VIP_continue_clickAction(productId)
self.pruchaseProductVIP(with: productId)
}else {
//
MP_HUD.error("Sorry. Subscription purchase failed", delay: 1.0, completion: nil)
MP_AnalyticsManager.shared.VIP_buy_failureAction(productId, error: "The current project status is not supported")
}
}
///
func restorePurchases(_ isLaunch:Bool = false) {
if isLaunch == true {
showHUD = false
}else {
MP_HUD.loading()
showHUD = true
}
self.transactions.removeAll()
SwiftyStoreKit.restorePurchases(atomically: false) { [weak self] results in
guard let self = self else { return }
if !results.restoredPurchases.isEmpty, let productId = results.restoredPurchases.first?.productId {
//restore
self.transactions.append(contentsOf: results.restoredPurchases.map({$0.transaction}))
self.purchaseVerificationProductVIP(with: productId)
return
}
if !results.restoreFailedPurchases.isEmpty {
MP_HUD.error("Restore purchase failed", delay: 1.0, completion: nil)
return
}
MP_HUD.error("No purchase can be restored", delay: 1.0, completion: nil)
}
}
}
//MARK: -
extension MP_IAPManager {
///
private func pruchaseProductVIP(with productId:String) {
//
self.transactions.removeAll()
SwiftyStoreKit.purchaseProduct(productId, quantity: 1, atomically: false) { [weak self] (result) in
guard let self = self else { return }
switch result {
case .success(let product)://
print("VIP Purchase Successfully.")
//
self.transactions.append(product.transaction)
//
self.purchaseVerificationProductVIP(with: product.productId)
case .error(let error)://
MP_HUD.error("Sorry. Subscription purchase failed", delay: 1.0, completion: nil)
MP_AnalyticsManager.shared.VIP_buy_failureAction(productId, error: "The current project status is not supported")
print("VIP: \(error.localizedDescription)")
}
}
}
///
private func purchaseVerificationProductVIP(with productId:String) {
//
let receiptValidator = AppleReceiptValidator(service: checkIsSandbox() ? .sandbox:.production, sharedSecret: "d29627e4f78b4b50a0ce5166acd8aa9f")
SwiftyStoreKit.verifyReceipt(using: receiptValidator, forceRefresh: true) { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let receipt)://
print("VIP Receipt: \(receipt)")
//
if productId == "lifetimevip" {
//
let purchaseResult = SwiftyStoreKit.verifyPurchase(productId: productId, inReceipt: receipt)
switch purchaseResult {
case .purchased(let item):
print("VIP LifeTime verifyPurchase successed current item: \(item)")
//
let lifeDate = Date().addingTimeInterval(60 * 60 * 24 * 365 * 100)
//VIP
UserDefaults.standard.set(lifeDate, forKey: "PurchaseVIPDate")
UserDefaults.standard.synchronize()
//
self.showSuccessfullyHUD()
self.finishedAllTransactionsVIP()
case .notPurchased://
self.finishedAllTransactionsVIP()
self.showFailedHUD()
}
}else {
//
let purchaseResult = SwiftyStoreKit.verifySubscription(ofType: .autoRenewable, productId: productId, inReceipt: receipt)
switch purchaseResult {
case .purchased(let expiryDate, let items):
print("VIP \(productId) valid until \(expiryDate)")
UserDefaults.standard.set(expiryDate, forKey: "PurchaseVIPDate")
UserDefaults.standard.synchronize()
//
self.showSuccessfullyHUD()
self.finishedAllTransactionsVIP()
case .expired(let expiryDate, let items)://
self.finishedAllTransactionsVIP()
self.showFailedHUD()
case .notPurchased://
self.finishedAllTransactionsVIP()
self.showFailedHUD()
}
}
//
if let purchasedProducts = UserDefaults.standard.array(forKey: "PurchasedProducts") as? [String], !purchasedProducts.isEmpty {
print("清理旧版VIP信息")
UserDefaults.standard.set(nil, forKey: "PurchasedProducts")
}
case .error(let error)://
self.finishedAllTransactionsVIP()
self.showFailedHUD()
}
}
}
//
private func showSuccessfullyHUD() {
if showHUD == true {
MP_HUD.success("Successfully purchased", delay: 1.5, completion: nil)
}
}
//
private func showFailedHUD() {
if showHUD == true {
MP_HUD.error("Failed purchased", delay: 1.5, completion: nil)
}
}
//
private func finishedAllTransactionsVIP() {
self.transactions.forEach { item in
SwiftyStoreKit.finishTransaction(item)
}
self.transactions.removeAll()
}
private func checkIsSandbox() -> Bool {
var isSandbox = false
#if DEBUG
isSandbox = true
#endif
return isSandbox
}
}