标签: storekit

如何恢复丢失的SKPaymentTransactions?

我有一个测试帐户,在其交易历史记录中只有两次购买.这两种产品都是非消耗品.

我在iPad 1上登录并购买了产品A.

然后我退出iPad 1并登录iPad 2并购买了产品B.

然后我尝试使用[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];在iPad 2上解锁产品A 来恢复以前的交易.

当呼叫回来时,只有产品B在可恢复交易列表中.

此外,当我尝试在iPad 2上再次购买产品A.

SKPayment *payment = [SKPayment paymentWithProduct:productA];
[[SKPaymentQueue defaultQueue] addPayment:payment];
Run Code Online (Sandbox Code Playgroud)

我得到一个弹出窗口说'你已经购买了它.点按"确定"即可免费下载.

如果我已经购买了产品A,当我尝试恢复之前的购买时,为什么它不在产品列表中?为什么我必须让用户再次尝试购买?

编辑:
我发现无论我使用哪种iPad(iPad 1或iPad 2)都没关系,只有产品B出现在可恢复交易列表中,而产品A需要重新购买.

编辑:
我将产品请求,恢复和购买工作外推到自己的项目中,使用与原始相同的捆绑包ID和产品ID.

现在,可恢复交易列表中没有任何内容,但是当我尝试购买任一产品时,会出现相同的弹出窗口.

用破碎的Apple工具再次沿着兔子洞走下去.

编辑:
这次调查的灵感来自用户对丢失权利的一系列投诉.当用户从iPad 2切换到新的iPad 3时,这在很大程度上开始成为一个问题.这在我的所有用户中并不一致,但是他们中的很多人已经提出了将其作为优先事项的恶臭,并且Apple客户支持已经将它们发回给我,但我不确定这是我可以解决的问题特别是因为Apple坚持要成为应用内购买的收银机.

storekit ios

9
推荐指数
1
解决办法
2497
查看次数

如何使用StoreKit更新订阅?

我正在尝试找出处理自动更新部分的最佳机制,以便它可以处理订阅到下一个时期的延续.

处理这个的最好方法是什么?

我是否应该设置NSTimer以检查是否已达到当前的expires_date ..然后尝试发送购买请求?

objective-c nstimer storekit ios

9
推荐指数
1
解决办法
898
查看次数

我应该在应用程序购买期间对失败的交易调用finishTransation吗?

我正在为iOS应用程序编写应用内购买功能.我正在销售一些简单的消耗品(没有下载).我的代码基于本教程/主题 如何在iOS应用程序中添加应用程序内购买? 但是我注意到它与官方苹果文档冲突.

在此代码中,当一个Transaction因任何原因失败时,此代码[[SKPaymentQueue defaultQueue] finishTransaction:transaction]; 叫做.但是在Apple页面上 https://developer.apple.com/library/ios/documentation/StoreKit/Reference/SKPaymentQueue_Class/Reference/Reference.html#//apple_ref/occ/instm/SKPaymentQueue/finishTransaction:它写道:"你的应用程序只有在成功处理完交易并解锁用户购买的功能后才能调用finishTransaction.

那么哪种方法是正确的?我应该在失败的交易上致电完成吗?

storekit ios

9
推荐指数
1
解决办法
1753
查看次数

调用 finishTransaction 后 SKPaymentTransaction 被困在队列中

我们有一个应用程序被苹果拒绝了几次,因为它无法完成自动续订 IAP 购买,并且如果尝试也无法恢复。我们最终通过添加一些额外的日志记录来缩小错误范围,并Payment added for transaction already in the SKPaymentQueue: ...在日志中注意到。

在尝试重现时,我们启动了一段时间没有使用的手机,并注意到队列中有27 笔SKPaymentTransactionState.purchased相同购买的交易,全部处于状态。我们SKPaymentTransactionObserver会收到这些交易的通知,并且会进行拜访finishTransaction。我假设有这么多交易,因为我们有每月订阅,沙盒中每 5 分钟自动续订一次,并且我们一直在另一部手机上使用相同的 App Store 帐户额外购买同一个 IAP - 所以现在,该手机将收到所有更新的通知。

