В моем Podfile
я использую SwiftyStoreKit (0.15.0)
:
pod 'SwiftyStoreKit'
В моем приложении используется банку с советами для IAP, поэтому я использую только Consumable
.
Я отправил свое приложение в App Store сегодня утром и получил отказ, в котором говорилось, что они не могут сделать IAP при попытке сделать Consumable
покупку (совет).
Во время тестирования в качестве тестера песочницы, когда я проверял покупку, я постоянно получал ошибку: "Unknown error. Please contact support"
:
SwiftyStoreKit.purchaseProduct(product, quantity: 1, atomically: true) { result in
switch result {
case .success(let product):
// fetch content from your server, then:
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
print("Purchase Success: \(product.productId)")
case .error(let error):
switch error.code {
case .unknown:
print("Unknown error. Please contact support")
// failed cases ...
}
}
При дальнейшей проверке, хотя у меня был этот код ниже в AppDelegate, closure
никогда не вызывается. Это необходимо, этот код запускается один раз в AppDelegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Doesn't enter closure
SwiftyStoreKit.completeTransactions(atomically: true) {
// *** it never reaches this point ***
(purchases) in
for purchase in purchases {
switch purchase.transaction.transactionState {
case .purchased, .restored:
if purchase.needsFinishTransaction {
// Deliver content from server, then:
let downloads = purchase.transaction.downloads
SKPaymentQueue.default().start(downloads)
SwiftyStoreKit.finishTransaction(purchase.transaction)
}
// Unlock content
case .failed, .purchasing, .deferred:
break // do nothing
}
}
}
return true
}
Мой адрес электронной почты тестировщика песочницы подтвержден, я вышел из устройства как настоящий я, я вошел в систему на устройстве как тестер песочницы, я вошел в iCloud как тестер песочницы.
По какой причине замыкание не вводится в AppDelegate?
Вот код из vc, который я использую для покупки Consumable
:
var dataSource = [Tip]()
var sharedSecret = appStoreConnectSecretKey
let inAppProductIds = ["com.myCo.myAppName.firstTip", // 0.99
"com.myCo.myAppName.secondTip", // 9.99 ]
override func viewDidLoad() {
super.viewDidLoad()
getInAppPurchaseAmounts()
}
func getInAppPurchaseAmounts() {
// show spinner
let dispatchGroup = DispatchGroup()
for productId in inAppProductIds {
dispatchGroup.enter()
SwiftyStoreKit.retrieveProductsInfo([productId]) { [weak self](result) in
if let product = result.retrievedProducts.first {
let priceString = product.localizedPrice!
print("Product: \(product.localizedDescription), price: \(priceString)")
let tip = Tip(displayName: product.description,
description: product.localizedDescription,
productId: productId
price: priceString)
self?.addTipToDataSource(tip)
if let sharedSecret = self?.sharedSecret {
self?.verifyPurchase(with: productId, sharedSecret: sharedSecret)
}
dispatchGroup.leave()
} else if let invalidProductId = result.invalidProductIDs.first {
print("Invalid product identifier: \(invalidProductId)")
dispatchGroup.leave()
} else {
print("Error: \(String(describing: result.error))")
dispatchGroup.leave()
}
}
}
dispatchGroup.notify(queue: .global(qos: .background)) { [weak self] in
DispatchQueue.main.async { [weak self] in
// removeSpinnerAndReloadData()
}
}
}
func verifyPurchase(with productId: String, sharedSecret: String) {
let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: sharedSecret)
SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
switch result {
case .success(let receipt):
let productId = productId
// Verify the purchase of Consumable or NonConsumable
let purchaseResult = SwiftyStoreKit.verifyPurchase(
productId: productId,
inReceipt: receipt)
switch purchaseResult {
case .purchased(let receiptItem):
print("\(productId) is purchased: \(receiptItem)")
case .notPurchased:
print("The user has never purchased \(productId)")
}
case .error(let error):
print("Receipt verification failed: \(error)")
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? TipCell else { return }
guard let indexPath = collectionView.indexPath(for: cell) else { return }
let tip = dataSource[indexPath.item]
purchaseProduct(with: tip.productId)
}
func purchaseProduct(with productId: String) {
SwiftyStoreKit.retrieveProductsInfo([productId]) { result in
if let product = result.retrievedProducts.first {
SwiftyStoreKit.purchaseProduct(product, quantity: 1, atomically: true) { result in
switch result {
case .success(let product):
// fetch content from your server, then:
if product.needsFinishTransaction {
SwiftyStoreKit.finishTransaction(product.transaction)
}
print("Purchase Success: \(product.productId)")
case .error(let error):
switch error.code {
case .unknown:
print("Unknown error. Please contact support")
case .clientInvalid:
print("Not allowed to make the payment")
case .paymentCancelled:
print("Payment cancelled")
case .paymentInvalid:
print("The purchase identifier was invalid")
case .paymentNotAllowed:
print("The device is not allowed to make the payment")
case .storeProductNotAvailable:
print("The product is not available in the current storefront")
case .cloudServicePermissionDenied:
print("Access to cloud service information is not allowed")
case .cloudServiceNetworkConnectionFailed:
print("Could not connect to the network")
case .cloudServiceRevoked:
print("User has revoked permission to use this cloud service")
default:
print((error as NSError).localizedDescription)
}
}
}
}
}
}
Xcode 11.5 and swift 5
. Также используетсяSwiftyStoreKit
последняя версия0.15.0
- person Zubair Ahmed   schedule 24.06.2020Settings > Your Username (AppleID, iCloud, iTunes & App Store) > iTunes & App Store > SANDBOX ACCOUNT
— этот Apple ID должен быть тем, что вы создали в AppStoreConnect для электронной почты песочницы. Убедитесь, что вы входите в свой iPhone и iCloud как один и тот же тестер песочницы для любого тестера песочницы электронной почты APP ID, который вы создали в AppStoreConnect. Опять же, это расплывчато, но я считаю, что именно так я заставил все работать правильно. - person Lance Samaria   schedule 03.05.2021