Skip to content

Commit a2346cd

Browse files
committed
wip: adding more fields to LocalTransactionMetadata
1 parent d07de19 commit a2346cd

File tree

5 files changed

+105
-3
lines changed

5 files changed

+105
-3
lines changed

Sources/Purchasing/ProductRequestData.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct ProductRequestData {
6666

6767
}
6868

69-
extension ProductRequestData: Encodable {
69+
extension ProductRequestData: Codable {
7070

7171
enum CodingKeys: String, CodingKey {
7272

@@ -116,4 +116,24 @@ extension ProductRequestData: Encodable {
116116
}
117117
}
118118

119+
init(from decoder: Decoder) throws {
120+
let container = try decoder.container(keyedBy: CodingKeys.self)
121+
122+
self.productIdentifier = try container.decode(String.self, forKey: .productIdentifier)
123+
124+
self.paymentMode = try container.decodeIfPresent(StoreProductDiscount.PaymentMode.self, forKey: .paymentMode)
125+
self.currencyCode = try container.decodeIfPresent(String.self, forKey: .currencyCode)
126+
127+
// TODO: check the following types. They can't be as easily decoded into their original types as they are encoded
128+
self.storefront = nil
129+
self.price = 0
130+
self.discounts = nil
131+
self.introPrice = nil
132+
self.introDuration = nil
133+
self.introDurationType = nil
134+
135+
self.normalDuration = try container.decodeIfPresent(String.self, forKey: .normalDuration)
136+
self.subscriptionGroup = try container.decodeIfPresent(String.self, forKey: .subscriptionGroup)
137+
}
138+
119139
}

Sources/Purchasing/Purchases/LocalTransactionMetadataCache.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,46 @@ internal struct LocalTransactionMetadata: Equatable, Codable, Sendable {
3838
/// Whether purchases are completed by RevenueCat or the app (observer mode equivalent).
3939
let observerMode: Bool
4040

41+
/// Apple Ad Services attribution token.
42+
let aadAttributionToken: String?
43+
44+
/// The encoded receipt data.
45+
let receipt: EncodedAppleReceipt?
46+
47+
/// Product request data (product info, pricing, discounts, etc.).
48+
// let productData: ProductRequestData?
49+
// TODO: does not conform to Codable and Equatable (yet)
50+
51+
/// AppTransaction JWS string (StoreKit 2).
52+
let appTransactionJWS: String?
53+
4154
init(
4255
appUserID: String,
4356
productIdentifier: String,
4457
presentedOfferingContext: PresentedOfferingContext?,
4558
paywallPostReceiptData: PaywallPostReceiptData?,
46-
observerMode: Bool
59+
observerMode: Bool,
60+
aadAttributionToken: String? = nil,
61+
receipt: EncodedAppleReceipt? = nil,
62+
productData: ProductRequestData? = nil,
63+
appTransactionJWS: String? = nil
4764
) {
4865
self.schemaVersion = 1
4966
self.appUserID = appUserID
5067
self.productIdentifier = productIdentifier
5168
self.presentedOfferingContext = presentedOfferingContext
5269
self.paywallPostReceiptData = paywallPostReceiptData
5370
self.observerMode = observerMode
71+
self.aadAttributionToken = aadAttributionToken
72+
self.receipt = receipt
73+
// self.productData = productData
74+
self.appTransactionJWS = appTransactionJWS
5475
}
5576

5677
enum CodingKeys: String, CodingKey {
5778
case schemaVersion, productIdentifier, presentedOfferingContext, paywallPostReceiptData, observerMode
5879
case appUserID = "appUserId"
80+
case aadAttributionToken, receipt, /*productData,*/ appTransactionJWS
5981
}
6082
}
6183

Sources/Purchasing/StoreKitAbstractions/EncodedAppleReceipt.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,64 @@ enum EncodedAppleReceipt: Equatable {
2424

2525
}
2626

27+
extension EncodedAppleReceipt: Codable {
28+
enum CodingKeys: String, CodingKey {
29+
case type
30+
case value
31+
}
32+
33+
enum ReceiptType: String, Codable {
34+
case jws
35+
case receipt
36+
case sk2receipt
37+
case empty
38+
}
39+
40+
init(from decoder: Decoder) throws {
41+
let container = try decoder.container(keyedBy: CodingKeys.self)
42+
let type = try container.decode(ReceiptType.self, forKey: .type)
43+
44+
switch type {
45+
case .jws:
46+
let value = try container.decode(String.self, forKey: .value)
47+
self = .jws(value)
48+
case .receipt:
49+
let base64String = try container.decode(String.self, forKey: .value)
50+
guard let data = Data(base64Encoded: base64String) else {
51+
throw DecodingError.dataCorruptedError(
52+
forKey: .value,
53+
in: container,
54+
debugDescription: "Invalid base64 string for receipt data"
55+
)
56+
}
57+
self = .receipt(data)
58+
case .sk2receipt:
59+
let value = try container.decode(StoreKit2Receipt.self, forKey: .value)
60+
self = .sk2receipt(value)
61+
case .empty:
62+
self = .empty
63+
}
64+
}
65+
66+
func encode(to encoder: Encoder) throws {
67+
var container = encoder.container(keyedBy: CodingKeys.self)
68+
69+
switch self {
70+
case .jws(let jws):
71+
try container.encode(ReceiptType.jws, forKey: .type)
72+
try container.encode(jws, forKey: .value)
73+
case .receipt(let data):
74+
try container.encode(ReceiptType.receipt, forKey: .type)
75+
try container.encode(data.base64EncodedString(), forKey: .value)
76+
case .sk2receipt(let receipt):
77+
try container.encode(ReceiptType.sk2receipt, forKey: .type)
78+
try container.encode(receipt, forKey: .value)
79+
case .empty:
80+
try container.encode(ReceiptType.empty, forKey: .type)
81+
}
82+
}
83+
}
84+
2785
extension EncodedAppleReceipt {
2886

2987
func serialized() -> String? {

Sources/Purchasing/StoreKitAbstractions/StoreProductDiscount.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ extension StoreProductDiscount.DiscountType {
308308

309309
}
310310

311-
extension StoreProductDiscount.PaymentMode: Encodable {}
311+
extension StoreProductDiscount.PaymentMode: Codable {}
312312

313313
extension StoreProductDiscount: Identifiable {
314314

Tests/UnitTests/Purchasing/Purchases/LocalTransactionMetadataCacheTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ class LocalTransactionMetadataCacheTests: TestCase {
426426
expect(self.localTransactionMetadataCache.retrieve(forTransactionID: transactionID)) == transactionMetadata
427427
expect(self.localTransactionMetadataCache.retrieve(for: storeTransaction)) == transactionMetadata
428428
}
429+
430+
// TODO: expand tests to add new codable fields + add minimal + maximum example of all fields comparing against serialized JSON string
429431
}
430432

431433
extension LocalTransactionMetadataCacheTests {

0 commit comments

Comments
 (0)