@jimrising/easymerchantsdk-react-native 2.3.6 → 2.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
package/android/build.gradle
CHANGED
|
@@ -39,7 +39,7 @@ repositories {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
dependencies {
|
|
42
|
-
implementation 'com.app:paysdk:1.6.1.
|
|
42
|
+
implementation 'com.app:paysdk:1.6.1.4'
|
|
43
43
|
implementation 'com.hbb20:ccp:2.7.3'
|
|
44
44
|
implementation 'com.github.bumptech.glide:glide:4.16.0'
|
|
45
45
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1"
|
|
@@ -1208,7 +1208,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
1208
1208
|
self.heightViewNewCardFields.constant = 458
|
|
1209
1209
|
}
|
|
1210
1210
|
|
|
1211
|
-
self.heightSubViewNewAccountFields.constant =
|
|
1211
|
+
self.heightSubViewNewAccountFields.constant = 662
|
|
1212
1212
|
}
|
|
1213
1213
|
|
|
1214
1214
|
if selectedPaymentMethod == "Card" {
|
|
@@ -2670,40 +2670,43 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
2670
2670
|
return
|
|
2671
2671
|
}
|
|
2672
2672
|
|
|
2673
|
-
// Validate expiry date format
|
|
2674
|
-
let expiryDateFormat = "MM/yyyy"
|
|
2675
|
-
let dateFormatter = DateFormatter()
|
|
2676
|
-
dateFormatter.dateFormat = expiryDateFormat
|
|
2677
|
-
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
|
2678
|
-
|
|
2679
2673
|
// Split the expiry date and validate its format
|
|
2680
2674
|
let exp = expiryDate.split(separator: "/")
|
|
2681
|
-
|
|
2682
|
-
|
|
2675
|
+
guard exp.count == 2, exp[0].count == 2, exp[1].count == 2,
|
|
2676
|
+
let month = Int(exp[0]), let year = Int(exp[1]), (1...12).contains(month) else {
|
|
2677
|
+
let alert = UIAlertController(title: "Invalid Expiry Date", message: "Please enter the expiry date in the format MM/yy.", preferredStyle: .alert)
|
|
2683
2678
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
2684
2679
|
self.present(alert, animated: true, completion: nil)
|
|
2685
2680
|
return
|
|
2686
2681
|
}
|
|
2687
|
-
|
|
2688
|
-
//
|
|
2689
|
-
|
|
2690
|
-
|
|
2682
|
+
|
|
2683
|
+
// Convert 2-digit year -> 4-digit year dynamically
|
|
2684
|
+
let currentYear = Calendar.current.component(.year, from: Date()) // e.g. 2025
|
|
2685
|
+
let currentCentury = currentYear / 100 // e.g. 20
|
|
2686
|
+
let fullYear = (year + currentCentury * 100) // e.g. 56 -> 2056
|
|
2687
|
+
|
|
2688
|
+
// Create expiry date as the last day of that month
|
|
2689
|
+
var components = DateComponents()
|
|
2690
|
+
components.year = fullYear
|
|
2691
|
+
components.month = month + 1
|
|
2692
|
+
components.day = 0 // trick: day 0 = last day of previous month
|
|
2693
|
+
let calendar = Calendar.current
|
|
2694
|
+
|
|
2695
|
+
if let expiryDateObj = calendar.date(from: components) {
|
|
2691
2696
|
let currentDate = Date()
|
|
2692
|
-
|
|
2693
|
-
let currentMonthYear = calendar.date(from: calendar.dateComponents([.year, .month], from: currentDate))
|
|
2694
|
-
if expiryDateObj < currentMonthYear! {
|
|
2697
|
+
if expiryDateObj < currentDate {
|
|
2695
2698
|
let alert = UIAlertController(title: "Expired Card", message: "The expiry date cannot be in the past. Please enter a valid expiry date.", preferredStyle: .alert)
|
|
2696
2699
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
2697
2700
|
self.present(alert, animated: true, completion: nil)
|
|
2698
2701
|
return
|
|
2699
2702
|
}
|
|
2700
2703
|
} else {
|
|
2701
|
-
let alert = UIAlertController(title: "Invalid Expiry Date", message: "Please enter the expiry date in the format MM/
|
|
2704
|
+
let alert = UIAlertController(title: "Invalid Expiry Date", message: "Please enter the expiry date in the format MM/yy.", preferredStyle: .alert)
|
|
2702
2705
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
2703
2706
|
self.present(alert, animated: true, completion: nil)
|
|
2704
2707
|
return
|
|
2705
2708
|
}
|
|
2706
|
-
|
|
2709
|
+
|
|
2707
2710
|
// Recurring Plan + Date Validation (only if is_recurring is true)
|
|
2708
2711
|
if let req = self.request, req.is_recurring == true {
|
|
2709
2712
|
if self.txtFieldSelectPlanNewCardView.text.isEmpty {
|
|
@@ -4684,7 +4687,8 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
4684
4687
|
let cardName = self.cardNameTextField.text.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
4685
4688
|
let email = self.txtFieldEmailCardView.text.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
4686
4689
|
let sanitizedCardNumber = cardNumber.replacingOccurrences(of: " ", with: "")
|
|
4687
|
-
|
|
4690
|
+
// let expiryDateRegex = #"^(0[1-9]|1[0-2])\/\d{4}$"#
|
|
4691
|
+
let expiryDateRegex = #"^(0[1-9]|1[0-2])\/([0-9]{2})$"#
|
|
4688
4692
|
let nameRegex = #"^[A-Za-z\s]+$"#
|
|
4689
4693
|
|
|
4690
4694
|
if cardNumber.isEmpty {
|
|
@@ -4696,26 +4700,52 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
4696
4700
|
} else if expiryDate.isEmpty {
|
|
4697
4701
|
self.showAlert(title: "Missing Information", message: "Card Expiry Date is required.")
|
|
4698
4702
|
return
|
|
4699
|
-
}
|
|
4700
|
-
|
|
4703
|
+
}
|
|
4704
|
+
else if !expiryDate.matches(expiryDateRegex) {
|
|
4705
|
+
self.showAlert(title: "Invalid Expiry Date", message: "Expiry Date must be in format MM/YY (e.g., 02/26).")
|
|
4701
4706
|
return
|
|
4702
4707
|
} else {
|
|
4703
|
-
let
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4708
|
+
let expComponents = expiryDate.split(separator: "/")
|
|
4709
|
+
guard expComponents.count == 2,
|
|
4710
|
+
let month = Int(expComponents[0]),
|
|
4711
|
+
let year = Int(expComponents[1]),
|
|
4712
|
+
(1...12).contains(month) else {
|
|
4713
|
+
self.showAlert(title: "Invalid Expiry Date", message: "Expiry Date must be in format MM/YY (e.g., 02/26).")
|
|
4714
|
+
return
|
|
4715
|
+
}
|
|
4716
|
+
|
|
4717
|
+
// Convert 2-digit year to 4-digit year
|
|
4718
|
+
let currentYear = Calendar.current.component(.year, from: Date())
|
|
4719
|
+
let currentCentury = currentYear / 100
|
|
4720
|
+
var fullYear = currentCentury * 100 + year
|
|
4721
|
+
|
|
4722
|
+
// Adjust for future years (e.g., 20 could mean 2020 or 2120)
|
|
4723
|
+
if fullYear < currentYear - 50 {
|
|
4724
|
+
fullYear += 100
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
// Build expiry date as the last day of the month
|
|
4728
|
+
var components = DateComponents()
|
|
4729
|
+
components.year = fullYear
|
|
4730
|
+
components.month = month
|
|
4731
|
+
components.day = 1 // Start of the month for comparison
|
|
4732
|
+
|
|
4733
|
+
let calendar = Calendar.current
|
|
4734
|
+
guard let expiryDateObj = calendar.date(from: components) else {
|
|
4716
4735
|
self.showAlert(title: "Invalid Expiry Date", message: "Unable to parse expiry date.")
|
|
4717
4736
|
return
|
|
4718
4737
|
}
|
|
4738
|
+
|
|
4739
|
+
// Compare with current date
|
|
4740
|
+
let today = calendar.startOfDay(for: Date())
|
|
4741
|
+
let nowComponents = calendar.dateComponents([.year, .month], from: today)
|
|
4742
|
+
let expiryComponents = calendar.dateComponents([.year, .month], from: expiryDateObj)
|
|
4743
|
+
|
|
4744
|
+
if expiryComponents.year! < nowComponents.year! ||
|
|
4745
|
+
(expiryComponents.year! == nowComponents.year! && expiryComponents.month! < nowComponents.month!) {
|
|
4746
|
+
self.showAlert(title: "Expired Card", message: "Card is expired. Please enter a valid expiry date.")
|
|
4747
|
+
return
|
|
4748
|
+
}
|
|
4719
4749
|
}
|
|
4720
4750
|
|
|
4721
4751
|
if cvv.isEmpty {
|
|
@@ -4958,7 +4988,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
4958
4988
|
let sanitizedCardNumber = cardNumber.replacingOccurrences(of: " ", with: "")
|
|
4959
4989
|
|
|
4960
4990
|
// Regular expression for expiry date format MM/yyyy
|
|
4961
|
-
let expiryDateRegex = #"^(0[1-9]|1[0-2])\/\d{
|
|
4991
|
+
let expiryDateRegex = #"^(0[1-9]|1[0-2])\/\d{2}$"#
|
|
4962
4992
|
|
|
4963
4993
|
// Regular expression for a valid name (only letters and spaces)
|
|
4964
4994
|
let nameRegex = #"^[A-Za-z\s]+$"#
|
|
@@ -4975,29 +5005,50 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
4975
5005
|
return
|
|
4976
5006
|
}
|
|
4977
5007
|
else if !expiryDate.matches(expiryDateRegex) {
|
|
4978
|
-
self.showAlert(title: "Invalid Expiry Date", message: "Expiry Date must be in format MM/
|
|
5008
|
+
self.showAlert(title: "Invalid Expiry Date", message: "Expiry Date must be in format MM/YY (e.g., 02/26).")
|
|
4979
5009
|
return
|
|
4980
|
-
}
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
5010
|
+
} else {
|
|
5011
|
+
let expComponents = expiryDate.split(separator: "/")
|
|
5012
|
+
guard expComponents.count == 2,
|
|
5013
|
+
let month = Int(expComponents[0]),
|
|
5014
|
+
let year = Int(expComponents[1]),
|
|
5015
|
+
(1...12).contains(month) else {
|
|
5016
|
+
self.showAlert(title: "Invalid Expiry Date", message: "Expiry Date must be in format MM/YY (e.g., 02/26).")
|
|
5017
|
+
return
|
|
5018
|
+
}
|
|
5019
|
+
|
|
5020
|
+
// Convert 2-digit year to 4-digit year
|
|
5021
|
+
let currentYear = Calendar.current.component(.year, from: Date())
|
|
5022
|
+
let currentCentury = currentYear / 100
|
|
5023
|
+
var fullYear = currentCentury * 100 + year
|
|
5024
|
+
|
|
5025
|
+
// Adjust for future years (e.g., 20 could mean 2020 or 2120)
|
|
5026
|
+
if fullYear < currentYear - 50 {
|
|
5027
|
+
fullYear += 100
|
|
5028
|
+
}
|
|
5029
|
+
|
|
5030
|
+
// Build expiry date as the last day of the month
|
|
5031
|
+
var components = DateComponents()
|
|
5032
|
+
components.year = fullYear
|
|
5033
|
+
components.month = month
|
|
5034
|
+
components.day = 1 // Start of the month for comparison
|
|
5035
|
+
|
|
5036
|
+
let calendar = Calendar.current
|
|
5037
|
+
guard let expiryDateObj = calendar.date(from: components) else {
|
|
4998
5038
|
self.showAlert(title: "Invalid Expiry Date", message: "Unable to parse expiry date.")
|
|
4999
5039
|
return
|
|
5000
5040
|
}
|
|
5041
|
+
|
|
5042
|
+
// Compare with current date
|
|
5043
|
+
let today = calendar.startOfDay(for: Date())
|
|
5044
|
+
let nowComponents = calendar.dateComponents([.year, .month], from: today)
|
|
5045
|
+
let expiryComponents = calendar.dateComponents([.year, .month], from: expiryDateObj)
|
|
5046
|
+
|
|
5047
|
+
if expiryComponents.year! < nowComponents.year! ||
|
|
5048
|
+
(expiryComponents.year! == nowComponents.year! && expiryComponents.month! < nowComponents.month!) {
|
|
5049
|
+
self.showAlert(title: "Expired Card", message: "Card is expired. Please enter a valid expiry date.")
|
|
5050
|
+
return
|
|
5051
|
+
}
|
|
5001
5052
|
}
|
|
5002
5053
|
|
|
5003
5054
|
if cvv.isEmpty {
|
|
@@ -6998,15 +7049,19 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
6998
7049
|
}
|
|
6999
7050
|
|
|
7000
7051
|
// Validate expiry date format
|
|
7001
|
-
let expiryDateFormat = "MM/
|
|
7052
|
+
let expiryDateFormat = "MM/yy"
|
|
7002
7053
|
let dateFormatter = DateFormatter()
|
|
7003
7054
|
dateFormatter.dateFormat = expiryDateFormat
|
|
7004
7055
|
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
|
7005
|
-
|
|
7056
|
+
|
|
7006
7057
|
// Split the expiry date and validate its format
|
|
7007
7058
|
let exp = expiryText.split(separator: "/")
|
|
7008
|
-
if exp.count != 2 || exp[0].count != 2 || exp[1].count !=
|
|
7009
|
-
let alert = UIAlertController(
|
|
7059
|
+
if exp.count != 2 || exp[0].count != 2 || exp[1].count != 2 {
|
|
7060
|
+
let alert = UIAlertController(
|
|
7061
|
+
title: "Invalid Expiry Date",
|
|
7062
|
+
message: "Please enter the expiry date in the format MM/yy (e.g., 09/25).",
|
|
7063
|
+
preferredStyle: .alert
|
|
7064
|
+
)
|
|
7010
7065
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
7011
7066
|
self.present(alert, animated: true, completion: nil)
|
|
7012
7067
|
return
|
|
@@ -7025,7 +7080,11 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
7025
7080
|
return
|
|
7026
7081
|
}
|
|
7027
7082
|
} else {
|
|
7028
|
-
let alert = UIAlertController(
|
|
7083
|
+
let alert = UIAlertController(
|
|
7084
|
+
title: "Invalid Expiry Date",
|
|
7085
|
+
message: "Please enter the expiry date in the format MM/yy (e.g., 09/25).",
|
|
7086
|
+
preferredStyle: .alert
|
|
7087
|
+
)
|
|
7029
7088
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
7030
7089
|
self.present(alert, animated: true, completion: nil)
|
|
7031
7090
|
return
|
|
@@ -7534,40 +7593,38 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
7534
7593
|
return
|
|
7535
7594
|
}
|
|
7536
7595
|
|
|
7537
|
-
//
|
|
7538
|
-
let expiryDateFormat = "MM/yyyy"
|
|
7539
|
-
let dateFormatter = DateFormatter()
|
|
7540
|
-
dateFormatter.dateFormat = expiryDateFormat
|
|
7541
|
-
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
|
7542
|
-
|
|
7543
|
-
// Split the expiry date and validate its format
|
|
7596
|
+
// Split expiry
|
|
7544
7597
|
let exp = expiryText.split(separator: "/")
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7598
|
+
guard exp.count == 2,
|
|
7599
|
+
let month = Int(exp[0]),
|
|
7600
|
+
let year = Int(exp[1]) else {
|
|
7601
|
+
showAlert(title: "Invalid Expiry Date", message: "Please enter in MM/yy format (e.g., 09/25).")
|
|
7549
7602
|
return
|
|
7550
7603
|
}
|
|
7551
|
-
|
|
7552
|
-
//
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7604
|
+
|
|
7605
|
+
// Convert 2-digit year -> 4-digit year dynamically
|
|
7606
|
+
let currentYear = Calendar.current.component(.year, from: Date())
|
|
7607
|
+
let currentCentury = currentYear / 100 // e.g., 20 for 2025
|
|
7608
|
+
let fullYear = (year + currentCentury * 100)
|
|
7609
|
+
|
|
7610
|
+
// Build expiry date as last day of the month
|
|
7611
|
+
var components = DateComponents()
|
|
7612
|
+
components.year = fullYear
|
|
7613
|
+
components.month = month + 1
|
|
7614
|
+
components.day = 0 // trick: day 0 gives last day of previous month
|
|
7615
|
+
let calendar = Calendar.current
|
|
7616
|
+
|
|
7617
|
+
if let expiryDate = calendar.date(from: components) {
|
|
7618
|
+
let now = Date()
|
|
7619
|
+
if expiryDate < now {
|
|
7620
|
+
showAlert(title: "Expired Card", message: "The expiry date cannot be in the past.")
|
|
7562
7621
|
return
|
|
7563
7622
|
}
|
|
7564
7623
|
} else {
|
|
7565
|
-
|
|
7566
|
-
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
7567
|
-
self.present(alert, animated: true, completion: nil)
|
|
7624
|
+
showAlert(title: "Invalid Expiry Date", message: "Please enter in MM/yy format (e.g., 09/25).")
|
|
7568
7625
|
return
|
|
7569
7626
|
}
|
|
7570
|
-
|
|
7627
|
+
|
|
7571
7628
|
// Set up parameters with selected card details
|
|
7572
7629
|
let params: [String: Any] = [
|
|
7573
7630
|
"card_id": cardID,
|
|
@@ -9964,20 +10021,24 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
9964
10021
|
}
|
|
9965
10022
|
|
|
9966
10023
|
// Validate expiry date format
|
|
9967
|
-
let expiryDateFormat = "MM/
|
|
10024
|
+
let expiryDateFormat = "MM/yy"
|
|
9968
10025
|
let dateFormatter = DateFormatter()
|
|
9969
10026
|
dateFormatter.dateFormat = expiryDateFormat
|
|
9970
10027
|
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
|
9971
|
-
|
|
10028
|
+
|
|
9972
10029
|
// Split the expiry date and validate its format
|
|
9973
10030
|
let exp = expiryText.split(separator: "/")
|
|
9974
|
-
if exp.count != 2 || exp[0].count != 2 || exp[1].count !=
|
|
9975
|
-
let alert = UIAlertController(
|
|
10031
|
+
if exp.count != 2 || exp[0].count != 2 || exp[1].count != 2 {
|
|
10032
|
+
let alert = UIAlertController(
|
|
10033
|
+
title: "Invalid Expiry Date",
|
|
10034
|
+
message: "Please enter the expiry date in the format MM/yy (e.g., 09/25).",
|
|
10035
|
+
preferredStyle: .alert
|
|
10036
|
+
)
|
|
9976
10037
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
9977
10038
|
self.present(alert, animated: true, completion: nil)
|
|
9978
10039
|
return
|
|
9979
10040
|
}
|
|
9980
|
-
|
|
10041
|
+
|
|
9981
10042
|
// Check if the expiry date is valid
|
|
9982
10043
|
if let expiryDateObj = dateFormatter.date(from: expiryText) {
|
|
9983
10044
|
// Check if the expiry date is in the past
|
|
@@ -9985,13 +10046,21 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
|
|
|
9985
10046
|
let calendar = Calendar.current
|
|
9986
10047
|
let currentMonthYear = calendar.date(from: calendar.dateComponents([.year, .month], from: currentDate))
|
|
9987
10048
|
if expiryDateObj < currentMonthYear! {
|
|
9988
|
-
let alert = UIAlertController(
|
|
10049
|
+
let alert = UIAlertController(
|
|
10050
|
+
title: "Expired Card",
|
|
10051
|
+
message: "The expiry date cannot be in the past. Please enter a valid expiry date.",
|
|
10052
|
+
preferredStyle: .alert
|
|
10053
|
+
)
|
|
9989
10054
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
9990
10055
|
self.present(alert, animated: true, completion: nil)
|
|
9991
10056
|
return
|
|
9992
10057
|
}
|
|
9993
10058
|
} else {
|
|
9994
|
-
let alert = UIAlertController(
|
|
10059
|
+
let alert = UIAlertController(
|
|
10060
|
+
title: "Invalid Expiry Date",
|
|
10061
|
+
message: "Please enter the expiry date in the format MM/yy (e.g., 09/25).",
|
|
10062
|
+
preferredStyle: .alert
|
|
10063
|
+
)
|
|
9995
10064
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
|
9996
10065
|
self.present(alert, animated: true, completion: nil)
|
|
9997
10066
|
return
|
|
@@ -11077,14 +11146,17 @@ extension PaymentInfoVC: UITextFieldDelegate {
|
|
|
11077
11146
|
}
|
|
11078
11147
|
|
|
11079
11148
|
// Handle card expiry date input for both old and new card fields
|
|
11080
|
-
else if textField == cardExpiryTextField.textField ||
|
|
11081
|
-
|
|
11149
|
+
else if textField == cardExpiryTextField.textField ||
|
|
11150
|
+
textField == txtFieldExpiryDateNewCardView ||
|
|
11151
|
+
textField == txtFieldExpireDateUpdateCardView {
|
|
11152
|
+
|
|
11153
|
+
if range.length > 0 { // allow backspace
|
|
11082
11154
|
return true
|
|
11083
11155
|
}
|
|
11084
|
-
if string.isEmpty {
|
|
11156
|
+
if string.isEmpty { // prevent empty string issues
|
|
11085
11157
|
return false
|
|
11086
11158
|
}
|
|
11087
|
-
if range.location >
|
|
11159
|
+
if range.location > 4 { // max length "MM/yy" = 5
|
|
11088
11160
|
return false
|
|
11089
11161
|
}
|
|
11090
11162
|
|
|
@@ -11096,8 +11168,8 @@ extension PaymentInfoVC: UITextFieldDelegate {
|
|
|
11096
11168
|
return false
|
|
11097
11169
|
}
|
|
11098
11170
|
|
|
11099
|
-
//
|
|
11100
|
-
if
|
|
11171
|
+
// Auto-insert "/" after entering MM
|
|
11172
|
+
if originalText.count == 2 {
|
|
11101
11173
|
originalText.append("/")
|
|
11102
11174
|
}
|
|
11103
11175
|
|
|
@@ -2910,7 +2910,7 @@
|
|
|
2910
2910
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wBs-bW-IlA">
|
|
2911
2911
|
<rect key="frame" x="0.0" y="24.333333333333371" width="172.66666666666666" height="50"/>
|
|
2912
2912
|
<subviews>
|
|
2913
|
-
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="MM/
|
|
2913
|
+
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="MM/YY" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="dwB-uJ-vVL">
|
|
2914
2914
|
<rect key="frame" x="12" y="0.0" width="148.66666666666666" height="50"/>
|
|
2915
2915
|
<color key="tintColor" name="G_000000"/>
|
|
2916
2916
|
<fontDescription key="fontDescription" name="Inter-Regular" family="Inter" pointSize="16"/>
|
|
@@ -4075,7 +4075,7 @@
|
|
|
4075
4075
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JcZ-JP-XpP">
|
|
4076
4076
|
<rect key="frame" x="0.0" y="24.333333333333485" width="172.66666666666666" height="50"/>
|
|
4077
4077
|
<subviews>
|
|
4078
|
-
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="MM/
|
|
4078
|
+
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="MM/YY" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="6bS-xy-xdJ">
|
|
4079
4079
|
<rect key="frame" x="12" y="0.0" width="148.66666666666666" height="50"/>
|
|
4080
4080
|
<color key="tintColor" name="G_000000"/>
|
|
4081
4081
|
<fontDescription key="fontDescription" name="Inter-Regular" family="Inter" pointSize="16"/>
|
|
@@ -4494,7 +4494,7 @@
|
|
|
4494
4494
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="SBL-4j-yn1">
|
|
4495
4495
|
<rect key="frame" x="0.0" y="24.333333333333485" width="172.66666666666666" height="50"/>
|
|
4496
4496
|
<subviews>
|
|
4497
|
-
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="MM/
|
|
4497
|
+
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="MM/YY" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="WJr-2D-4Xq">
|
|
4498
4498
|
<rect key="frame" x="12" y="0.0" width="148.66666666666666" height="50"/>
|
|
4499
4499
|
<color key="tintColor" name="G_000000"/>
|
|
4500
4500
|
<fontDescription key="fontDescription" name="Inter-Regular" family="Inter" pointSize="16"/>
|