diff --git a/.swiftlint.yml b/.swiftlint.yml
index 3420abbe04..9b55eddd33 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -5,6 +5,7 @@ disabled_rules:
- operator_whitespace
- unused_closure_parameter
- todo
+ - fallthrough
#Review:
- large_tuple
diff --git a/Adyen.xcodeproj/project.pbxproj b/Adyen.xcodeproj/project.pbxproj
index 569a7a8a0c..f6fa996ad0 100644
--- a/Adyen.xcodeproj/project.pbxproj
+++ b/Adyen.xcodeproj/project.pbxproj
@@ -884,7 +884,6 @@
E20AD0061EFAB0310065B70E /* Headers */,
E20AD0071EFAB0310065B70E /* Resources */,
E226F1431EFCF50A009E04C9 /* SwiftLint */,
- 02474A22ADD502EEE43DCD38 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -904,7 +903,6 @@
E20AD00F1EFAB0310065B70E /* Frameworks */,
E20AD0101EFAB0310065B70E /* Resources */,
B2D23B80357D0CC2DABA91CB /* [CP] Embed Pods Frameworks */,
- 8DAFF072F5EADA4FC2A33B45 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -943,7 +941,6 @@
E2E9D0181F0389C80056E0AC /* Frameworks */,
E2E9D0191F0389C80056E0AC /* Resources */,
2DC1652936EDFD1499FBF286 /* [CP] Embed Pods Frameworks */,
- 6F9EB542D6DFC7ED0AD003A8 /* [CP] Copy Pods Resources */,
E250E1431F0E606000BFFF2F /* Embed Frameworks */,
);
buildRules = (
@@ -963,7 +960,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
- LastUpgradeCheck = 0910;
+ LastUpgradeCheck = 0930;
ORGANIZATIONNAME = Adyen;
TargetAttributes = {
E20AD0081EFAB0310065B70E = {
@@ -1066,21 +1063,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
- 02474A22ADD502EEE43DCD38 /* [CP] Copy Pods Resources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Copy Pods Resources";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Adyen/Pods-Adyen-resources.sh\"\n";
- showEnvVarsInLog = 0;
- };
2DC1652936EDFD1499FBF286 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -1117,36 +1099,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
- 6F9EB542D6DFC7ED0AD003A8 /* [CP] Copy Pods Resources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Copy Pods Resources";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AdyenUIHost/Pods-AdyenUIHost-resources.sh\"\n";
- showEnvVarsInLog = 0;
- };
- 8DAFF072F5EADA4FC2A33B45 /* [CP] Copy Pods Resources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Copy Pods Resources";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AdyenTests/Pods-AdyenTests-resources.sh\"\n";
- showEnvVarsInLog = 0;
- };
B07087D0BC32240A0F60E2AC /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -1405,6 +1357,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -1412,6 +1365,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -1420,7 +1374,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 1.17.1;
+ CURRENT_PROJECT_VERSION = 1.18.0;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1465,6 +1419,7 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
@@ -1472,6 +1427,7 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
@@ -1480,7 +1436,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 1.17.1;
+ CURRENT_PROJECT_VERSION = 1.18.0;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -1509,7 +1465,7 @@
buildSettings = {
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1.17.1;
+ DYLIB_CURRENT_VERSION = 1.18.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = Adyen/Info.plist;
@@ -1528,7 +1484,7 @@
buildSettings = {
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 1.17.1;
+ DYLIB_CURRENT_VERSION = 1.18.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = Adyen/Info.plist;
diff --git a/Adyen.xcodeproj/xcshareddata/xcschemes/Adyen.xcscheme b/Adyen.xcodeproj/xcshareddata/xcschemes/Adyen.xcscheme
index 81f4b092a9..3038d673d6 100644
--- a/Adyen.xcodeproj/xcshareddata/xcschemes/Adyen.xcscheme
+++ b/Adyen.xcodeproj/xcshareddata/xcschemes/Adyen.xcscheme
@@ -1,6 +1,6 @@
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/Adyen/Core/CurrencyFormatter.swift b/Adyen/Core/CurrencyFormatter.swift
index 9881f7b732..44c55df449 100644
--- a/Adyen/Core/CurrencyFormatter.swift
+++ b/Adyen/Core/CurrencyFormatter.swift
@@ -6,25 +6,27 @@
import Foundation
-/// Convenience class to format a number with a given currency.
-internal class CurrencyFormatter {
+/// Convenience class to format a payment amount for display.
+public final class AmountFormatter {
- // MARK: - Initialization
+ // MARK: - Public
- private init() {
-
+ /// Formats a string based on the provided amount and currency code.
+ ///
+ /// - Parameters:
+ /// - amount: Amount in minor units, i.e. 2000.
+ /// - currencyCode: The currency code, i.e. "USD".
+ /// - Returns: A formatted string, i.e. "$20.00".
+ public static func formatted(amount: Int, currencyCode: String) -> String? {
+ let decimalAmount = AmountFormatter.decimalAmount(amount, currencyCode: currencyCode)
+ return defaultFormatter(currencyCode: currencyCode).string(from: decimalAmount)
}
// MARK: - Internal
- internal static func formatted(amount: Int, currencyCode: String) -> String? {
- let decimalAmount = CurrencyFormatter.decimalAmount(amount, currencyCode: currencyCode)
- return defaultFormatter(currencyCode: currencyCode).string(from: decimalAmount)
- }
-
internal static func decimalAmount(_ amount: Int, currencyCode: String) -> NSDecimalNumber {
- let defaultFormatter = CurrencyFormatter.defaultFormatter(currencyCode: currencyCode)
- let maximumFractionDigits = CurrencyFormatter.maximumFractionDigits(for: currencyCode)
+ let defaultFormatter = AmountFormatter.defaultFormatter(currencyCode: currencyCode)
+ let maximumFractionDigits = AmountFormatter.maximumFractionDigits(for: currencyCode)
defaultFormatter.maximumFractionDigits = maximumFractionDigits
let decimalMinorAmount = NSDecimalNumber(value: amount)
diff --git a/Adyen/Core/Enum/InputType.swift b/Adyen/Core/Enum/InputType.swift
index 42e683d40a..9b1aca2ac5 100644
--- a/Adyen/Core/Enum/InputType.swift
+++ b/Adyen/Core/Enum/InputType.swift
@@ -93,8 +93,8 @@ public enum InputType: RawRepresentable, Equatable {
return true
case (.cvc, .cvc):
return true
- case let (.cardToken(a), .cardToken(b)):
- return a == b
+ case let (.cardToken(first), .cardToken(second)):
+ return first == second
case (.applePayToken, .applePayToken):
return true
case (.address, .address):
diff --git a/Adyen/Core/InputDetail.swift b/Adyen/Core/InputDetail.swift
index c9eca1a315..4b599777fe 100644
--- a/Adyen/Core/InputDetail.swift
+++ b/Adyen/Core/InputDetail.swift
@@ -65,7 +65,7 @@ public class InputDetail {
let selectItems: [InputSelectItem]? = items.count > 0 ? items : nil
// Embedded Input Details
- let inputDetails = (info["inputDetails"] as? [[String: Any]])?.flatMap { InputDetail(info: $0) }
+ let inputDetails = (info["inputDetails"] as? [[String: Any]])?.compactMap { InputDetail(info: $0) }
self.init(type: type, key: key, value: value, optional: optional, items: selectItems, inputDetails: inputDetails, configuration: configuration)
}
diff --git a/Adyen/Core/PaymentMethod.swift b/Adyen/Core/PaymentMethod.swift
index 7101581897..c189e552f7 100644
--- a/Adyen/Core/PaymentMethod.swift
+++ b/Adyen/Core/PaymentMethod.swift
@@ -42,7 +42,7 @@ public final class PaymentMethod: Equatable {
let logoURL = URL(string: logoBaseURL + type + UIScreen.retinaExtension() + ".png")
let inputDetailDescriptions = info["inputDetails"] as? [[String: Any]]
- let inputDetails = inputDetailDescriptions?.flatMap { InputDetail(info: $0) }
+ let inputDetails = inputDetailDescriptions?.compactMap { InputDetail(info: $0) }
var group: Group?
if let groupInfo = info["group"] as? [String: Any] {
diff --git a/Adyen/Core/PaymentRequestToken.swift b/Adyen/Core/PaymentRequestToken.swift
index f21f8648f2..2c0d8ed4ef 100644
--- a/Adyen/Core/PaymentRequestToken.swift
+++ b/Adyen/Core/PaymentRequestToken.swift
@@ -31,8 +31,12 @@ internal struct PaymentRequestToken: Encodable {
/// The version of the device's system.
internal var systemVersion = UIDevice.current.systemVersion
- /// The identifier of the device's locale.
- internal var localeIdentifier = NSLocale.current.identifier
+ /// The identifier of the device's locale in the format aa_BB, where "aa" is language code and "BB" is region code.
+ internal var localeIdentifier: String = {
+ let languageCode = NSLocale.current.languageCode ?? ""
+ let regionCode = NSLocale.current.regionCode ?? ""
+ return "\(languageCode)_\(regionCode)"
+ }()
/// A string identifying the device.
internal var deviceIdentifier = UIDevice.current.identifierForVendor?.uuidString ?? ""
diff --git a/Adyen/Core/PaymentSetup.swift b/Adyen/Core/PaymentSetup.swift
index 5ac7193e32..d785eb77b8 100644
--- a/Adyen/Core/PaymentSetup.swift
+++ b/Adyen/Core/PaymentSetup.swift
@@ -54,21 +54,21 @@ internal struct PaymentSetup {
self.paymentData = paymentData
let preferredPaymentMethodDictionaries = dictionary["recurringDetails"] as? [[String: Any]] ?? []
- self.preferredPaymentMethods = preferredPaymentMethodDictionaries.flatMap {
+ self.preferredPaymentMethods = preferredPaymentMethodDictionaries.compactMap {
return PaymentMethod(info: $0, logoBaseURL: logoBaseURL.absoluteString, isOneClick: true)
}
let availablePaymentMethodsDictionaries = dictionary["paymentMethods"] as? [[String: Any]] ?? []
- self.availablePaymentMethods = availablePaymentMethodsDictionaries.flatMap {
+ self.availablePaymentMethods = availablePaymentMethodsDictionaries.compactMap {
return PaymentMethod(info: $0, logoBaseURL: logoBaseURL.absoluteString, isOneClick: false)
}.groupBy {
return $0.group?.type ?? UUID().uuidString
- }.flatMap {
+ }.compactMap {
return $0.count == 1 ? $0.first : PaymentMethod(members: $0)
}
if let lineItemDictionaries = dictionary["lineItems"] as? [[String: Any]] {
- lineItems = lineItemDictionaries.flatMap({ item in
+ lineItems = lineItemDictionaries.compactMap({ item in
let itemId = item["itemId"] as? String
let description = item["description"] as? String
let amountExcludingTax = item["amountExcludingTax"] as? Int
diff --git a/Adyen/CoreUI/Appearance/AppearanceConfiguration.swift b/Adyen/CoreUI/Appearance/AppearanceConfiguration.swift
index 3305de86d5..c7a446df04 100644
--- a/Adyen/CoreUI/Appearance/AppearanceConfiguration.swift
+++ b/Adyen/CoreUI/Appearance/AppearanceConfiguration.swift
@@ -67,6 +67,10 @@ public final class AppearanceConfiguration {
/// When no type is specified, a default button is used.
public var checkoutButtonType: UIButton.Type = UIButton.self
+ /// The title of the checkout button.
+ /// If none provided, the amount in the format "Pay $x.xx" will be used.
+ public var checkoutButtonTitle: String?
+
// MARK: - Configuring Safari View Controller
/// The color to tint the background of the Safari View Controller navigation bar and toolbar. Only has an effect on iOS 11 and higher.
@@ -138,6 +142,7 @@ extension AppearanceConfiguration: NSCopying {
appearanceConfiguration.safariControlTintColor = safariControlTintColor
appearanceConfiguration.tintColor = tintColor
appearanceConfiguration.backgroundColor = backgroundColor
+ appearanceConfiguration.checkoutButtonTitle = checkoutButtonTitle
appearanceConfiguration.internalCheckoutButtonTitleTextAttributes = internalCheckoutButtonTitleTextAttributes
appearanceConfiguration.internalCheckoutButtonTitleEdgeInsets = internalCheckoutButtonTitleEdgeInsets
@@ -212,6 +217,20 @@ internal extension AppearanceConfiguration {
private static var _shared = AppearanceConfiguration.default
+ internal func payActionTitle(forAmount amount: Int?, currencyCode: String?) -> String {
+ let payActionTitle: String
+ if let buttonTitle = checkoutButtonTitle {
+ payActionTitle = buttonTitle
+ } else if let amount = amount, let currencyCode = currencyCode {
+ let formattedAmount = AmountFormatter.formatted(amount: amount, currencyCode: currencyCode) ?? ""
+ payActionTitle = ADYLocalizedString("payButton.formatted", formattedAmount)
+ } else {
+ payActionTitle = ADYLocalizedString("payButton.formatted")
+ }
+
+ return payActionTitle
+ }
+
internal func cancelButtonItem(target: Any, selector: Selector) -> UIBarButtonItem {
var cancelButtonItem: UIBarButtonItem!
if let cancelButtonImage = navigationBarCancelButtonImage {
diff --git a/Adyen/CoreUI/Container/ContainerView.swift b/Adyen/CoreUI/Container/ContainerView.swift
index 0df49b5c6f..aa862af5cd 100644
--- a/Adyen/CoreUI/Container/ContainerView.swift
+++ b/Adyen/CoreUI/Container/ContainerView.swift
@@ -104,7 +104,7 @@ internal class ContainerView: UIScrollView {
}
-fileprivate class ContainerContentBackgroundView: UIView {
+private class ContainerContentBackgroundView: UIView {
override func draw(_ rect: CGRect) {
// Draw background color.
diff --git a/Adyen/CoreUI/Plugins/PaymentDetailsPresenter.swift b/Adyen/CoreUI/Plugins/PaymentDetailsPresenter.swift
index 2cfc30a770..6bc02fff09 100644
--- a/Adyen/CoreUI/Plugins/PaymentDetailsPresenter.swift
+++ b/Adyen/CoreUI/Plugins/PaymentDetailsPresenter.swift
@@ -10,7 +10,7 @@ import Foundation
internal protocol PaymentDetailsPresenter: class {
/// The delegate of the details presenter.
- weak var delegate: PaymentDetailsPresenterDelegate? { get set }
+ var delegate: PaymentDetailsPresenterDelegate? { get set }
/// Requests the user to enter the payment details.
func start()
diff --git a/Adyen/Plugins/ApplePay/ApplePayDetailsPresenter.swift b/Adyen/Plugins/ApplePay/ApplePayDetailsPresenter.swift
index 306a3ceaab..83dad6ed24 100644
--- a/Adyen/Plugins/ApplePay/ApplePayDetailsPresenter.swift
+++ b/Adyen/Plugins/ApplePay/ApplePayDetailsPresenter.swift
@@ -104,15 +104,15 @@ fileprivate extension PKPaymentRequest {
}
// Make sure all items have a description, otherwise we won't have anything to display.
- let itemDescriptions = lineItems.flatMap({ $0.description })
+ let itemDescriptions = lineItems.compactMap({ $0.description })
guard itemDescriptions.count == lineItems.count else {
return []
}
var items: [PKPaymentSummaryItem] = []
- let totalIncludingTax = lineItems.flatMap({ $0.amountIncludingTax }).reduce(0, +)
- let totalWithTaxExplicitlyAdded = lineItems.flatMap({
+ let totalIncludingTax = lineItems.compactMap({ $0.amountIncludingTax }).reduce(0, +)
+ let totalWithTaxExplicitlyAdded = lineItems.compactMap({
($0.amountExcludingTax ?? 0) + ($0.taxAmount ?? 0)
}).reduce(0, +)
@@ -120,7 +120,7 @@ fileprivate extension PKPaymentRequest {
// Show each item on its own line, without a new line for tax.
for item in lineItems {
let amount = item.amountIncludingTax ?? 0
- let formattedAmount = CurrencyFormatter.decimalAmount(amount, currencyCode: paymentSetup.currencyCode)
+ let formattedAmount = AmountFormatter.decimalAmount(amount, currencyCode: paymentSetup.currencyCode)
let description = item.description ?? ""
let lineItem = PKPaymentSummaryItem(label: description, amount: formattedAmount)
items.append(lineItem)
@@ -129,15 +129,15 @@ fileprivate extension PKPaymentRequest {
// Show each item on its own line, with a new line for tax.
for item in lineItems {
let amount = item.amountExcludingTax ?? 0
- let formattedAmount = CurrencyFormatter.decimalAmount(amount, currencyCode: paymentSetup.currencyCode)
+ let formattedAmount = AmountFormatter.decimalAmount(amount, currencyCode: paymentSetup.currencyCode)
let description = item.description ?? ""
let lineItem = PKPaymentSummaryItem(label: description, amount: formattedAmount)
items.append(lineItem)
}
let taxLabel = ADYLocalizedString("taxLabel")
- let taxAmount = lineItems.flatMap({ $0.taxAmount }).reduce(0, +)
- let formattedTaxAmount = CurrencyFormatter.decimalAmount(taxAmount, currencyCode: paymentSetup.currencyCode)
+ let taxAmount = lineItems.compactMap({ $0.taxAmount }).reduce(0, +)
+ let formattedTaxAmount = AmountFormatter.decimalAmount(taxAmount, currencyCode: paymentSetup.currencyCode)
let taxLineItem = PKPaymentSummaryItem(label: taxLabel, amount: formattedTaxAmount)
items.append(taxLineItem)
@@ -148,7 +148,7 @@ fileprivate extension PKPaymentRequest {
private static func paymentSummaryLineItem(_ paymentSetup: PaymentSetup) -> PKPaymentSummaryItem {
let companyName = paymentSetup.companyDetails?.name ?? paymentSetup.merchantReference
- let amount = CurrencyFormatter.decimalAmount(paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
+ let amount = AmountFormatter.decimalAmount(paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
let summaryItem = PKPaymentSummaryItem(label: companyName, amount: amount)
return summaryItem
}
diff --git a/Adyen/Plugins/Cards/CardFormDetailsPresenter.swift b/Adyen/Plugins/Cards/CardFormDetailsPresenter.swift
index a4596d7d36..b3fc7d4659 100644
--- a/Adyen/Plugins/Cards/CardFormDetailsPresenter.swift
+++ b/Adyen/Plugins/Cards/CardFormDetailsPresenter.swift
@@ -22,12 +22,12 @@ internal class CardFormDetailsPresenter: PaymentDetailsPresenter {
internal func start() {
let paymentMethod = pluginConfiguration.paymentMethod
let paymentSetup = pluginConfiguration.paymentSetup
- let formattedAmount = CurrencyFormatter.formatted(amount: paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
+
let inputDetails = paymentMethod.inputDetails
let formViewController = CardFormViewController()
formViewController.title = paymentMethod.name
- formViewController.formattedAmount = formattedAmount
+ formViewController.payButtonTitle = AppearanceConfiguration.shared.payActionTitle(forAmount: paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
formViewController.paymentMethod = paymentMethod
formViewController.shouldHideStoreDetails = inputDetails?.filter({ $0.key == "storeDetails" }).count == 0
formViewController.shouldHideInstallments = inputDetails?.filter({ $0.key == "installments" }).count == 0
diff --git a/Adyen/Plugins/Cards/CardFormViewController.swift b/Adyen/Plugins/Cards/CardFormViewController.swift
index ae56a6177c..6bc811fd09 100644
--- a/Adyen/Plugins/Cards/CardFormViewController.swift
+++ b/Adyen/Plugins/Cards/CardFormViewController.swift
@@ -31,7 +31,7 @@ class CardFormViewController: UIViewController, CheckoutPaymentFieldDelegate {
// If the payment method represents a group of cards,
// then acceptedCards should include all card types of its members.
if let members = paymentMethod.members {
- acceptedCards = members.flatMap({ CardType(rawValue: $0.type) })
+ acceptedCards = members.compactMap({ CardType(rawValue: $0.type) })
} else if let cardType = CardType(rawValue: paymentMethod.type) {
// Otherwise, we would expect only the card type associated with the payment method.
acceptedCards = [cardType]
@@ -67,7 +67,7 @@ class CardFormViewController: UIViewController, CheckoutPaymentFieldDelegate {
var cardDetailsHandler: ((CardInputData) -> Void)?
var cardScanButtonHandler: ((@escaping CardScanCompletion) -> Void)?
- var formattedAmount: String?
+ var payButtonTitle = ""
var paymentMethod: PaymentMethod?
var shouldHideStoreDetails = false
var shouldHideInstallments = false
@@ -156,7 +156,7 @@ class CardFormViewController: UIViewController, CheckoutPaymentFieldDelegate {
storeDetailsButton.setImage(UIImage.bundleImage("checkbox_active"), for: .selected)
storeDetailsButton.tintColor = AppearanceConfiguration.shared.tintColor
- payButton.setTitle(ADYLocalizedString("payButton.formatted", formattedAmount ?? ""), for: .normal)
+ payButton.setTitle(payButtonTitle, for: .normal)
contentView.addSubview(payButton)
configurePayButtonLayout()
diff --git a/Adyen/Plugins/Cards/CardFormViewController.xib b/Adyen/Plugins/Cards/CardFormViewController.xib
index 2be9aedcd1..ef5ede2675 100644
--- a/Adyen/Plugins/Cards/CardFormViewController.xib
+++ b/Adyen/Plugins/Cards/CardFormViewController.xib
@@ -1,11 +1,11 @@
-
+
-
+
@@ -67,7 +67,6 @@
-
diff --git a/Adyen/Plugins/Cards/CardOneClickDetailsPresenter.swift b/Adyen/Plugins/Cards/CardOneClickDetailsPresenter.swift
index 0c4b22d59a..165142c884 100644
--- a/Adyen/Plugins/Cards/CardOneClickDetailsPresenter.swift
+++ b/Adyen/Plugins/Cards/CardOneClickDetailsPresenter.swift
@@ -51,8 +51,7 @@ internal class CardOneClickDetailsPresenter: PaymentDetailsPresenter {
let cancelAction = UIAlertAction(title: cancelActionTitle, style: .cancel, handler: nil)
alertController.addAction(cancelAction)
- let formattedAmount = CurrencyFormatter.formatted(amount: paymentSetup.amount, currencyCode: paymentSetup.currencyCode) ?? ""
- let confirmActionTitle = ADYLocalizedString("payButton.formatted", formattedAmount)
+ var confirmActionTitle = AppearanceConfiguration.shared.payActionTitle(forAmount: paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
let confirmAction = UIAlertAction(title: confirmActionTitle, style: .default) { [unowned self] _ in
self.didSelectOneClickAlertControllerConfirmAction()
}
diff --git a/Adyen/Plugins/Cards/Utilities/CardValidator.swift b/Adyen/Plugins/Cards/Utilities/CardValidator.swift
index 8978bee27e..d2cecdb5b1 100644
--- a/Adyen/Plugins/Cards/Utilities/CardValidator.swift
+++ b/Adyen/Plugins/Cards/Utilities/CardValidator.swift
@@ -119,7 +119,7 @@ public final class CardValidator {
}
private static func luhnCheck(_ cardNumber: String) -> Bool {
- let reversedCardNumberDigits = cardNumber.reversed().flatMap { Int(String($0)) }
+ let reversedCardNumberDigits = cardNumber.reversed().compactMap { Int(String($0)) }
var sum = 0
for (index, digit) in reversedCardNumberDigits.enumerated() {
diff --git a/Adyen/Plugins/SEPADirectDebit/IBAN/IBANValidator.swift b/Adyen/Plugins/SEPADirectDebit/IBAN/IBANValidator.swift
index 89e681e498..6914c86097 100644
--- a/Adyen/Plugins/SEPADirectDebit/IBAN/IBANValidator.swift
+++ b/Adyen/Plugins/SEPADirectDebit/IBAN/IBANValidator.swift
@@ -59,7 +59,7 @@ public class IBANValidator {
let alphanumerics = CharacterSet.alphanumerics
let lowercaseLetters = CharacterSet.lowercaseLetters
- let components = string.unicodeScalars.flatMap { unicodeScalar -> String? in
+ let components = string.unicodeScalars.compactMap { unicodeScalar -> String? in
guard alphanumerics.contains(unicodeScalar) else {
return nil
}
diff --git a/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitDetailsPresenter.swift b/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitDetailsPresenter.swift
index a2b4d2e686..55c5dc9769 100644
--- a/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitDetailsPresenter.swift
+++ b/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitDetailsPresenter.swift
@@ -21,11 +21,10 @@ internal class SEPADirectDebitDetailsPresenter: PaymentDetailsPresenter {
func start() {
let paymentSetup = pluginConfiguration.paymentSetup
- let formattedAmount = CurrencyFormatter.formatted(amount: paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
let formViewController = SEPADirectDebitFormViewController()
formViewController.title = pluginConfiguration.paymentMethod.name
- formViewController.formattedAmount = formattedAmount
+ formViewController.payButtonTitle = AppearanceConfiguration.shared.payActionTitle(forAmount: paymentSetup.amount, currencyCode: paymentSetup.currencyCode)
formViewController.delegate = self
hostViewController.pushViewController(formViewController, animated: true)
}
diff --git a/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitFormViewController.swift b/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitFormViewController.swift
index 46910577a1..7402ddc44c 100644
--- a/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitFormViewController.swift
+++ b/Adyen/Plugins/SEPADirectDebit/SEPADirectDebitFormViewController.swift
@@ -10,14 +10,9 @@ internal class SEPADirectDebitFormViewController: FormViewController {
internal weak var delegate: SEPADirectDebitFormViewControllerDelegate?
- internal var formattedAmount: String? {
+ internal var payButtonTitle: String = "" {
didSet {
- var title = ""
- if let formattedAmount = formattedAmount {
- title = ADYLocalizedString("payButton.formatted", formattedAmount)
- }
-
- payButton.setTitle(title, for: .normal)
+ payButton.setTitle(payButtonTitle, for: .normal)
}
}
diff --git a/Adyen/UI/Checkout/CheckoutViewController.swift b/Adyen/UI/Checkout/CheckoutViewController.swift
index 48d999829f..058d28d84b 100644
--- a/Adyen/UI/Checkout/CheckoutViewController.swift
+++ b/Adyen/UI/Checkout/CheckoutViewController.swift
@@ -298,13 +298,7 @@ public final class CheckoutViewController: UIViewController, PaymentRequestDeleg
let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
// Confirm alert action
- let confirmActionTitle: String
- if let amount = request.amount, let currencyCode = request.currency {
- let formattedAmount = CurrencyFormatter.formatted(amount: amount, currencyCode: currencyCode) ?? ""
- confirmActionTitle = ADYLocalizedString("payButton.formatted", formattedAmount)
- } else {
- confirmActionTitle = ADYLocalizedString("payButton.formatted")
- }
+ let confirmActionTitle = AppearanceConfiguration.shared.payActionTitle(forAmount: request.amount, currencyCode: request.currency)
let confirmAction = UIAlertAction(title: confirmActionTitle, style: .default) { action in
completion(true)
}
diff --git a/AdyenTests/Core/CurrencyFormatterTests.swift b/AdyenTests/Core/CurrencyFormatterTests.swift
index 5fd9d8a69e..5074211bc2 100644
--- a/AdyenTests/Core/CurrencyFormatterTests.swift
+++ b/AdyenTests/Core/CurrencyFormatterTests.swift
@@ -7,39 +7,39 @@
import XCTest
@testable import Adyen
-class CurrencyFormatterTests: XCTestCase {
+class AmountFormatterTests: XCTestCase {
- func testCurrencyFormatWithEUR() {
+ func testAmountFormatWithEUR() {
let expected = "€103.47"
- let formatted = CurrencyFormatter.formatted(amount: 10347, currencyCode: "EUR")
+ let formatted = AmountFormatter.formatted(amount: 10347, currencyCode: "EUR")
XCTAssertEqual(formatted, expected)
}
- func testCurrencyFormatWithEURAndLargeAmount() {
+ func testAmountFormatWithEURAndLargeAmount() {
let expected = "€90,331.47"
- let formatted = CurrencyFormatter.formatted(amount: 9033147, currencyCode: "EUR")
+ let formatted = AmountFormatter.formatted(amount: 9033147, currencyCode: "EUR")
XCTAssertEqual(formatted, expected)
}
- func testCurrencyFormatWithUSD() {
+ func testAmountFormatWithUSD() {
let expected = "$103.47"
- let formatted = CurrencyFormatter.formatted(amount: 10347, currencyCode: "USD")
+ let formatted = AmountFormatter.formatted(amount: 10347, currencyCode: "USD")
XCTAssertEqual(formatted, expected)
}
- func testCurrencyFormatWithUSDAndLargeAmount() {
+ func testAmountFormatWithUSDAndLargeAmount() {
let expected = "$90,331.47"
- let formatted = CurrencyFormatter.formatted(amount: 9033147, currencyCode: "USD")
+ let formatted = AmountFormatter.formatted(amount: 9033147, currencyCode: "USD")
XCTAssertEqual(formatted, expected)
}
- func testCurrencyFormatWithBRLAndLargeAmount() {
+ func testAmountFormatWithBRLAndLargeAmount() {
let expected = "R$90,331.47"
- let formatted = CurrencyFormatter.formatted(amount: 9033147, currencyCode: "BRL")
+ let formatted = AmountFormatter.formatted(amount: 9033147, currencyCode: "BRL")
XCTAssertEqual(formatted, expected)
}
diff --git a/Docs/Classes/AmountFormatter.html b/Docs/Classes/AmountFormatter.html
new file mode 100644
index 0000000000..e26f2441d0
--- /dev/null
+++ b/Docs/Classes/AmountFormatter.html
@@ -0,0 +1,293 @@
+
+
+
+ AmountFormatter Class Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Adyen Reference
+
+ AmountFormatter Class Reference
+
+
+
+
+
+
+
+
+
AmountFormatter
+
+
+
public final class AmountFormatter
+
+
+
+
Convenience class to format a payment amount for display.
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
Formats a string based on the provided amount and currency code.
+
+
+
+
Declaration
+
+
Swift
+
public static func formatted(amount: Int, currencyCode: String) -> String?
+
+
+
+
+
Parameters
+
+
+
+
+
+ amount
+
+ |
+
+
+ Amount in minor units, i.e. 2000.
+
+ |
+
+
+
+
+ currencyCode
+
+ |
+
+
+ The currency code, i.e. USD .
+
+ |
+
+
+
+
+
+
Return Value
+
A formatted string, i.e. $20.00
.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Docs/Classes/AppearanceConfiguration.html b/Docs/Classes/AppearanceConfiguration.html
index 293744ef1a..03432cdf42 100644
--- a/Docs/Classes/AppearanceConfiguration.html
+++ b/Docs/Classes/AppearanceConfiguration.html
@@ -159,6 +159,34 @@
+
+ Other Classes
+
+
+
+ Other Type Aliases
+
+
@@ -168,7 +196,7 @@
AppearanceConfiguration
-
public final class AppearanceConfiguration
+
public final class AppearanceConfiguration
@@ -209,7 +237,7 @@ Initializing
Declaration
Swift
-
public init()
+
public init()
@@ -230,9 +258,9 @@ Configuring the Status Bar
@@ -247,7 +275,7 @@
Configuring the Status Bar
Declaration
Swift
-
public var preferredStatusBarStyle = UIStatusBarStyle.default
+
public var preferredStatusBarStyle: UIStatusBarStyle
@@ -268,9 +296,9 @@ Configuring the Navigation Bar Title Text Appearance
@@ -285,7 +313,7 @@
Configuring the Navigation Bar Title Text AppearanceDeclaration
Swift
-
public var navigationBarTitleTextAttributes: [NSAttributedStringKey: Any]?
+
public var navigationBarTitleTextAttributes: [NSAttributedStringKey : Any]?
@@ -295,9 +323,9 @@ Declaration
@@ -312,7 +340,7 @@
Declaration
Declaration
Swift
-
public var navigationBarLargeTitleTextAttributes: [NSAttributedStringKey: Any]?
+
public var navigationBarLargeTitleTextAttributes: [NSAttributedStringKey : Any]?
@@ -340,7 +368,7 @@ Declaration
Declaration
Swift
-
public enum NavigationBarLargeTitleDisplayMode
+
public enum NavigationBarLargeTitleDisplayMode
@@ -350,9 +378,9 @@ Declaration
@@ -367,7 +395,7 @@
Declaration
Declaration
@@ -388,9 +416,9 @@ Configuring the Navigation Bar Appearance
@@ -405,7 +433,7 @@
Configuring the Navigation Bar Appearance
Declaration
Swift
-
public var navigationBarTintColor: UIColor?
+
public var navigationBarTintColor: UIColor?
@@ -415,9 +443,9 @@ Declaration
@@ -432,7 +460,7 @@
Declaration
Declaration
Swift
-
public var navigationBarBackgroundColor: UIColor?
+
public var navigationBarBackgroundColor: UIColor?
@@ -442,9 +470,9 @@ Declaration
@@ -459,7 +487,7 @@
Declaration
Declaration
Swift
-
public var isNavigationBarTranslucent = true
+
public var isNavigationBarTranslucent: Bool
@@ -469,9 +497,9 @@ Declaration
@@ -486,7 +514,7 @@
Declaration
Declaration
Swift
-
public var navigationBarCancelButtonImage: UIImage?
+
public var navigationBarCancelButtonImage: UIImage?
@@ -507,9 +535,9 @@ Configuring the Checkout Button
@@ -526,7 +554,35 @@
Configuring the Checkout Button
Declaration
Swift
-
public var checkoutButtonType: UIButton.Type = UIButton.self
+
public var checkoutButtonType: UIButton.Type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The title of the checkout button.
+If none provided, the amount in the format Pay $x.xx
will be used.
+
+
+
+
Declaration
+
+
Swift
+
public var checkoutButtonTitle: String?
@@ -547,9 +603,9 @@ Configuring Safari View Controller
@@ -564,7 +620,7 @@
Configuring Safari View Controller
Declaration
Swift
-
public var safariBarTintColor: UIColor?
+
public var safariBarTintColor: UIColor?
@@ -574,9 +630,9 @@ Declaration
@@ -591,7 +647,7 @@
Declaration
Declaration
Swift
-
public var safariControlTintColor: UIColor?
+
public var safariControlTintColor: UIColor?
@@ -612,9 +668,9 @@ Configuring General Display Properties
@@ -629,7 +685,7 @@
Configuring General Display Properties
Declaration
Swift
-
public var tintColor: UIColor?
+
public var tintColor: UIColor?
@@ -639,9 +695,9 @@ Declaration
@@ -656,7 +712,7 @@
Declaration
Declaration
Swift
-
public var backgroundColor: UIColor = #colorLiteral(red: 0.9764705882, green: 0.9764705882, blue: 0.9764705882, alpha: 1)
+
public var backgroundColor: UIColor
@@ -677,9 +733,9 @@ Getting the Default Appearance Configuration
@@ -694,7 +750,7 @@
Getting the Default Appearance Configuration
Declaration
Swift
-
public static var `default`: AppearanceConfiguration
+
public static var `default`: AppearanceConfiguration { get }
@@ -704,13 +760,20 @@ Declaration
+
-
@@ -718,14 +781,15 @@
Declaration
-
The attributes used for the checkout button’s title. Only used when checkoutButtonType
is the default.
+
The attributes used for the checkout button’s title. Only used when checkoutButtonType
is the default.
Declaration
Swift
-
public var checkoutButtonTitleTextAttributes: [NSAttributedStringKey: Any]?
+
@available(*, deprecated, message: "Provide a custom button via checkoutButtonType instead.")
+public var checkoutButtonTitleTextAttributes: [NSAttributedStringKey : Any]? { get set }
@@ -735,9 +799,9 @@ Declaration
-
@@ -745,14 +809,15 @@
Declaration
-
The insets from the edges of the checkout button to the title. Only used when checkoutButtonType
the default.
+
The insets from the edges of the checkout button to the title. Only used when checkoutButtonType
the default.
Declaration
Swift
-
public var checkoutButtonTitleEdgeInsets: UIEdgeInsets?
+
@available(*, deprecated, message: "Provide a custom button via checkoutButtonType instead.")
+public var checkoutButtonTitleEdgeInsets: UIEdgeInsets? { get set }
@@ -762,9 +827,9 @@ Declaration
-
@@ -772,14 +837,15 @@
Declaration
-
The corner radius of the checkout button. Only used when checkoutButtonType
the default.
+
The corner radius of the checkout button. Only used when checkoutButtonType
the default.
Declaration
Swift
-
public var checkoutButtonCornerRadius: CGFloat
+
@available(*, deprecated, message: "Provide a custom button via checkoutButtonType instead.")
+public var checkoutButtonCornerRadius: CGFloat { get set }
@@ -794,8 +860,8 @@ Declaration