@primer-io/react-native 2.26.2 → 2.27.0

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 (76) hide show
  1. package/android/.project +6 -0
  2. package/android/.settings/org.eclipse.buildship.core.prefs +5 -5
  3. package/android/build.gradle +1 -3
  4. package/android/src/main/AndroidManifest.xml +1 -4
  5. package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +3 -3
  6. package/android/src/main/java/com/primerioreactnative/PrimerRNEventListener.kt +4 -3
  7. package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckout.kt +2 -2
  8. package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckoutListener.kt +46 -9
  9. package/android/src/main/java/com/primerioreactnative/ReactNativePackage.kt +4 -0
  10. package/android/src/main/java/com/primerioreactnative/components/manager/ach/AchMandateManager.kt +70 -0
  11. package/android/src/main/java/com/primerioreactnative/components/manager/ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.kt +283 -0
  12. package/android/src/main/java/com/primerioreactnative/components/manager/banks/PrimerRNHeadlessUniversalCheckoutBanksComponent.kt +7 -37
  13. package/android/src/main/java/com/primerioreactnative/components/manager/klarna/PrimerRNHeadlessUniversalCheckoutKlarnaComponent.kt +5 -31
  14. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerCheckoutAdditionalInfoRN.kt +17 -4
  15. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerSettingsRN.kt +44 -37
  16. package/android/src/main/java/com/primerioreactnative/datamodels/ach/AchUserDetailsCollectableDataRN.kt +22 -0
  17. package/android/src/main/java/com/primerioreactnative/datamodels/ach/AchUserDetailsStepRN.kt +22 -0
  18. package/android/src/main/java/com/primerioreactnative/datamodels/extensions/ach/AchUserDetailsCollectableData.kt +11 -0
  19. package/android/src/main/java/com/primerioreactnative/datamodels/extensions/ach/AchUserDetailsStep.kt +14 -0
  20. package/android/src/main/java/com/primerioreactnative/extensions/JSONExtensions.kt +41 -0
  21. package/android/src/main/java/com/primerioreactnative/extensions/PrimerCheckoutAdditionalInfo.kt +4 -0
  22. package/android/src/main/java/com/primerioreactnative/extensions/PrimerPaymentMethodOptionsRN.kt +42 -15
  23. package/ios/Sources/DataModels/Ach Component/RNTAchUserDetailsCollectableData.swift +54 -0
  24. package/ios/Sources/DataModels/Ach Component/RNTAchUserDetailsStep.swift +40 -0
  25. package/ios/Sources/DataModels/PrimerCheckoutAdditionalInfoRN.swift +61 -0
  26. package/ios/Sources/DataModels/PrimerSettings+Extensions.swift +24 -1
  27. package/ios/Sources/Headless Universal Checkout/Managers/Ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.m +28 -0
  28. package/ios/Sources/Headless Universal Checkout/Managers/Ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.swift +233 -0
  29. package/ios/Sources/Headless Universal Checkout/Managers/Ach/RNTAchMandateManager.m +16 -0
  30. package/ios/Sources/Headless Universal Checkout/Managers/Ach/RNTAchMandateManager.swift +53 -0
  31. package/ios/Sources/Headless Universal Checkout/Managers/Klarna/PrimerRNHeadlessUniversalCheckoutKlarnaComponent.swift +2 -2
  32. package/ios/Sources/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckout.swift +56 -7
  33. package/ios/Sources/version.swift +1 -1
  34. package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js +106 -0
  35. package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js.map +1 -0
  36. package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js +38 -0
  37. package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js.map +1 -0
  38. package/lib/commonjs/index.js +70 -0
  39. package/lib/commonjs/index.js.map +1 -1
  40. package/lib/commonjs/models/ach/AchCollectableData.js +6 -0
  41. package/lib/commonjs/models/ach/AchCollectableData.js.map +1 -0
  42. package/lib/commonjs/models/ach/AchSteps.js +6 -0
  43. package/lib/commonjs/models/ach/AchSteps.js.map +1 -0
  44. package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js +99 -0
  45. package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js.map +1 -0
  46. package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js +31 -0
  47. package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js.map +1 -0
  48. package/lib/module/index.js +8 -0
  49. package/lib/module/index.js.map +1 -1
  50. package/lib/module/models/ach/AchCollectableData.js +2 -0
  51. package/lib/module/models/ach/AchCollectableData.js.map +1 -0
  52. package/lib/module/models/ach/AchSteps.js +2 -0
  53. package/lib/module/models/ach/AchSteps.js.map +1 -0
  54. package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.d.ts +53 -0
  55. package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.d.ts.map +1 -0
  56. package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.d.ts +12 -0
  57. package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.d.ts.map +1 -0
  58. package/lib/typescript/index.d.ts +8 -0
  59. package/lib/typescript/index.d.ts.map +1 -1
  60. package/lib/typescript/models/PrimerCheckoutAdditionalInfo.d.ts +10 -0
  61. package/lib/typescript/models/PrimerCheckoutAdditionalInfo.d.ts.map +1 -1
  62. package/lib/typescript/models/PrimerSettings.d.ts +14 -0
  63. package/lib/typescript/models/PrimerSettings.d.ts.map +1 -1
  64. package/lib/typescript/models/ach/AchCollectableData.d.ts +25 -0
  65. package/lib/typescript/models/ach/AchCollectableData.d.ts.map +1 -0
  66. package/lib/typescript/models/ach/AchSteps.d.ts +28 -0
  67. package/lib/typescript/models/ach/AchSteps.d.ts.map +1 -0
  68. package/package.json +1 -1
  69. package/primer-io-react-native.podspec +1 -1
  70. package/src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.ts +158 -0
  71. package/src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.ts +32 -0
  72. package/src/index.tsx +8 -0
  73. package/src/models/PrimerCheckoutAdditionalInfo.ts +19 -5
  74. package/src/models/PrimerSettings.ts +19 -0
  75. package/src/models/ach/AchCollectableData.ts +29 -0
  76. package/src/models/ach/AchSteps.ts +29 -0
