1
This commit is contained in:
@@ -255,12 +255,17 @@ internal class StoreKitService: ObservableObject {
|
|||||||
switch result {
|
switch result {
|
||||||
case .success(let verification):
|
case .success(let verification):
|
||||||
do {
|
do {
|
||||||
|
let payload = verification.jwsRepresentation
|
||||||
let transaction = try verifyPurchase(verification)
|
let transaction = try verifyPurchase(verification)
|
||||||
|
|
||||||
await printProductDetails(product)
|
await printProductDetails(product)
|
||||||
// 打印详细的交易信息
|
// 打印详细的交易信息
|
||||||
await printTransactionDetails(transaction)
|
await printTransactionDetails(transaction)
|
||||||
|
|
||||||
|
await MainActor.run {
|
||||||
|
self.delegate?.service(self, didCompletePurchaseFor: transaction.productID, payload: payload)
|
||||||
|
}
|
||||||
|
|
||||||
// 先完成交易
|
// 先完成交易
|
||||||
await transaction.finish()
|
await transaction.finish()
|
||||||
|
|
||||||
@@ -561,11 +566,13 @@ internal class StoreKitService: ObservableObject {
|
|||||||
// 持续监听,直到任务被取消
|
// 持续监听,直到任务被取消
|
||||||
while !Task.isCancelled {
|
while !Task.isCancelled {
|
||||||
// 检查所有订阅的状态(并行检查,提高效率)
|
// 检查所有订阅的状态(并行检查,提高效率)
|
||||||
let now = Date()
|
if self.config.showLog {
|
||||||
let formatter = DateFormatter()
|
let now = Date()
|
||||||
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
let formatter = DateFormatter()
|
||||||
formatter.timeZone = TimeZone.current
|
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
||||||
print("当前订阅检测时间: \(formatter.string(from: now))")
|
formatter.timeZone = TimeZone.current
|
||||||
|
print("当前订阅检测时间: \(formatter.string(from: now))")
|
||||||
|
}
|
||||||
await self.checkSubscriptionStatus()
|
await self.checkSubscriptionStatus()
|
||||||
|
|
||||||
// 等待指定间隔(默认30秒)后再次检查
|
// 等待指定间隔(默认30秒)后再次检查
|
||||||
|
|||||||
@@ -20,5 +20,7 @@ internal protocol StoreKitServiceDelegate: AnyObject {
|
|||||||
|
|
||||||
/// 已购买交易订单更新
|
/// 已购买交易订单更新
|
||||||
func service(_ service: StoreKitService, didUpdatePurchasedTransactions efficient: [Transaction], latests: [Transaction])
|
func service(_ service: StoreKitService, didUpdatePurchasedTransactions efficient: [Transaction], latests: [Transaction])
|
||||||
}
|
|
||||||
|
|
||||||
|
/// 某个交易完成(验证成功)
|
||||||
|
func service(_ service: StoreKitService, didCompletePurchaseFor productId: String, payload: String)
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ final class KBStoreKitBridge: NSObject, StoreKitDelegate {
|
|||||||
do {
|
do {
|
||||||
try await self.manager.purchase(productId: productId)
|
try await self.manager.purchase(productId: productId)
|
||||||
|
|
||||||
if let payload = await Self.latestJWSPayload(for: productId) {
|
if let payload = await self.fetchPayload(for: productId) {
|
||||||
self.verifySignedPayload(payload, completion: completion)
|
self.verifySignedPayload(payload, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
@@ -115,10 +115,24 @@ final class KBStoreKitBridge: NSObject, StoreKitDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func latestJWSPayload(for productId: String) async -> String? {
|
@MainActor
|
||||||
guard let result = await Transaction.latest(for: productId) else { return nil }
|
private func fetchPayload(for productId: String) async -> String? {
|
||||||
if case .verified = result {
|
if let payload = manager.consumeRecentPayload(for: productId) {
|
||||||
return result.jwsRepresentation
|
return payload
|
||||||
|
}
|
||||||
|
return await Self.latestJWSPayload(for: productId, retryCount: 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func latestJWSPayload(for productId: String, retryCount: Int = 1) async -> String? {
|
||||||
|
var attempts = 0
|
||||||
|
while attempts < retryCount {
|
||||||
|
if let result = await Transaction.latest(for: productId), case .verified = result {
|
||||||
|
return result.jwsRepresentation
|
||||||
|
}
|
||||||
|
attempts += 1
|
||||||
|
if attempts < retryCount {
|
||||||
|
try? await Task.sleep(nanoseconds: 300_000_000) // 0.3s
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ public class StoreKit2Manager {
|
|||||||
/// 每个产品的最新交易记录集合
|
/// 每个产品的最新交易记录集合
|
||||||
public private(set) var latestTransactions: [Transaction] = []
|
public private(set) var latestTransactions: [Transaction] = []
|
||||||
|
|
||||||
|
/// 最近一次完成购买的交易签名缓存(按产品ID)
|
||||||
|
private var recentJWSPayloads: [String: String] = [:]
|
||||||
|
|
||||||
// MARK: - 按类型分类的产品(计算属性)
|
// MARK: - 按类型分类的产品(计算属性)
|
||||||
|
|
||||||
/// 非消耗品
|
/// 非消耗品
|
||||||
@@ -379,6 +382,14 @@ public class StoreKit2Manager {
|
|||||||
return latestTransactions
|
return latestTransactions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取指定产品最近一次完成的 JWS(仅限 StoreKitService 捕获到的交易)
|
||||||
|
/// - Parameter productId: 产品 ID
|
||||||
|
/// - Returns: 若存在则返回并移除缓存
|
||||||
|
@MainActor
|
||||||
|
func consumeRecentPayload(for productId: String) -> String? {
|
||||||
|
return recentJWSPayloads.removeValue(forKey: productId)
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取交易历史
|
/// 获取交易历史
|
||||||
/// - Parameter productId: 可选的产品ID,如果提供则只返回该产品的交易历史
|
/// - Parameter productId: 可选的产品ID,如果提供则只返回该产品的交易历史
|
||||||
/// - Returns: 交易历史记录数组,按购买日期倒序排列
|
/// - Returns: 交易历史记录数组,按购买日期倒序排列
|
||||||
@@ -532,5 +543,9 @@ extension StoreKit2Manager: StoreKitServiceDelegate {
|
|||||||
// 通知闭包回调
|
// 通知闭包回调
|
||||||
onPurchasedTransactionsUpdated?(efficient, latests)
|
onPurchasedTransactionsUpdated?(efficient, latests)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func service(_ service: StoreKitService, didCompletePurchaseFor productId: String, payload: String) {
|
||||||
|
recentJWSPayloads[productId] = payload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completion) completion(KBBizCodeSuccess, @"ok");
|
if (completion) completion(KBBizCodeSuccess, @"JWS-ok");
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user