Skip to content

Commit

Permalink
Move Credit card to OmiseSDK
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Solovev committed Mar 4, 2024
1 parent ee6023a commit 4e9b2ff
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 209 deletions.
15 changes: 11 additions & 4 deletions ExampleApp/Views/ProductDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ class ProductDetailViewController: BaseViewController {
return true
}

override func viewDidLoad() {
super.viewDidLoad()
}

// override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// super.prepare(for: segue, sender: sender)
//
Expand Down Expand Up @@ -71,6 +67,10 @@ class ProductDetailViewController: BaseViewController {
guard currentCodePathMode == .code else {
return
}

let viewController = omiseSDK.creditCardController(delegate: self)
present(viewController, animated: true, completion: nil)

// let creditCardFormController = CreditCardPaymentController.makeCreditCardPaymentController(withPublicKey: publicKey)
// creditCardFormController.handleErrors = true
// creditCardFormController.delegate = self
Expand All @@ -82,6 +82,13 @@ class ProductDetailViewController: BaseViewController {
guard currentCodePathMode == .code else {
return
}

let nc = omiseSDK.creditCardController(delegate: self)
addChild(nc)
if let vc = nc.topViewController {
navigationController?.pushViewController(vc, animated: true)
}

// let creditCardFormController = CreditCardPaymentController.makeCreditCardPaymentController(withPublicKey: publicKey)
// creditCardFormController.handleErrors = true
// creditCardFormController.delegate = self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ extension OmiseError {
}

var localizedRecoverySuggestion: String {

enum CommonStrings: String {
case tryAgainLater = "Please try again later"
}
Expand Down
51 changes: 48 additions & 3 deletions OmiseSDK/Sources/OmiseSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ public class OmiseSDK {
/// Client is used to communicate with Omise API
public let client: Client

/// If it's `true` SDK will handle errors and will not notify ChoosePaymentMethodDelegate
public let handleErrors: Bool

/// Creates a new instance of Omise SDK that provides interface to functionallity that SDK provides
///
/// - Parameters:
/// - publicKey: Omise public key
/// - configuration: Optional configuration is used for testing
public init(publicKey: String, configuration: Configuration? = nil) {
public init(publicKey: String, handleErrors: Bool = true, configuration: Configuration? = nil) {
self.publicKey = publicKey
self.handleErrors = handleErrors
self.client = Client(
publicKey: publicKey,
version: version,
Expand Down Expand Up @@ -69,7 +73,13 @@ public class OmiseSDK {
allowedCardPayment: Bool,
delegate: ChoosePaymentMethodDelegate
) -> UINavigationController {
let paymentFlow = ChoosePaymentCoordinator(client: client, amount: amount, currency: currency, currentCountry: country)
let paymentFlow = ChoosePaymentCoordinator(
client: client,
amount: amount,
currency: currency,
currentCountry: country,
handleErrors: handleErrors
)
let viewController = paymentFlow.createChoosePaymentMethodController(
allowedPaymentMethods: allowedPaymentMethods,
allowedCardPayment: allowedCardPayment,
Expand All @@ -78,6 +88,7 @@ public class OmiseSDK {
)

let navigationController = UINavigationController(rootViewController: viewController)
navigationController.delegate = paymentFlow
return navigationController
}

Expand All @@ -93,7 +104,13 @@ public class OmiseSDK {
currency: String,
delegate: ChoosePaymentMethodDelegate
) -> UINavigationController {
let paymentFlow = ChoosePaymentCoordinator(client: client, amount: amount, currency: currency, currentCountry: country)
let paymentFlow = ChoosePaymentCoordinator(
client: client,
amount: amount,
currency: currency,
currentCountry: country,
handleErrors: handleErrors
)
let viewController = paymentFlow.createChoosePaymentMethodController(
usePaymentMethodsFromCapability: true,
delegate: delegate
Expand All @@ -104,8 +121,36 @@ public class OmiseSDK {
navigationController.navigationBar.prefersLargeTitles = true
}

navigationController.delegate = paymentFlow
return navigationController
}

/// Creates a Credit Card Controller with payment methods loaded from Capability API
///
/// - Parameters:
/// - delegate: Delegate to be notified when Source or Token is created
public func creditCardController(delegate: ChoosePaymentMethodDelegate) -> UINavigationController {
let paymentFlow = ChoosePaymentCoordinator(
client: client,
amount: 0,
currency: "",
currentCountry: country,
handleErrors: handleErrors
)
let viewController = paymentFlow.createCreditCardPaymentController(delegate: delegate)

let navigationController = UINavigationController(rootViewController: viewController)
if #available(iOSApplicationExtension 11.0, *) {
navigationController.navigationBar.prefersLargeTitles = true
}

navigationController.delegate = paymentFlow
return navigationController
}

func showAuthorizedController() {

}
}

public extension OmiseSDK {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import UIKit

extension ChoosePaymentCoordinator {
func navigate(to viewController: UIViewController) {
rootViewController?.navigationController?.pushViewController(
viewController,
animated: true
)
}

func processError(_ error: Error) {
if handleErrors {
if let error = error as? OmiseError {
displayErrorWith(title: error.localizedDescription,
message: error.localizedRecoverySuggestion,
animated: true,
sender: self)
} else if let error = error as? LocalizedError {
displayErrorWith(title: error.localizedDescription,
message: error.recoverySuggestion,
animated: true,
sender: self)
} else {
displayErrorWith(title: error.localizedDescription,
message: nil,
animated: true,
sender: self)
}
} else {
choosePaymentMethodDelegate?.choosePaymentMethodDidComplete(with: error)
}
}

func processPayment(_ card: CreateTokenPayload.Card, completion: @escaping () -> Void) {
guard let delegate = choosePaymentMethodDelegate else { return }
let tokenPayload = CreateTokenPayload(card: card)

client.createToken(payload: tokenPayload) { [weak self, weak delegate] result in
switch result {
case .success(let token):
delegate?.choosePaymentMethodDidComplete(with: token)
case .failure(let error):
self?.processError(error)
}
completion()
}
}

func processPayment(_ payment: Source.Payment, completion: @escaping () -> Void) {
guard let delegate = choosePaymentMethodDelegate else { return }
let sourcePayload = CreateSourcePayload(
amount: amount,
currency: currency,
details: payment
)

client.createSource(payload: sourcePayload) { [weak self, weak delegate] result in
switch result {
case .success(let source):
delegate?.choosePaymentMethodDidComplete(with: source)
case .failure(let error):
self?.processError(error)
}
completion()
}
}
}

extension ChoosePaymentCoordinator {
func setupErrorView() {
errorViewHeightConstraint = errorView.heightAnchor.constraint(equalToConstant: 0)
errorViewHeightConstraint?.isActive = true

let dismissErrorBannerTapGestureRecognizer = UITapGestureRecognizer(target: self,
action: #selector(self.dismissErrorMessageBanner(_:)))
errorView.addGestureRecognizer(dismissErrorBannerTapGestureRecognizer)
}

/// Displays an error banner at the top of the UI with the given error message.
///
/// - Parameters:
/// - title: Title message to be displayed in the banner
/// - message: Subtitle message to be displayed in the banner
/// - animated: Pass true to animate the presentation; otherwise, pass false
/// - sender: The object that initiated the request
func displayErrorWith(title: String, message: String?, animated: Bool, sender: Any?) {
guard let navController = rootViewController?.navigationController else { return }

errorView.titleLabel.text = title
errorView.detailLabel.text = message
navController.view.insertSubview(self.errorView, belowSubview: navController.navigationBar)

NSLayoutConstraint.activate([
errorView.topAnchor.constraint(equalTo: navController.navigationBar.bottomAnchor),
errorView.leadingAnchor.constraint(equalTo: navController.view.leadingAnchor),
errorView.trailingAnchor.constraint(equalTo: navController.view.trailingAnchor)
])

errorViewHeightConstraint?.isActive = true
navController.view.layoutIfNeeded()

let animationBlock = { [weak navController] in
guard let navController = navController else { return }
self.errorViewHeightConstraint?.isActive = false
navController.view.layoutIfNeeded()
if #available(iOS 13, *) {
navController.topViewController?.additionalSafeAreaInsets.top = self.errorView.bounds.height
} else if #available(iOS 11, *) {
navController.additionalSafeAreaInsets.top = self.errorView.bounds.height
}
}

if animated {
UIView.animate(withDuration: TimeInterval(UINavigationController.hideShowBarDuration) + 0.07,
delay: 0.0,
options: [.layoutSubviews, .beginFromCurrentState],
animations: animationBlock)
} else {
animationBlock()
}
}

@objc func dismissErrorMessageBanner(_ sender: AnyObject) {
dismissErrorMessage(animated: true, sender: sender)
}

func dismissErrorMessage(animated: Bool, sender: Any?) {
guard errorView.superview != nil, let navController = rootViewController?.navigationController else {
return
}

let animationBlock = { [weak navController] in
self.errorViewHeightConstraint?.isActive = true
navController?.view.layoutIfNeeded()
if #available(iOS 13, *) {
navController?.topViewController?.additionalSafeAreaInsets.top = 0
} else if #available(iOS 11, *) {
navController?.topViewController?.additionalSafeAreaInsets.top = 0
}
}

if animated {
UIView.animate(
withDuration: TimeInterval(UINavigationController.hideShowBarDuration),
delay: 0.0,
options: [.layoutSubviews],
animations: animationBlock
) { [weak navController] _ in
var isCompleted: Bool {
if #available(iOS 13, *) {
return navController?.topViewController?.additionalSafeAreaInsets.top == 0
} else if #available(iOS 11, *) {
return navController?.topViewController?.additionalSafeAreaInsets.top == 0
} else {
return true
}
}
guard isCompleted else { return }
self.errorView.removeFromSuperview()
}
} else {
animationBlock()
self.errorView.removeFromSuperview()
}
}
}

extension ChoosePaymentCoordinator: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
dismissErrorMessage(animated: animated, sender: nil)
}
}
Loading

0 comments on commit 4e9b2ff

Please sign in to comment.