@jimrising/easymerchantsdk-react-native 1.3.4 → 1.3.6

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.
Files changed (47) hide show
  1. package/README.md +11 -4
  2. package/android/.gradle/8.10/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.10/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/8.10/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/8.10/fileHashes/fileHashes.bin +0 -0
  6. package/android/.gradle/8.10/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/8.10/gc.properties +0 -0
  8. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  9. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  10. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  11. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  12. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  13. package/android/.gradle/8.9/gc.properties +0 -0
  14. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  15. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  16. package/android/.gradle/nb-cache/trust/0B5D6BE682AD6AEE9815EC13516BF075752CAE5AD5BECDCC00315C37622C2FD3 +1 -0
  17. package/android/.gradle/nb-cache/trust/23843E1876B2E51C07E80AB52D1E797E5D8053D8097EEEB15FB63DD903195C14 +1 -0
  18. package/android/.gradle/vcs-1/gc.properties +0 -0
  19. package/android/.settings/org.eclipse.buildship.core.prefs +2 -0
  20. package/ios/Classes/EasyMerchantSdk.m +43 -28
  21. package/ios/Classes/EasyMerchantSdk.swift +68 -9
  22. package/ios/CustomComponents/PlanSelector.swift +28 -30
  23. package/ios/EnvironmentConfig.swift +30 -30
  24. package/ios/Example/ViewController.swift +47 -51
  25. package/ios/Models/AdditionalInfo.swift +43 -6
  26. package/ios/Models/BillingInfo.swift +50 -6
  27. package/ios/Models/RecurringIntervals.swift +34 -0
  28. package/ios/Models/RecurringStartDateType.swift +13 -0
  29. package/ios/Models/Request.swift +120 -11
  30. package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +609 -79
  31. package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +72 -25
  32. package/ios/Pods/ViewControllers/EmailVerificationVC.swift +14 -0
  33. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +459 -42
  34. package/ios/Pods/ViewControllers/PaymentDoneVC.swift +16 -2
  35. package/ios/Pods/ViewControllers/PaymentErrorVC.swift +0 -2
  36. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +1553 -372
  37. package/ios/Pods/ViewControllers/PaymentInformation/SavedAccountsTVC/SavedAccountTVC.swift +6 -2
  38. package/ios/Pods/ViewControllers/PaymentInformation/SavedCardsTVC/SavedCardsTVC.swift +6 -1
  39. package/ios/Pods/ViewControllers/ThreeDSecurePaymentDoneVC.swift +105 -0
  40. package/ios/easymerchantsdk.podspec +1 -1
  41. package/ios/easymerchantsdk.storyboard +554 -57
  42. package/package.json +2 -2
  43. package/.idea/caches/deviceStreaming.xml +0 -571
  44. package/.idea/em-MobileCheckoutSDK-ReactNative.iml +0 -9
  45. package/.idea/misc.xml +0 -5
  46. package/.idea/modules.xml +0 -8
  47. package/.idea/vcs.xml +0 -6
@@ -1,5 +1,3 @@
1
- //
2
- //
3
1
  //import UIKit
4
2
  //import EasyPay
5
3
  //
@@ -28,53 +26,51 @@
28
26
  // }
29
27
  //
30
28
  // @IBAction private func payAction() {
31
- //// let apiKey = "f149cf5afc3a67c79e0aa87e7"
32
- //// let apiSecret = "22b9dd1e588146077ca77da82"
33
- //
34
- // let apiKey = "14fbf8a186091763e59c289c1"
35
- // let apiSecret = "f90863e7a853539f8ace8d6de"
29
+ // let apiKey = "14fbf8a186091763e59c289c1"
30
+ // let apiSecret = "f90863e7a853539f8ace8d6de"
36
31
  //
37
32
  // EasyPay.EnvironmentConfig.configure(apiKey: apiKey, apiSecret: apiSecret)
38
33
  //
39
- // // Theme Configuration
34
+ //
40
35
  // let themeConfiguration = ThemeConfiguration(
