Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/Signal/src/ViewControllers/Donations/DonateViewController+OneTimeApplePayDonation.swift
1 views
//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation
import PassKit
import SignalServiceKit
import SignalUI

extension DonateViewController {
    /// Handle Apple Pay authorization for a one-time payment.
    ///
    /// See also: code for other payment methods, such as credit/debit cards.
    func paymentAuthorizationControllerForOneTime(
        _ controller: PKPaymentAuthorizationController,
        didAuthorizePayment payment: PKPayment,
        handler completion: @escaping (PKPaymentAuthorizationResult) -> Void,
    ) {
        guard let oneTime = state.oneTime, let amount = oneTime.amount else {
            owsFail("Amount or currency code are missing")
        }

        let boostBadge = oneTime.profileBadge

        Task {
            let confirmedIntent: Stripe.ConfirmedPaymentIntent
            do {
                confirmedIntent = try await Stripe.boost(
                    amount: amount,
                    level: .boostBadge,
                    for: .applePay(payment: payment),
                )
                owsPrecondition(
                    confirmedIntent.redirectToUrl == nil,
                    "[Donations] There shouldn't be a 3DS redirect for Apple Pay",
                )
                completion(.init(status: .success, errors: nil))
            } catch {
                completion(.init(status: .failure, errors: [error]))
                owsFailDebugUnlessNetworkFailure(error)
                return
            }

            do {
                try await DonationViewsUtil.wrapInProgressView(
                    from: self,
                    operation: {
                        try await DonationViewsUtil.waitForRedemption(paymentMethod: .applePay) {
                            try await DonationSubscriptionManager.requestAndRedeemReceipt(
                                boostPaymentIntentId: confirmedIntent.paymentIntentId,
                                amount: amount,
                                paymentProcessor: .stripe,
                                paymentMethod: .applePay,
                            )
                        }
                    },
                )
                self.didCompleteDonation(receiptCredentialSuccessMode: .oneTimeBoost)
            } catch {
                owsFailDebugUnlessNetworkFailure(error)
                self.didFailDonation(
                    error: error,
                    mode: .oneTime,
                    badge: boostBadge,
                    paymentMethod: .applePay,
                )
            }
        }
    }
}