Skip to content
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = Environment.sandbox
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)
Expand All @@ -71,7 +71,7 @@ let bundleId = "com.example"
let appleRootCAs = loadRootCAs() // Specific implementation may vary
let appAppleId: Int64? = nil // appAppleId must be provided for the Production environment
let enableOnlineChecks = true
let environment = Environment.sandbox
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let verifier = try! SignedDataVerifier(rootCertificates: appleRootCAs, bundleId: bundleId, appAppleId: appAppleId, environment: environment, enableOnlineChecks: enableOnlineChecks)
Expand All @@ -95,7 +95,7 @@ let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = Environment.sandbox
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class AppStoreServerAPIClient {
///- Parameter issuerId: Your issuer ID from the Keys page in App Store Connect
///- Parameter bundleId: Your app’s bundle ID
///- Parameter environment: The environment to target
public init(signingKey: String, keyId: String, issuerId: String, bundleId: String, environment: Environment) throws {
public init(signingKey: String, keyId: String, issuerId: String, bundleId: String, environment: AppStoreEnvironment) throws {
self.signingKey = try P256.Signing.PrivateKey(pemRepresentation: signingKey)
self.keyId = keyId
self.issuerId = issuerId
Expand Down
4 changes: 2 additions & 2 deletions Sources/AppStoreServerLibrary/ChainVerifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct ChainVerifier {
self.requester = Requester()
}

func verify<T: DecodedSignedData>(signedData: String, type: T.Type, onlineVerification: Bool, environment: Environment) async -> VerificationResult<T> where T: Decodable {
func verify<T: DecodedSignedData>(signedData: String, type: T.Type, onlineVerification: Bool, environment: AppStoreEnvironment) async -> VerificationResult<T> where T: Decodable {
let header: JWTHeader;
let decodedBody: T;
do {
Expand All @@ -41,7 +41,7 @@ struct ChainVerifier {
return VerificationResult.invalid(VerificationError.INVALID_JWT_FORMAT)
}

if (environment == Environment.xcode || environment == Environment.localTesting) {
if (environment == AppStoreEnvironment.xcode || environment == AppStoreEnvironment.localTesting) {
// Data is not signed by the App Store, and verification should be skipped
// The environment MUST be checked in the public method calling this
return VerificationResult.valid(decodedBody)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
///The server environment, either sandbox or production.
///
///[environment](https://developer.apple.com/documentation/appstoreserverapi/environment)
public enum Environment: String, Decodable, Encodable, Hashable, Sendable {
public enum AppStoreEnvironment: String, Decodable, Encodable, Hashable, Sendable {
case sandbox = "Sandbox"
case production = "Production"
case xcode = "Xcode"
Expand Down
6 changes: 3 additions & 3 deletions Sources/AppStoreServerLibrary/Models/AppTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Foundation
///[AppTransaction](https://developer.apple.com/documentation/storekit/apptransaction)
public struct AppTransaction: DecodedSignedData, Decodable, Encodable, Hashable, Sendable {

public init(receiptType: Environment? = nil, appAppleId: Int64? = nil, bundleId: String? = nil, applicationVersion: String? = nil, versionExternalIdentifier: Int64? = nil, receiptCreationDate: Date? = nil, originalPurchaseDate: Date? = nil, originalApplicationVersion: String? = nil, deviceVerification: String? = nil, deviceVerificationNonce: UUID? = nil, preorderDate: Date? = nil) {
public init(receiptType: AppStoreEnvironment? = nil, appAppleId: Int64? = nil, bundleId: String? = nil, applicationVersion: String? = nil, versionExternalIdentifier: Int64? = nil, receiptCreationDate: Date? = nil, originalPurchaseDate: Date? = nil, originalApplicationVersion: String? = nil, deviceVerification: String? = nil, deviceVerificationNonce: UUID? = nil, preorderDate: Date? = nil) {
self.receiptType = receiptType
self.appAppleId = appAppleId
self.bundleId = bundleId
Expand Down Expand Up @@ -39,9 +39,9 @@ public struct AppTransaction: DecodedSignedData, Decodable, Encodable, Hashable,
///The server environment that signs the app transaction.
///
///[environment](https://developer.apple.com/documentation/storekit/apptransaction/3963901-environment)
public var receiptType: Environment? {
public var receiptType: AppStoreEnvironment? {
get {
return rawReceiptType.flatMap { Environment(rawValue: $0) }
return rawReceiptType.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawReceiptType = newValue.map { $0.rawValue }
Expand Down
6 changes: 3 additions & 3 deletions Sources/AppStoreServerLibrary/Models/HistoryResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
///[HistoryResponse](https://developer.apple.com/documentation/appstoreserverapi/historyresponse)
public struct HistoryResponse: Decodable, Encodable, Hashable, Sendable {

public init(revision: String? = nil, hasMore: Bool? = nil, bundleId: String? = nil, appAppleId: Int64? = nil, environment: Environment? = nil, signedTransactions: [String]? = nil) {
public init(revision: String? = nil, hasMore: Bool? = nil, bundleId: String? = nil, appAppleId: Int64? = nil, environment: AppStoreEnvironment? = nil, signedTransactions: [String]? = nil) {
self.revision = revision
self.hasMore = hasMore
self.bundleId = bundleId
Expand Down Expand Up @@ -46,9 +46,9 @@ public struct HistoryResponse: Decodable, Encodable, Hashable, Sendable {
///The server environment in which you’re making the request, whether sandbox or production.
///
///[environment](https://developer.apple.com/documentation/appstoreserverapi/environment)
public var environment: Environment? {
public var environment: AppStoreEnvironment? {
get {
return rawEnvironment.flatMap { Environment(rawValue: $0) }
return rawEnvironment.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawEnvironment = newValue.map { $0.rawValue }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Foundation
///[JWSRenewalInfoDecodedPayload](https://developer.apple.com/documentation/appstoreserverapi/jwsrenewalinfodecodedpayload)
public struct JWSRenewalInfoDecodedPayload: DecodedSignedData, Decodable, Encodable, Hashable, Sendable {

public init(expirationIntent: ExpirationIntent? = nil, originalTransactionId: String? = nil, autoRenewProductId: String? = nil, productId: String? = nil, autoRenewStatus: AutoRenewStatus? = nil, isInBillingRetryPeriod: Bool? = nil, priceIncreaseStatus: PriceIncreaseStatus? = nil, gracePeriodExpiresDate: Date? = nil, offerType: OfferType? = nil, offerIdentifier: String? = nil, signedDate: Date? = nil, environment: Environment? = nil, recentSubscriptionStartDate: Date? = nil, renewalDate: Date? = nil, currency: String? = nil, renewalPrice: Int64? = nil, offerDiscountType: OfferDiscountType? = nil, eligibleWinBackOfferIds: [String]? = nil) {
public init(expirationIntent: ExpirationIntent? = nil, originalTransactionId: String? = nil, autoRenewProductId: String? = nil, productId: String? = nil, autoRenewStatus: AutoRenewStatus? = nil, isInBillingRetryPeriod: Bool? = nil, priceIncreaseStatus: PriceIncreaseStatus? = nil, gracePeriodExpiresDate: Date? = nil, offerType: OfferType? = nil, offerIdentifier: String? = nil, signedDate: Date? = nil, environment: AppStoreEnvironment? = nil, recentSubscriptionStartDate: Date? = nil, renewalDate: Date? = nil, currency: String? = nil, renewalPrice: Int64? = nil, offerDiscountType: OfferDiscountType? = nil, eligibleWinBackOfferIds: [String]? = nil) {
self.expirationIntent = expirationIntent
self.originalTransactionId = originalTransactionId
self.autoRenewProductId = autoRenewProductId
Expand Down Expand Up @@ -146,9 +146,9 @@ public struct JWSRenewalInfoDecodedPayload: DecodedSignedData, Decodable, Encoda
///The server environment, either sandbox or production.
///
///[environment](https://developer.apple.com/documentation/appstoreserverapi/environment)
public var environment: Environment? {
public var environment: AppStoreEnvironment? {
get {
return rawEnvironment.flatMap { Environment(rawValue: $0) }
return rawEnvironment.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawEnvironment = newValue.map { $0.rawValue }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Foundation
///[JWSTransactionDecodedPayload](https://developer.apple.com/documentation/appstoreserverapi/jwstransactiondecodedpayload)
public struct JWSTransactionDecodedPayload: DecodedSignedData, Decodable, Encodable, Hashable, Sendable {

public init(originalTransactionId: String? = nil, transactionId: String? = nil, webOrderLineItemId: String? = nil, bundleId: String? = nil, productId: String? = nil, subscriptionGroupIdentifier: String? = nil, purchaseDate: Date? = nil, originalPurchaseDate: Date? = nil, expiresDate: Date? = nil, quantity: Int32? = nil, type: ProductType? = nil, appAccountToken: UUID? = nil, inAppOwnershipType: InAppOwnershipType? = nil, signedDate: Date? = nil, revocationReason: RevocationReason? = nil, revocationDate: Date? = nil, isUpgraded: Bool? = nil, offerType: OfferType? = nil, offerIdentifier: String? = nil, environment: Environment? = nil, storefront: String? = nil, storefrontId: String? = nil, transactionReason: TransactionReason? = nil, currency: String? = nil, price: Int64? = nil, offerDiscountType: OfferDiscountType? = nil) {
public init(originalTransactionId: String? = nil, transactionId: String? = nil, webOrderLineItemId: String? = nil, bundleId: String? = nil, productId: String? = nil, subscriptionGroupIdentifier: String? = nil, purchaseDate: Date? = nil, originalPurchaseDate: Date? = nil, expiresDate: Date? = nil, quantity: Int32? = nil, type: ProductType? = nil, appAccountToken: UUID? = nil, inAppOwnershipType: InAppOwnershipType? = nil, signedDate: Date? = nil, revocationReason: RevocationReason? = nil, revocationDate: Date? = nil, isUpgraded: Bool? = nil, offerType: OfferType? = nil, offerIdentifier: String? = nil, environment: AppStoreEnvironment? = nil, storefront: String? = nil, storefrontId: String? = nil, transactionReason: TransactionReason? = nil, currency: String? = nil, price: Int64? = nil, offerDiscountType: OfferDiscountType? = nil) {
self.originalTransactionId = originalTransactionId
self.transactionId = transactionId
self.webOrderLineItemId = webOrderLineItemId
Expand Down Expand Up @@ -202,9 +202,9 @@ public struct JWSTransactionDecodedPayload: DecodedSignedData, Decodable, Encoda
///The server environment, either sandbox or production.
///
/// [environment](https://developer.apple.com/documentation/appstoreserverapi/environment)
public var environment: Environment? {
public var environment: AppStoreEnvironment? {
get {
return rawEnvironment.flatMap { Environment(rawValue: $0) }
return rawEnvironment.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawEnvironment = newValue.map { $0.rawValue }
Expand Down
6 changes: 3 additions & 3 deletions Sources/AppStoreServerLibrary/Models/NotificationData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
///[data](https://developer.apple.com/documentation/appstoreservernotifications/data)
public struct NotificationData: Decodable, Encodable, Hashable, Sendable {

public init(environment: Environment? = nil, appAppleId: Int64? = nil, bundleId: String? = nil, bundleVersion: String? = nil, signedTransactionInfo: String? = nil, signedRenewalInfo: String? = nil, status: Status? = nil, consumptionRequestReason: ConsumptionRequestReason? = nil) {
public init(environment: AppStoreEnvironment? = nil, appAppleId: Int64? = nil, bundleId: String? = nil, bundleVersion: String? = nil, signedTransactionInfo: String? = nil, signedRenewalInfo: String? = nil, status: Status? = nil, consumptionRequestReason: ConsumptionRequestReason? = nil) {
self.environment = environment
self.appAppleId = appAppleId
self.bundleId = bundleId
Expand All @@ -30,9 +30,9 @@ public struct NotificationData: Decodable, Encodable, Hashable, Sendable {
///The server environment that the notification applies to, either sandbox or production.
///
///[environment](https://developer.apple.com/documentation/appstoreservernotifications/environment)
public var environment: Environment? {
public var environment: AppStoreEnvironment? {
get {
return rawEnvironment.flatMap { Environment(rawValue: $0) }
return rawEnvironment.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawEnvironment = newValue.map { $0.rawValue }
Expand Down
6 changes: 3 additions & 3 deletions Sources/AppStoreServerLibrary/Models/StatusResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
///[StatusResponse](https://developer.apple.com/documentation/appstoreserverapi/statusresponse)
public struct StatusResponse: Decodable, Encodable, Hashable, Sendable {

public init(environment: Environment? = nil, bundleId: String? = nil, appAppleId: Int64? = nil, data: [SubscriptionGroupIdentifierItem]? = nil) {
public init(environment: AppStoreEnvironment? = nil, bundleId: String? = nil, appAppleId: Int64? = nil, data: [SubscriptionGroupIdentifierItem]? = nil) {
self.environment = environment
self.bundleId = bundleId
self.appAppleId = appAppleId
Expand All @@ -22,9 +22,9 @@ public struct StatusResponse: Decodable, Encodable, Hashable, Sendable {
///The server environment, sandbox or production, in which the App Store generated the response.
///
///[environment](https://developer.apple.com/documentation/appstoreserverapi/environment)
public var environment: Environment? {
public var environment: AppStoreEnvironment? {
get {
return rawEnvironment.flatMap { Environment(rawValue: $0) }
return rawEnvironment.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawEnvironment = newValue.map { $0.rawValue }
Expand Down
6 changes: 3 additions & 3 deletions Sources/AppStoreServerLibrary/Models/Summary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
///[summary](https://developer.apple.com/documentation/appstoreservernotifications/summary)
public struct Summary: Decodable, Encodable, Hashable, Sendable {

public init(environment: Environment? = nil, appAppleId: Int64? = nil, bundleId: String? = nil, productId: String? = nil, requestIdentifier: String? = nil, storefrontCountryCodes: [String]? = nil, succeededCount: Int64? = nil, failedCount: Int64? = nil) {
public init(environment: AppStoreEnvironment? = nil, appAppleId: Int64? = nil, bundleId: String? = nil, productId: String? = nil, requestIdentifier: String? = nil, storefrontCountryCodes: [String]? = nil, succeededCount: Int64? = nil, failedCount: Int64? = nil) {
self.environment = environment
self.appAppleId = appAppleId
self.bundleId = bundleId
Expand All @@ -30,9 +30,9 @@ public struct Summary: Decodable, Encodable, Hashable, Sendable {
///The server environment that the notification applies to, either sandbox or production.
///
///[environment](https://developer.apple.com/documentation/appstoreservernotifications/environment)
public var environment: Environment? {
public var environment: AppStoreEnvironment? {
get {
return rawEnvironment.flatMap { Environment(rawValue: $0) }
return rawEnvironment.flatMap { AppStoreEnvironment(rawValue: $0) }
}
set {
self.rawEnvironment = newValue.map { $0.rawValue }
Expand Down
10 changes: 5 additions & 5 deletions Sources/AppStoreServerLibrary/SignedDataVerifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public struct SignedDataVerifier {

private var bundleId: String
private var appAppleId: Int64?
private var environment: Environment
private var environment: AppStoreEnvironment
private var chainVerifier: ChainVerifier
private var enableOnlineChecks: Bool

Expand All @@ -21,7 +21,7 @@ public struct SignedDataVerifier {
/// - Parameter environment: The server environment, either sandbox or production.
/// - Parameter enableOnlineChecks: Whether to enable revocation checking and check expiration using the current date
/// - Throws: When the root certificates are malformed
public init(rootCertificates: [Data], bundleId: String, appAppleId: Int64?, environment: Environment, enableOnlineChecks: Bool) throws {
public init(rootCertificates: [Data], bundleId: String, appAppleId: Int64?, environment: AppStoreEnvironment, enableOnlineChecks: Bool) throws {

guard !(environment == .production && appAppleId == nil) else {
throw ConfigurationError.INVALID_APP_APPLE_ID
Expand Down Expand Up @@ -79,13 +79,13 @@ public struct SignedDataVerifier {
return await verifyAndDecodeNotification(signedPayload: signedPayload, validateNotification: self.verifyNotificationAppIdentifierAndEnvironment)
}

internal func verifyAndDecodeNotification(signedPayload: String, validateNotification: (_ appBundleID: String?, _ appAppleID: Int64?, _ environment: Environment?) -> VerificationError?) async -> VerificationResult<ResponseBodyV2DecodedPayload> {
internal func verifyAndDecodeNotification(signedPayload: String, validateNotification: (_ appBundleID: String?, _ appAppleID: Int64?, _ environment: AppStoreEnvironment?) -> VerificationError?) async -> VerificationResult<ResponseBodyV2DecodedPayload> {
let notificationResult = await decodeSignedData(signedData: signedPayload, type: ResponseBodyV2DecodedPayload.self)
switch notificationResult {
case .valid(let notification):
let appAppleId: Int64?
let bundleId : String?
let environment: Environment?
let environment: AppStoreEnvironment?
if let data = notification.data {
appAppleId = data.appAppleId
bundleId = data.bundleId
Expand Down Expand Up @@ -116,7 +116,7 @@ public struct SignedDataVerifier {
return notificationResult
}

internal func verifyNotificationAppIdentifierAndEnvironment(bundleId: String?, appAppleId: Int64?, environment: Environment?) -> VerificationError? {
internal func verifyNotificationAppIdentifierAndEnvironment(bundleId: String?, appAppleId: Int64?, environment: AppStoreEnvironment?) -> VerificationError? {
if self.bundleId != bundleId || (self.environment == .production && self.appAppleId != appAppleId) {
return .INVALID_APP_IDENTIFIER
}
Expand Down
Loading