Initial commit

This commit is contained in:
oscarz
2024-08-12 10:49:20 +08:00
parent 3002510aaf
commit 00fd0adf89
331 changed files with 53210 additions and 130 deletions

View File

@ -6,13 +6,197 @@
//
import SwiftUI
import StoreKit
struct IAPTestView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
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()
}