您好,我一直在App Store上发布我的App,因为他们一直坚持我的应用内购买设置不正确。
在沙盒中对它们进行自我测试后,一切正常。
这是他们发送给我的消息,我在下面粘贴了我的代码。
感谢您抽出宝贵的时间来帮助我!
指南2.1-性能-应用完整性
我们发现您的应用内购买产品存在一个或多个错误 在运行Wi-Fi且运行iOS 12的iPhone和iPad上进行了审查。
具体来说,您的应用内购买按钮不起作用。
后续步骤
验证服务器上的收据时,您的服务器需要能够 处理生产签名的应用程序,从苹果公司获得收据 测试环境。推荐的方法适合您的生产 服务器始终根据生产App Store验证收据 第一。如果验证失败,并显示错误代码“已使用沙盒收据 在生产中”,您应该针对测试环境进行验证 代替。
class IAPService: NSObject {
private override init() {}
static let shared = IAPService()
var products = [SKProduct]()
let paymentQueue = SKPaymentQueue.default()
func getProducts() {
let products: Set = [IAPProduct.consumable.rawValue,
IAPProduct.nonConsumable.rawValue]
let request = SKProductsRequest(productIdentifiers: products)
request.delegate = self
request.start()
paymentQueue.add(self)
}
func purchase(product: IAPProduct) {
for p in products {
if p.productIdentifier == product.rawValue {
let payment = SKPayment(product: p)
paymentQueue.add(payment)
print("Adding product to payment queue")
}
}
}
func restorePurchase() {
print("Restoring purchases")
paymentQueue.restoreCompletedTransactions()
}
func givePurchasedProduct(productID: String) {
if productID.range(of: "Zap") != nil {
NotificationCenter.default.post(name: Notification.Name.init("zapPurchased"), object: nil)
} else if productID.range(of: "Ads") != nil {
NotificationCenter.default.post(name: Notification.Name.init("noAdsPurchased"), object: nil)
}
}
}
extension IAPService: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
self.products = response.products
for product in response.products {
print(product.localizedTitle)
}
}
}
extension IAPService: SKPaymentTransactionObserver {
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
print(transaction.transactionState.status(), transaction.payment.productIdentifier)
switch transaction.transactionState {
case .purchasing, .deferred: break // do nothing
case .purchased:
queue.finishTransaction(transaction)
givePurchasedProduct(productID: transaction.payment.productIdentifier)
case .restored:
self.restorePurchase()
queue.finishTransaction(transaction)
case .failed:
queue.finishTransaction(transaction)
}
}
}
}
extension SKPaymentTransactionState {
func status() -> String {
switch self {
case .deferred:
return "deferred"
case .failed:
return "failed"
case .purchased:
return "purchased"
case .purchasing:
return "purchasing"
case .restored:
return "restored"
}
}
}
答案 0 :(得分:2)
对于苹果,应用程序审查非常严格。从经验上来讲,我遇到过很多次这个问题。在执行givePurchasedProduct
函数之前,您的代码对我来说似乎还不错。
好的,我注意到了:
return "purchased"
case .purchased:
,则我们调用GivePurchasedProduct 关于您的功能。您可以分开购买,以查看是 Zap 购买还是要删除广告
但是。这行让我感到困惑-最近介绍range
时为什么要使用contains
。
if productID.contains("Zap") {
// No Zapp? it has to be Ads then
NotificationCenter.default.post(name: Notification.Name.init("zapPurchased"), object: nil)
} else {
NotificationCenter.default.post(name: Notification.Name.init("noAdsPurchased"), object: nil)
}
旁注。您可能已经忘记了:
import Foundation
还有更多。 Receipt Validating
令人头疼,但是需要时。这是您的应用程序的放松和更高的安全性。
如果您要验证收据。这些问题及其答案对我有很大帮助。请参阅:
奖金。使用SwiftyStoreKit
。收据验证就像点击一个按钮一样:
使用此方法(可选)刷新收据并一步执行验证。
let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "your-shared-secret")
SwiftyStoreKit.verifyReceipt(using: appleValidator, forceRefresh: false) { result in
switch result {
case .success(let receipt):
print("Verify receipt success: \(receipt)")
case .error(let error):
print("Verify receipt failed: \(error)")
}
}
现在,现在。对审阅者,购买的内容没有交付。因此,他们认为这是购买验证。
您如何验证购买?提供内容?请更新您的问题。我敢肯定我会帮忙的
祝你好运
答案 1 :(得分:0)
我认为您的iOS代码没有问题。他们从Apple的回应中说,您的服务器指向Apple InApp购买的生产环境,并验证从App内使用的Apple InApp购买的测试环境中收到的收据。
Apple有2个用于InApp购买的环境-测试和生产。两种环境的行为相同。当您在iPhone上运行该应用以进行质量检查或调试时进行测试时,该应用会连接到“测试”环境。使用测试环境时不会向您收取实际费用。但是生成的收据与实际生产环境中的收据几乎相同
现在,当您将应用程序提交存储时,它将自动从生产环境进行购买。向用户收费并生成实际收据。
我认为您的应用会将这些收据发送到服务器,并且您的服务器使用了错误的InApp服务器环境来验证收据。
在服务器上,请确保根据您的InApp购买收据正确选择了Apple InApp购买环境URL。如果您或您的团队正在测试应用程序,则服务器必须使用测试URL,而当应用程序提交到生产环境时,您的服务器必须使用InApp Purchase的生产URL。