Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AppleReceipt: refactored declarations into nested types #1933

Merged
merged 1 commit into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions Sources/LocalReceiptParsing/BasicTypes/AppleReceipt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,33 @@

import Foundation

// https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
struct ReceiptAttribute {
// swiftlint:disable nesting

let type: ReceiptAttributeType
let version: Int
let value: String
/// The contents of a parsed IAP receipt.
struct AppleReceipt: Equatable {

}
// swiftlint:disable:next line_length
// https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
struct Attribute {

enum ReceiptAttributeType: Int {
enum AttributeType: Int {

case bundleId = 2,
applicationVersion = 3,
opaqueValue = 4,
sha1Hash = 5,
creationDate = 12,
inAppPurchase = 17,
originalApplicationVersion = 19,
expirationDate = 21
case bundleId = 2,
applicationVersion = 3,
opaqueValue = 4,
sha1Hash = 5,
creationDate = 12,
inAppPurchase = 17,
originalApplicationVersion = 19,
expirationDate = 21

}
}

struct AppleReceipt: Equatable {
let type: AttributeType
let version: Int
let value: String

}

let bundleId: String
let applicationVersion: String
Expand Down
39 changes: 10 additions & 29 deletions Sources/LocalReceiptParsing/BasicTypes/InAppPurchase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,23 @@

import Foundation

// https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
enum InAppPurchaseAttributeType: Int {

case quantity = 1701,
productId = 1702,
transactionId = 1703,
purchaseDate = 1704,
originalTransactionId = 1705,
originalPurchaseDate = 1706,
productType = 1707,
expiresDate = 1708,
webOrderLineItemId = 1711,
cancellationDate = 1712,
isInTrialPeriod = 1713,
isInIntroOfferPeriod = 1719,
promotionalOfferIdentifier = 1721

}

enum InAppPurchaseProductType: Int {
struct InAppPurchase: Equatable {

case unknown = -1,
nonConsumable,
consumable,
nonRenewingSubscription,
autoRenewableSubscription
enum ProductType: Int {

}
case unknown = -1,
nonConsumable,
consumable,
nonRenewingSubscription,
autoRenewableSubscription

struct InAppPurchase: Equatable {
}

let quantity: Int
let productId: String
let transactionId: String
let originalTransactionId: String?
let productType: InAppPurchaseProductType?
let productType: ProductType?
let purchaseDate: Date
let originalPurchaseDate: Date?
let expiresDate: Date?
Expand Down Expand Up @@ -83,5 +64,5 @@ struct InAppPurchase: Equatable {

}

extension InAppPurchaseProductType: Codable {}
extension InAppPurchase.ProductType: Codable {}
extension InAppPurchase: Codable {}
11 changes: 6 additions & 5 deletions Sources/LocalReceiptParsing/Builders/AppleReceiptBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ class AppleReceiptBuilder {
}
let typeContainer = receiptAttribute.internalContainers[typeContainerIndex]
let valueContainer = receiptAttribute.internalContainers[attributeTypeContainerIndex]
let attributeType = ReceiptAttributeType(rawValue: typeContainer.internalPayload.toInt())
guard let nonOptionalType = attributeType else {
continue
}

guard let attributeType = AppleReceipt.Attribute.AttributeType(
rawValue: typeContainer.internalPayload.toInt()
) else { continue }

let payload = valueContainer.internalPayload

switch nonOptionalType {
switch attributeType {
case .opaqueValue:
opaqueValue = payload.toData()
case .sha1Hash:
Expand Down
26 changes: 23 additions & 3 deletions Sources/LocalReceiptParsing/Builders/InAppPurchaseBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ import Foundation

class InAppPurchaseBuilder {

// swiftlint:disable:next line_length
// https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html
enum AttributeType: Int {

case quantity = 1701,
productId = 1702,
transactionId = 1703,
purchaseDate = 1704,
originalTransactionId = 1705,
originalPurchaseDate = 1706,
productType = 1707,
expiresDate = 1708,
webOrderLineItemId = 1711,
cancellationDate = 1712,
isInTrialPeriod = 1713,
isInIntroOfferPeriod = 1719,
promotionalOfferIdentifier = 1721

}

private let containerBuilder: ASN1ContainerBuilder
private let typeContainerIndex = 0
private let versionContainerIndex = 1 // unused
Expand All @@ -23,7 +43,7 @@ class InAppPurchaseBuilder {
var productId: String?
var transactionId: String?
var originalTransactionId: String?
var productType: InAppPurchaseProductType?
var productType: InAppPurchase.ProductType?
var purchaseDate: Date?
var originalPurchaseDate: Date?
var expiresDate: Date?
Expand All @@ -40,7 +60,7 @@ class InAppPurchaseBuilder {
let typeContainer = internalContainer.internalContainers[typeContainerIndex]
let valueContainer = internalContainer.internalContainers[attributeTypeContainerIndex]

guard let attributeType = InAppPurchaseAttributeType(rawValue: typeContainer.internalPayload.toInt())
guard let attributeType = AttributeType(rawValue: typeContainer.internalPayload.toInt())
else { continue }

let internalContainer = try containerBuilder.build(fromPayload: valueContainer.internalPayload)
Expand All @@ -52,7 +72,7 @@ class InAppPurchaseBuilder {
case .webOrderLineItemId:
webOrderLineItemId = internalContainer.internalPayload.toInt64()
case .productType:
productType = InAppPurchaseProductType(rawValue: internalContainer.internalPayload.toInt())
productType = .init(rawValue: internalContainer.internalPayload.toInt())
case .isInIntroOfferPeriod:
isInIntroOfferPeriod = internalContainer.internalPayload.toBool()
case .isInTrialPeriod:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ class AppleReceiptBuilderTests: TestCase {

func testBuildGetsExpiresDate() throws {
let expirationDate = try Date.from(year: 2020, month: 7, day: 4, hour: 5, minute: 3, second: 2)
let expirationDateContainer =
containerFactory.receiptAttributeContainer(attributeType: ReceiptAttributeType.expirationDate,
expirationDate)
let expirationDateContainer = containerFactory.receiptAttributeContainer(
attributeType: AppleReceipt.Attribute.AttributeType.expirationDate,
expirationDate
)
let receiptContainer =
containerFactory.receiptContainerFromContainers(containers: minimalAttributes() + [expirationDateContainer])

Expand All @@ -76,7 +77,9 @@ class AppleReceiptBuilderTests: TestCase {
func testBuildGetsInAppPurchases() throws {
let totalInAppPurchases = Int.random(in: 5..<20)
let inAppContainers = (Int(0)..<totalInAppPurchases).map { _ in
containerFactory.receiptDataAttributeContainer(attributeType: ReceiptAttributeType.inAppPurchase)
containerFactory.receiptDataAttributeContainer(
attributeType: AppleReceipt.Attribute.AttributeType.inAppPurchase
)
}

let receiptContainer = containerFactory
Expand Down Expand Up @@ -192,30 +195,34 @@ private extension AppleReceiptBuilderTests {
private extension AppleReceiptBuilderTests {

func creationDateContainer() -> ASN1Container {
containerFactory.receiptAttributeContainer(attributeType: ReceiptAttributeType.creationDate,
containerFactory.receiptAttributeContainer(attributeType: AppleReceipt.Attribute.AttributeType.creationDate,
creationDate)
}

func sha1HashContainer() -> ASN1Container {
containerFactory.receiptDataAttributeContainer(attributeType: ReceiptAttributeType.sha1Hash)
containerFactory.receiptDataAttributeContainer(attributeType: AppleReceipt.Attribute.AttributeType.sha1Hash)
}

func opaqueValueContainer() -> ASN1Container {
containerFactory.receiptDataAttributeContainer(attributeType: ReceiptAttributeType.opaqueValue)
containerFactory.receiptDataAttributeContainer(attributeType: AppleReceipt.Attribute.AttributeType.opaqueValue)
}

func originalAppVersionContainer() -> ASN1Container {
containerFactory.receiptAttributeContainer(attributeType: ReceiptAttributeType.originalApplicationVersion,
originalApplicationVersion)
containerFactory.receiptAttributeContainer(
attributeType: AppleReceipt.Attribute.AttributeType.originalApplicationVersion,
originalApplicationVersion
)
}

func appVersionContainer() -> ASN1Container {
containerFactory.receiptAttributeContainer(attributeType: ReceiptAttributeType.applicationVersion,
applicationVersion)
containerFactory.receiptAttributeContainer(
attributeType: AppleReceipt.Attribute.AttributeType.applicationVersion,
applicationVersion
)
}

func bundleIdContainer() -> ASN1Container {
containerFactory.receiptAttributeContainer(attributeType: ReceiptAttributeType.bundleId,
containerFactory.receiptAttributeContainer(attributeType: AppleReceipt.Attribute.AttributeType.bundleId,
bundleId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import XCTest
@testable import RevenueCat

class InAppPurchaseBuilderTests: TestCase {

// swiftlint:disable force_try
let quantity = 2
let productId = "com.revenuecat.sampleProduct"
let transactionId = "089230953203"
let originalTransactionId = "089230953101"
let productType = InAppPurchaseProductType.autoRenewableSubscription
let productType = InAppPurchase.ProductType.autoRenewableSubscription
let purchaseDate = try! Date.from(year: 2019, month: 5, day: 3, hour: 1, minute: 55, second: 1)
let originalPurchaseDate = try! Date.from(year: 2018, month: 6, day: 22, hour: 1, minute: 55, second: 1)
let expiresDate = try! Date.from(year: 2018, month: 6, day: 22, hour: 1, minute: 55, second: 1)
Expand Down Expand Up @@ -269,92 +270,93 @@ private extension InAppPurchaseBuilderTests {

func quantityContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.quantity,
attributeType: InAppPurchaseBuilder.AttributeType.quantity,
quantity
)
}

func productIdContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.productId,
attributeType: InAppPurchaseBuilder.AttributeType.productId,
productId
)
}

func transactionIdContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.transactionId,
attributeType: InAppPurchaseBuilder.AttributeType.transactionId,
transactionId
)
}

func originalTransactionIdContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.originalTransactionId,
attributeType: InAppPurchaseBuilder.AttributeType.originalTransactionId,
originalTransactionId
)
}

func productTypeContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.productType,
attributeType: InAppPurchaseBuilder.AttributeType.productType,
productType.rawValue
)
}

func purchaseDateContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.purchaseDate,
attributeType: InAppPurchaseBuilder.AttributeType.purchaseDate,
purchaseDate
)
}

func originalPurchaseDateContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.originalPurchaseDate,
attributeType: InAppPurchaseBuilder.AttributeType.originalPurchaseDate,
originalPurchaseDate
)
}

func expiresDateContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.expiresDate,
attributeType: InAppPurchaseBuilder.AttributeType.expiresDate,
expiresDate
)
}

func cancellationDateContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.cancellationDate,
attributeType: InAppPurchaseBuilder.AttributeType.cancellationDate,
cancellationDate
)
}

func isInTrialPeriodContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.isInTrialPeriod,
attributeType: InAppPurchaseBuilder.AttributeType.isInTrialPeriod,
isInTrialPeriod
)
}

func isInIntroOfferPeriodContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.isInIntroOfferPeriod,
attributeType: InAppPurchaseBuilder.AttributeType.isInIntroOfferPeriod,
isInIntroOfferPeriod
)
}

func webOrderLineItemIdContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.webOrderLineItemId,
attributeType: InAppPurchaseBuilder.AttributeType.webOrderLineItemId,
webOrderLineItemId
)
}

func promotionalOfferIdentifierContainer() -> ASN1Container {
return containerFactory.receiptAttributeContainer(
attributeType: InAppPurchaseAttributeType.promotionalOfferIdentifier,
attributeType: InAppPurchaseBuilder.AttributeType.promotionalOfferIdentifier,
promotionalOfferIdentifier
)
}

}
5 changes: 3 additions & 2 deletions Tests/UnitTests/TestHelpers/ContainerFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,6 @@ private extension ContainerFactory {
protocol BuildableReceiptAttributeType {
var rawValue: Int { get }
}
extension InAppPurchaseAttributeType: BuildableReceiptAttributeType {}
extension ReceiptAttributeType: BuildableReceiptAttributeType {}

extension InAppPurchaseBuilder.AttributeType: BuildableReceiptAttributeType {}
extension AppleReceipt.Attribute.AttributeType: BuildableReceiptAttributeType {}