Files
swiftGrammar/AIGrammar/GrammarSubView/IAPTestView.swift
2024-08-12 10:49:20 +08:00

203 lines
7.2 KiB
Swift
Raw Permalink 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.

//
// IAPTestView.swift
// AIGrammar
//
// Created by oscar on 2024/6/19.
//
import SwiftUI
import StoreKit
enum IAPProductTest: String, CaseIterable {
case premiumFeature1 = "grammar_1_month"
case premiumFeature2 = "grammar_1_week"
}
class IAPManagerTest: ObservableObject {
@Published var products: [Product] = []
@Published var purchasedProducts: [Product] = []
init() {
Task {
await requestProducts()
await updatePurchasedProducts()
await listenForTransactions()
}
}
func requestProducts() async {
do {
let products = try await Product.products(for: IAPProductTest.allCases.map { $0.rawValue })
DispatchQueue.main.async {
//
self.products = products
//
for product in self.products {
print("--------------------------")
print("Product ID: \(product.id)")
print("Product Title: \(product.displayName)")
print("Product Description: \(product.description)")
print("Product Price: \(product.price)")
print("Product displayPrice: \(product.displayPrice)")
print("Product priceFormatStyle: \(product.priceFormatStyle)")
print("Product subscriptionPeriodFormatStyle: \(product.subscriptionPeriodFormatStyle)")
print("Product subscriptionPeriodUnitFormatStyle: \(product.subscriptionPeriodUnitFormatStyle)")
print("--------------------------")
}
}
} catch {
print("Failed to fetch products: \(error.localizedDescription)")
}
}
func buy(product: Product) async {
do {
let uuid = UUID()
let token = Product.PurchaseOption.appAccountToken(uuid)
print("purchase appAccountToken: \(uuid.uuidString)")
let result = try await product.purchase(options: [token])
switch result {
case .success(let verification):
if case .verified(let transaction) = verification {
// listenForTransactions
//
print("Purchase initiated for product: \(product.id)")
}
case .userCancelled:
print("User cancelled the purchase.")
case .pending:
print("Purchase is pending.")
default:
break
}
} catch {
print("Failed to purchase product: \(error.localizedDescription)")
}
}
func updatePurchasedProducts() async {
for await result in Transaction.currentEntitlements {
if case .verified(let transaction) = result {
if let product = products.first(where: { $0.id == transaction.productID }) {
DispatchQueue.main.async {
self.purchasedProducts.append(product)
}
}
}
}
}
func listenForTransactions() async {
for await transactionResult in Transaction.updates {
if case .verified(let transaction) = transactionResult {
if let product = products.first(where: { $0.id == transaction.productID }) {
DispatchQueue.main.async {
self.purchasedProducts.append(product)
}
}
//
print("Transaction ID: \(transaction.id)")
print("Product ID: \(transaction.productID)")
print("Purchase Date: \(transaction.purchaseDate)")
//print("Transaction State: \(transaction.revocationReason ?? "None")")
//print("Original Transaction ID: \(transaction.originalID ?? "None")")
//
// jsonRepresentation
let jsonData = try transaction.jsonRepresentation
// Data String
if let jsonString = String(data: jsonData, encoding: .utf8) {
print("Transaction Receipt: \(jsonString)")
} else {
print("Failed to convert JSON data to string.")
}
await transaction.finish()
}
}
}
func restorePurchases() async {
do {
try await AppStore.sync()
await updatePurchasedProducts()
print("Purchases restored")
} catch {
print("Failed to restore purchases: \(error.localizedDescription)")
}
}
}
struct IAPTestView: View {
@StateObject var iapManager = IAPManager()
//@StateObject var iapManager = IAPManagerTest()
var body: some View {
VStack(spacing: 20) {
if iapManager.products.isEmpty {
Text("Loading products...")
} else {
ForEach(iapManager.products, id: \.id) { product in
VStack {
Text(product.displayName)
.font(.title)
Button("Buy \(product.displayName)") {
Task {
await iapManager.buy(product: product){ result in
switch result {
case .success(let message):
logger.info("succ")
case .failure(let error):
logger.error("error")
}
}
}
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
Button("Restore Purchases") {
Task {
await iapManager.restorePurchases(){ result in
switch result {
case .success(let message):
logger.info("restore purchase succ. message: \(message)")
case .failure(let error):
logger.error("restore purchase error. message: \(error)")
}
}
}
}
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.onAppear {
Task {
//await iapManager.requestProducts()
}
}
}
}
#Preview {
IAPTestView()
}