@primer-io/react-native 2.3.0 → 2.5.1
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/android/.project +11 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +2 -2
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +1 -20
- package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckout.kt +2 -21
- package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckoutListener.kt +5 -6
- package/android/src/main/java/com/primerioreactnative/ReactNativePackage.kt +3 -1
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerPaymentMethodDataRN.kt +1 -3
- package/android/src/main/java/com/primerioreactnative/huc/datamodels/manager/raw/PrimerRNHeadlessCheckoutInputData.kt +22 -0
- package/android/src/main/java/com/primerioreactnative/huc/events/PrimerHeadlessUniversalCheckoutRawDataManagerEvent.kt +7 -0
- package/android/src/main/java/com/primerioreactnative/huc/manager/raw/PrimerRNHeadlessUniversalCheckoutRawManager.kt +140 -0
- package/android/src/main/java/com/primerioreactnative/huc/manager/raw/PrimerRNHeadlessUniversalCheckoutRawManagerListener.kt +49 -0
- package/ios/DataModels/PrimerErrorRN.swift +2 -0
- package/ios/DataModels/RNTPrimerCardData.swift +46 -0
- package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckout.swift +70 -107
- package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckoutRawDataManager.m +21 -0
- package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckoutRawDataManager.swift +152 -0
- package/ios/RNTPrimer.m +1 -1
- package/ios/RNTPrimer.swift +2 -9
- package/ios/ReactNative-Bridging-Header.h +10 -0
- package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckout.js +5 -4
- package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckout.js.map +1 -1
- package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js +106 -0
- package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
- package/lib/commonjs/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js +85 -0
- package/lib/commonjs/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
- package/lib/commonjs/index.js +28 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/PrimerRawData.js +2 -0
- package/lib/commonjs/models/PrimerRawData.js.map +1 -0
- package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckout.js +3 -3
- package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckout.js.map +1 -1
- package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js +88 -0
- package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
- package/lib/module/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js +76 -0
- package/lib/module/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/PrimerRawData.js +2 -0
- package/lib/module/models/PrimerRawData.js.map +1 -0
- package/lib/typescript/src/headless_checkout/PrimerHeadlessUniversalCheckout.d.ts +1 -0
- package/lib/typescript/src/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.d.ts +16 -0
- package/lib/typescript/src/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.d.ts +12 -0
- package/lib/typescript/src/index.d.ts +3 -1
- package/lib/typescript/src/models/PrimerRawData.d.ts +9 -0
- package/package.json +1 -1
- package/primer-io-react-native.podspec +1 -1
- package/src/headless_checkout/PrimerHeadlessUniversalCheckout.ts +3 -3
- package/src/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.ts +104 -0
- package/src/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.ts +91 -0
- package/src/index.tsx +8 -1
- package/src/models/PrimerRawData.ts +9 -0
- package/ios/Core/ReactNative-Bridging-Header.h +0 -14
|
@@ -10,7 +10,7 @@ import PrimerSDK
|
|
|
10
10
|
|
|
11
11
|
@objc
|
|
12
12
|
enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
case onHUCTokenizeStart = 0
|
|
15
15
|
case onHUCPrepareStart
|
|
16
16
|
case onHUCAvailablePaymentMethodsLoaded
|
|
@@ -22,7 +22,7 @@ enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
|
|
|
22
22
|
case onClientSessionUpdate
|
|
23
23
|
case onCheckoutComplete
|
|
24
24
|
case onError
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
var stringValue: String {
|
|
27
27
|
switch self {
|
|
28
28
|
case .onHUCPrepareStart:
|
|
@@ -53,28 +53,28 @@ enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
|
|
|
53
53
|
|
|
54
54
|
@objc(PrimerHeadlessUniversalCheckout)
|
|
55
55
|
class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
private var primerWillCreatePaymentWithDataDecisionHandler: ((_ errorMessage: String?) -> Void)?
|
|
58
58
|
private var primerDidTokenizePaymentMethodDecisionHandler: ((_ resumeToken: String?, _ errorMessage: String?) -> Void)?
|
|
59
59
|
private var primerDidResumeWithDecisionHandler: ((_ resumeToken: String?, _ errorMessage: String?) -> Void)?
|
|
60
60
|
private var primerDidFailWithErrorDecisionHandler: ((_ errorMessage: String) -> Void)?
|
|
61
61
|
private var implementedRNCallbacks: ImplementedRNCallbacks?
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
override class func requiresMainQueueSetup() -> Bool {
|
|
64
64
|
return true
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
override init() {
|
|
68
68
|
super.init()
|
|
69
69
|
PrimerHeadlessUniversalCheckout.current.delegate = self
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
override func supportedEvents() -> [String]! {
|
|
73
73
|
return PrimerHeadlessUniversalCheckoutEvents.allCases.compactMap({ $0.stringValue })
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
// MARK: - API
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
@objc
|
|
79
79
|
public func startWithClientToken(_ clientToken: String,
|
|
80
80
|
settingsStr: String?,
|
|
@@ -90,134 +90,97 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
90
90
|
return
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
PrimerHeadlessUniversalCheckout.current.start(withClientToken: clientToken, settings: settings, delegate: self) { paymentMethodTypes, err in
|
|
95
95
|
if let err = err {
|
|
96
96
|
errorCallback([err.rnError])
|
|
97
97
|
} else if let paymentMethodTypes = paymentMethodTypes {
|
|
98
|
-
successCallback([paymentMethodTypes
|
|
98
|
+
successCallback([paymentMethodTypes])
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
@objc
|
|
104
104
|
public func getAssetForPaymentMethodType(_ paymentMethodTypeStr: String,
|
|
105
105
|
assetType assetTypeStr: String,
|
|
106
106
|
errorCallback: @escaping RCTResponseSenderBlock,
|
|
107
107
|
successCallback: @escaping RCTResponseSenderBlock)
|
|
108
108
|
{
|
|
109
|
+
guard let unwrappedAssetType = PrimerAsset.ImageType(rawValue: assetTypeStr), let image = PrimerHeadlessUniversalCheckout.getAsset(for: paymentMethodTypeStr, assetType: unwrappedAssetType) else {
|
|
110
|
+
let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(paymentMethodTypeStr)", recoverySuggestion: nil)
|
|
111
|
+
errorCallback([err.rnError])
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
|
|
109
115
|
do {
|
|
110
|
-
try validate(assetStr: paymentMethodTypeStr, assetTypeStr: assetTypeStr)
|
|
111
|
-
let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodTypeStr)
|
|
112
|
-
|
|
113
|
-
guard let image = PrimerHeadlessUniversalCheckout.getAsset(for: paymentMethodType, assetType: PrimerAsset.ImageType(rawValue: assetTypeStr)!) else {
|
|
114
|
-
let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(paymentMethodTypeStr)", recoverySuggestion: nil)
|
|
115
|
-
errorCallback([err.rnError])
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
116
|
let imageURL = try self.tempStoreImage(image: image, name: paymentMethodTypeStr)
|
|
121
117
|
successCallback([imageURL.absoluteString])
|
|
122
118
|
} catch {
|
|
123
119
|
errorCallback([error.rnError])
|
|
124
120
|
}
|
|
125
121
|
}
|
|
126
|
-
|
|
122
|
+
|
|
127
123
|
@objc
|
|
128
124
|
public func getAssetForCardNetwork(_ cardNetworkStr: String,
|
|
129
125
|
assetType assetTypeStr: String,
|
|
130
126
|
errorCallback: @escaping RCTResponseSenderBlock,
|
|
131
127
|
successCallback: @escaping RCTResponseSenderBlock)
|
|
132
128
|
{
|
|
129
|
+
guard let cardNetwork = CardNetwork(rawValue: cardNetworkStr) else {
|
|
130
|
+
let err = NativeError(errorId: "invalid-card-network", errorDescription: "Card network for \(cardNetworkStr) does not exist, make sure you don't have any typos.", recoverySuggestion: nil)
|
|
131
|
+
errorCallback([err.rnError])
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
guard let unwrappedAssetType = PrimerAsset.ImageType(rawValue: assetTypeStr), let image = PrimerHeadlessUniversalCheckout.getAsset(for: cardNetwork, assetType: unwrappedAssetType) else {
|
|
136
|
+
let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(cardNetworkStr)", recoverySuggestion: nil)
|
|
137
|
+
errorCallback([err.rnError])
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
133
141
|
do {
|
|
134
|
-
try validate(assetStr: cardNetworkStr, assetTypeStr: assetTypeStr)
|
|
135
|
-
guard let cardNetwork = CardNetwork(rawValue: cardNetworkStr) else {
|
|
136
|
-
let err = NativeError(errorId: "invalid-card-network", errorDescription: "Card network for \(cardNetworkStr) does not exist, make sure you don't have any typos.", recoverySuggestion: nil)
|
|
137
|
-
errorCallback([err.rnError])
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
guard let image = PrimerHeadlessUniversalCheckout.getAsset(for: cardNetwork, assetType: PrimerAsset.ImageType(rawValue: assetTypeStr)!) else {
|
|
142
|
-
let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(cardNetworkStr)", recoverySuggestion: nil)
|
|
143
|
-
errorCallback([err.rnError])
|
|
144
|
-
return
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
142
|
let imageURL = try self.tempStoreImage(image: image, name: cardNetworkStr)
|
|
149
143
|
successCallback([imageURL.absoluteString])
|
|
150
144
|
} catch {
|
|
151
145
|
errorCallback([error.rnError])
|
|
152
146
|
}
|
|
153
147
|
}
|
|
154
|
-
|
|
148
|
+
|
|
155
149
|
@objc
|
|
156
150
|
public func showPaymentMethod(_ paymentMethodTypeStr: String,
|
|
157
151
|
resolver: RCTPromiseResolveBlock,
|
|
158
152
|
rejecter: RCTPromiseRejectBlock)
|
|
159
153
|
{
|
|
160
|
-
|
|
161
|
-
PrimerHeadlessUniversalCheckout.current.showPaymentMethod(paymentMethodType)
|
|
154
|
+
PrimerHeadlessUniversalCheckout.current.showPaymentMethod(paymentMethodTypeStr)
|
|
162
155
|
resolver(nil)
|
|
163
156
|
}
|
|
164
|
-
|
|
157
|
+
|
|
165
158
|
@objc
|
|
166
159
|
public func disposePrimerHeadlessUniversalCheckout() {
|
|
167
|
-
|
|
160
|
+
|
|
168
161
|
}
|
|
169
|
-
|
|
162
|
+
|
|
170
163
|
// MARK: - HELPERS
|
|
171
|
-
|
|
172
|
-
private func validate(assetStr: String, assetTypeStr: String) throws {
|
|
173
|
-
var errors: [NativeError] = []
|
|
174
|
-
|
|
175
|
-
if PrimerPaymentMethodType(rawValue: assetStr) != .other(rawValue: assetStr) {
|
|
176
|
-
// ...
|
|
177
|
-
} else if CardNetwork(rawValue: assetStr) != nil {
|
|
178
|
-
// ...
|
|
179
|
-
} else {
|
|
180
|
-
let err = NativeError(errorId: "invalid-payment-method-type", errorDescription: "Asset for \(assetStr) does not exist, make sure you don't have any typos.", recoverySuggestion: nil)
|
|
181
|
-
errors.append(err)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if PrimerAsset.ImageType(rawValue: assetTypeStr) == nil {
|
|
186
|
-
let err = NativeError(errorId: "mismatch", errorDescription: "You have provided assetType=\(assetTypeStr), which is not valid", recoverySuggestion: "Use one of the following values: \(PrimerAsset.ImageType.allCases.compactMap({ $0.rawValue }))")
|
|
187
|
-
errors.append(err)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if errors.isEmpty {
|
|
191
|
-
return
|
|
192
|
-
} else if errors.count == 1 {
|
|
193
|
-
throw errors.first!
|
|
194
|
-
} else {
|
|
195
|
-
let errorDescription: String = errors.compactMap({ $0.errorDescription }).joined(separator: "/n")
|
|
196
|
-
let recoverySuggestion = errors.compactMap({ $0.recoverySuggestion }).joined(separator: "/n")
|
|
197
|
-
let err = NativeError(errorId: "underlying-errors", errorDescription: errorDescription, recoverySuggestion: recoverySuggestion)
|
|
198
|
-
throw err
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
164
|
+
|
|
202
165
|
private func tempStoreImage(image: UIImage, name: String) throws -> URL {
|
|
203
166
|
guard let imageURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(name).png") else {
|
|
204
167
|
let err = NativeError(errorId: "error", errorDescription: "Failed to create URL for asset", recoverySuggestion: nil)
|
|
205
168
|
throw err
|
|
206
169
|
}
|
|
207
|
-
|
|
170
|
+
|
|
208
171
|
guard let pngData = image.pngData() else {
|
|
209
172
|
let err = NativeError(errorId: "error", errorDescription: "Failed to get image's PNG data", recoverySuggestion: nil)
|
|
210
173
|
throw err
|
|
211
174
|
}
|
|
212
|
-
|
|
175
|
+
|
|
213
176
|
try pngData.write(to: imageURL)
|
|
214
177
|
return imageURL
|
|
215
178
|
}
|
|
216
|
-
|
|
179
|
+
|
|
217
180
|
// MARK: - DECISION HANDLERS
|
|
218
|
-
|
|
181
|
+
|
|
219
182
|
// MARK: Tokenization
|
|
220
|
-
|
|
183
|
+
|
|
221
184
|
@objc
|
|
222
185
|
public func handleTokenizationNewClientToken(_ newClientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
223
186
|
DispatchQueue.main.async {
|
|
@@ -226,7 +189,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
226
189
|
resolver(nil)
|
|
227
190
|
}
|
|
228
191
|
}
|
|
229
|
-
|
|
192
|
+
|
|
230
193
|
@objc
|
|
231
194
|
public func handleTokenizationSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
232
195
|
DispatchQueue.main.async {
|
|
@@ -236,7 +199,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
236
199
|
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
237
200
|
}
|
|
238
201
|
}
|
|
239
|
-
|
|
202
|
+
|
|
240
203
|
@objc
|
|
241
204
|
public func handleTokenizationFailure(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
242
205
|
DispatchQueue.main.async {
|
|
@@ -246,9 +209,9 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
246
209
|
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
247
210
|
}
|
|
248
211
|
}
|
|
249
|
-
|
|
212
|
+
|
|
250
213
|
// MARK: Resume Payment
|
|
251
|
-
|
|
214
|
+
|
|
252
215
|
@objc
|
|
253
216
|
public func handleResumeWithNewClientToken(_ newClientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
254
217
|
DispatchQueue.main.async {
|
|
@@ -257,7 +220,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
257
220
|
resolver(nil)
|
|
258
221
|
}
|
|
259
222
|
}
|
|
260
|
-
|
|
223
|
+
|
|
261
224
|
@objc
|
|
262
225
|
public func handleResumeSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
263
226
|
DispatchQueue.main.async {
|
|
@@ -265,7 +228,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
265
228
|
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
266
229
|
}
|
|
267
230
|
}
|
|
268
|
-
|
|
231
|
+
|
|
269
232
|
@objc
|
|
270
233
|
public func handleResumeFailure(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
271
234
|
DispatchQueue.main.async {
|
|
@@ -273,9 +236,9 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
273
236
|
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
274
237
|
}
|
|
275
238
|
}
|
|
276
|
-
|
|
239
|
+
|
|
277
240
|
// MARK: Payment Creation
|
|
278
|
-
|
|
241
|
+
|
|
279
242
|
@objc
|
|
280
243
|
public func handlePaymentCreationAbort(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
281
244
|
DispatchQueue.main.async {
|
|
@@ -284,7 +247,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
284
247
|
resolver(nil)
|
|
285
248
|
}
|
|
286
249
|
}
|
|
287
|
-
|
|
250
|
+
|
|
288
251
|
@objc
|
|
289
252
|
public func handlePaymentCreationContinue(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
290
253
|
DispatchQueue.main.async {
|
|
@@ -293,13 +256,13 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
293
256
|
resolver(nil)
|
|
294
257
|
}
|
|
295
258
|
}
|
|
296
|
-
|
|
259
|
+
|
|
297
260
|
// MARK: Helpers
|
|
298
|
-
|
|
261
|
+
|
|
299
262
|
private func detectImplemetedCallbacks() {
|
|
300
263
|
sendEvent(withName: PrimerEvents.detectImplementedRNCallbacks.stringValue, body: nil)
|
|
301
264
|
}
|
|
302
|
-
|
|
265
|
+
|
|
303
266
|
@objc
|
|
304
267
|
public func setImplementedRNCallbacks(_ implementedRNCallbacksStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
305
268
|
DispatchQueue.main.async {
|
|
@@ -316,13 +279,13 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
316
279
|
}
|
|
317
280
|
}
|
|
318
281
|
}
|
|
319
|
-
|
|
282
|
+
|
|
320
283
|
private func handleRNBridgeError(_ error: Error, checkoutData: PrimerCheckoutData?, stopOnDebug: Bool) {
|
|
321
284
|
DispatchQueue.main.async {
|
|
322
285
|
if stopOnDebug {
|
|
323
286
|
assertionFailure(error.localizedDescription)
|
|
324
287
|
}
|
|
325
|
-
|
|
288
|
+
|
|
326
289
|
var body: [String: Any] = ["error": error.rnError]
|
|
327
290
|
if let checkoutData = checkoutData,
|
|
328
291
|
let data = try? JSONEncoder().encode(checkoutData),
|
|
@@ -338,23 +301,23 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
|
|
|
338
301
|
// MARK: - EVENTS
|
|
339
302
|
|
|
340
303
|
extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDelegate {
|
|
341
|
-
|
|
304
|
+
|
|
342
305
|
func primerHeadlessUniversalCheckoutPreparationDidStart(for paymentMethodType: String) {
|
|
343
306
|
sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCPrepareStart.stringValue, body: ["paymentMethodType": paymentMethodType])
|
|
344
307
|
}
|
|
345
|
-
|
|
308
|
+
|
|
346
309
|
func primerHeadlessUniversalCheckoutTokenizationDidStart(for paymentMethodType: String) {
|
|
347
310
|
sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCTokenizeStart.stringValue, body: ["paymentMethodType": paymentMethodType])
|
|
348
311
|
}
|
|
349
|
-
|
|
312
|
+
|
|
350
313
|
func primerHeadlessUniversalCheckoutDidLoadAvailablePaymentMethods(_ paymentMethodTypes: [String]) {
|
|
351
314
|
sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCAvailablePaymentMethodsLoaded.stringValue, body: ["paymentMethodTypes": paymentMethodTypes])
|
|
352
315
|
}
|
|
353
|
-
|
|
316
|
+
|
|
354
317
|
func primerHeadlessUniversalCheckoutPaymentMethodDidShow(for paymentMethodType: String) {
|
|
355
318
|
sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCPaymentMethodShow.stringValue, body: ["paymentMethodType": paymentMethodType])
|
|
356
319
|
}
|
|
357
|
-
|
|
320
|
+
|
|
358
321
|
func primerHeadlessUniversalCheckoutDidTokenizePaymentMethod(_ paymentMethodTokenData: PrimerPaymentMethodTokenData, decisionHandler: @escaping (PrimerResumeDecision) -> Void) {
|
|
359
322
|
if self.implementedRNCallbacks?.isOnTokenizeSuccessImplemented == true {
|
|
360
323
|
self.primerDidTokenizePaymentMethodDecisionHandler = { (newClientToken, errorMessage) in
|
|
@@ -368,7 +331,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
368
331
|
}
|
|
369
332
|
}
|
|
370
333
|
}
|
|
371
|
-
|
|
334
|
+
|
|
372
335
|
do {
|
|
373
336
|
let data = try JSONEncoder().encode(paymentMethodTokenData)
|
|
374
337
|
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
|
|
@@ -384,7 +347,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
384
347
|
// auto flow.
|
|
385
348
|
}
|
|
386
349
|
}
|
|
387
|
-
|
|
350
|
+
|
|
388
351
|
func primerHeadlessUniversalCheckoutDidResumeWith(_ resumeToken: String, decisionHandler: @escaping (PrimerResumeDecision) -> Void) {
|
|
389
352
|
if self.implementedRNCallbacks?.isOnResumeSuccessImplemented == true {
|
|
390
353
|
self.primerDidResumeWithDecisionHandler = { (resumeToken, errorMessage) in
|
|
@@ -398,7 +361,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
398
361
|
}
|
|
399
362
|
}
|
|
400
363
|
}
|
|
401
|
-
|
|
364
|
+
|
|
402
365
|
DispatchQueue.main.async {
|
|
403
366
|
self.sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onResumeSuccess.stringValue, body: ["resumeToken": resumeToken])
|
|
404
367
|
}
|
|
@@ -407,18 +370,18 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
407
370
|
// Throw an error if it's the manual flow.
|
|
408
371
|
}
|
|
409
372
|
}
|
|
410
|
-
|
|
373
|
+
|
|
411
374
|
func primerHeadlessUniversalCheckoutDidFail(withError err: Error) {
|
|
412
375
|
if self.implementedRNCallbacks?.isOnErrorImplemented == true {
|
|
413
376
|
// Send the error message to the RN bridge.
|
|
414
377
|
self.handleRNBridgeError(err, checkoutData: nil, stopOnDebug: false)
|
|
415
|
-
|
|
378
|
+
|
|
416
379
|
} else {
|
|
417
380
|
// RN dev hasn't opted in on listening SDK dismiss.
|
|
418
381
|
// Ignore!
|
|
419
382
|
}
|
|
420
383
|
}
|
|
421
|
-
|
|
384
|
+
|
|
422
385
|
func primerHeadlessUniversalCheckoutDidCompleteCheckoutWithData(_ data: PrimerCheckoutData) {
|
|
423
386
|
DispatchQueue.main.async {
|
|
424
387
|
if self.implementedRNCallbacks?.isOnCheckoutCompleteImplemented == true {
|
|
@@ -435,7 +398,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
435
398
|
}
|
|
436
399
|
}
|
|
437
400
|
}
|
|
438
|
-
|
|
401
|
+
|
|
439
402
|
func primerHeadlessUniversalCheckoutClientSessionWillUpdate() {
|
|
440
403
|
if self.implementedRNCallbacks?.isOnBeforeClientSessionUpdateImplemented == true {
|
|
441
404
|
DispatchQueue.main.async {
|
|
@@ -445,7 +408,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
445
408
|
// RN Dev hasn't implemented this callback, ignore.
|
|
446
409
|
}
|
|
447
410
|
}
|
|
448
|
-
|
|
411
|
+
|
|
449
412
|
func primerHeadlessUniversalCheckoutClientSessionDidUpdate(_ clientSession: PrimerClientSession) {
|
|
450
413
|
if self.implementedRNCallbacks?.isOnClientSessionUpdateImplemented == true {
|
|
451
414
|
do {
|
|
@@ -461,7 +424,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
461
424
|
// RN Dev hasn't implemented this callback, ignore.
|
|
462
425
|
}
|
|
463
426
|
}
|
|
464
|
-
|
|
427
|
+
|
|
465
428
|
func primerHeadlessUniversalCheckoutWillCreatePaymentWithData(_ data: PrimerCheckoutPaymentMethodData, decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void) {
|
|
466
429
|
if self.implementedRNCallbacks?.isOnBeforePaymentCreateImplemented == true {
|
|
467
430
|
self.primerWillCreatePaymentWithDataDecisionHandler = { errorMessage in
|
|
@@ -473,7 +436,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
|
|
|
473
436
|
}
|
|
474
437
|
}
|
|
475
438
|
}
|
|
476
|
-
|
|
439
|
+
|
|
477
440
|
DispatchQueue.main.async {
|
|
478
441
|
do {
|
|
479
442
|
let checkoutPaymentmethodData = try JSONEncoder().encode(data)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNTPrimerHeadlessUniversalCheckoutRawDataManager.m
|
|
3
|
+
// primer-io-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Evangelos on 3/8/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
#import <React/RCTEventEmitter.h>
|
|
10
|
+
|
|
11
|
+
@interface RCT_EXTERN_MODULE(PrimerHeadlessUniversalCheckoutRawDataManager, RCTEventEmitter)
|
|
12
|
+
|
|
13
|
+
RCT_EXTERN_METHOD(initialize:(NSString *)paymentMethodTypeStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
14
|
+
|
|
15
|
+
RCT_EXTERN_METHOD(listRequiredInputElementTypesForPaymentMethodType:(NSString *)paymentMethodTypeStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
16
|
+
|
|
17
|
+
RCT_EXTERN_METHOD(setRawData:(NSString *)rawDataStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
18
|
+
|
|
19
|
+
RCT_EXTERN_METHOD(submit:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
20
|
+
|
|
21
|
+
@end
|
package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckoutRawDataManager.swift
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RNTPrimerHeadlessUniversalCheckoutRawDataManager.swift
|
|
3
|
+
// primer-io-react-native
|
|
4
|
+
//
|
|
5
|
+
// Created by Evangelos on 3/8/22.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import PrimerSDK
|
|
10
|
+
|
|
11
|
+
@objc
|
|
12
|
+
enum PrimerHeadlessUniversalCheckoutRawDataManagerEvents: Int, CaseIterable {
|
|
13
|
+
|
|
14
|
+
case onMetadataChange = 0
|
|
15
|
+
case onValidation
|
|
16
|
+
case onNativeError
|
|
17
|
+
|
|
18
|
+
var stringValue: String {
|
|
19
|
+
switch self {
|
|
20
|
+
case .onMetadataChange:
|
|
21
|
+
return "onMetadataChange"
|
|
22
|
+
case .onValidation:
|
|
23
|
+
return "onValidation"
|
|
24
|
+
case .onNativeError:
|
|
25
|
+
return "onNativeError"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@objc(PrimerHeadlessUniversalCheckoutRawDataManager)
|
|
31
|
+
class RNTPrimerHeadlessUniversalCheckoutRawDataManager: RCTEventEmitter {
|
|
32
|
+
|
|
33
|
+
private var rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager!
|
|
34
|
+
private var paymentMethodType: String?
|
|
35
|
+
|
|
36
|
+
override class func requiresMainQueueSetup() -> Bool {
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override func supportedEvents() -> [String]! {
|
|
41
|
+
return PrimerHeadlessUniversalCheckoutRawDataManagerEvents.allCases.compactMap({ $0.stringValue })
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// MARK: - API
|
|
45
|
+
|
|
46
|
+
@objc
|
|
47
|
+
public func initialize(
|
|
48
|
+
_ paymentMethodTypeStr: String,
|
|
49
|
+
resolver: RCTPromiseResolveBlock,
|
|
50
|
+
rejecter: RCTPromiseRejectBlock
|
|
51
|
+
) {
|
|
52
|
+
self.paymentMethodType = paymentMethodTypeStr
|
|
53
|
+
|
|
54
|
+
do {
|
|
55
|
+
self.rawDataManager = try PrimerHeadlessUniversalCheckout.RawDataManager(paymentMethodType: self.paymentMethodType!)
|
|
56
|
+
self.rawDataManager.delegate = self
|
|
57
|
+
resolver(nil)
|
|
58
|
+
} catch {
|
|
59
|
+
rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@objc
|
|
64
|
+
public func listRequiredInputElementTypesForPaymentMethodType(
|
|
65
|
+
_ paymentMethodTypeStr: String,
|
|
66
|
+
resolver: RCTPromiseResolveBlock,
|
|
67
|
+
rejecter: RCTPromiseRejectBlock
|
|
68
|
+
) {
|
|
69
|
+
guard let rawDataManager = rawDataManager else {
|
|
70
|
+
let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "The PrimerHeadlessUniversalCheckoutRawDataManager has not been initialized. Make sure you have called the PrimerHeadlessUniversalCheckoutRawDataManager.configure function first."])
|
|
71
|
+
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let inputElementTypes = rawDataManager.listRequiredInputElementTypes(for: rawDataManager.paymentMethodType).compactMap({ $0.stringValue })
|
|
76
|
+
resolver(["inputElementTypes": inputElementTypes])
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@objc
|
|
80
|
+
public func setRawData(
|
|
81
|
+
_ rawDataStr: String,
|
|
82
|
+
resolver: RCTPromiseResolveBlock,
|
|
83
|
+
rejecter: RCTPromiseRejectBlock
|
|
84
|
+
) {
|
|
85
|
+
guard let rawDataManager = rawDataManager else {
|
|
86
|
+
let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "The PrimerHeadlessUniversalCheckoutRawDataManager has not been initialized. Make sure you have called the PrimerHeadlessUniversalCheckoutRawDataManager.configure function first."])
|
|
87
|
+
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
guard let rawCardData = PrimerCardData(cardDataStr: rawDataStr) else {
|
|
92
|
+
let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decode PrimerCardData on iOS. Make sure you're providing a valid 'PrimerRawCardData' object"])
|
|
93
|
+
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
rawDataManager.rawData = rawCardData
|
|
98
|
+
resolver(nil)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@objc
|
|
102
|
+
public func submit(
|
|
103
|
+
_ resolver: RCTPromiseResolveBlock,
|
|
104
|
+
rejecter: RCTPromiseRejectBlock
|
|
105
|
+
) {
|
|
106
|
+
guard let rawDataManager = rawDataManager else {
|
|
107
|
+
let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "The PrimerHeadlessUniversalCheckoutRawDataManager has not been initialized. Make sure you have called the PrimerHeadlessUniversalCheckoutRawDataManager.configure function first."])
|
|
108
|
+
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
rawDataManager.submit()
|
|
113
|
+
resolver(nil)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
extension RNTPrimerHeadlessUniversalCheckoutRawDataManager: PrimerRawDataManagerDelegate {
|
|
118
|
+
|
|
119
|
+
func primerRawDataManager(_ rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager, metadataDidChange metadata: [String : Any]?) {
|
|
120
|
+
DispatchQueue.main.async {
|
|
121
|
+
self.sendEvent(withName: PrimerHeadlessUniversalCheckoutRawDataManagerEvents.onMetadataChange.stringValue, body: metadata)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func primerRawDataManager(_ rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager, dataIsValid isValid: Bool, errors: [Error]?) {
|
|
126
|
+
DispatchQueue.main.async {
|
|
127
|
+
var body: [String: Any] = ["isValid": isValid]
|
|
128
|
+
if let errors = errors {
|
|
129
|
+
let rnErrors = errors.compactMap({ $0.rnError })
|
|
130
|
+
body["errors"] = rnErrors
|
|
131
|
+
}
|
|
132
|
+
self.sendEvent(withName: PrimerHeadlessUniversalCheckoutRawDataManagerEvents.onValidation.stringValue, body: body)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private func handleRNBridgeError(_ error: Error, checkoutData: PrimerCheckoutData?, stopOnDebug: Bool) {
|
|
137
|
+
DispatchQueue.main.async {
|
|
138
|
+
if stopOnDebug {
|
|
139
|
+
assertionFailure(error.localizedDescription)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
var body: [String: Any] = ["error": error.rnError]
|
|
143
|
+
if let checkoutData = checkoutData,
|
|
144
|
+
let data = try? JSONEncoder().encode(checkoutData),
|
|
145
|
+
let json = try? JSONSerialization.jsonObject(with: data){
|
|
146
|
+
body["checkoutData"] = json
|
|
147
|
+
}
|
|
148
|
+
print(body)
|
|
149
|
+
self.sendEvent(withName: PrimerEvents.onError.stringValue, body: body)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
package/ios/RNTPrimer.m
CHANGED
|
@@ -18,7 +18,7 @@ RCT_EXTERN_METHOD(showUniversalCheckoutWithClientToken:(NSString *)clientToken r
|
|
|
18
18
|
|
|
19
19
|
RCT_EXTERN_METHOD(showVaultManagerWithClientToken: (NSString *)clientToken resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
20
20
|
|
|
21
|
-
RCT_EXTERN_METHOD(showPaymentMethod:(NSString *)
|
|
21
|
+
RCT_EXTERN_METHOD(showPaymentMethod:(NSString *)paymentMethodTypeStr intent:(NSString *)intentStr clientToken:(NSString *)clientToken resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
22
22
|
|
|
23
23
|
RCT_EXTERN_METHOD(dismiss)
|
|
24
24
|
|
package/ios/RNTPrimer.swift
CHANGED
|
@@ -119,22 +119,15 @@ class RNTPrimer: RCTEventEmitter {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
@objc
|
|
122
|
-
public func showPaymentMethod(_
|
|
122
|
+
public func showPaymentMethod(_ paymentMethodTypeStr: String, intent: String, clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
123
123
|
DispatchQueue.main.async {
|
|
124
124
|
do {
|
|
125
|
-
let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodStr)
|
|
126
|
-
|
|
127
|
-
guard paymentMethodType != PrimerPaymentMethodType.other(rawValue: paymentMethodStr) else {
|
|
128
|
-
let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Payment method type \(paymentMethodStr) is not valid."])
|
|
129
|
-
throw err
|
|
130
|
-
}
|
|
131
|
-
|
|
132
125
|
guard let primerIntent = PrimerSessionIntent(rawValue: intent) else {
|
|
133
126
|
let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Intent \(intent) is not valid."])
|
|
134
127
|
throw err
|
|
135
128
|
}
|
|
136
129
|
|
|
137
|
-
PrimerSDK.Primer.shared.showPaymentMethod(
|
|
130
|
+
PrimerSDK.Primer.shared.showPaymentMethod(paymentMethodTypeStr, withIntent: primerIntent, andClientToken: clientToken) { err in
|
|
138
131
|
DispatchQueue.main.async {
|
|
139
132
|
if let err = err {
|
|
140
133
|
rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
|
|
@@ -2,3 +2,13 @@
|
|
|
2
2
|
#import <React/RCTEventEmitter.h>
|
|
3
3
|
#import <React/RCTViewManager.h>
|
|
4
4
|
#import <React/RCTUIManager.h>
|
|
5
|
+
#import <React/RCTView.h>
|
|
6
|
+
|
|
7
|
+
// for view controller implementation https://stackoverflow.com/questions/45741903/react-native-ios-how-can-i-navigate-to-a-non-react-native-view-native-ios-vie/46007680#46007680
|
|
8
|
+
//#import "React/RCTBridge.h"
|
|
9
|
+
//#import "React/RCTEventDispatcher.h"
|
|
10
|
+
//#import "React/RCTRootView.h"
|
|
11
|
+
//#import "React/RCTUtils.h"
|
|
12
|
+
//#import "React/RCTConvert.h"
|
|
13
|
+
//#import "React/RCTBundleURLProvider.h"
|
|
14
|
+
//#import "RCTViewManager.h"
|