๐Ÿ“ฆ manideepk90 / react-native-hyperswitch-sdk

๐Ÿ“„ PaymentMethodManagementViewController.swift ยท 142 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142//
//  PaymentMethodManagementViewController.swift
//  hyperSwitch
//
//  Created by Kuntimaddi Manideep on 19/12/25.
//


import Foundation
import WebKit
import Combine
import SwiftUI

class PaymentMethodManagementViewController: UIViewController {
    @ObservedObject var hyperViewModel = HyperViewModel()
    private var paymentSession: PaymentSession?
    private var cancellables = Set<AnyCancellable>()
    private let topBarView = UIView()
    private let textLabel = UILabel()
    private let backButton = UIButton(type: .custom)
    
    private func setupPaymentWidget(onAddPaymentMethod: @escaping () -> Void) {
        guard hyperViewModel.paymentSession != nil else { return }
        
        lazy var paymentWidget = PaymentMethodManagementWidget(
            onAddPaymentMethod: onAddPaymentMethod,
            completion: { result in
                switch result {
                case .failed(let error):
                    print("Payment Method Management failed: \(error)")
                case .closed:
                    print("Payment Method Management closed.")
                }
            }
        )
        
        view.addSubview(paymentWidget)
        paymentWidget.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            paymentWidget.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            paymentWidget.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            paymentWidget.topAnchor.constraint(equalTo: topBarView.bottomAnchor),
            paymentWidget.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])
    }
    
    private func asyncBindPaymentManagementWidget(onAddPaymentMethod: @escaping () -> Void) {
        hyperViewModel.$status
            .receive(on: DispatchQueue.main)
            .sink { [weak self] status in
                switch status {
                case .loading:
                    print("Loading payment method management session...")
                case .success:
                    self?.setupPaymentWidget(onAddPaymentMethod: onAddPaymentMethod)
                case .failure(let error):
                    print("Failed to prepare payment method management session: \(error)")
                }
            }
            .store(in: &cancellables)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .green
        viewFrame()
        hyperViewModel.preparePaymentMethodManagement()
        asyncBindPaymentManagementWidget(onAddPaymentMethod: onAddPaymentMethod)
    }
    
    @objc func onAddPaymentMethod() -> Void {
        var configuration = PaymentSheet.Configuration()
        configuration.primaryButtonLabel = "Purchase ($0.00)"
        configuration.paymentSheetHeaderLabel = "Add payment method"
        configuration.displaySavedPaymentMethods = false
        
        var appearance = PaymentSheet.Appearance()
        appearance.colors.background = UIColor(red: 0.96, green: 0.97, blue: 0.98, alpha: 1.00)
        appearance.primaryButton.cornerRadius = 32
        configuration.appearance = appearance
        
        self.hyperViewModel.paymentSession?.presentPaymentSheet(viewController: self, configuration: configuration, completion: { result in
            DispatchQueue.main.async {
                switch result {
                case .completed:
                    self.showAlert(title: "Success", message: "Successfully saved the payment method")
                    self.hyperViewModel.preparePaymentMethodManagement()
                case .failed(let error):
                    self.showAlert(title: "Error", message: "Failure: \(error.localizedDescription)")
                    self.hyperViewModel.preparePaymentMethodManagement()
                case .canceled:
                    break
                }
            }
        })
    }
    
    @objc func backButtonTapped() {
        self.dismiss(animated: true, completion: nil)
    }
}

extension PaymentMethodManagementViewController {
    func viewFrame() {
        view.addSubview(topBarView)
        topBarView.translatesAutoresizingMaskIntoConstraints = false
        topBarView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        topBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        topBarView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        topBarView.heightAnchor.constraint(equalToConstant: 65).isActive = true
        
        backButton.setImage(UIImage(systemName: "chevron.left"), for: .normal)
        backButton.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
        topBarView.addSubview(backButton)
        backButton.translatesAutoresizingMaskIntoConstraints = false
        backButton.topAnchor.constraint(equalTo: topBarView.topAnchor, constant: 20).isActive = true
        backButton.leadingAnchor.constraint(equalTo: topBarView.leadingAnchor, constant: 10).isActive = true
        backButton.widthAnchor.constraint(equalToConstant: 25).isActive = true
        backButton.heightAnchor.constraint(equalToConstant: 25).isActive = true
        
        textLabel.text = "Hyperswitch"
        textLabel.font = .boldSystemFont(ofSize: 16.5)
        topBarView.addSubview(textLabel)
        textLabel.translatesAutoresizingMaskIntoConstraints = false
        textLabel.topAnchor.constraint(equalTo: topBarView.topAnchor, constant: 23.5).isActive = true
        textLabel.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 4).isActive = true
        textLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
        
    }
}

extension PaymentMethodManagementViewController {
    func showAlert(title: String, message: String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(okAction)
        DispatchQueue.main.async {
            self.present(alertController, animated: true, completion: nil)
        }
    }
}