AppStore.sync() 不恢复购买

vau*_*all 12 macos storekit in-app-purchase ios swift

在使用旧 API 进行应用内购买的应用程序 ( StoreKit 1 ) 上。该应用程序已在 App Store 上发布。购买的是非消耗品

在尝试迁移到StoreKit 2时,我无法恢复购买。具体显示和购买产品按预期工作,但是当删除并重新安装应用程序,然后尝试恢复购买时,我无法做到这一点。

我正在尝试使用新的 API 来恢复它们,但它似乎不起作用。到目前为止我已经尝试过:

我在应用程序的整个生命周期中监听交易更新,其中:

Task.detached {
    for await result in Transaction.updates {
        if case let .verified(safe) = result {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个调用此方法的按钮,但除了提示使用 Apple ID 再次登录之外,它似乎根本没有任何效果:

try? await AppStore.sync()
Run Code Online (Sandbox Code Playgroud)

这不会返回任何项目

for await result in Transaction.currentEntitlements {
    if case let .verified(transaction) = result {

    }
}
Run Code Online (Sandbox Code Playgroud)

这不会返回任何项目

for await result in Transaction.all {
    if case let .verified(transaction) = result {

    }
}
Run Code Online (Sandbox Code Playgroud)

如前所述,我在购买该商品并删除该应用程序后尝试此操作。所以我确信它应该能够恢复购买。我在模拟器上使用Configuration.storekit文件尝试此操作,而在沙盒环境中的真实设备上则不使用它。

有人能够使用 StoreKit 2 恢复购买吗?

Ps:我已经在反馈助手上提交了反馈报告,但到目前为止他们唯一回复的是:

由于 Xcode 中的 StoreKit 测试是本地环境,并且数据与应用程序绑定,因此当您删除应用程序时,您还将删除 Xcode 环境中该应用程序的所有交易数据。提供的代码片段是 API 的正确用法。

所以,是的,使用Configuration.storekit文件无法恢复购买,但如果我无法在沙盒环境中恢复它们,我担心一旦发布就无法恢复,让我的用户完全无法恢复什么他们已经购买了。

vau*_*all 11

iOS 17 更新

在 iOS 17 上,我们有一个新的 API 来处理这个问题,集成在SwiftUI currentEntitlementTask(for:priority:action:)中

它可以更轻松地处理这个问题,并且只需几行代码。我还可以验证它在发布调试模式下都有效。

例子

import SwiftUI
import StoreKit

struct MyView: View {
    var body: some View {
        VStack {
            /// your view
        }
        .currentEntitlementTask(for: "My Purchase ID") { state in
            guard
                let transaction = state.transaction,
                case .verified(let verified) = transaction
            else { return }
            /// ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住导入 StoreKit才能使用它View Modifier

原答案

iOS 17 之前的版本

在发布到App Store并最终在生产中直接尝试该应用程序后,我可以确认它可以工作,但我不得不说,无法在沙箱环境中测试它是不理想的

另外我觉得文档不够清晰,至少对我来说不是。对于其他人来说可能很清楚,但我希望购买能够自动恢复并继续使用for await result in Transaction.updates,但这没有用。

所做的工作是检查Transaction.currentEntitlements,如果权利不存在,则执行 async()并再次检查。这是对我有用的代码:

try? await AppStore.sync()
        
for await result in Transaction.currentEntitlements {
    if case let .verified(transaction) = result {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

注意事项

  • 如前所述,这仅适用release mode于没有debug modeStoreKit Test 的情况,即没有Configuration.storekit.
  • 如果您想使用StoreKit 测试(使用Configuration.storekit)恢复购买有效(使用相同的方法),但前提是您不删除应用程序并再次重新安装。通过删除应用程序,您将丢失 StoreKit 测试历史记录。
  • 正如 @loremipsum 所提到的,这也可以在 TestFlight 上进行测试(因为它是发布模式)。
  • 已验证 iOS 和 macOS。