//
|
// StoreTransaction.swift
|
// ExplorerProject
|
//
|
// Created by 无故事王国 on 2024/4/1.
|
// Copyright © 2024 younger_times. All rights reserved.
|
//
|
|
import SwiftyStoreKit
|
import StoreKit
|
import HandyJSON
|
|
struct PurchaseModel:HandyJSON{
|
var environment: String?
|
var receipt:PurchaseReceiptModel?
|
var status: Int = 0
|
}
|
|
struct PurchaseReceiptModel:HandyJSON{
|
var adam_id: Int = 0
|
var app_item_id: Int = 0
|
var application_version: Int = 0
|
var bundle_id: String?
|
var download_id: Int = 0
|
var in_app = [PurchageInAppModel]()
|
var original_application_version: String?
|
var original_purchase_date: String?
|
var original_purchase_date_ms: Int = 0
|
var original_purchase_date_pst: String?
|
var receipt_creation_date: String?
|
var receipt_creation_date_ms: Int = 0
|
var receipt_creation_date_pst: String?
|
var receipt_type: String?
|
var request_date: String?
|
var request_date_ms: Int = 0
|
var request_date_pst: String?
|
var version_external_identifier: Int = 0
|
}
|
|
struct PurchageInAppModel:HandyJSON{
|
|
}
|
|
struct PurchaseResultModel:HandyJSON{
|
var environment: String?
|
var receipt: PurchaseReceipt?
|
var status: Int = 0
|
}
|
|
struct PurchaseReceipt:HandyJSON{
|
var adam_id: Int = 0
|
var app_item_id: Int = 0
|
var application_version: String?
|
var bundle_id: String?
|
var download_id: Int = 0
|
var in_app = [PurchaseInAPP]()
|
var original_application_version: String?
|
var original_purchase_date: String?
|
var original_purchase_date_ms: String?
|
var original_purchase_date_pst: String?
|
var receipt_creation_date: String?
|
var receipt_creation_date_ms: String?
|
var receipt_creation_date_pst: String?
|
var receipt_type: String?
|
var request_date: String?
|
var request_date_ms: String?
|
var request_date_pst: String?
|
var version_external_identifier: Int = 0
|
}
|
|
struct PurchaseInAPP:HandyJSON{
|
var in_app_ownership_type: String?
|
var is_trial_period: String?
|
var original_purchase_date: String?
|
var original_purchase_date_ms: String?
|
var original_purchase_date_pst: String?
|
var original_transaction_id: String?
|
var product_id: String?
|
var purchase_date: String?
|
var purchase_date_ms: String?
|
var purchase_date_pst: String?
|
var quantity: String?
|
var transaction_id: String?
|
|
}
|
|
class InPurchaseManager:NSObject{
|
|
private static var _sharedInstance: InPurchaseManager!
|
private var productList = Set<String>()
|
private(set) var products = Set<SKProduct>()
|
|
@discardableResult
|
public class func instance() -> InPurchaseManager {
|
guard let instance = _sharedInstance else {
|
_sharedInstance = InPurchaseManager()
|
return _sharedInstance!
|
}
|
return instance
|
}
|
|
func setProductList(_ list:Set<String>,clouse:@escaping (Set<SKProduct>)->Void){
|
productList = list
|
|
SwiftyStoreKit.retrieveProductsInfo(list) { result in
|
if result.retrievedProducts.count > 0 {
|
InPurchaseManager._sharedInstance.products = result.retrievedProducts
|
clouse(result.retrievedProducts)
|
}
|
}
|
}
|
|
func dismiss(){
|
InPurchaseManager._sharedInstance = nil
|
}
|
|
/// 购买
|
/// - Parameters:
|
/// - ID: ID值
|
/// - quantity: 购买数量
|
/// - applicationUsername: 购买用户名的唯一标识
|
class func purchaseProduct(ID:String,quantity:Int = 1,applicationUsername:String, completion: @escaping ( PurchaseResultModel) -> Void,errorClouse:@escaping (Error)->Void){
|
var purcahseProduct:SKProduct?
|
for product in _sharedInstance.products {
|
if product.productIdentifier == ID{
|
purcahseProduct = product;break
|
}
|
}
|
|
guard let product = purcahseProduct else {return}
|
var inSanbox:Bool = false
|
|
#if DEBUG
|
inSanbox = true
|
#endif
|
|
SwiftyStoreKit.completeTransactions { purchases in
|
if let product = purchases.first{
|
switch product.transaction.transactionState {
|
case .purchased:
|
alertSuccess(msg: "完成购买")
|
case .purchasing:
|
showHUD("购买中")
|
case .failed:
|
alertError(msg: "购买失败")
|
case .restored:
|
alertSuccess(msg: "恢复购买")
|
default:break
|
}
|
}
|
}
|
|
SwiftyStoreKit.purchaseProduct(product, quantity: quantity, atomically: true, applicationUsername: applicationUsername, simulatesAskToBuyInSandbox: false, paymentDiscount: nil) { result in
|
switch result {
|
case .success(let purchase):
|
var type:AppleReceiptValidator.VerifyReceiptURLType = .production
|
if inSanbox{
|
type = .sandbox
|
}
|
|
var recepit = AppleReceiptValidator(service: type, sharedSecret: nil)
|
SwiftyStoreKit.verifyReceipt(using: recepit) { result in
|
switch result {
|
case .success(let receipt):
|
if let model = PurchaseResultModel.deserialize(from: receipt){
|
completion(model)
|
}
|
break
|
case .error(let error):
|
errorClouse(error)
|
// print(error.localizedDescription)
|
}
|
}
|
case .error(let error):
|
// print(error.localizedDescription)
|
errorClouse(error)
|
}
|
}
|
}
|
|
/// 恢复购买
|
class func resotrePurchase(applicationUsername:String, completion: @escaping ( PurchaseResultModel) -> Void,errorClouse:@escaping (Error)->Void){
|
|
SwiftyStoreKit.completeTransactions { purchases in
|
if let product = purchases.first{
|
switch product.transaction.transactionState {
|
case .purchased:
|
alertSuccess(msg: "完成购买")
|
case .purchasing:
|
showHUD("购买中")
|
case .failed:
|
alertError(msg: "购买失败")
|
case .restored:
|
alertSuccess(msg: "恢复购买")
|
default:break
|
}
|
}
|
}
|
|
|
SwiftyStoreKit.restorePurchases(atomically: true, applicationUsername: applicationUsername) { result in
|
if result.restoreFailedPurchases.count > 0 {
|
//恢复失败
|
print("restore Failed:\(result.restoredPurchases)")
|
}else if result.restoredPurchases.count > 0 {
|
print("restore Success")
|
var inSanbox:Bool = false
|
|
#if DEBUG
|
inSanbox = true
|
#endif
|
var type:AppleReceiptValidator.VerifyReceiptURLType = .production
|
if inSanbox{
|
type = .sandbox
|
}
|
let recepit = AppleReceiptValidator(service: type, sharedSecret: nil)
|
SwiftyStoreKit.verifyReceipt(using: recepit) { result in
|
switch result {
|
case .success(let receipt):
|
if let model = PurchaseResultModel.deserialize(from: receipt){
|
completion(model)
|
}
|
break
|
case .error(let error):
|
errorClouse(error)
|
}
|
}
|
}else{
|
print("Nothing to Restore")
|
}
|
}
|
}
|
}
|