41
- // bodyBackgroundColor: "#EBF8FF",
42
- // containerBackgroundColor: "#FFFFFF",
43
- // primaryFontColor: "#1E3A8A",
44
- // secondaryFontColor: "#696969",
45
- // primaryButtonBackgroundColor: "#1D4ED8",
46
- // primaryButtonHoverColor: "#2563EB",
47
- // primaryButtonFontColor: "#FFFFFF",
48
- // secondaryButtonBackgroundColor: "#FFFFFF",
49
- // secondaryButtonHoverColor: "#BFDBFE",
50
- // secondaryButtonFontColor: "#1E40AF",
36
+ // bodyBackgroundColor: "#1F2937", // dark gray-blue
37
+ // containerBackgroundColor: "#374151", // darker container
38
+ // primaryFontColor: "#F9FAFB", // near white
39
+ // secondaryFontColor: "#D1D5DB", // light gray
40
+ // primaryButtonBackgroundColor: "#4F46E5", // indigo (keep for contrast)
41
+ // primaryButtonHoverColor: "#4338CA", // deeper indigo
42
+ // primaryButtonFontColor: "#FFFFFF", // white text on button
43
+ // secondaryButtonBackgroundColor: "#1E40AF", // dark blue
44
+ // secondaryButtonHoverColor: "#1E3A8A", // deeper blue on hover
45
+ // secondaryButtonFontColor: "#E0E7FF", // soft blue-white
51
46
  // borderRadius: "8",
52
47
  // fontSize: "14"
53
48
  // )
54
49
  //
55
- // let additionalInfoRequest: [String: Any] = [
56
- // "name": "Test User",
57
- // "email": "test@gmail.com",
58
- // "phone_number": "9465351125",
59
- // "country_code": "91",
60
- // "description": "Test"
61
- // ]
62
- //
63
- // let json: [String: Any] = [
64
- // "address": "Mohali, Punjab",
65
- // "country": "India",
66
- // "state": "Punjab",
67
- // "city": "Anandpur Sahib",
68
- // "postal_code": "140118",
69
- // "additional_info": additionalInfoRequest
70
- // ]
71
- //
72
- // guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) else {
73
- // print("Failed to serialize JSON")
50
+ // let additionalInfo = AdditionalInfo(
51
+ // name: "Test User",
52
+ // email: "test@gmail.com",
53
+ // phone_number: "9465351125",
54
+ // country_code: "91",
55
+ // description: "Test"
56
+ // )
57
+ //
58
+ // let billingInfo = BillingInfo(
59
+ // address: "Mohali, Punjab",
60
+ // country: "India",
61
+ // state: "Punjab",
62
+ // city: "Anandpur Sahib",
63
+ // postal_code: "140118",
64
+ // additional_info: additionalInfo
65
+ // )
66
+ //
67
+ // // Encode Billing Info to Data
68
+ // guard let billingData = try? JSONEncoder().encode(billingInfo) else {
69
+ // print("Failed to encode BillingInfo")
74
70
  // return
75
71
  // }
76
72
  //
77
- // let authenticatedACH = true
73
+ // let authenticatedACH = false
78
74
  //
79
75
  // let grailPayParams = GrailPayRequest(
80
76
  // accessToken: "251|uTijpDGfrS88UR2V1cZNMQ8S4hUJA0sVzsnsoUZF",
@@ -89,15 +85,20 @@
89
85
  //
90
86
  // let request = EasyPay.Request(
91
87
  // amount: 99,
92
- // billingInfoData: jsonData,
93
- // paymentMethods: [.Card, .Bank, .Crypto],
88
+ // billingInfoData: billingData,
89
+ // paymentMethods: [.Card, .Bank],
94
90
  // themeConfiguration: themeConfiguration,
95
91
  // tokenOnly: false,
96
92
  // saveCard: false,
97
93
  // saveAccount: false,
98
94
  // submitButtonText: "Submit",
99
95
  // authenticatedACH: authenticatedACH,
100
- // grailPayParams: authenticatedACH ? grailPayParams : nil
96
+ // grailPayParams: authenticatedACH ? grailPayParams : nil,
97
+ // is_recurring: true,
98
+ // recurringIntervals: [.weekly, .monthly],
99
+ // recurringStartDateType: .custom,
100
+ // recurringStartDate: "05/30/2025", /// Format MM/dd/yyyy, must be today or future date
101
+ // enable3DS: true
101
102
  // )
102
103
  //
103
104
  // if request.tokenOnly == true {
@@ -120,6 +121,11 @@
120
121
  // switch result.type {
121
122
  // case .cancelled:
122
123
  // print("Cancelled")
124
+ // lblResponseShow.isHidden = false
125
+ // if let message = result.chargeData?["message"] as? String {
126
+ // print("Message from chargeData: \(message)")
127
+ // lblResponseShow.text = message
128
+ // }
123
129
  // case .success:
124
130
  // if let chargeData = result.chargeData {
125
131
  // if let clientToken = chargeData["clientToken"] as? String {
@@ -148,13 +154,3 @@
148
154
  //
149
155
  //}
150
156
  //
