mirror of
https://github.com/ProtonMail/protoncore_ios.git
synced 2026-01-16 23:00:24 +00:00
[CP-7427] fix: Don't check amounts and don't credit for auto-renewing subscriptions
Refs: https://gitlab.protontech.ch/apple/shared/protoncore/-/merge_requests/1657
This commit is contained in:
commit
f3b810e6f7
4 changed files with 34 additions and 23 deletions
|
|
@ -133,7 +133,7 @@ protocol PaymentsApiProtocol {
|
|||
/// Get the status of any vendor
|
||||
func paymentStatusRequest(api: APIService) -> PaymentStatusRequest
|
||||
func buySubscriptionRequest(
|
||||
api: APIService, planId: String, amount: Int, amountDue: Int, cycle: Int, paymentAction: PaymentAction
|
||||
api: APIService, planId: String, amount: Int, amountDue: Int, cycle: Int, paymentAction: PaymentAction, isCreditingAllowed: Bool
|
||||
) throws -> SubscriptionRequest
|
||||
func buySubscriptionForZeroRequest(api: APIService, planId: String) -> SubscriptionRequest
|
||||
/// Get current subscription
|
||||
|
|
@ -158,21 +158,30 @@ class PaymentsApiImplementation: PaymentsApiProtocol {
|
|||
PaymentStatusRequest(api: api)
|
||||
}
|
||||
|
||||
func buySubscriptionRequest(api: APIService, planId: String, amount: Int, amountDue: Int, cycle: Int, paymentAction: PaymentAction) throws -> SubscriptionRequest {
|
||||
guard Thread.isMainThread == false else {
|
||||
assertionFailure("This is a blocking network request, should never be called from main thread")
|
||||
throw AwaitInternalError.synchronousCallPerformedFromTheMainThread
|
||||
}
|
||||
if amountDue == amount {
|
||||
// if amountDue is equal to amount, request subscription
|
||||
return SubscriptionRequest(api: api, planId: planId, amount: amount, cycle: cycle, paymentAction: paymentAction)
|
||||
} else {
|
||||
// if amountDue is not equal to amount, request credit for a full amount
|
||||
let creditReq = creditRequest(api: api, amount: amount, paymentAction: paymentAction)
|
||||
_ = try creditReq.awaitResponse(responseObject: CreditResponse())
|
||||
// then request subscription for amountDue = 0
|
||||
return SubscriptionRequest(api: api, planId: planId, amount: 0, cycle: cycle, paymentAction: paymentAction)
|
||||
}
|
||||
func buySubscriptionRequest(api: APIService,
|
||||
planId: String,
|
||||
amount: Int,
|
||||
amountDue: Int,
|
||||
cycle: Int,
|
||||
paymentAction: PaymentAction,
|
||||
isCreditingAllowed: Bool) throws -> SubscriptionRequest {
|
||||
guard Thread.isMainThread == false else {
|
||||
assertionFailure("This is a blocking network request, should never be called from main thread")
|
||||
throw AwaitInternalError.synchronousCallPerformedFromTheMainThread
|
||||
}
|
||||
guard isCreditingAllowed else { // dynamic plans case
|
||||
return SubscriptionRequest(api: api, planId: planId, amount: amount, cycle: cycle, paymentAction: paymentAction)
|
||||
}
|
||||
if amountDue == amount {
|
||||
// if amountDue is equal to amount, request subscription
|
||||
return SubscriptionRequest(api: api, planId: planId, amount: amount, cycle: cycle, paymentAction: paymentAction)
|
||||
} else {
|
||||
// if amountDue is not equal to amount, request credit for a full amount
|
||||
let creditReq = creditRequest(api: api, amount: amount, paymentAction: paymentAction)
|
||||
_ = try creditReq.awaitResponse(responseObject: CreditResponse())
|
||||
// then request subscription for amountDue = 0
|
||||
return SubscriptionRequest(api: api, planId: planId, amount: 0, cycle: cycle, paymentAction: paymentAction)
|
||||
}
|
||||
}
|
||||
|
||||
func buySubscriptionForZeroRequest(api: APIService, planId: String) -> SubscriptionRequest {
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ final class ProcessAuthenticated: ProcessProtocol {
|
|||
|
||||
unowned let dependencies: ProcessDependencies
|
||||
let tokenHandler: TokenHandler?
|
||||
private let featureFlagsRepository: FeatureFlagsRepositoryProtocol
|
||||
let areSubscriptionsEnabled: Bool
|
||||
|
||||
init(dependencies: ProcessDependencies, featureFlagsRepository: FeatureFlagsRepositoryProtocol = FeatureFlagsRepository.shared) {
|
||||
self.dependencies = dependencies
|
||||
self.tokenHandler = TokenHandler(dependencies: dependencies)
|
||||
self.featureFlagsRepository = featureFlagsRepository
|
||||
self.areSubscriptionsEnabled = featureFlagsRepository.isEnabled(CoreFeatureFlagType.dynamicPlan)
|
||||
}
|
||||
|
||||
let queue = DispatchQueue(label: "ProcessAuthenticated async queue", qos: .userInitiated)
|
||||
|
|
@ -111,7 +111,8 @@ final class ProcessAuthenticated: ProcessProtocol {
|
|||
amount: plan.amount,
|
||||
amountDue: plan.amountDue,
|
||||
cycle: plan.cycle,
|
||||
paymentAction: .token(token: token.token)
|
||||
paymentAction: .token(token: token.token),
|
||||
isCreditingAllowed: !areSubscriptionsEnabled
|
||||
)
|
||||
let receiptRes = try request.awaitResponse(responseObject: SubscriptionResponse())
|
||||
PMLog.debug("StoreKit: success (1)")
|
||||
|
|
@ -135,7 +136,7 @@ final class ProcessAuthenticated: ProcessProtocol {
|
|||
|
||||
} catch let error where error.isPaymentAmountMismatchOrUnavailablePlanError {
|
||||
PMLog.debug("StoreKit: amount mismatch")
|
||||
if featureFlagsRepository.isEnabled(CoreFeatureFlagType.dynamicPlan){
|
||||
if areSubscriptionsEnabled {
|
||||
// we no longer credit the account for this kind of mismatch.
|
||||
finish(transaction: transaction, result: .errored(.noNewSubscriptionInSuccessfulResponse), completion: completion)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -351,7 +351,8 @@ final class ProcessUnauthenticated: ProcessUnathenticatedProtocol {
|
|||
amount: plan.amount,
|
||||
amountDue: plan.amountDue,
|
||||
cycle: plan.cycle,
|
||||
paymentAction: .token(token: token.token)
|
||||
paymentAction: .token(token: token.token),
|
||||
isCreditingAllowed: !areSubscriptionsEnabled
|
||||
)
|
||||
let receiptRes = try request.awaitResponse(responseObject: SubscriptionResponse())
|
||||
PMLog.debug("StoreKit: success (2)")
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ public final class PaymentsApiMock: PaymentsApiProtocol {
|
|||
|
||||
@ThrowingFuncStub(PaymentsApiProtocol.buySubscriptionRequest, initialReturn: { SubscriptionRequest(api: $0.0, planId: $0.1) }) public var buySubscriptionRequestStub
|
||||
public func buySubscriptionRequest(
|
||||
api: APIService, planId: String, amount: Int, amountDue: Int, cycle: Int, paymentAction: PaymentAction
|
||||
) throws -> SubscriptionRequest { try buySubscriptionRequestStub(api, planId, amount, amountDue, cycle, paymentAction) }
|
||||
api: APIService, planId: String, amount: Int, amountDue: Int, cycle: Int, paymentAction: PaymentAction, isCreditingAllowed: Bool
|
||||
) throws -> SubscriptionRequest { try buySubscriptionRequestStub(api, planId, amount, amountDue, cycle, paymentAction, isCreditingAllowed) }
|
||||
|
||||
@FuncStub(PaymentsApiProtocol.buySubscriptionForZeroRequest, initialReturn: { SubscriptionRequest(api: $0.0, planId: $0.1) }) public var buySubscriptionForZeroRequestStub
|
||||
public func buySubscriptionForZeroRequest(api: APIService, planId: String) -> SubscriptionRequest { buySubscriptionForZeroRequestStub(api, planId) }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue