My app retains getting rejected as a result of the acquisition button does not work. It really works completely high quality after I examined it with the xcode simulator and in addition on actual gadget. I did get the App Retailer buy window poped up. Nevertheless, after I examined it with TestFlight it certainly does not reply.
I’ve said I am utilizing StoreKit2 and does not have to validate receipt so I do not really feel the rule of thumb is useful. Beneath is my code. It is simply one-click to set off product buy. Any concept why it really works properly however not for TestFlight nor Apple reviewers?
Button(motion: {
Job { attempt await storeManager.buy() }
}) {
Textual content("Proceed")
}
import Basis
import StoreKit
let productIDs = ["my_product_1", "my_product_2"]
class StoreManager: ObservableObject {
static let shared = StoreManager()
@Revealed var storeProducts: [Product] = []
@Revealed var purchasedProducts: Set<Product> = []
var transacitonListener: Job<Void, Error>? = nil
init() {
transacitonListener = listenForTransactions()
Job {
await loadProducts()
await updateCurrentEntitlements()
}
}
func getProduct(index: Int) -> Product? {
for product in storeProducts {
if product.id == productIDs[index] {
return product
}
}
return nil
}
func getProductPrice() -> String {
if let product = getProduct(index: 0) {
return product.displayPrice
}
return "4.99 USD"
}
func getProductPriceOrigin() -> String {
if let product = getProduct(index: 1) {
return product.displayPrice
}
return "9.99 USD"
}
func isPurchased() -> Bool {
return purchasedProducts.comprises { $0.id == productIDs[0] }
}
@MainActor
func buy() async throws -> Transaction? {
log("enter")
let product: Product? = getProduct(index: 0)
if product == nil {
log("product nil")
return nil
}
log("earlier than buy")
let outcome = attempt await product!.buy()
log("after buy")
change outcome {
case let .success(.verified(transaction)):
purchasedProducts.insert(product!)
await transaction.end()
log("success")
return transaction
case let .success(.unverified(_, error)):
print("buy.success.unverified:", error)
log("success unverified")
break
case .pending:
log("pending")
break
case .userCancelled:
log("userCancelled")
break
default:
log("default")
break
}
return nil
}
@MainActor
non-public func loadProducts() async {
do {
storeProducts = attempt await Product.merchandise(for: productIDs)
} catch {
print("Didn't load product (productIDs):", error)
}
}
non-public func listenForTransactions() -> Job < Void, Error > {
return Job.indifferent {
for await lead to Transaction.updates {
await self.handleTransaction(transactionVerification: outcome)
}
}
}
non-public func updateCurrentEntitlements() async {
for await lead to Transaction.currentEntitlements {
await self.handleTransaction(transactionVerification: outcome)
}
}
@MainActor
non-public func handleTransaction(transactionVerification outcome: VerificationResult <Transaction>) async {
change outcome {
case let.verified(transaction):
guard
let product = self.storeProducts.first(the place: {
$0.id == transaction.productID
})
else {
return
}
self.purchasedProducts.insert(product)
await transaction.end()
default:
return
}
}
@MainActor
func restore() async throws {
attempt await AppStore.sync()
}
}