Skip to content

Commit

Permalink
Introduce transaction log to prevent handling already processed trans…
Browse files Browse the repository at this point in the history
…actions
  • Loading branch information
Andrej Mihajlov committed Oct 27, 2023
1 parent 1de3f4e commit 5aa67bc
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 90 deletions.
6 changes: 5 additions & 1 deletion ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
58F2E14C276A61C000A79513 /* RotateKeyOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F2E14B276A61C000A79513 /* RotateKeyOperation.swift */; };
58F3C0A4249CB069003E76BE /* HeaderBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F3C0A3249CB069003E76BE /* HeaderBarView.swift */; };
58F3F36A2AA08E3C00D3B0A4 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F3F3692AA08E3C00D3B0A4 /* PacketTunnelProvider.swift */; };
58F70FE52AEA707800E6890E /* StoreTransactionLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F70FE42AEA707800E6890E /* StoreTransactionLog.swift */; };
58F7753D2AB8473200425B47 /* BlockedStateErrorMapperStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F7753C2AB8473200425B47 /* BlockedStateErrorMapperStub.swift */; };
58F8AC0E25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */; };
58FB865526E8BF3100F188BC /* StorePaymentManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FB865426E8BF3100F188BC /* StorePaymentManagerError.swift */; };
Expand Down Expand Up @@ -1479,6 +1480,7 @@
58F3C0A524A50155003E76BE /* relays.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = relays.json; sourceTree = "<group>"; };
58F3F3652AA086A400D3B0A4 /* AutoCancellingTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCancellingTask.swift; sourceTree = "<group>"; };
58F3F3692AA08E3C00D3B0A4 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
58F70FE42AEA707800E6890E /* StoreTransactionLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreTransactionLog.swift; sourceTree = "<group>"; };
58F7753C2AB8473200425B47 /* BlockedStateErrorMapperStub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedStateErrorMapperStub.swift; sourceTree = "<group>"; };
58F7D26427EB50A300E4D821 /* ResultOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultOperation.swift; sourceTree = "<group>"; };
58F8AC0D25D3F8CE002BE0ED /* ProblemReportReviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProblemReportReviewViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2279,14 +2281,15 @@
5846226F26E229CD0035F7C2 /* StorePaymentManager */ = {
isa = PBXGroup;
children = (
5878A27629093A4F0096FC88 /* StorePaymentBlockObserver.swift */,
585E820227F3285E00939F0E /* SendStoreReceiptOperation.swift */,
5878A27629093A4F0096FC88 /* StorePaymentBlockObserver.swift */,
5878A27429093A310096FC88 /* StorePaymentEvent.swift */,
58DF28A42417CB4B00E836B0 /* StorePaymentManager.swift */,
5846227626E22A7C0035F7C2 /* StorePaymentManagerDelegate.swift */,
58FB865426E8BF3100F188BC /* StorePaymentManagerError.swift */,
5846227226E22A160035F7C2 /* StorePaymentObserver.swift */,
5846227026E229F20035F7C2 /* StoreSubscription.swift */,
58F70FE42AEA707800E6890E /* StoreTransactionLog.swift */,
);
path = StorePaymentManager;
sourceTree = "<group>";
Expand Down Expand Up @@ -4342,6 +4345,7 @@
5878A279290954790096FC88 /* TunnelViewControllerInteractor.swift in Sources */,
7A818F1F29F0305800C7F0F4 /* RootConfiguration.swift in Sources */,
7A9CCCBF2A96302800DD6A34 /* SettingsCoordinator.swift in Sources */,
58F70FE52AEA707800E6890E /* StoreTransactionLog.swift in Sources */,
582AE3102440A6CA00E6733A /* InputTextFormatter.swift in Sources */,
7A9CCCBA2A96302800DD6A34 /* CreateAccountVoucherCoordinator.swift in Sources */,
5820EDAB288FF0D2006BF4E4 /* DeviceRowView.swift in Sources */,
Expand Down
7 changes: 4 additions & 3 deletions ios/MullvadVPN/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
tunnelManager.addObserver(relayConstraintsObserver)

storePaymentManager = StorePaymentManager(
application: application,
backgroundTaskProvider: application,
queue: .default(),
apiProxy: apiProxy,
accountsProxy: accountsProxy
accountsProxy: accountsProxy,
transactionLog: .default
)

let urlSessionTransport = URLSessionTransport(urlSession: REST.makeURLSession())
Expand Down Expand Up @@ -448,7 +449,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
self.logger.debug("Finished initialization.")

NotificationManager.shared.updateNotifications()
self.storePaymentManager.startPaymentQueueMonitoring()
self.storePaymentManager.start()

finish(nil)
}
Expand Down
22 changes: 22 additions & 0 deletions ios/MullvadVPN/StorePaymentManager/StorePaymentEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ import Foundation
import MullvadREST
import StoreKit

/// The payment event received by observers implementing ``StorePaymentObserver``.
enum StorePaymentEvent {
/// The payment is successfully completed.
case finished(StorePaymentCompletion)

/// Failure to complete the payment.
case failure(StorePaymentFailure)

/// An instance of `SKPayment` held in the associated value.
var payment: SKPayment {
switch self {
case let .finished(completion):
Expand All @@ -24,15 +29,32 @@ enum StorePaymentEvent {
}
}

/// Successful payment metadata.
struct StorePaymentCompletion {
/// Transaction object.
let transaction: SKPaymentTransaction

/// The account number credited.
let accountNumber: String

/// The server response received after uploading the AppStore receipt.
let serverResponse: REST.CreateApplePaymentResponse
}

/// Failed payment metadata.
struct StorePaymentFailure {
/// Transaction object, if available.
/// May not be available due to account validation failure.
let transaction: SKPaymentTransaction?

/// The payment object associated with payment request.
let payment: SKPayment

/// The account number to credit.
/// May not be available if the payment manager couldn't establish the association between the payment and account number.
/// Typically in such case, the error would be set to ``StorePaymentManagerError/noAccountSet``.
let accountNumber: String?

/// The payment manager error.
let error: StorePaymentManagerError
}
Loading

0 comments on commit 5aa67bc

Please sign in to comment.