151
- //
152
- //
153
- //
154
- //
155
- //
156
- //
157
- //
158
- //
159
- //
160
- //
@@ -7,10 +7,47 @@
7
7
 
8
8
  import Foundation
9
9
 
10
- struct AdditionalInfo {
11
- let name: String
12
- let email: String
13
- let phone: String
14
- let description: String
15
- }
10
+ //struct AdditionalInfo {
11
+ // let name: String
12
+ // let email: String
13
+ // let phone: String
14
+ // let description: String
15
+ //}
16
+
17
+ //public struct AdditionalInfo: Codable {
18
+ // public let name: String
19
+ // public let email: String
20
+ // public let phone_number: String
21
+ // public let country_code: String
22
+ // public let description: String
23
+ //
24
+ // public init(name: String, email: String, phone_number: String, country_code: String, description: String) {
25
+ // self.name = name
26
+ // self.email = email
27
+ // self.phone_number = phone_number
28
+ // self.country_code = country_code
29
+ // self.description = description
30
+ // }
31
+ //}
16
32
 
33
+ public struct AdditionalInfo: Codable {
34
+ public let name: String?
35
+ public let email: String?
36
+ public let phone_number: String?
37
+ public let country_code: String?
38
+ public let description: String?
39
+
40
+ public init(
41
+ name: String? = nil,
42
+ email: String? = nil,
43
+ phone_number: String? = nil,
44
+ country_code: String? = nil,
45
+ description: String? = nil
46
+ ) {
47
+ self.name = name
48
+ self.email = email
49
+ self.phone_number = phone_number
50
+ self.country_code = country_code
51
+ self.description = description
52
+ }
53
+ }
@@ -7,10 +7,54 @@
7
7
 
8
8
  import Foundation
9
9
 