@@ -0,0 +1,61 @@
1
+ //
2
+ // PrimerCheckoutAdditionalInfoRN.swift
3
+ // primer-io-react-native
4
+ //
5
+ // Created by Flaviu Dunca on 17.06.2024.
6
+ //
7
+
8
+ import Foundation
9
+ import PrimerSDK
10
+
11
+
12
+ protocol PrimerCheckoutAdditionalInfoRN: Encodable {
13
+ var additionalInfoName: String { get }
14
+ }
15
+
16
+ class MultibancoCheckoutAdditionalInfoRN: PrimerCheckoutAdditionalInfoRN {
17
+ let expiresAt: String?
18
+ let reference: String?
19
+ let entity: String?
20
+ let additionalInfoName: String = "MultibancoCheckoutAdditionalInfo"
21
+
22
+ init(expiresAt: String?, reference: String?, entity: String?) {
23
+ self.expiresAt = expiresAt
24
+ self.reference = reference
25
+ self.entity = entity
26
+ }
27
+ }
28
+
29
+ protocol PrimerCheckoutQRCodeInfoRN: PrimerCheckoutAdditionalInfoRN {}
30
+
31
+ class PromptPayCheckoutAdditionalInfoRN: PrimerCheckoutQRCodeInfoRN {
32
+ let expiresAt: String
33
+ let qrCodeUrl: String?
34
+ let qrCodeBase64: String?
35
+ var additionalInfoName: String = "PromptPayCheckoutAdditionalInfo"
36
+
37
+ init(expiresAt: String, qrCodeUrl: String?, qrCodeBase64: String?) {
38
+ self.expiresAt = expiresAt
39
+ self.qrCodeUrl = qrCodeUrl
40
+ self.qrCodeBase64 = qrCodeBase64
41
+ }
42
+ }
43
+
44
+ protocol PrimerCheckoutVoucherInfoRN: PrimerCheckoutAdditionalInfoRN {}
45
+
46
+ class XenditCheckoutVoucherAdditionalInfoRN: PrimerCheckoutVoucherInfoRN {
47
+ let expiresAt: String
48
+ let couponCode: String
49
+ let retailerName: String?
50
+ var additionalInfoName: String = "XenditCheckoutVoucherAdditionalInfo"
51
+
52
+ init(expiresAt: String, couponCode: String, retailerName: String?) {
53
+ self.expiresAt = expiresAt
54
+ self.couponCode = couponCode
55
+ self.retailerName = retailerName
56
+ }
57
+ }
58
+
59
+ class AchAdditionalInfoDisplayMandateRN: PrimerCheckoutAdditionalInfoRN {
60
+ var additionalInfoName: String = "DisplayStripeAchMandateAdditionalInfo"
61
+ }
@@ -85,12 +85,35 @@ extension PrimerSettings {
85
85
  if let rnThreeDsAppRequestorUrlStr = (((settingsJson["paymentMethodOptions"] as? [String: Any])?["threeDsOptions"] as? [String: Any])?["iOS"] as? [String: Any])?["threeDsAppRequestorUrl"] as? String {
86
86
  threeDsOptions = PrimerThreeDsOptions(threeDsAppRequestorUrl: rnThreeDsAppRequestorUrlStr)
87
87
  }
88
+
89
+ var stripeOptions: PrimerStripeOptions?
90
+ if let stripeOptionsMap = ((settingsJson["paymentMethodOptions"] as? [String: Any])?["stripeOptions"] as? [String: Any]) {
91
+ if let publishableKey = stripeOptionsMap["publishableKey"] as? String {
92
+ var mandateData: PrimerStripeOptions.MandateData?
93
+ if let mandateDataMap = stripeOptionsMap["mandateData"] as? [String: String] {
94
+ if let fullMandateText = mandateDataMap["fullMandateText"] {
95
+ mandateData = .fullMandate(text: fullMandateText)
96
+ } else if let merchantName = mandateDataMap["merchantName"] {
97
+ mandateData = .templateMandate(merchantName: merchantName)
98
+ } else {
99
+ PrimerLogging.shared.logger.warn(message: "Found mandate data but no resource key or merchant name - check your stripe config")
100
+ }
101
+ } else {
102
+ PrimerLogging.shared.logger.warn(message: "Found stripe options but no mandate data - check your stripe config")
103
+ }
104
+ stripeOptions = .init(
105
+ publishableKey: publishableKey,
106
+ mandateData: mandateData
107
+ )
108
+ }
109
+ }
88
110
 
89
111
  let paymentMethodOptions = PrimerPaymentMethodOptions(
90
112
  urlScheme: rnUrlScheme,
91
113
  applePayOptions: applePayOptions,
92
114
  klarnaOptions: klarnaOptions,
93
- threeDsOptions: threeDsOptions)
115
+ threeDsOptions: threeDsOptions,
116
+ stripeOptions: stripeOptions)
94
117
 
