Files
purchases-ios/Sources/Networking/CustomerAPI.swift
T
NachoSoto a2fc04c09e SubscriberAttribute: converted into struct (#1648)
### Motivation:

Initially I wanted to make `SubscriberAttribute.asDictionary` work using `Codable`. However, this isn't the right refactor because we need the actual raw types to be encoded inside `UserDefaults`.
At least this refactor provides several improvements:

### Changes:

- `SubscriberAttribute` now has value semantics
- ⚠️  `SubscriberAttribute.isSynced` used to be mutable, with reference semantics, which was dangerous
- `SubscriberAttribute: Equatable` implementation is now automatic
- Cleaned up `SubscriberAttribute.asDictionary` implementation, extracting keys into an `enum`
- Moved `Dictionary` -> `SubscriberAttribute` creation to the type itself
- ⚠️ `SubscriberAttribute.init(dictionary:)` returns an `Optional` instead of using force-unwrap, avoiding potential crashes
- Added more serialization / deserialization tests
- Removed `SubscriberAttributesMarshaller` and moved method into `SubscriberAttribute` extension
- Moved `SubscriberAttributeDict` into `SubscriberAttribute.Dictionary`
2022-06-17 10:00:51 -07:00

105 lines
5.6 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
//
// SubscribersAPI.swift
//
// Created by Joshua Liebowitz on 11/17/21.
import Foundation
class CustomerAPI {
typealias CustomerInfoResponseHandler = (Result<CustomerInfo, BackendError>) -> Void
typealias SimpleResponseHandler = (BackendError?) -> Void
private let backendConfig: BackendConfiguration
private let customerInfoCallbackCache: CallbackCache<CustomerInfoCallback>
private let attributionFetcher: AttributionFetcher
init(backendConfig: BackendConfiguration, attributionFetcher: AttributionFetcher) {
self.backendConfig = backendConfig
self.attributionFetcher = attributionFetcher
self.customerInfoCallbackCache = CallbackCache<CustomerInfoCallback>(callbackQueue: backendConfig.callbackQueue)
}
func getCustomerInfo(appUserID: String, completion: @escaping CustomerInfoResponseHandler) {
let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient,
appUserID: appUserID)
let operation = GetCustomerInfoOperation(configuration: config,
customerInfoCallbackCache: self.customerInfoCallbackCache)
let callback = CustomerInfoCallback(operation: operation, completion: completion)
let cacheStatus = self.customerInfoCallbackCache.add(callback: callback)
self.backendConfig.operationQueue.addCacheableOperation(operation, cacheStatus: cacheStatus)
}
func post(subscriberAttributes: SubscriberAttribute.Dictionary,
appUserID: String,
completion: SimpleResponseHandler?) {
let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient,
appUserID: appUserID)
let operation = PostSubscriberAttributesOperation(configuration: config,
subscriberAttributes: subscriberAttributes,
completion: completion)
self.backendConfig.operationQueue.addOperation(operation)
}
func post(attributionData: [String: Any],
network: AttributionNetwork,
appUserID: String,
completion: SimpleResponseHandler?) {
let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient,
appUserID: appUserID)
let postAttributionDataOperation = PostAttributionDataOperation(configuration: config,
attributionData: attributionData,
network: network,
responseHandler: completion)
self.backendConfig.operationQueue.addOperation(postAttributionDataOperation)
}
// swiftlint:disable:next function_parameter_count
func post(receiptData: Data,
appUserID: String,
isRestore: Bool,
productData: ProductRequestData?,
presentedOfferingIdentifier offeringIdentifier: String?,
observerMode: Bool,
subscriberAttributes subscriberAttributesByKey: SubscriberAttribute.Dictionary?,
completion: @escaping CustomerAPI.CustomerInfoResponseHandler) {
let attributionStatus = self.attributionFetcher.authorizationStatus
var subscriberAttributesByKey = subscriberAttributesByKey ?? [:]
let consentStatus = SubscriberAttribute(withKey: ReservedSubscriberAttribute.consentStatus.rawValue,
value: attributionStatus.description,
dateProvider: self.backendConfig.dateProvider)
subscriberAttributesByKey[ReservedSubscriberAttribute.consentStatus.key] = consentStatus
let config = NetworkOperation.UserSpecificConfiguration(httpClient: self.backendConfig.httpClient,
appUserID: appUserID)
let postData = PostReceiptDataOperation.PostData(appUserID: appUserID,
receiptData: receiptData,
isRestore: isRestore,
productData: productData,
presentedOfferingIdentifier: offeringIdentifier,
observerMode: observerMode,
subscriberAttributesByKey: subscriberAttributesByKey)
let postReceiptOperation = PostReceiptDataOperation(configuration: config,
postData: postData,
customerInfoCallbackCache: self.customerInfoCallbackCache)
let callbackObject = CustomerInfoCallback(operation: postReceiptOperation, completion: completion)
let cacheStatus = customerInfoCallbackCache.add(callback: callbackObject)
self.backendConfig.operationQueue.addCacheableOperation(postReceiptOperation, cacheStatus: cacheStatus)
}
}