10
- struct BillingInfo {
11
- let address: String
12
- let country: String
13
- let state: String
14
- let city: String
15
- let postalCode: String
10
+ //struct BillingInfo {
11
+ // let address: String
12
+ // let country: String
13
+ // let state: String
14
+ // let city: String
15
+ // let postalCode: String
16
+ //}
17
+
18
+ //public struct BillingInfo: Codable {
19
+ // public let address: String
20
+ // public let country: String
21
+ // public let state: String
22
+ // public let city: String
23
+ // public let postal_code: String
24
+ // public let additional_info: AdditionalInfo
25
+ //
26
+ // public init(address: String, country: String, state: String, city: String, postal_code: String, additional_info: AdditionalInfo) {
27
+ // self.address = address
28
+ // self.country = country
29
+ // self.state = state
30
+ // self.city = city
31
+ // self.postal_code = postal_code
32
+ // self.additional_info = additional_info
33
+ // }
34
+ //}
35
+
36
+ public struct BillingInfo: Codable {
37
+ public let address: String?
38
+ public let country: String?
39
+ public let state: String?
40
+ public let city: String?
41
+ public let postal_code: String?
42
+ public let additional_info: AdditionalInfo?
43
+
44
+ public init(
45
+ address: String? = nil,
46
+ country: String? = nil,
47
+ state: String? = nil,
48
+ city: String? = nil,
49
+ postal_code: String? = nil,
50
+ additional_info: AdditionalInfo? = nil
51
+ ) {
52
+ self.address = address
53
+ self.country = country
54
+ self.state = state
55
+ self.city = city
56
+ self.postal_code = postal_code
57
+ self.additional_info = additional_info
58
+ }
16
59
  }
60
+
@@ -0,0 +1,34 @@
1
+ //
2
+ // RecurringIntervals.swift
3
+ // EasyPay
4
+ //
5
+ // Created by Mony's Mac on 22/05/25.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ public enum RecurringIntervals: String, CaseIterable {
11
+ case daily = "daily"
12
+ case weekly = "weekly"
13
+ case monthly = "monthly"
14
+ case quarterly = "quarterly"
15
+ case halfYearly = "halfyearly"
16
+ case yearly = "yearly"
17
+ case everyTwoYears = "everytwoyears"
18
+ case everyThreeYears = "everythreeyears"
19
+ case everyFourYears = "everyfouryears"
20
+ case everyFiveYears = "everyfiveyears"
21
+
22
+ var displayName: String {
23
+ switch self {
24
+ case .halfYearly: return "Half Yearly"
25
+ case .everyTwoYears: return "Every Two Years"
26
+ case .everyThreeYears: return "Every Three Years"
27
+ case .everyFourYears: return "Every Four Years"
28
+ case .everyFiveYears: return "Every Five Years"
29
+ default: return rawValue.capitalized
30
+ }
31
+ }
32
+ }
33
+
34
+
@@ -0,0 +1,13 @@
1
+ //
2
+ // RecurringStartDateType.swift
3
+ // EasyPay
4
+ //
5
+ // Created by Mony's Mac on 24/05/25.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ public enum RecurringStartDateType: String, CaseIterable {
11
+ case custom
12
+ case fixed
13
+ }
@@ -20,7 +20,7 @@ public struct ThemeConfiguration: Codable {
20
20
  public let secondaryButtonFontColor: String?
21
21
  public let borderRadius: String?
22
22
  public let fontSize: String?
23
-
23
+
24
24
  public init(
25
25
  bodyBackgroundColor: String? = nil,
26
26
  containerBackgroundColor: String? = nil,
@@ -59,7 +59,7 @@ public struct GrailPayRequest: Codable {
59
59
  public let brandingName: String
60
60
  public let finderSubtitle: String
61
61
  public let searchPlaceholder: String
62
-
62
+
63
63
  public init(
64
64
  accessToken: String,
65
65
  vendorId: String,
@@ -75,9 +75,9 @@ public struct GrailPayRequest: Codable {
75
75
  self.role = role
76
76
  self.timeout = timeout
77
77
  self.isSandbox = isSandbox
78
- self.brandingName = brandingName // Fixed: Use the actual parameter
79
- self.finderSubtitle = finderSubtitle // Fixed: Use the actual parameter
80
- self.searchPlaceholder = searchPlaceholder // Fixed: Use the actual parameter
78
+ self.brandingName = brandingName
79
+ self.finderSubtitle = finderSubtitle
80
+ self.searchPlaceholder = searchPlaceholder
81
81
  }
82
82
  }
83
83
 
@@ -95,7 +95,11 @@ public final class Request: NSObject {
95
95
  public let submitButtonText: String?
96
96
  public let authenticatedACH: Bool?
97
97
  public let grailPayParams: GrailPayRequest?
98
- public let enableRecurring: Bool?
98
+ public var is_recurring: Bool?
99
+ public var recurringIntervals: [RecurringIntervals]?
100
+ public var recurringStartDateType: RecurringStartDateType?
101
+ public var recurringStartDate: String?
102
+ public let enable3DS: Bool?
99
103
 
100
104
  public init(
101
105
  amount: Double,
@@ -108,7 +112,11 @@ public final class Request: NSObject {
108
112
  submitButtonText: String? = nil,
109
113
  authenticatedACH: Bool = false,
110
114
  grailPayParams: GrailPayRequest? = nil,
111
- enableRecurring: Bool = false
115
+ is_recurring: Bool = false,
116
+ recurringIntervals: [RecurringIntervals]? = nil,
117
+ recurringStartDateType: RecurringStartDateType? = nil,
118
+ recurringStartDate: String? = nil,
119
+ enable3DS: Bool = false
112
120
  ) {
113
121
  self.amount = amount
114
122
  self.billingInfoData = billingInfoData
@@ -119,7 +127,24 @@ public final class Request: NSObject {
119
127
  self.submitButtonText = submitButtonText
120
128
  self.authenticatedACH = authenticatedACH
121
129
  self.grailPayParams = authenticatedACH ? grailPayParams : nil
122
- self.enableRecurring = enableRecurring
130
+ self.is_recurring = is_recurring
131
+ self.recurringIntervals = recurringIntervals
132
+ self.recurringStartDateType = recurringStartDateType
133
+ self.recurringStartDate = recurringStartDate
134
+ self.enable3DS = enable3DS
135
+
136
+ // Conditionally assign recurring fields only if is_recurring == true
137
+ if is_recurring {
138
+ self.is_recurring = true
139
+ self.recurringIntervals = recurringIntervals
140
+ self.recurringStartDateType = recurringStartDateType
141
+ self.recurringStartDate = recurringStartDate
142
+ } else {
143
+ self.is_recurring = false
144
+ self.recurringIntervals = nil
145
+ self.recurringStartDateType = nil
146
+ self.recurringStartDate = nil
147
+ }
123
148
 
124
149
  if let paymentMethods = paymentMethods {
125
150
  self.selectedPaymentMethods = paymentMethods
@@ -171,8 +196,6 @@ public final class Request: NSObject {
171
196
 
172
197
  //MARK: - Payment Intent Api
173
198
  func paymentIntentApi(completion: @escaping (Bool) -> Void) {
174
- // Start loader when API call starts
175
-
176
199
  guard let serviceURL = URL(string: EnvironmentConfig.baseURL + EnvironmentConfig.Endpoints.paymentIntent.path()) else {
177
200
  print("Invalid URL")
178
201
  completion(false)
@@ -185,11 +208,47 @@ public final class Request: NSObject {
185
208
  request.addValue(EnvironmentConfig.apiKey ?? "", forHTTPHeaderField: "X-Api-Key")
186
209
  request.addValue(EnvironmentConfig.apiSecret ?? "", forHTTPHeaderField: "X-Api-Secret")
187
210
 
211
+ // Check if recurringStartDate is not in the past
212
+ if let startDateString = recurringStartDate,
213
+ let startDate = DateFormatter.recurringDateFormatter.date(from: startDateString) {
214
+
215
+ let today = Calendar.current.startOfDay(for: Date())
216
+ let startDay = Calendar.current.startOfDay(for: startDate)
217
+
218
+ if startDay < today {
219
+ DispatchQueue.main.async {
220
+ if let topVC = UIApplication.topViewController() {
221
+ let alert = UIAlertController(title: "Invalid Date",
222
+ message: "The recurring start date cannot be in the past. Please select today or a future date.",
223
+ preferredStyle: .alert)
224
+ alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
225
+ if let easyPayVC = UIApplication.findEasyPayViewController(from: topVC) {
226
+ easyPayVC.dismiss(animated: true)
227
+ } else {
228
+ // fallback: dismiss topVC itself if it's presented modally
229
+ topVC.dismiss(animated: true)
230
+ }
231
+ }))
232
+ topVC.present(alert, animated: true)
233
+ }
234
+ }
235
+
236
+ completion(false)
237
+ return
238
+ }
239
+ }
240
+
188
241
  let params: [String: Any] = [
189
242
  "amount": amount,
243
+ "allowed_cycles": String(recurringIntervals?.count ?? 0),
244
+ "intervals": recurringIntervals?.map { $0.rawValue } ?? [],
245
+ "is_recurring": self.is_recurring ?? false,
246
+ "recurring_start_date": recurringStartDate ?? "",
247
+ "recurring_start_date_type": recurringStartDateType?.rawValue ?? ""
190
248
  ]
191
249
 
192
250
  do {
251
+
193
252
  request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
194
253
  } catch {
195
254
  print("Error creating JSON data: \(error)")
@@ -240,7 +299,14 @@ public final class Request: NSObject {
240
299
  completion(false)
241
300
  }
242
301
  } else {
243
- print("HTTP Status Code: \(httpResponse.statusCode)")
302
+ if let data = data,
303
+ let responseObj = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
304
+ let message = responseObj["message"] as? String {
305
+ print(message)
306
+ } else {
307
+ print("HTTP Status Code: \(httpResponse.statusCode)")
308
+ }
309
+
244
310
  completion(false)
245
311
  }
246
312
  }
@@ -375,3 +441,46 @@ public final class Request: NSObject {
375
441
  }
376
442
 
377
443
  }
444
+
445
+ extension DateFormatter {
446
+ static let recurringDateFormatter: DateFormatter = {
447
+ let formatter = DateFormatter()
448
+ formatter.dateFormat = "MM/dd/yyyy"
449
+ formatter.timeZone = .current
450
+ return formatter
451
+ }()
452
+ }
453
+
454
+ extension UIApplication {
455
+ static func topViewController(base: UIViewController? = UIApplication.shared.connectedScenes
456
+ .compactMap { ($0 as? UIWindowScene)?.windows.first(where: \.isKeyWindow) }
457
+ .first?.rootViewController) -> UIViewController? {
458
+ if let nav = base as? UINavigationController {
459
+ return topViewController(base: nav.visibleViewController)
460
+ }
461
+ if let tab = base as? UITabBarController {
462
+ if let selected = tab.selectedViewController {
463
+ return topViewController(base: selected)
464
+ }
465
+ }
466
+ if let presented = base?.presentedViewController {
467
+ return topViewController(base: presented)
468
+ }
469
+ return base
470
+ }
471
+ }
472
+
473
+ extension UIApplication {
474
+ // Recursively find the presented EasyPayViewController (if any)
475
+ static func findEasyPayViewController(from vc: UIViewController?) -> EasyPayViewController? {
476
+ if let easyPayVC = vc as? EasyPayViewController {
477
+ return easyPayVC
478
+ }
479
+ if let presented = vc?.presentedViewController {
480
+ return findEasyPayViewController(from: presented)
481
+ }
482
+ return nil
483
+ }
484
+ }
485
+
486
+