奇怪的是,即使我们调用finishTransaction这些交易,它们似乎仍未完成,这就是为什么我们在控制台中看到“为已在队列中的交易添加的付款”消息。

因此,为了调试这个,我实现了paymentQueue(_:removedTransactions:)of SKPaymentTransactionObserver,并注意到,即使我们调用了finishTransaction如此多的事务,我们也只会看到一个被删除 - 而且似乎如果我们在应用程序中停留很长时间,只是什么也不做,那么更多的事务就会被删除。历时10多分钟。

在我的沮丧中,我继续做了这样的事情

    public func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
        let remainingTransactions = queue.transactions
        let hasRemainingTransactions = !remainingTransactions.isEmpty
        
        if hasRemainingTransactions {
            paymentQueue(queue, updatedTransactions: remainingTransactions)
        }
    }
Run Code Online (Sandbox Code Playgroud)

当然是非常恶心的,但你难道不知道,对于 n 笔交易中的每笔交易,它们都被一笔一笔地删除——一次只删除一笔。

所以我的第一个想法是,嗯,这在现实世界中可能不太可能发生,因为你一次又一次地购买、更新得如此之快等,所以也许 SDK 并不期望一次完成这么多交易?我尝试了一些不那么恶心的东西,并paymentQueue(_:updatedTransactions:)从这样的地方改变了我们的东西

    public func …
Run Code Online (Sandbox Code Playgroud)

storekit in-app-purchase ios skpaymenttransaction

9
推荐指数
1
解决办法
1854
查看次数

在后端验证 Apple StoreKit2 应用内购买收据 jwsRepresentation (理想情况下是节点,但任何方法都可以)

如何在 Node 后端验证来自 StoreKit2 的应用内购买 JWS 表示?

Its easy enough to decode the payload, but I can't find public keys that Apple uses to sign these JWS/JWTs anywhere. Any other time I've worked with JWTs, you simply used the node jsonwebtoken library and passed in the signers public key or shared secret key, either configured or fetched from a JWK.

I can easily decode the JWS using node-jose j.JWS.createVerify().verify(jwsString, {allowEmbeddedKey: true}).then(r => obj = r) which gives me an object …

storekit in-app-purchase ios jwt

9
推荐指数
2
解决办法
5292
查看次数

StoreKit2 Transaction.updates 不会在订阅续订时发出交易

我在应用程序的整个生命周期内监听事务更新,如下所述Transaction.updates

