Подходящий способ локального сохранения состояния IAP (особенно подписки) в SwiftUI с помощью StoreKit2.IOS

Программируем под IOS
Ответить
Anonymous
 Подходящий способ локального сохранения состояния IAP (особенно подписки) в SwiftUI с помощью StoreKit2.

Сообщение Anonymous »

Я создаю приложение, которое предлагает автоматическое продление подписки, а также устаревший план, который будет удален из продажи (однако пользователи, купившие его, продолжат пользоваться преимуществами).
По сути, я никогда не реализовал IAP в SwiftUI, особенно с помощью StoreKit 2, поэтому я тщательно следовал этому руководству, чтобы реализовать весь процесс покупки. Однако, учитывая опыт работы с UIKit, у меня есть много сомнений.
Я читал здесь, что вам следует делать это с помощью UserDefaults или iCloud, однако в прошлом я обычно использовал связку ключей.< /p>
Я хочу локально сохранять информацию о том, купил ли пользователь что-то или нет, особенно в отношении подписок, чтобы иметь возможность всегда доставлять купленный контент даже в автономном режиме.
код, который я реализовал в соответствии со связанным руководством, уже предоставляет некоторые функции для этого, но я боюсь, что это работает только при включенном подключении к Интернету. Для справки:

Код: Выделить всё

@MainActor
private func handle(transactionVerification result: VerificationResult  ) async {
switch result {
case let.verified(transaction):
guard
let product = self.products.first(where: {
$0.id == transaction.productID
})
else {
return
}
self.purchasedNonConsumables.insert(product)
await transaction.finish()
default:
return
}
}

func listenForTransactions() -> Task {
return Task.detached {
for await result in Transaction.updates {
await self.handle(transactionVerification: result)
}
}
}
На данный момент я сохраняю состояние с помощью брелка, как для восстановления нерасходника, так и для сохранения состояния автопродления подписки после его покупки. Для справки я также приложу код своего брелка. Эти функции затем интегрируются в функции магазина (возьмем в качестве примера функции из предыдущего блока, после проверки я вызываю их для сохранения товаров в цепочке ключей).

Код: Выделить всё

class KeychainManager {
static func save(key: String, data: Data) -> OSStatus {
let query = [
kSecClass as String       : kSecClassGenericPassword as String,
kSecAttrAccount as String : key,
kSecValueData as String   : data
] as [String : Any]

SecItemDelete(query as CFDictionary)  // Ensures we remove any existing item before adding new one
return SecItemAdd(query as CFDictionary, nil)
}

static func load(key: String) -> Data? {
let query = [
kSecClass as String       : kSecClassGenericPassword,
kSecAttrAccount as String : key,
kSecReturnData as String  : kCFBooleanTrue!,
kSecMatchLimit as String  : kSecMatchLimitOne
] as [String : Any]

var dataTypeRef: AnyObject? = nil
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)

if status == noErr {
return dataTypeRef as? Data
}
return nil
}

static func saveSubscriptionInfo(key: String, subscriptionInfo: SubscriptionInfo) -> OSStatus {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(subscriptionInfo)
return save(key: key, data: data)
} catch {
print("Failed to encode subscription info: \(error)")
return errSecInternalError  // Using a generic internal error code
}
}

static func loadSubscriptionInfo(key: String) -> SubscriptionInfo? {
guard let data = load(key: key) else { return nil }
let decoder = JSONDecoder()
do {
let subscriptionInfo = try decoder.decode(SubscriptionInfo.self, from: data)
return subscriptionInfo
} catch {
print("Failed to decode subscription info: \(error)")
return nil
}
}

}

struct SubscriptionInfo: Codable {
var expiryDate: Date?
var isSubscribed: Bool
}

Мой вопрос: как правильно сохранить статус покупки? Кроме того, следует ли мне хранить разные типы покупок по-разному или связка ключей — лучший способ хранить как нерасходные материалы, так и автоматически обновляемые подписки?


Подробнее здесь: https://stackoverflow.com/questions/783 ... -swiftui-u
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»