-
Notifications
You must be signed in to change notification settings - Fork 8
Transaction persistence
Tenfay edited this page Nov 11, 2024
·
6 revisions
DYFStore
provides an optional reference implementation for storing transactions in NSUserDefaults
(DYFStoreUserDefaultsPersistence
).
When the client crashes during the payment process, it is particularly important to store transaction information. When StoreKit
notifies the uncompleted payment again, it takes the data directly from keychain and performs the receipt verification until the transaction is completed.
func storeReceipt() {
guard let url = DYFStore.receiptURL() else {
self.refreshReceipt()
return
}
do {
let data = try Data(contentsOf: url)
let info = self.purchaseInfo!
let persister = DYFStoreUserDefaultsPersistence()
let tx = DYFStoreTransaction()
if info.state! == .succeeded {
tx.state = DYFStoreTransactionState.purchased.rawValue
} else if info.state! == .restored {
tx.state = DYFStoreTransactionState.restored.rawValue
}
tx.productIdentifier = info.productIdentifier
tx.userIdentifier = info.userIdentifier
tx.transactionTimestamp = info.transactionDate?.timestamp()
tx.transactionIdentifier = info.transactionIdentifier
tx.originalTransactionTimestamp = info.originalTransactionDate?.timestamp()
tx.originalTransactionIdentifier = info.originalTransactionIdentifier
tx.transactionReceipt = data.base64EncodedString()
persister.storeTransaction(tx)
self.verifyReceipt(data)
} catch let error {
DYFStoreLog("error: \(error.localizedDescription)")
self.refreshReceipt()
return
}
}
let info = self.purchaseInfo!
let store = DYFStore.default
let persister = DYFStoreUserDefaultsPersistence()
let identifier = info.transactionIdentifier!
if info.state! == .restored {
let tx = store.extractRestoredTransaction(identifier)
store.finishTransaction(tx)
} else {
let tx = store.extractPurchasedTransaction(identifier)
// The transaction can be finished only after the receipt verification passed under the client and the server can adopt the communication of security and data encryption. In this way, we can avoid refreshing orders and cracking in-app purchase. If we were unable to complete the verification we want StoreKit to keep reminding us of the transaction.
store.finishTransaction(tx)
}
persister.removeTransaction(identifier)
if let id = info.originalTransactionIdentifier {
persister.removeTransaction(id)
}
To learn more, please view the demo.