'In app purchases not selectable in appstoreconnect
My new app has four in app purchases (consumables) and I submitted the first version with these IAPs. These IAP's were marked as "Ready for Review". However, the app got rejected due to another reason, and when I uploaded a new build, I couldn't select these IAP's anymore in the app details page, even though they're still "Ready for Review": screenshot of the app details page
So after resubmitting a new version of the app for review, I got this rejection information:
We found that your in-app purchase products exhibited one or more bugs when reviewed on iPad running iOS 15.4 on Wi-Fi.
Specifically, we were not able to buy the in app purchases. The buttons did not react to taps
Next Steps
When validating receipts on your server, your server needs to be able to handle a production-signed app getting its receipts from Apple’s test environment. The recommended approach is for your production server to always validate receipts against the production App Store first. If validation fails with the error code "Sandbox receipt used in production," you should validate against the test environment instead.
I tested everything on Testflight before and all the IAP's were working fine. I know that prior to submitting an app with IAP's, these purchases have to be selected on the app details page, so I'm curious why I can't select them and if that's causing the issue.
Right when the app launches, in the AppDelegate, I fetch the products: IAPManager.shared.fetchProducts()
and the code for the IAPManager is as follows:
final class IAPManager: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
static let shared = IAPManager()
var products = [SKProduct]()
enum Product: String, CaseIterable {
case firstIdentifier = "com.fahrprueferCreate.tokens_1_1000"
case secondIdentifier = "com.FahrprueferCreate.tokens_5_4000"
case thirdIdentifier = "com.FahrprueferCreate.tokens_10_8000"
case fourthIdentifier = "com.FahrprueferCreate.tokens_20_15000"
var count: Int {
switch self {
case .firstIdentifier:
return 1
case .secondIdentifier:
return 5
case .thirdIdentifier:
return 10
case .fourthIdentifier:
return 20
}
}
}
private var completion: ((Int) -> Void)?
// Fetch Product Objects from Apple
func fetchProducts() {
let request = SKProductsRequest(productIdentifiers: Set(Product.allCases.compactMap({ $0.rawValue})))
request.delegate = self
request.start()
}
// Prompt a product payment transaction
public func purchase(product: Product, completion: @escaping ((Int) -> Void)) {
guard SKPaymentQueue.canMakePayments() else {
// Show some error here
return
}
guard let storeKitProduct = products.first(where: { $0.productIdentifier == product.rawValue }) else {
return
}
self.completion = completion
let payment = SKPayment(product: storeKitProduct)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
}
// Observe the transaction state
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
transactions.forEach({ transaction in
switch transaction.transactionState {
case.purchasing:
break
case .purchased:
if let product = Product(rawValue: transaction.payment.productIdentifier) {
completion?(product.count)
}
SKPaymentQueue.default().finishTransaction(transaction)
SKPaymentQueue.default().remove(self)
break
case .restored:
break
case .failed:
break
case .deferred:
break
@unknown default:
break
}
})
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.products = response.products
print("products: ", response.products)
}
func request(_ request: SKRequest, didFailWithError error: Error) {
guard request is SKProductsRequest else {
return
}
print("Product fetch request failed")
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
