创建 时SKStoreProductViewController,我传递一个带有商店标识符参数的字典。:
@{ SKStoreProductParameterITunesItemIdentifier : @010101010 };
Run Code Online (Sandbox Code Playgroud)
该值应该是NSNumber(如上所示):
与此键关联的值是 NSNumber 的实例,代表您希望商店在呈现视图控制器时显示的项目的 iTunes 标识符。
但当我将值作为字符串传递时,它可以毫无怨言地工作:
@{ SKStoreProductParameterITunesItemIdentifier : @"010101010" };
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?是否NSNumber根据给定的字符串自动创建正确的数字类型?这是发生在StoreKit 中NSNumber还是 StoreKit 正在这样做?
有谁知道在应用程序加载时检查用户是否已经购买订阅的简单方法?
我只需要检查用户是否已经购买了订阅,不需要其他任何东西。看起来很容易,但实际上并不容易,因为我需要验证收据并检查订阅日期......订阅验证技术似乎不是一件容易的任务,我没有找到好的教程或好的指南描述了如何逐步实施它。我在这里阅读了Apple文档 是否有任何简单的本地收据验证和订阅验证技术来检查用户是否订阅?
也许有人知道一个框架或一种快速完成它的方法?任何帮助表示赞赏。
使用:Swift 4、Xcode 9.4
我目前正在开发的应用程序混合了非消耗性产品和自动更新订阅。看起来一两天后,购买的非消耗性产品将从沙盒收据中删除。恢复后,产品由 StoreKit 观察者回调提供,但收据中仍然缺少它们。
我已经尝试过通过 OpenSSL 进行本地验证和解析,以及通过 Apple 服务器进行远程验证,结果匹配:这些产品总是丢失。请注意,订阅永远不会发生这种情况,收据中始终存在过期和有效的订阅。另一个有趣的细节:产品不会一下子全部丢失,它们会随着采购订单逐渐消失,因为沙盒测试用户正在被“清理”。
由于 Apple 文档 在这里 声明“非消耗品、自动续订订阅项目和非续订订阅项目无限期地保留在收据中”,我希望它们在那里。
有人知道这是否是预期的沙箱行为吗?是否有任何官方的 Apple 资源说明一旦应用程序投入生产就可以了?
编辑:在此处的开发论坛中找到了某人发布的完全相同的问题。
我正在实现自动续订订阅,其中 IAP 收据被发送到我们的服务器,然后通过 Apple 的服务器(服务器到服务器)进行验证。
我注意到自动续订交易仍在添加到我的设备中SKPaymentQueue。不过,我已经将收据数据发送到我的服务器,所以我想跳过这些交易,因为我的服务器正在轮询/从 Apple 获取回调来管理用户订阅状态。有没有办法做到这一点?
或者我不应该跳过这些交易并在每次在队列中收到新交易时发送收据数据,即使它只是自动续订。
我已经为使用 SwiftUI 创建的独立 WatchOS 应用程序实现了应用程序内购买,但是,我找不到有关在 Apple Watch 的沙盒环境中测试 StoreKit 功能的资源。
当我在手表 App Store 上登录我的普通 Apple ID 或根本没有 Apple ID 时,我在手表上收到以下提醒:
无法购买应用
在 iPhone 上的 Apple Watch 应用中使用您的 Apple ID 登录。
我收到以下错误:
SKErrorDomain 错误 0。
有谁知道如何将沙盒测试帐户用于独立的 Apple Watch 应用程序?任何帮助,将不胜感激。
在 www.raywenderlich.com App Store Review 教程Requesting App Ratings and Reviews Tutorial for iOS中,作者 (Sanket Firodiya) 表示 Apple 实施了某些限制:
我正在写关于第三个限制的文章。该教程似乎说 Apple 强制执行该版本限制,但教程的示例代码也执行了该强制操作(Apple 的示例代码也是如此)。我相信在调用之前进行版本测试requestReview很容易导致没有评级请求。正如我在下面解释的那样,如果苹果公司进行了这项测试会更好,但是他们这样做了吗?
细节:
在请求应用程序商店评论中,Apple 表示我们应该对[SKStoreReviewController requestReview]每个应用程序版本只执行一次,并且 Apple 的示例代码在调用之前包含版本测试requestReview。此外,我们还被告知,requestReview对话框的出现次数每年不得超过 3 次。因此,如果特定的调用requestReview导致没有对话框,则将不再有调用requestReview(直到版本更改),因此该版本绝对不会有评级对话框。当版本更改时,似乎不太可能出现审阅对话框(除非第一次调用显示requestReview对话框)。
这很令人困惑。由于 Calling 的版本限制requestReview,每年 3 次的限制似乎毫无用处,或者至少是过度的。由于这两个相互冲突的限制,即使发布了新版本,用户也可能永远不会看到审阅对话框。但是,我知道事实并非如此。所以,我相信苹果测试当前版本的示例代码是不正确的。苹果强制实施这一限制更有意义,因为他们知道是否出现对话框。
如果API返回一个布尔值来指示对话框是否出现,那么只有对话框出现时我们才能保存版本号。我想知道Apple是否在SDK中这样做了。
我了解苹果关于何时发出请求的其他建议,例如等待用户参与、不中断活动等。这个问题仅涉及与应用程序版本有关的限制。
我是否应该实施版本限制?如果我进行该测试,我怎么能期望出现一个对话框呢?也许,第一次调用requestReview总是会导致审核对话框(如果不是一年内的第三次调用)——是吗?
顺便说一句,我不是第一个有这种担忧的人。请参阅forums.raywenderlich.com。
杰夫
我正在尝试在我的应用程序中添加应用程序内购买。我能够加载产品,在设备中显示和测试它们。当我单击购买选项时,我确实收到了输入凭据并在沙盒环境中确认购买的提醒[下面的屏幕截图]。但我在控制台中没有看到 paymentQueue 方法的任何显示。谁能让我知道我在这里缺少什么。下面是代码中的几行:
谢谢。
import UIKit
import StoreKit
class testing: NSObject {
private var productIds : Set<String> = []
@objc private(set) var productsArray = [SKProduct]()
func getProducts() {
productIds = ["xxxxx", "yyyyy"]
let request = SKProductsRequest(productIdentifiers: productIds)
request.delegate = self
request.start()
}
func purchase(product: String) {
guard SKPaymentQueue.canMakePayments() else {
return
}
guard SKPaymentQueue.default().transactions.last?.transactionState != .purchasing else {
return
}
guard let productToPurchase = productsArray.filter({$0.productIdentifier == product}).first else {return}
print(productToPurchase.localizedTitle)
let payment = SKPayment(product: productToPurchase)
SKPaymentQueue.default().add(payment)
}
func restorePurchases(){
print("calling …Run Code Online (Sandbox Code Playgroud) 我在新的 iOS 应用程序中使用StoreKit2来处理应用程序内订阅购买。我想支持在应用程序中兑换优惠代码,但我不知道如何使用 StoreKit2 实现这一点。
是否有相当于原始 StoreKit 的SKPaymentQueue.presentCodeRedemptionSheet()的 StoreKit2 ?
我在文档中没有看到任何专门处理优惠代码的内容。虽然有这样的:
static func promotionalOffer(offerID: String, keyID: String, nonce: UUID, signature: Data, timestamp: Int) -> Product.PurchaseOption
Run Code Online (Sandbox Code Playgroud)
我的理解是,促销优惠与优惠代码是分开的。
感谢任何人提供的有关如何允许使用 StoreKit2 在应用程序内兑换优惠代码的任何指示。我假设我不应该包含原始 StoreKit 以及 StoreKit2 并调用旧的 API,对吗?
我试图从 using 中获取产品App Store Connect,StoreKit 2但总是返回一个空数组:
let keys = [
"com.app.suscripcion.mes.1"
]
let storeProducts = try await Product.products(for: keys)
Run Code Online (Sandbox Code Playgroud)
我在该部分添加了一个键InApp Purchase:
我需要做什么才能从 获取产品App Store Connect?如果我使用.storekit配置文件,它可以工作,但在真实场景中则不起作用
使用 StoreKit 2 API 完成购买并收到成功且经过验证的 后Product.PurchaseResult,本地收据要么仍然为空,要么未随成功购买而更新(在沙盒环境中)。理想情况下,我不再需要它,但我们的服务器端实现当前需要编码的收据数据,因此对于我当前的用例,我仍然需要访问它。
我的购买流程是这样的:
let purchaseResult = try await product.purchase(options: purchaseOptions)
switch purchaseResult {
case .success(let verification):
let transaction = try checkVerified(verification)
...
guard let receiptPath = Bundle.main.appStoreReceiptURL?.path else {
throw Error.missingReceipt
}
let receiptData = NSData(contentsOfFile: receiptPath) // Receipt data is nil here
let receiptString = receiptData?.base64EncodedString(options: .endLineWithLineFeed) ?? ""
...
// Handle server logic
...
await transaction.finish()
case ...
...
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,使用 StoreKit 2 API 时仍应生成收据数据 - 有没有办法保证在成功完成购买后和交易处理期间填充收据数据?
storekit ×10
ios ×8
swift ×4
app-store ×1
apple-watch ×1
cocoa-touch ×1
nsnumber ×1
objective-c ×1
sandbox ×1
subscription ×1
watchos ×1