95
118
  self.init(
96
119
  paymentHandling: paymentHandling,
@@ -0,0 +1,28 @@
1
+ //
2
+ // PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.m
3
+ // primer-io-react-native
4
+ //
5
+ // Created by Flaviu Dunca on 14.06.2024.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+ #import <React/RCTBridgeModule.h>
10
+ #import <React/RCTEventEmitter.h>
11
+
12
+ @interface RCT_EXTERN_MODULE(RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent, RCTEventEmitter)
13
+
14
+ RCT_EXTERN_METHOD(configure:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
15
+
16
+ RCT_EXTERN_METHOD(onSetFirstName:(NSString *)firstName resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
17
+
18
+ RCT_EXTERN_METHOD(onSetLastName:(NSString *)lastName resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
19
+
20
+ RCT_EXTERN_METHOD(onSetEmailAddress:(NSString *)emailAddress resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
21
+
22
+ RCT_EXTERN_METHOD(start:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
23
+
24
+ RCT_EXTERN_METHOD(submit:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
25
+
26
+ RCT_EXTERN_METHOD(cleanUp:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
27
+
28
+ @end
@@ -0,0 +1,233 @@
1
+ //
2
+ // PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.swift
3
+ // Pods
4
+ //
5
+ // Created by Flaviu Dunca on 12.06.2024.
6
+ //
7
+
8
+ import Foundation
9
+ import UIKit
10
+ import PrimerSDK
11
+
12
+ @objc(RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent)
13
+ class RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: RCTEventEmitter {
14
+
15
+ #if canImport(PrimerStripeSDK)
16
+ private var achManager: PrimerHeadlessUniversalCheckout.AchManager = PrimerHeadlessUniversalCheckout.AchManager()
17
+ #endif
18
+ var stripeAchUserDetailsComponent: (any StripeAchUserDetailsComponent)?
19
+ var clientToken: String?
20
+
21
+ override class func requiresMainQueueSetup() -> Bool {
22
+ return true
23
+ }
24
+
25
+ override init() {
26
+ super.init()
27
+ }
28
+
29
+ override func supportedEvents() -> [String] {
30
+ return PrimerHeadlessUniversalCheckoutComponentEvent.allCases.compactMap({ $0.stringValue })
31
+ }
32
+
33
+ // MARK: - API
34
+
35
+ @objc
36
+ public func configure(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
37
+ print("configure")
38
+
39
+ do {
40
+ #if canImport(PrimerStripeSDK)
41
+ guard let stripeAchUserDetailsComponent: any StripeAchUserDetailsComponent = try? achManager.provide(paymentMethodType: "STRIPE_ACH") else {
42
+ let err = RNTNativeError(
43
+ errorId: "native-ios",
44
+ errorDescription: "Failed to find asset of STRIPE_ACH for this session",
45
+ recoverySuggestion: nil)
46
+ throw err
47
+ }
48
+ self.stripeAchUserDetailsComponent = stripeAchUserDetailsComponent
49
+ RNTAchMandateManager.mandateDelegate = achManager.mandateDelegate
50
+ stripeAchUserDetailsComponent.stepDelegate = self
51
+ stripeAchUserDetailsComponent.errorDelegate = self
52
+ stripeAchUserDetailsComponent.validationDelegate = self
53
+ #else
54
+ let err = RNTNativeError(
55
+ errorId: "native-ios",
56
+ errorDescription: "PrimerStripeSDK missing",
57
+ recoverySuggestion: "Check if PrimerStripeSDK is included in your Podfile")
58
+
59
+ throw err
60
+ #endif
61
+
62
+ resolver(nil)
63
+ } catch {
64
+ rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
65
+ }
66
+ }
67
+
68
+ @objc
69
+ public func cleanUp(
70
+ _ resolver: RCTPromiseResolveBlock,
71
+ rejecter: RCTPromiseRejectBlock
72
+ ) {
73
+ RNTAchMandateManager.mandateDelegate = nil
74
+ stripeAchUserDetailsComponent = nil
75
+ resolver(nil)
76
+ }
77
+
78
+ @objc
79
+ public func start(
80
+ _ resolver: RCTPromiseResolveBlock,
81
+ rejecter: RCTPromiseRejectBlock
82
+ ) {
83
+ print("Start Stripe ACH process")
84
+
85
+ guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
86
+ rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
87
+ return
88
+ }
89
+
90
+ stripeAchUserDetailsComponent.start()
91
+ resolver(nil)
92
+ }
93
+
94
+ @objc
95
+ public func submit(
96
+ _ resolver: RCTPromiseResolveBlock,
97
+ rejecter: RCTPromiseRejectBlock
98
+ ) {
99
+ guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
100
+ rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
101
+ return
102
+ }
103
+
104
+ stripeAchUserDetailsComponent.submit()
105
+ resolver(nil)
106
+ }
107
+
108
+ @objc
109
+ public func onSetFirstName(
110
+ _ firstName: String,
111
+ resolver: RCTPromiseResolveBlock,
112
+ rejecter: RCTPromiseRejectBlock
113
+ ) {
114
+ guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
115
+ rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
116
+ return
117
+ }
118
+
119
+ DispatchQueue.main.async {
120
+ stripeAchUserDetailsComponent.updateCollectedData(collectableData: ACHUserDetailsCollectableData.firstName(firstName))
121
+ }
122
+
123
+ resolver(nil)
124
+ }
125
+
126
+ @objc
127
+ public func onSetLastName(
128
+ _ lastName: String,
129
+ resolver: RCTPromiseResolveBlock,
130
+ rejecter: RCTPromiseRejectBlock
131
+ ) {
132
+ guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
133
+ rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
134
+ return
135
+ }
136
+
137
+ DispatchQueue.main.async {
138
+ stripeAchUserDetailsComponent.updateCollectedData(collectableData: ACHUserDetailsCollectableData.lastName(lastName))
139
+ }
140
+
141
+ resolver(nil)
142
+ }
143
+
144
+ @objc
145
+ public func onSetEmailAddress(
146
+ _ emailAddress: String,
147
+ resolver: RCTPromiseResolveBlock,
148
+ rejecter: RCTPromiseRejectBlock
149
+ ) {
150
+ guard let stripeAchUserDetailsComponent = self.stripeAchUserDetailsComponent else {
151
+ rejecter("UNINITIALIZED_ERROR", "Stripe ACH user details component is uninitialized", nil)
152
+ return
153
+ }
154
+
155
+ DispatchQueue.main.async {
156
+ stripeAchUserDetailsComponent.updateCollectedData(collectableData: ACHUserDetailsCollectableData.emailAddress(emailAddress))
157
+ }
158
+
159
+ resolver(nil)
160
+ }
161
+ }
162
+
163
+ extension RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: PrimerHeadlessSteppableDelegate {
164
+ func didReceiveStep(step: PrimerSDK.PrimerHeadlessStep) {
165
+ guard let step = step as? ACHUserDetailsStep else { return }
166
+
167
+ switch step {
168
+ case .retrievedUserDetails(let details):
169
+ let json = try? step.toUserDetailsRetrievedRN(firstName: details.firstName, lastName: details.lastName, emailAddress: details.emailAddress).toJsonObject()
170
+
171
+ sendEvent(
172
+ withName: PrimerHeadlessUniversalCheckoutComponentEvent.onStep.stringValue,
173
+ body: json
174
+ )
175
+
176
+ case .didCollectUserDetails:
177
+ let json = try? step.toUserDetailsCollectedRN().toJsonObject()
178
+
179
+ sendEvent(
180
+ withName: PrimerHeadlessUniversalCheckoutComponentEvent.onStep.stringValue,
181
+ body: json
182
+ )
183
+
184
+ default:
185
+ break
186
+ }
187
+ }
188
+ }
189
+
190
+ extension RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: PrimerHeadlessValidatableDelegate {
191
+ func didUpdate(validationStatus: PrimerSDK.PrimerValidationStatus, for data: PrimerSDK.PrimerCollectableData?) {
192
+ guard let data = data as? ACHUserDetailsCollectableData else { return }
193
+
194
+ var errorJsonObject: Any?
195
+ let eventName: String
196
+
197
+ switch validationStatus {
198
+ case .valid:
199
+ eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValid.stringValue
200
+ case .validating:
201
+ eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValidating.stringValue
202
+ case .invalid(let errors):
203
+ errorJsonObject = try? ["errors": errors.map { $0.toPrimerValidationErrorRN() }].toJsonObject()
204
+ eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onInvalid.stringValue
205
+ case .error(let error):
206
+ errorJsonObject = try? ["errors": [error.toPrimerErrorRN()]].toJsonObject()
207
+ eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValidationError.stringValue
208
+ }
209
+
210
+ var dataJsonObject: Any?
211
+ switch data {
212
+ case .firstName(let value):
213
+ dataJsonObject = try? ["data": data.toFirstNameRN(value: value)].toJsonObject()
214
+ case .lastName(let value):
215
+ dataJsonObject = try? ["data": data.toLastNameRN(value: value)].toJsonObject()
216
+ case .emailAddress(let value):
217
+ dataJsonObject = try? ["data": data.toEmailAddressRN(value: value)].toJsonObject()
218
+ }
219
+ let allData = ((dataJsonObject as? [String: Any]) ?? [:]).merging((errorJsonObject as? [String: Any]) ?? [:]) { (_, new) in new }
220
+ sendEvent(withName: eventName, body: allData)
221
+ }
222
+ }
223
+
224
+ extension RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent: PrimerHeadlessErrorableDelegate {
225
+ func didReceiveError(error: PrimerSDK.PrimerError) {
226
+ let rnError = error.toPrimerErrorRN()
227
+ let serializedData = try? ["errors": [rnError]].toJsonObject()
228
+
229
+ self.sendEvent(
230
+ withName: PrimerHeadlessUniversalCheckoutComponentEvent.onError.stringValue,
231
+ body: serializedData)
232
+ }
233
+ }
@@ -0,0 +1,16 @@
1
+ //
2
+ // RNTAchMandateManager.m
3
+ // primer-io-react-native
4
+ //
5
+ // Created by Flaviu Dunca on 18.06.2024.
6
+ //
7
+
8
+ #import <React/RCTBridgeModule.h>
9
+
10
+ @interface RCT_EXTERN_MODULE(RNTAchMandateManager, NSObject)
11
+
12
+ RCT_EXTERN_METHOD(acceptMandate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
13
+
14
+ RCT_EXTERN_METHOD(declineMandate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
15
+
16
+ @end
@@ -0,0 +1,53 @@
1
+ //
2
+ // RNTAchMandateManager.swift
3
+ // primer-io-react-native
4
+ //
5
+ // Created by Flaviu Dunca on 18.06.2024.
6
+ //
7
+
8
+ import Foundation
9
+ import React
10
+ import PrimerSDK
11
+
12
+ @objc(RNTAchMandateManager)
13
+ class RNTAchMandateManager: NSObject, RCTBridgeModule {
14
+ private let errorMessage = "Mandate delegate is not defined"
15
+
16
+ static func moduleName() -> String! {
17
+ return "RNTAchMandateManager"
18
+ }
19
+
20
+ func methodQueue() -> DispatchQueue {
21
+ return DispatchQueue.main
22
+ }
23
+
24
+ @objc static func requiresMainQueueSetup() -> Bool {
25
+ return true
26
+ }
27
+
28
+ static var mandateDelegate: ACHMandateDelegate? = nil
29
+
30
+ @objc
31
+ func acceptMandate(
32
+ _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
33
+ ) {
34
+ if let delegate = RNTAchMandateManager.mandateDelegate {
35
+ delegate.acceptMandate()
36
+ resolver(nil)
37
+ } else {
38
+ rejecter("native-ios", errorMessage, nil)
39
+ }
40
+ }
41
+
42
+ @objc
43
+ func declineMandate(
44
+ _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
45
+ ) {
46
+ if let delegate = RNTAchMandateManager.mandateDelegate {
47
+ delegate.declineMandate()
48
+ resolver(nil)
49
+ } else {
50
+ rejecter("native-ios", errorMessage, nil)
51
+ }
52
+ }
53
+ }
@@ -241,7 +241,7 @@ extension RNTPrimerHeadlessUniversalCheckoutKlarnaComponent: PrimerHeadlessValid
241
241
  eventName = PrimerHeadlessUniversalCheckoutComponentEvent.onValidating.stringValue
242
242
  case .invalid(let errors):
243
243
  let rnErrors = errors.map { $0.toPrimerValidationErrorRN() }
244
- let serializedData = try? ["errors": rnErrors].toJsonObject()
244
+ let serializedData = try? ["errors": rnErrors].toJsonObject() // TODO TWS iOS: include 'data'
245
245
 
246
246
  self.sendEvent(
247
247
  withName: PrimerHeadlessUniversalCheckoutComponentEvent.onInvalid.stringValue,
@@ -249,7 +249,7 @@ extension RNTPrimerHeadlessUniversalCheckoutKlarnaComponent: PrimerHeadlessValid
249
249
  return
250
250
  case .error(let error):
251
251
  let rnError = error.toPrimerErrorRN()
252
- let serializedData = try? ["errors": [rnError]].toJsonObject()
252
+ let serializedData = try? ["errors": [rnError]].toJsonObject() // TODO TWS iOS: include 'data'
253
253
 
254
254
  self.sendEvent(
255
255
  withName: PrimerHeadlessUniversalCheckoutComponentEvent.onValidationError.stringValue,
@@ -7,6 +7,8 @@
7
7
 
8
8
  import Foundation
9
9
  import PrimerSDK
10
+ import PrimerStripeSDK
11
+ import React
10
12
 
11
13
  @objc
12
14
  enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
@@ -75,8 +77,6 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
75
77
 
76
78
  override init() {
77
79
  super.init()
78
- PrimerHeadlessUniversalCheckout.current.delegate = self
79
- PrimerHeadlessUniversalCheckout.current.uiDelegate = self
80
80
  }
81
81
 
82
82
  override func supportedEvents() -> [String]! {
@@ -91,6 +91,9 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
91
91
  resolver: @escaping RCTPromiseResolveBlock,
92
92
  rejecter: @escaping RCTPromiseRejectBlock)
93
93
  {
94
+ PrimerHeadlessUniversalCheckout.current.delegate = self
95
+ PrimerHeadlessUniversalCheckout.current.uiDelegate = self
96
+
94
97
  do {
95
98
  var tmpSettings: PrimerSettings?
96
99
  if let settingsStr = settingsStr {
@@ -346,11 +349,57 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
346
349
  DispatchQueue.main.async {
347
350
  if self.implementedRNCallbacks?.isOnCheckoutAdditionalInfoImplemented == true {
348
351
  do {
349
- let checkoutAdditionalInfoJson = try additionalInfo?.toJsonObject()
350
- self.sendEvent(
351
- withName: rnCallbackName,
352
- body: checkoutAdditionalInfoJson)
353
-
352
+ switch additionalInfo {
353
+ case let info as ACHBankAccountCollectorAdditionalInfo:
354
+ // Handled internally, nothing for merchant to handle
355
+ let keyWindow = UIApplication
356
+ .shared
357
+ .connectedScenes
358
+ .flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
359
+ .last { $0.isKeyWindow }
360
+ DispatchQueue.main.async {
361
+ if let rootViewController = keyWindow?.rootViewController {
362
+ rootViewController.present(info.collectorViewController, animated: true, completion: nil)
363
+ } else {
364
+ let checkoutData = PrimerCheckoutData(payment: nil, additionalInfo: additionalInfo)
365
+ self.handleRNBridgeError(
366
+ RNTNativeError(
367
+ errorId: "native-ios",
368
+ errorDescription: "Failed to retrieve root view controller, cannot present Stripe view controller",
369
+ recoverySuggestion: nil
370
+ ),
371
+ checkoutData: checkoutData,
372
+ stopOnDebug: true
373
+ )
374
+ }
375
+ }
376
+ return
377
+ case _ as ACHMandateAdditionalInfo:
378
+ self.sendEvent(
379
+ withName: rnCallbackName,
380
+ body: try AchAdditionalInfoDisplayMandateRN().toJsonObject()
381
+ )
382
+ case let info as MultibancoCheckoutAdditionalInfo:
383
+ self.sendEvent(
384
+ withName: rnCallbackName,
385
+ body: try MultibancoCheckoutAdditionalInfoRN(expiresAt: info.expiresAt, reference: info.reference, entity: info.entity).toJsonObject()
386
+ )
387
+ case let info as PromptPayCheckoutAdditionalInfo:
388
+ self.sendEvent(
389
+ withName: rnCallbackName,
390
+ body: try PromptPayCheckoutAdditionalInfoRN(expiresAt: info.expiresAt, qrCodeUrl: info.qrCodeUrl, qrCodeBase64: info.qrCodeBase64).toJsonObject()
391
+ )
392
+ case let info as XenditCheckoutVoucherAdditionalInfo:
393
+ self.sendEvent(
394
+ withName: rnCallbackName,
395
+ body: try XenditCheckoutVoucherAdditionalInfoRN(expiresAt: info.expiresAt, couponCode: info.couponCode, retailerName: info.retailerName).toJsonObject()
396
+ )
397
+ default:
398
+ self.sendEvent(
399
+ withName: rnCallbackName,
400
+ body: try additionalInfo?.toJsonObject()
401
+ )
402
+ }
354
403
  } catch {
355
404
  let checkoutData = PrimerCheckoutData(payment: nil, additionalInfo: additionalInfo)
356
405
  self.handleRNBridgeError(error, checkoutData: checkoutData, stopOnDebug: true)
@@ -1,2 +1,2 @@
1
1
  // swiftlint:disable:next identifier_name
2
- public let PrimerReactNativeSDKVersion = "2.26.1"
2
+ public let PrimerReactNativeSDKVersion = "2.27.0"
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PrimerHeadlessUniversalCheckoutAchManager = void 0;
7
+ var _reactNative = require("react-native");
8
+ var _EventType = require("./Utils/EventType");
9
+ const {
10
+ RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent
11
+ } = _reactNative.NativeModules;
12
+ const eventEmitter = new _reactNative.NativeEventEmitter(RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent);
13
+ class PrimerHeadlessUniversalCheckoutAchManager {
14
+ ///////////////////////////////////////////
15
+ // Init
16
+ ///////////////////////////////////////////
17
+ constructor() {}
18
+
19
+ ///////////////////////////////////////////
20
+ // API
21
+ ///////////////////////////////////////////
22
+
23
+ async provide(props) {
24
+ await this.configureListeners(props);
25
+ if (props.paymentMethodType == "STRIPE_ACH") {
26
+ const component = {
27
+ start: async () => {
28
+ RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent.start();
29
+ },
30
+ submit: async () => {
31
+ RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent.submit();
32
+ },
33
+ handleFirstNameChange: async value => {
34
+ RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent.onSetFirstName(value);
35
+ },
36
+ handleLastNameChange: async value => {
37
+ RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent.onSetLastName(value);
38
+ },
39
+ handleEmailAddressChange: async value => {
40
+ RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent.onSetEmailAddress(value);
41
+ }
42
+ };
43
+ await RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent.configure();
44
+ return component;
45
+ } else {
46
+ return null;
47
+ }
48
+ }
49
+ async configureListeners(props) {
50
+ if (props !== null && props !== void 0 && props.onStep) {
51
+ this.addListener('onStep', data => {
52
+ var _props$onStep;
53
+ (_props$onStep = props.onStep) === null || _props$onStep === void 0 || _props$onStep.call(props, data);
54
+ });
55
+ }
56
+ if (props !== null && props !== void 0 && props.onInvalid) {
57
+ this.addListener('onInvalid', data => {
58
+ var _props$onInvalid;
59
+ (_props$onInvalid = props.onInvalid) === null || _props$onInvalid === void 0 || _props$onInvalid.call(props, data);
60
+ });
61
+ }
62
+ if (props !== null && props !== void 0 && props.onError) {
63
+ this.addListener('onError', data => {
64
+ var _props$onError;
65
+ (_props$onError = props.onError) === null || _props$onError === void 0 || _props$onError.call(props, data);
66
+ });
67
+ }
68
+ if (props !== null && props !== void 0 && props.onValid) {
69
+ this.addListener('onValid', data => {
70
+ var _props$onValid;
71
+ (_props$onValid = props.onValid) === null || _props$onValid === void 0 || _props$onValid.call(props, data);
72
+ });
73
+ }
74
+ if (props !== null && props !== void 0 && props.onValidating) {
75
+ this.addListener('onValidating', data => {
76
+ var _props$onValidating;
77
+ (_props$onValidating = props.onValidating) === null || _props$onValidating === void 0 || _props$onValidating.call(props, data);
78
+ });
79
+ }
80
+ if (props !== null && props !== void 0 && props.onValidationError) {
81
+ this.addListener('onValidationError', data => {
82
+ var _props$onValidationEr;
83
+ (_props$onValidationEr = props.onValidationError) === null || _props$onValidationEr === void 0 || _props$onValidationEr.call(props, data);
84
+ });
85
+ }
86
+ }
87
+
88
+ ///////////////////////////////////////////
89
+ // HELPERS
90
+ ///////////////////////////////////////////
91
+
92
+ async addListener(eventType, listener) {
93
+ return eventEmitter.addListener(eventType, listener);
94
+ }
95
+ removeListener(subscription) {
96
+ return subscription.remove();
97
+ }
98
+ removeAllListenersForEvent(eventType) {
99
+ eventEmitter.removeAllListeners(eventType);
100
+ }
101
+ removeAllListeners() {
102
+ _EventType.eventTypes.forEach(eventType => this.removeAllListenersForEvent(eventType));
103
+ }
104
+ }
105
+ exports.PrimerHeadlessUniversalCheckoutAchManager = PrimerHeadlessUniversalCheckoutAchManager;
106
+ //# sourceMappingURL=AchManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","_EventType","RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent","NativeModules","eventEmitter","NativeEventEmitter","PrimerHeadlessUniversalCheckoutAchManager","constructor","provide","props","configureListeners","paymentMethodType","component","start","submit","handleFirstNameChange","value","onSetFirstName","handleLastNameChange","onSetLastName","handleEmailAddressChange","onSetEmailAddress","configure","onStep","addListener","data","_props$onStep","call","onInvalid","_props$onInvalid","onError","_props$onError","onValid","_props$onValid","onValidating","_props$onValidating","onValidationError","_props$onValidationEr","eventType","listener","removeListener","subscription","remove","removeAllListenersForEvent","removeAllListeners","eventTypes","forEach","exports"],"sourceRoot":"../../../../../src","sources":["HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.ts"],"mappings":"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"}