func startObservingTransactions() -> Task<Void, Error> {
    return Task.detached {
        for await result in Transaction.updates {
            print("Transaction update")

            if case .verified(let transaction) = result {
                await transaction.finish()

                ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Transaction.updates当订阅续订时,永远不会发出交易。此外,我在应用程序启动时不会收到未完成的交易。然而,对交易进行退款会产生预期的更新。

我在使用 Xcode、Sandbox 和 TestFlight 环境的模拟器和真实设备上遇到了相同的行为。

它是否应该通知订阅续订,或者我应该像往常一样观察交易队列?

我使用的是 Xcode 13.2.1,iOS 15.2。

storekit ios swift

9
推荐指数
0
解决办法
2649
查看次数

Skproduct 跳过产品,因为没有可用价格

这是我第一次创建购买的经历。我正在开发的应用程序尚未发布。我一直在使用 Configuration.storekit 文件在本地测试订阅。一切正常。\n我最近遇到了一个问题 - 我的订阅不再显示在项目中。我在终端中收到如下错误:\n终端输出的图像

\n

更新:

\n
    \n
  • 我决定在模拟器上检查应用程序,一切正常。据我记得安装 xcode 14 并更新到 ios 16 后一切都崩溃了。
  • \n
  • 在物理设备上,问题仍然存在。
  • \n
\n

我没有更改那些地方的代码。我尝试创建新的 .storekit 文件,但仍然不起作用。\n我尝试通过同步加载 .storekit 文件。在其中,价格被拉高并正确显示,与网站上一样,但在终端中再次写入相同的错误。

\n

这是适用于购买的文件:

\n
import StoreKit\n\ntypealias RequestProductsResult = Result<[SKProduct], Error>\ntypealias PurchaseProductResult = Result<Bool, Error>\n\ntypealias RequestProductsCompletion = (RequestProductsResult) -> Void\ntypealias PurchaseProductCompletion = (PurchaseProductResult) -> Void\n\n\nclass Purchases: NSObject {\n    static let `default` = Purchases()\n    private let productIdentifiers = Set<String>(\n        arrayLiteral: "test.1month", "test.6month", "test.12month"\n    )\n\n    private var products: [String: SKProduct]?\n    private var productRequest: SKProductsRequest?\n    private var productsRequestCallbacks …
Run Code Online (Sandbox Code Playgroud)

storekit in-app-purchase skproduct swift in-app-subscription

9
推荐指数
1
解决办法
2258
查看次数

SKStoreProductViewController显示延迟

我在我的应用程序中使用了SKStoreProductViewController.它显示正确,但有几秒钟的延迟,这会降低用户体验.

我的代码中有什么问题吗?或者我应该通知用户VC正在加载?因为现在可以相信按下按钮后没有发生任何事情(触发以下代码):

-(void)launchApp:(id)sender {

    // Recall on main thread if necessary
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(launchApp:)
                               withObject:sender
                            waitUntilDone:NO];
        return;
    }

    // Initialize Product View Controller
    SKStoreProductViewController *storeProductViewController = [[SKStoreProductViewController alloc] init];

    // Configure View Controller
    [storeProductViewController setDelegate:self];
    [storeProductViewController loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier : @"*********"}
                                          completionBlock:^(BOOL result, NSError *error) {
        if (error) {
            NSLog(@"Error %@ with User Info %@.", error, [error userInfo]);
        } else {
            // Present Store Product View Controller
            [self presentViewController:storeProductViewController animated:YES completion:nil];
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)

storekit ios

8
推荐指数
1
解决办法
4365
查看次数

Xcode 12 iOS 14 .storekit 恢复购买测试

如何在 Xcode 12 中使用新的 .storekit 测试恢复购买?当我打电话时SKPaymentQueue.default().restoreCompletedTransactions(),它直接转到paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)0 个事务。

在这段25 分钟的 WWDC 视频这篇同样来自 Apple 的文档文章以及 Internet 上的任何少数教程中,都没有提到“恢复” 。更令我困惑的是我找不到任何关于此的抱怨/问题?!

我觉得我已经疯了。如果有人可以点亮一些灯,那就太好了。提前致谢!

testing restore storekit in-app-purchase xcode12

8
推荐指数
1
解决办法
361
查看次数

StoreKit2 Transaction.currentEntitlements 不返回自动续订

如何返回Transaction.currentEntitlements应用程序关闭时发生的订阅自动续订交易?


我已经在 macOS 应用程序中实现了自动续订订阅。

我有一个可以在和StoreManager上创建听众的Transaction.currentEntitlementsTransaction.updates

如果在应用程序运行时续订订阅,Transaction.updates则会按预期接收最新交易。

但是,当应用程序未运行时自动发生续订时,重新打开应用程序时Transaction.currentEntitlements不会返回续订交易。

按照以下步骤进行重现:

  • 启动应用程序并购买自动续订订阅
  • 杀死该应用程序
  • 等待订阅到期自动续订(测试时可以设置每月30秒续订)
  • 重新启动应用程序
  • Transaction.currentEntitlements什么也不返回。

在应用程序启动时检查StoreKit Transactions调试窗口,应用程序关闭时发生的续订交易显示为“未完成”。

在此输入图像描述

未完成的交易是指未返回的交易。

如果在应用程序运行时再次续订订阅,则会Transaction.updates触发侦听器,并返回新的续订以及任何未完成的事务。

这是来自的相关代码StoreManager

@MainActor
class StoreManager: ObservableObject {
    
    var updates: Task<Void, Never>? = nil
    var transactions: Task<Void, Never>? = nil

    init() {
        updates = updatesListenerTask()
        transactions = transactionsListenerTask()
    }

    @Published private (set) var transaction: StoreKit.Transaction?
    
    func updatesListenerTask() -> Task<Void, Never> {
        Task.detached(priority: .background) {
            for …
Run Code Online (Sandbox Code Playgroud)

storekit swift storekit2

8
推荐指数
0
解决办法
1612
查看次数