Обзор Apple отклонил мое сообщение о покупках в приложении. Я не уверен, что делаю неправильноIOS

Программируем под IOS
Ответить
Anonymous
 Обзор Apple отклонил мое сообщение о покупках в приложении. Я не уверен, что делаю неправильно

Сообщение Anonymous »

Я не совсем понимаю, что делаю не так.
Вот каково было их сообщение:

Мы обнаружили, что в ваших продуктах, приобретаемых через приложение, обнаружена одна или несколько ошибок, которые ухудшают взаимодействие с пользователем. В частности, кнопка «Удалить рекламу» не работала. Ознакомьтесь с подробной информацией и ресурсами ниже и выполните следующие шаги.

а затем:

Дальнейшие шаги


При проверке квитанций на вашем сервере ваш сервер должен быть в состоянии обрабатывать производственную информацию. подписанное приложение получает квитанции из тестовой среды Apple. Рекомендуемый подход заключается в том, чтобы ваш рабочий сервер всегда сначала проверял поступления в рабочем магазине приложений. Если проверка завершается неудачей с кодом ошибки «Квитанция из песочницы, используемая в рабочей среде», вам следует вместо этого проверить ее в тестовой среде.

Вот вся моя покупка в приложении. класс

Код: Выделить всё

import StoreKit
import SystemConfiguration

class InAppPurchaseManager: NSObject, SKPaymentTransactionObserver, SKProductsRequestDelegate {

static let shared = InAppPurchaseManager()

var productRequest: SKProductsRequest?
var products: [SKProduct]!

override init() {
super.init()
SKPaymentQueue.default().add(self)
}

func unlockContent() {

adsRemoved = true
TitleScreen.shared.removeAdsButton.isHidden = true

GameViewController.shared.bannerView.isHidden = true
SavedSettings.shared.setAdsSettings()
}

func isInternetAvailable() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)

let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}

var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}

func fetchProducts() {
let productIdentifiers = Set(["remove_ads"])
productRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productRequest?.delegate = self
productRequest?.start()
}

func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.products = response.products
if let product = products.first {
print("Fetched product: \(product.productIdentifier)")
} else {
print("Failed to fetch product")
}
}

// These two methods below are to request a purchase/restore which are called from TitleScreen buttons "removeAdButton" and "restorePurchases"

func requestPurchase() {
if isInternetAvailable() {
if let product = InAppPurchaseManager.shared.products.first(where: { $0.productIdentifier == "remove_ads"  }) {
Task {
do {
try await InAppPurchaseManager.shared.purchase(product)
} catch {
print("Failed to initiate purchase: \(error)")
}
}
}
} else {
print("No internet connection available")
GameViewController.shared.showAlert(title: "Failure", message: "No internet connection available")
}
}

func restorePurchases() {
SKPaymentQueue.default().restoreCompletedTransactions()
}

func purchase(_ product: SKProduct) async throws {
print("request called")
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchased:

print("Transaction Successful: \(transaction.payment.productIdentifier)")

unlockContent()
verifyReceipt()
SKPaymentQueue.default().finishTransaction(transaction)

case .failed:

print("Transaction Failed: \(transaction.error?.localizedDescription ?? "Unknown error")")

SKPaymentQueue.default().finishTransaction(transaction)

case .restored:

print("Transaction Restored: \(transaction.payment.productIdentifier)")

unlockContent()
verifyReceipt()
SKPaymentQueue.default().finishTransaction(transaction)

case .deferred:
print("Transaction Deferred: \(transaction.payment.productIdentifier)")

default:
break
}
}
}

func refreshReceipt() {
let receiptRefreshRequest = SKReceiptRefreshRequest()
receiptRefreshRequest.start()
}

func verifyReceipt() {
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
do {
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
let receiptString = receiptData.base64EncodedString(options: [])
} catch {
print("Couldn't read receipt data with error: " + error.localizedDescription)
}
}
}
}
Я вызываю requestPurchase() с помощью кнопки SKSpriteNode из меню. Когда я тестирую его в песочнице, он запрашивает то, что должен, а затем правильно делает то, что должен. Я предполагаю, что проверка вообще не вызывает никаких подсказок, но я также подумал, что покупки в приложении не должны работать, пока они не будут одобрены и запущены в эксплуатацию? У меня также нет сервера для проверки квитанций, я предполагал, что StoreKit 2 проверяет на устройстве.
Если кто-то может помочь, я был бы очень признателен, я' Я сейчас понятия не имею.

Подробнее здесь: https://stackoverflow.com/questions/787 ... -what-im-d
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»