mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-11 22:55:55 +05:45
### Depends on: - #1537 - #1540 - #1541 - #1543 - #1546 - #1547 - #1550 - #1551, - #1565 ### Changes - Removed all custom deserialization code thanks to #1537, #1541, and #1543. - The format of the customer info response is now very concise and only in one place (`CustomerInfoResponse`) instead of being passed through dictionaries and magic strings everywhere. - `CustomerInfo` was combining the dictionaries inside of `"subscriptions"` and `"non_subscriptions"`, despite them having different formats. This is now made explicit through type conversions between the two, (see `CustomerInfoResponse.allTransactionsByProductId`). - Removed all custom `CustomerInfo` errors since deserialization is automatic, and the underlying `Error` information will be provided thanks to `ErrorUtils.logDecodingError`. - `CustomerInfo` deserialization always wraps errors into `ErrorCode.customerInfoError`, which is now also covered in a new test. - Added a new snapshot test that covers `CustomerInfo` serialization by storing the result in a JSON file. ### Other changes: - `CustomerInfo` equality is now automatic through the `CustomerInfoResponse` `Equatable` conformance. - Simplified `schemaVersion` handling - All tests still use `CustomerInfo(data: [String: Any])`, but that method is only visible for tests now, and it uses the underlying `Decodable` implementation (see `CustomerInfo+TestExtensions.swift`). - Added extra tests for `CustomerInfoResponse` that use a fixture `CustomerInfo.json`, which is easier to maintain than having JSON in code. - `RawDataContainer` implementation is changed in #1565. ### TODO: - [x] Fix all tests - [x] Update `RawValueContainer` - [x] Consider recovering `CustomerInfoError` - [x] Look at all previously logged errors - [x] Finish `CustomerInfoResponseTests` - [x] Handle all TODOs - [x] Make `RawDataContainer` actually store all the original data: #1565
58 lines
1.8 KiB
Swift
58 lines
1.8 KiB
Swift
//
|
|
// Copyright RevenueCat Inc. All Rights Reserved.
|
|
//
|
|
// Licensed under the MIT License (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://opensource.org/licenses/MIT
|
|
//
|
|
// TransactionsFactory.swift
|
|
//
|
|
// Created by RevenueCat.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
enum TransactionsFactory {
|
|
|
|
static func nonSubscriptionTransactions(
|
|
withSubscriptionsData subscriptionsData: [String: [CustomerInfoResponse.Transaction]]
|
|
) -> [StoreTransaction] {
|
|
subscriptionsData
|
|
.flatMap { (productID, transactions) -> [StoreTransaction] in
|
|
transactions
|
|
.lazy
|
|
.compactMap { BackendParsedTransaction(with: $0, productID: productID) }
|
|
.map { StoreTransaction($0) }
|
|
}
|
|
.sorted { $0.purchaseDate < $1.purchaseDate }
|
|
}
|
|
|
|
}
|
|
|
|
/// `StoreTransactionType` backed by data parsed from the server
|
|
private struct BackendParsedTransaction: StoreTransactionType {
|
|
|
|
let productIdentifier: String
|
|
let purchaseDate: Date
|
|
let transactionIdentifier: String
|
|
let quantity: Int
|
|
|
|
init?(with transaction: CustomerInfoResponse.Transaction, productID: String) {
|
|
guard let transactionIdentifier = transaction.transactionIdentifier,
|
|
let purchaseDate = transaction.purchaseDate else {
|
|
Logger.error("Couldn't initialize Transaction. " +
|
|
"Reason: missing data: \(transaction).")
|
|
return nil
|
|
}
|
|
|
|
self.transactionIdentifier = transactionIdentifier
|
|
self.purchaseDate = purchaseDate
|
|
self.productIdentifier = productID
|
|
// Defaulting to `1` since multi-quantity purchases aren't currently supported.
|
|
self.quantity = 1
|
|
}
|
|
|
|
}
|