You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

订阅时传递app account token的StoreKit实现疑问

问题:订阅时传递App Account Token的实现方法

我需要在订阅内购时传递“app account token”,但不知道如何在现有StoreManager类中实现这个逻辑。我见过使用product.purchase(options: [.appAccountToken(token)])的写法,但不清楚怎么整合到当前代码里。

现有StoreManager代码

import Foundation
import StoreKit


final class StoreManager: NSObject {
    
    static let shared = StoreManager()
    
    let storeObserver = StoreObserver()
    var transactionState: SKPaymentTransactionState?
    var myProducts = [SKProduct]()
    
    private let subscriptionIndentifiers: Set<String> = [
        XXX.Subscription.monthly.productId,
        XXX.Subscription.annual.productId
    ]
    

    private override init() {
        super.init()
        SKPaymentQueue.default().add(storeObserver)
    }
    
    func getProducts() {
        let request = SKProductsRequest(productIdentifiers: subscriptionIndentifiers)
        request.delegate = self
        
        request.start()
    }
    
    func selectedType(type: SubscribeType) {
        switch type {
        case .month:
            purchase(product: myProducts[1])
        case .years:
            purchase(product: myProducts[0])
        }
    }
    
    
    func purchase(product: SKProduct) -> Bool {
               
        if !StoreManager.shared.canMakePayments() {
            return false
        } else {
            if !UserDefaultService.isLogin() {
                return false
            } else {
                let payment = SKPayment(product: product)
                SKPaymentQueue.default().add(payment)
            }
        }
        return true
    }
    
    func canMakePayments() -> Bool {
        return SKPaymentQueue.canMakePayments()
    }
}

extension StoreManager: SKProductsRequestDelegate, SKRequestDelegate {
    
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        debugPrint("Did receive response")
        if !response.products.isEmpty {
            for fetchedProduct in response.products {
                DispatchQueue.main.async {
                    self.myProducts.append(fetchedProduct)
                }
            }
        }
        
        for invalidIdentifier in response.invalidProductIdentifiers {
            debugPrint("Invalid identifiers found: \(invalidIdentifier)")
        }
    }
    
    func requestDidFinish(_ request: SKRequest) {
        DispatchQueue.main.async {
            debugPrint("request did finish ")
        }
    }
}

解决方案

你看到的product.purchase(options:)是StoreKit 2的异步API,和原代码使用的StoreKit 1同步队列方式不同,要整合到现有代码里,需要做以下修改:

1. 重写purchase方法为异步函数

将原来同步返回Bool的purchase方法,改成支持async/await的异步版本,同时接收appAccountToken参数:

func purchase(product: SKProduct, appAccountToken: Data) async throws -> Bool {
    guard StoreManager.shared.canMakePayments(), UserDefaultService.isLogin() else {
        return false
    }
    
    let purchaseResult = try await product.purchase(options: [.appAccountToken(appAccountToken)])
    
    // 根据购买结果返回状态,可根据业务需求调整逻辑
    switch purchaseResult {
    case .success(_):
        return true
    case .userCancelled, .pending:
        return false
    default:
        return false
    }
}

2. 修改selectedType方法调用异步purchase

由于purchase变成了异步方法,需要用Task包裹调用逻辑,同时传入生成好的appAccountToken:

func selectedType(type: SubscribeType) {
    // 从本地获取用户的唯一标识并转为Data,示例用UUID(需替换成实际业务的用户标识)
    guard let appAccountToken = UserDefaultService.getCurrentUserId()?.data(using: .utf8) else {
        // 无用户标识的处理逻辑
        return
    }
    
    let targetProduct: SKProduct
    switch type {
    case .month:
        targetProduct = myProducts[1]
    case .years:
        targetProduct = myProducts[0]
    }
    
    Task {
        do {
            let isSuccess = try await purchase(product: targetProduct, appAccountToken: appAccountToken)
            // 这里可以添加购买结果的UI反馈逻辑
            debugPrint(isSuccess ? "购买成功" : "购买取消/失败")
        } catch {
            debugPrint("购买出错:\(error.localizedDescription)")
        }
    }
}

3. 关键说明

  • appAccountToken要求为Data类型,通常可以将用户的唯一ID(如UUID、业务用户ID)转成Data使用
  • 若需要兼容旧版本StoreKit逻辑,可以保留原purchase方法,新增带token的异步版本
  • StoreKit 2的交易仍会进入SKPaymentQueue,原有的StoreObserver可以继续监听交易状态做后续处理

内容的提问来源于stack exchange,提问作者Evg Enii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:03:13