@yuno-payments/yuno-sdk-react-native 1.0.16 → 1.0.17-rc.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/README.md +795 -262
- package/YunoSdk.podspec +48 -0
- package/android/src/main/java/com/yunosdkreactnative/YunoSdkModule.kt +47 -0
- package/ios/YunoPaymentMethodsViewManager.m +10 -0
- package/ios/YunoPaymentMethodsViewManager.swift +324 -0
- package/ios/YunoSdk.m +26 -5
- package/ios/YunoSdk.swift +191 -72
- package/lib/commonjs/YunoPaymentMethods.js +9 -9
- package/lib/commonjs/YunoPaymentMethods.js.map +1 -1
- package/lib/commonjs/YunoSdk.js +53 -21
- package/lib/commonjs/YunoSdk.js.map +1 -1
- package/lib/module/YunoPaymentMethods.js +9 -9
- package/lib/module/YunoPaymentMethods.js.map +1 -1
- package/lib/module/YunoSdk.js +53 -21
- package/lib/module/YunoSdk.js.map +1 -1
- package/package.json +1 -1
- package/src/YunoPaymentMethods.tsx +12 -10
- package/src/YunoSdk.ts +54 -34
package/ios/YunoSdk.swift
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
+
import React
|
|
2
3
|
import YunoSDK
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Implementation of PaymentMethodSelected protocol for Lite SDK.
|
|
7
|
+
*/
|
|
8
|
+
private class PaymentMethodSelection: NSObject, PaymentMethodSelected {
|
|
9
|
+
let paymentMethodType: String
|
|
10
|
+
let vaultedToken: String?
|
|
11
|
+
|
|
12
|
+
init(paymentMethodType: String, vaultedToken: String?) {
|
|
13
|
+
self.paymentMethodType = paymentMethodType
|
|
14
|
+
self.vaultedToken = vaultedToken
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
/**
|
|
5
19
|
* Yuno SDK React Native Module for iOS.
|
|
6
20
|
*
|
|
@@ -12,8 +26,12 @@ class YunoSdk: RCTEventEmitter {
|
|
|
12
26
|
private var isInitialized = false
|
|
13
27
|
private var currentCountryCode: String?
|
|
14
28
|
private var currentLanguage: String?
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
var customerSession: String = ""
|
|
30
|
+
var checkoutSession: String = ""
|
|
31
|
+
|
|
32
|
+
// Store last payment status to prevent stale status from previous flows
|
|
33
|
+
private var lastPaymentStatus: String?
|
|
34
|
+
private var isPaymentFlowCleared: Bool = false
|
|
17
35
|
|
|
18
36
|
override init() {
|
|
19
37
|
super.init()
|
|
@@ -27,10 +45,23 @@ class YunoSdk: RCTEventEmitter {
|
|
|
27
45
|
return [
|
|
28
46
|
"YunoPaymentStatus",
|
|
29
47
|
"YunoEnrollmentStatus",
|
|
30
|
-
"YunoOneTimeToken"
|
|
48
|
+
"YunoOneTimeToken",
|
|
49
|
+
"YunoOneTimeTokenInfo",
|
|
50
|
+
"onPaymentMethodSelected",
|
|
51
|
+
"onPaymentMethodError"
|
|
31
52
|
]
|
|
32
53
|
}
|
|
33
54
|
|
|
55
|
+
@objc
|
|
56
|
+
override func addListener(_ eventName: String) {
|
|
57
|
+
super.addListener(eventName)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@objc
|
|
61
|
+
override func removeListeners(_ count: Double) {
|
|
62
|
+
super.removeListeners(count)
|
|
63
|
+
}
|
|
64
|
+
|
|
34
65
|
/**
|
|
35
66
|
* Initialize the Yuno SDK with configuration.
|
|
36
67
|
*/
|
|
@@ -55,28 +86,36 @@ class YunoSdk: RCTEventEmitter {
|
|
|
55
86
|
self.currentLanguage = lang
|
|
56
87
|
}
|
|
57
88
|
|
|
58
|
-
// Parse card flow
|
|
59
|
-
var cardFlow:
|
|
60
|
-
if let flow = yunoConfig["
|
|
61
|
-
cardFlow = self.
|
|
89
|
+
// Parse card flow (React Native sends "cardType", not "cardFlow")
|
|
90
|
+
var cardFlow: CardFormType = .oneStep
|
|
91
|
+
if let flow = yunoConfig["cardType"] as? String {
|
|
92
|
+
cardFlow = self.mapToCardFormType(flow)
|
|
62
93
|
}
|
|
63
94
|
|
|
64
95
|
// Parse other config options
|
|
65
|
-
let saveCardEnabled = yunoConfig["
|
|
66
|
-
|
|
96
|
+
let saveCardEnabled = yunoConfig["savedCardEnable"] as? Bool ?? false
|
|
97
|
+
// keepLoader is inverted from showPaymentStatus (if showPaymentStatus is false, keepLoader should be true)
|
|
98
|
+
let showPaymentStatus = yunoConfig["showPaymentStatus"] as? Bool ?? true
|
|
99
|
+
let keepLoader = !showPaymentStatus
|
|
67
100
|
|
|
68
101
|
// Initialize Yuno SDK
|
|
69
102
|
Yuno.initialize(
|
|
70
103
|
apiKey: apiKey,
|
|
71
104
|
config: YunoConfig(
|
|
72
|
-
|
|
105
|
+
cardFormType: cardFlow,
|
|
73
106
|
saveCardEnabled: saveCardEnabled,
|
|
74
107
|
keepLoader: keepLoader
|
|
75
|
-
)
|
|
108
|
+
),
|
|
109
|
+
callback: {
|
|
110
|
+
print("✅ Yuno.initialize callback invoked")
|
|
111
|
+
resolver(nil)
|
|
112
|
+
}
|
|
76
113
|
)
|
|
77
114
|
|
|
115
|
+
// Mark as initialized immediately after calling initialize (not inside callback)
|
|
116
|
+
// Similar to Android's approach where it marks immediately after Yuno.initialize()
|
|
78
117
|
self.isInitialized = true
|
|
79
|
-
|
|
118
|
+
print("✅ YunoSdk module marked as initialized (countryCode: \(countryCode), language: \(self.currentLanguage ?? "nil"))")
|
|
80
119
|
} catch {
|
|
81
120
|
rejecter("INITIALIZATION_ERROR", "Failed to initialize Yuno SDK: \(error.localizedDescription)", error)
|
|
82
121
|
}
|
|
@@ -155,20 +194,20 @@ class YunoSdk: RCTEventEmitter {
|
|
|
155
194
|
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "methodSelected is required"])
|
|
156
195
|
}
|
|
157
196
|
|
|
158
|
-
guard let vaultedToken = methodSelected["vaultedToken"] as? String, !vaultedToken.isEmpty else {
|
|
159
|
-
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "vaultedToken is required"])
|
|
160
|
-
}
|
|
161
|
-
|
|
162
197
|
guard let paymentMethodType = methodSelected["paymentMethodType"] as? String, !paymentMethodType.isEmpty else {
|
|
163
198
|
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "paymentMethodType is required"])
|
|
164
199
|
}
|
|
165
200
|
|
|
201
|
+
// vaultedToken is OPTIONAL (only required when using saved cards)
|
|
202
|
+
let vaultedToken = methodSelected["vaultedToken"] as? String
|
|
203
|
+
|
|
166
204
|
let showPaymentStatus = arguments["showPaymentStatus"] as? Bool ?? true
|
|
167
205
|
|
|
168
206
|
self.checkoutSession = checkoutSession
|
|
169
207
|
self.currentCountryCode = countryCode
|
|
170
208
|
|
|
171
|
-
|
|
209
|
+
// Create a PaymentMethodSelected implementation
|
|
210
|
+
let paymentSelected = PaymentMethodSelection(
|
|
172
211
|
paymentMethodType: paymentMethodType,
|
|
173
212
|
vaultedToken: vaultedToken
|
|
174
213
|
)
|
|
@@ -201,12 +240,9 @@ class YunoSdk: RCTEventEmitter {
|
|
|
201
240
|
}
|
|
202
241
|
|
|
203
242
|
DispatchQueue.main.async {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
} catch {
|
|
208
|
-
rejecter("PAYMENT_ERROR", "Failed to start payment: \(error.localizedDescription)", error)
|
|
209
|
-
}
|
|
243
|
+
// Start payment using the delegate already registered via getPaymentMethodViewAsync
|
|
244
|
+
Yuno.startPayment(showPaymentStatus: showPaymentStatus)
|
|
245
|
+
resolver(nil)
|
|
210
246
|
}
|
|
211
247
|
}
|
|
212
248
|
|
|
@@ -215,7 +251,9 @@ class YunoSdk: RCTEventEmitter {
|
|
|
215
251
|
*/
|
|
216
252
|
@objc
|
|
217
253
|
func continuePayment(
|
|
218
|
-
_
|
|
254
|
+
_ checkoutSession: String,
|
|
255
|
+
countryCode: String,
|
|
256
|
+
showPaymentStatus: Bool,
|
|
219
257
|
resolver: @escaping RCTPromiseResolveBlock,
|
|
220
258
|
rejecter: @escaping RCTPromiseRejectBlock
|
|
221
259
|
) {
|
|
@@ -224,13 +262,18 @@ class YunoSdk: RCTEventEmitter {
|
|
|
224
262
|
return
|
|
225
263
|
}
|
|
226
264
|
|
|
227
|
-
DispatchQueue.main.async {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
265
|
+
DispatchQueue.main.async { [weak self] in
|
|
266
|
+
guard let self = self else { return }
|
|
267
|
+
|
|
268
|
+
// Update checkout session and country code for the delegate
|
|
269
|
+
self.checkoutSession = checkoutSession
|
|
270
|
+
self.currentCountryCode = countryCode
|
|
271
|
+
|
|
272
|
+
// Continue payment using the delegate already registered
|
|
273
|
+
// The SDK will read checkoutSession and countryCode from the delegate properties
|
|
274
|
+
Yuno.continuePayment()
|
|
275
|
+
|
|
276
|
+
resolver(nil)
|
|
234
277
|
}
|
|
235
278
|
}
|
|
236
279
|
|
|
@@ -261,14 +304,13 @@ class YunoSdk: RCTEventEmitter {
|
|
|
261
304
|
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "methodSelected is required"])
|
|
262
305
|
}
|
|
263
306
|
|
|
264
|
-
guard let vaultedToken = methodSelected["vaultedToken"] as? String, !vaultedToken.isEmpty else {
|
|
265
|
-
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "vaultedToken is required"])
|
|
266
|
-
}
|
|
267
|
-
|
|
268
307
|
guard let paymentMethodType = methodSelected["paymentMethodType"] as? String, !paymentMethodType.isEmpty else {
|
|
269
308
|
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "paymentMethodType is required"])
|
|
270
309
|
}
|
|
271
310
|
|
|
311
|
+
// vaultedToken is OPTIONAL (only required when using saved cards)
|
|
312
|
+
let vaultedToken = methodSelected["vaultedToken"] as? String
|
|
313
|
+
|
|
272
314
|
let showPaymentStatus = arguments["showPaymentStatus"] as? Bool ?? true
|
|
273
315
|
|
|
274
316
|
var countryCode = arguments["countryCode"] as? String
|
|
@@ -283,7 +325,7 @@ class YunoSdk: RCTEventEmitter {
|
|
|
283
325
|
self.checkoutSession = checkoutSession
|
|
284
326
|
self.currentCountryCode = safeCountryCode
|
|
285
327
|
|
|
286
|
-
let paymentSelected =
|
|
328
|
+
let paymentSelected = PaymentMethodSelection(
|
|
287
329
|
paymentMethodType: paymentMethodType,
|
|
288
330
|
vaultedToken: vaultedToken
|
|
289
331
|
)
|
|
@@ -343,30 +385,84 @@ class YunoSdk: RCTEventEmitter {
|
|
|
343
385
|
}
|
|
344
386
|
}
|
|
345
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Gets the last One Time Token (OTT) that was generated.
|
|
390
|
+
*/
|
|
391
|
+
@objc
|
|
392
|
+
func getLastOneTimeToken(
|
|
393
|
+
_ resolver: @escaping RCTPromiseResolveBlock,
|
|
394
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
395
|
+
) {
|
|
396
|
+
// iOS doesn't need this implementation since tokens are emitted immediately
|
|
397
|
+
// Return nil as there's no stored token
|
|
398
|
+
resolver(nil)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Gets the last OneTimeTokenInfo object stored by the SDK.
|
|
403
|
+
*/
|
|
404
|
+
@objc
|
|
405
|
+
func getLastOneTimeTokenInfo(
|
|
406
|
+
_ resolver: @escaping RCTPromiseResolveBlock,
|
|
407
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
408
|
+
) {
|
|
409
|
+
// iOS doesn't need this implementation since tokens are emitted immediately
|
|
410
|
+
// Return nil as there's no stored token info
|
|
411
|
+
resolver(nil)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Clears the last OTT tokens stored by the SDK.
|
|
416
|
+
*/
|
|
417
|
+
@objc
|
|
418
|
+
func clearLastOneTimeToken(
|
|
419
|
+
_ resolver: @escaping RCTPromiseResolveBlock,
|
|
420
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
421
|
+
) {
|
|
422
|
+
// iOS doesn't need this implementation since tokens aren't stored
|
|
423
|
+
// Just resolve successfully
|
|
424
|
+
resolver(nil)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Clears the last payment status to prevent stale status from previous flows.
|
|
429
|
+
*/
|
|
430
|
+
@objc
|
|
431
|
+
func clearLastPaymentStatus(
|
|
432
|
+
_ resolver: @escaping RCTPromiseResolveBlock,
|
|
433
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
434
|
+
) {
|
|
435
|
+
// Don't set to nil - keep the last status to compare against stale events
|
|
436
|
+
// Just mark that we're starting a fresh flow
|
|
437
|
+
isPaymentFlowCleared = true
|
|
438
|
+
print("💫 Payment status cleared - fresh flow starting (last status was: \(lastPaymentStatus ?? "nil"))")
|
|
439
|
+
resolver(true)
|
|
440
|
+
}
|
|
441
|
+
|
|
346
442
|
// MARK: - Helper Methods
|
|
347
443
|
|
|
348
|
-
private func
|
|
349
|
-
switch
|
|
350
|
-
case "STEP_BY_STEP":
|
|
444
|
+
private func mapToCardFormType(_ cardFormType: String) -> CardFormType {
|
|
445
|
+
switch cardFormType.uppercased() {
|
|
446
|
+
case "STEP_BY_STEP", "TWO_STEPS":
|
|
351
447
|
return .multiStep
|
|
352
448
|
default:
|
|
353
449
|
return .oneStep
|
|
354
450
|
}
|
|
355
451
|
}
|
|
356
452
|
|
|
357
|
-
private func
|
|
358
|
-
switch
|
|
359
|
-
case .
|
|
453
|
+
private func mapResultToString(_ result: Yuno.Result) -> String {
|
|
454
|
+
switch result {
|
|
455
|
+
case .reject:
|
|
360
456
|
return "REJECTED"
|
|
361
457
|
case .succeeded:
|
|
362
458
|
return "SUCCEEDED"
|
|
363
|
-
case .
|
|
459
|
+
case .fail:
|
|
364
460
|
return "FAILED"
|
|
365
461
|
case .processing:
|
|
366
462
|
return "PROCESSING"
|
|
367
463
|
case .internalError:
|
|
368
464
|
return "INTERNAL_ERROR"
|
|
369
|
-
case .
|
|
465
|
+
case .userCancelled:
|
|
370
466
|
return "CANCELLED_BY_USER"
|
|
371
467
|
@unknown default:
|
|
372
468
|
return "INTERNAL_ERROR"
|
|
@@ -375,21 +471,55 @@ class YunoSdk: RCTEventEmitter {
|
|
|
375
471
|
|
|
376
472
|
// MARK: - Event Emitters
|
|
377
473
|
|
|
378
|
-
|
|
379
|
-
|
|
474
|
+
internal func sendPaymentStatusEvent(result: Yuno.Result, token: String? = nil) {
|
|
475
|
+
let statusString = mapResultToString(result)
|
|
476
|
+
sendPaymentStatusEvent(status: statusString, token: token)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
internal func sendPaymentStatusEvent(status: String, token: String? = nil) {
|
|
480
|
+
// If we just cleared the status and this is the same status as before,
|
|
481
|
+
// it's a stale event from the native SDK - ignore it
|
|
482
|
+
if isPaymentFlowCleared && status == lastPaymentStatus {
|
|
483
|
+
print("🚫 Ignoring stale payment status: \(status) (from previous flow)")
|
|
484
|
+
isPaymentFlowCleared = false
|
|
485
|
+
lastPaymentStatus = nil // Clear it now that we've ignored the stale event
|
|
486
|
+
return
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Reset the cleared flag after processing first real new event
|
|
490
|
+
if isPaymentFlowCleared {
|
|
491
|
+
print("✅ First new status after clear: \(status) (previous was: \(lastPaymentStatus ?? "nil"))")
|
|
492
|
+
isPaymentFlowCleared = false
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Store the current status for future comparison
|
|
496
|
+
lastPaymentStatus = status
|
|
497
|
+
|
|
498
|
+
print("✅ Emitting payment status: \(status)")
|
|
499
|
+
var params: [String: Any] = ["status": status]
|
|
380
500
|
if let token = token {
|
|
381
501
|
params["token"] = token
|
|
382
502
|
}
|
|
383
503
|
sendEvent(withName: "YunoPaymentStatus", body: params)
|
|
384
504
|
}
|
|
385
505
|
|
|
386
|
-
private func sendEnrollmentStatusEvent(
|
|
387
|
-
let params: [String: Any] = ["status":
|
|
506
|
+
private func sendEnrollmentStatusEvent(result: Yuno.Result) {
|
|
507
|
+
let params: [String: Any] = ["status": mapResultToString(result)]
|
|
388
508
|
sendEvent(withName: "YunoEnrollmentStatus", body: params)
|
|
389
509
|
}
|
|
390
510
|
|
|
391
|
-
|
|
511
|
+
internal func sendOneTimeTokenEvent(token: String) {
|
|
392
512
|
sendEvent(withName: "YunoOneTimeToken", body: token)
|
|
513
|
+
|
|
514
|
+
// Also emit the OneTimeTokenInfo event with the token
|
|
515
|
+
let tokenInfo: [String: Any] = [
|
|
516
|
+
"token": token
|
|
517
|
+
]
|
|
518
|
+
sendEvent(withName: "YunoOneTimeTokenInfo", body: tokenInfo)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
private func sendOneTimeTokenInfoEvent(tokenInfo: [String: Any]) {
|
|
522
|
+
sendEvent(withName: "YunoOneTimeTokenInfo", body: tokenInfo)
|
|
393
523
|
}
|
|
394
524
|
}
|
|
395
525
|
|
|
@@ -399,44 +529,33 @@ extension YunoSdk: YunoPaymentDelegate {
|
|
|
399
529
|
sendOneTimeTokenEvent(token: token)
|
|
400
530
|
}
|
|
401
531
|
|
|
532
|
+
func yunoCreatePayment(with token: String, information: [String : Any]) {
|
|
533
|
+
// Send both token and token info
|
|
534
|
+
sendOneTimeTokenEvent(token: token)
|
|
535
|
+
sendOneTimeTokenInfoEvent(tokenInfo: information)
|
|
536
|
+
}
|
|
537
|
+
|
|
402
538
|
func yunoPaymentResult(_ result: Yuno.Result) {
|
|
403
|
-
sendPaymentStatusEvent(
|
|
539
|
+
sendPaymentStatusEvent(result: result)
|
|
404
540
|
}
|
|
405
541
|
|
|
406
542
|
var countryCode: String {
|
|
407
543
|
return currentCountryCode ?? ""
|
|
408
544
|
}
|
|
409
545
|
|
|
410
|
-
var
|
|
411
|
-
return
|
|
546
|
+
var language: String? {
|
|
547
|
+
return currentLanguage
|
|
412
548
|
}
|
|
413
549
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
case .succeeded:
|
|
417
|
-
return .succeeded
|
|
418
|
-
case .failed:
|
|
419
|
-
return .failed
|
|
420
|
-
case .rejected:
|
|
421
|
-
return .rejected
|
|
422
|
-
case .processing:
|
|
423
|
-
return .processing
|
|
424
|
-
case .cancelledByUser:
|
|
425
|
-
return .cancelledByUser
|
|
426
|
-
@unknown default:
|
|
427
|
-
return .internalError
|
|
428
|
-
}
|
|
550
|
+
var viewController: UIViewController? {
|
|
551
|
+
return RCTPresentedViewController()
|
|
429
552
|
}
|
|
430
553
|
}
|
|
431
554
|
|
|
432
555
|
// MARK: - YunoEnrollmentDelegate Extension
|
|
433
556
|
extension YunoSdk: YunoEnrollmentDelegate {
|
|
434
557
|
func yunoEnrollmentResult(_ result: Yuno.Result) {
|
|
435
|
-
sendEnrollmentStatusEvent(
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
var customerSession: String {
|
|
439
|
-
return self.customerSession
|
|
558
|
+
sendEnrollmentStatusEvent(result: result)
|
|
440
559
|
}
|
|
441
560
|
}
|
|
442
561
|
|
|
@@ -42,11 +42,11 @@ const NativeYunoPaymentMethodsView = (0, _reactNative.requireNativeComponent)('Y
|
|
|
42
42
|
* YunoPaymentMethods Component
|
|
43
43
|
*
|
|
44
44
|
* A React Native component that displays available payment methods using the native Yuno SDK.
|
|
45
|
-
* This component embeds the native
|
|
45
|
+
* This component embeds the native payment methods list view from the Yuno SDK.
|
|
46
46
|
*
|
|
47
47
|
* **Platform Support:**
|
|
48
48
|
* - ✅ Android (using Jetpack Compose)
|
|
49
|
-
* -
|
|
49
|
+
* - ✅ iOS (using SwiftUI with UIHostingController)
|
|
50
50
|
*
|
|
51
51
|
* **Important:**
|
|
52
52
|
* - The Yuno SDK must be initialized before using this component
|
|
@@ -87,6 +87,10 @@ const NativeYunoPaymentMethodsView = (0, _reactNative.requireNativeComponent)('Y
|
|
|
87
87
|
* - User interactions and selections
|
|
88
88
|
* - Error states and loading indicators
|
|
89
89
|
*
|
|
90
|
+
* **Technical Note:** On iOS, uses `UIHostingController` to wrap the SwiftUI view from
|
|
91
|
+
* Yuno SDK's `getPaymentMethodViewAsync`, providing seamless integration with React Native.
|
|
92
|
+
* Android uses Jetpack Compose with native `PaymentMethodListViewComponent`.
|
|
93
|
+
*
|
|
90
94
|
* @public
|
|
91
95
|
*/
|
|
92
96
|
const YunoPaymentMethods = ({
|
|
@@ -94,7 +98,8 @@ const YunoPaymentMethods = ({
|
|
|
94
98
|
countryCode,
|
|
95
99
|
onPaymentMethodSelected,
|
|
96
100
|
onPaymentMethodError,
|
|
97
|
-
style
|
|
101
|
+
style,
|
|
102
|
+
testID
|
|
98
103
|
}) => {
|
|
99
104
|
// Set up event listeners
|
|
100
105
|
(0, _react.useEffect)(() => {
|
|
@@ -129,13 +134,8 @@ const YunoPaymentMethods = ({
|
|
|
129
134
|
});
|
|
130
135
|
};
|
|
131
136
|
}, [onPaymentMethodSelected, onPaymentMethodError]);
|
|
132
|
-
|
|
133
|
-
// Platform check
|
|
134
|
-
if (_reactNative.Platform.OS !== 'android') {
|
|
135
|
-
console.warn('YunoPaymentMethods: This component is currently only supported on Android. iOS support coming soon.');
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
137
|
return /*#__PURE__*/_react.default.createElement(NativeYunoPaymentMethodsView, {
|
|
138
|
+
testID: testID,
|
|
139
139
|
checkoutSession: checkoutSession,
|
|
140
140
|
countryCode: countryCode,
|
|
141
141
|
style: style
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","LINKING_ERROR","Platform","select","ios","YunoSdkNative","NativeModules","YunoSdk","eventEmitter","NativeEventEmitter","NativeYunoPaymentMethodsView","requireNativeComponent","YunoPaymentMethods","checkoutSession","countryCode","onPaymentMethodSelected","onPaymentMethodError","style","useEffect","console","warn","subscriptions","selectionListener","addListener","event","push","errorListener","forEach","sub","remove","
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","LINKING_ERROR","Platform","select","ios","YunoSdkNative","NativeModules","YunoSdk","eventEmitter","NativeEventEmitter","NativeYunoPaymentMethodsView","requireNativeComponent","YunoPaymentMethods","checkoutSession","countryCode","onPaymentMethodSelected","onPaymentMethodError","style","testID","useEffect","console","warn","subscriptions","selectionListener","addListener","event","push","errorListener","forEach","sub","remove","createElement","exports"],"sourceRoot":"../../src","sources":["YunoPaymentMethods.tsx"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/YunoSdk.js
CHANGED
|
@@ -6,20 +6,30 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.YunoSdk = void 0;
|
|
7
7
|
var _reactNative = require("react-native");
|
|
8
8
|
var _enums = require("./core/enums");
|
|
9
|
-
const LINKING_ERROR = `The package '@
|
|
9
|
+
const LINKING_ERROR = `The package '@yuno/yuno-sdk-react-native' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
|
|
10
10
|
ios: "- Run 'pod install'\n",
|
|
11
11
|
default: ''
|
|
12
12
|
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Devuelve el módulo nativo YunoSdk o lanza un error de linking
|
|
16
|
+
*/
|
|
17
|
+
function getYunoNative() {
|
|
18
|
+
const native = _reactNative.NativeModules.YunoSdk;
|
|
19
|
+
if (!native) {
|
|
15
20
|
throw new Error(LINKING_ERROR);
|
|
16
21
|
}
|
|
17
|
-
|
|
22
|
+
return native;
|
|
23
|
+
}
|
|
18
24
|
|
|
19
25
|
/**
|
|
20
|
-
*
|
|
26
|
+
* Devuelve un NativeEventEmitter para el módulo YunoSdk
|
|
27
|
+
* Se crea sólo cuando hace falta (no en top-level).
|
|
21
28
|
*/
|
|
22
|
-
|
|
29
|
+
function getYunoEventEmitter() {
|
|
30
|
+
const native = getYunoNative();
|
|
31
|
+
return new _reactNative.NativeEventEmitter(native);
|
|
32
|
+
}
|
|
23
33
|
|
|
24
34
|
/**
|
|
25
35
|
* Payment state event data.
|
|
@@ -125,7 +135,7 @@ class YunoSdk {
|
|
|
125
135
|
// Store country code and language
|
|
126
136
|
this.countryCode = countryCode;
|
|
127
137
|
this.language = config.lang;
|
|
128
|
-
await
|
|
138
|
+
await getYunoNative().initialize(apiKey, countryCode, config, iosConfig, androidConfig);
|
|
129
139
|
this.isInitialized = true;
|
|
130
140
|
}
|
|
131
141
|
|
|
@@ -149,7 +159,7 @@ class YunoSdk {
|
|
|
149
159
|
...params,
|
|
150
160
|
countryCode: params.countryCode ?? this.getCountryCode()
|
|
151
161
|
};
|
|
152
|
-
return
|
|
162
|
+
return getYunoNative().enrollmentPayment(args);
|
|
153
163
|
}
|
|
154
164
|
|
|
155
165
|
/**
|
|
@@ -173,7 +183,7 @@ class YunoSdk {
|
|
|
173
183
|
static async startPaymentLite(params, countryCode) {
|
|
174
184
|
this.checkInitialized();
|
|
175
185
|
const code = countryCode ?? this.getCountryCode();
|
|
176
|
-
return
|
|
186
|
+
return getYunoNative().startPaymentLite(params, code);
|
|
177
187
|
}
|
|
178
188
|
|
|
179
189
|
/**
|
|
@@ -188,7 +198,7 @@ class YunoSdk {
|
|
|
188
198
|
*/
|
|
189
199
|
static async startPayment(showPaymentStatus = true) {
|
|
190
200
|
this.checkInitialized();
|
|
191
|
-
return
|
|
201
|
+
return getYunoNative().startPayment(showPaymentStatus);
|
|
192
202
|
}
|
|
193
203
|
|
|
194
204
|
/**
|
|
@@ -206,7 +216,7 @@ class YunoSdk {
|
|
|
206
216
|
static async continuePayment(checkoutSession, countryCode, showPaymentStatus = true) {
|
|
207
217
|
this.checkInitialized();
|
|
208
218
|
const code = countryCode ?? this.getCountryCode();
|
|
209
|
-
return
|
|
219
|
+
return getYunoNative().continuePayment(checkoutSession, code, showPaymentStatus);
|
|
210
220
|
}
|
|
211
221
|
|
|
212
222
|
/**
|
|
@@ -235,7 +245,7 @@ class YunoSdk {
|
|
|
235
245
|
...params,
|
|
236
246
|
countryCode: params.countryCode ?? this.getCountryCode()
|
|
237
247
|
};
|
|
238
|
-
const statusString = await
|
|
248
|
+
const statusString = await getYunoNative().startPaymentSeamlessLite(args, this.getLanguage());
|
|
239
249
|
return statusString;
|
|
240
250
|
}
|
|
241
251
|
|
|
@@ -249,7 +259,7 @@ class YunoSdk {
|
|
|
249
259
|
*/
|
|
250
260
|
static async hideLoader() {
|
|
251
261
|
this.checkInitialized();
|
|
252
|
-
return
|
|
262
|
+
return getYunoNative().hideLoader();
|
|
253
263
|
}
|
|
254
264
|
|
|
255
265
|
/**
|
|
@@ -272,7 +282,7 @@ class YunoSdk {
|
|
|
272
282
|
return;
|
|
273
283
|
}
|
|
274
284
|
this.checkInitialized();
|
|
275
|
-
return
|
|
285
|
+
return getYunoNative().receiveDeeplink(url);
|
|
276
286
|
}
|
|
277
287
|
|
|
278
288
|
/**
|
|
@@ -292,7 +302,7 @@ class YunoSdk {
|
|
|
292
302
|
* ```
|
|
293
303
|
*/
|
|
294
304
|
static async getLastOneTimeToken() {
|
|
295
|
-
return
|
|
305
|
+
return getYunoNative().getLastOneTimeToken();
|
|
296
306
|
}
|
|
297
307
|
|
|
298
308
|
/**
|
|
@@ -309,7 +319,7 @@ class YunoSdk {
|
|
|
309
319
|
* ```
|
|
310
320
|
*/
|
|
311
321
|
static async getLastOneTimeTokenInfo() {
|
|
312
|
-
return
|
|
322
|
+
return getYunoNative().getLastOneTimeTokenInfo();
|
|
313
323
|
}
|
|
314
324
|
|
|
315
325
|
/**
|
|
@@ -326,7 +336,25 @@ class YunoSdk {
|
|
|
326
336
|
* ```
|
|
327
337
|
*/
|
|
328
338
|
static async clearLastOneTimeToken() {
|
|
329
|
-
return
|
|
339
|
+
return getYunoNative().clearLastOneTimeToken();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Clears the last stored payment status.
|
|
344
|
+
* This should be called at the start of each new payment flow
|
|
345
|
+
* to prevent stale status from previous flows affecting new transactions.
|
|
346
|
+
*
|
|
347
|
+
* @returns Promise that resolves when the status is cleared
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```typescript
|
|
351
|
+
* // Clear payment status before starting a new flow
|
|
352
|
+
* await YunoSdk.clearLastPaymentStatus();
|
|
353
|
+
* await YunoSdk.startPayment({ checkoutSession, countryCode });
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
static async clearLastPaymentStatus() {
|
|
357
|
+
return getYunoNative().clearLastPaymentStatus();
|
|
330
358
|
}
|
|
331
359
|
|
|
332
360
|
/**
|
|
@@ -352,7 +380,8 @@ class YunoSdk {
|
|
|
352
380
|
* ```
|
|
353
381
|
*/
|
|
354
382
|
static onPaymentStatus(listener) {
|
|
355
|
-
const
|
|
383
|
+
const emitter = getYunoEventEmitter();
|
|
384
|
+
const subscription = emitter.addListener('YunoPaymentStatus', listener);
|
|
356
385
|
return {
|
|
357
386
|
remove: () => subscription.remove()
|
|
358
387
|
};
|
|
@@ -381,7 +410,8 @@ class YunoSdk {
|
|
|
381
410
|
* ```
|
|
382
411
|
*/
|
|
383
412
|
static onEnrollmentStatus(listener) {
|
|
384
|
-
const
|
|
413
|
+
const emitter = getYunoEventEmitter();
|
|
414
|
+
const subscription = emitter.addListener('YunoEnrollmentStatus', listener);
|
|
385
415
|
return {
|
|
386
416
|
remove: () => subscription.remove()
|
|
387
417
|
};
|
|
@@ -404,7 +434,8 @@ class YunoSdk {
|
|
|
404
434
|
* ```
|
|
405
435
|
*/
|
|
406
436
|
static onOneTimeToken(listener) {
|
|
407
|
-
const
|
|
437
|
+
const emitter = getYunoEventEmitter();
|
|
438
|
+
const subscription = emitter.addListener('YunoOneTimeToken', listener);
|
|
408
439
|
return {
|
|
409
440
|
remove: () => subscription.remove()
|
|
410
441
|
};
|
|
@@ -428,7 +459,8 @@ class YunoSdk {
|
|
|
428
459
|
* ```
|
|
429
460
|
*/
|
|
430
461
|
static onOneTimeTokenInfo(listener) {
|
|
431
|
-
const
|
|
462
|
+
const emitter = getYunoEventEmitter();
|
|
463
|
+
const subscription = emitter.addListener('YunoOneTimeTokenInfo', listener);
|
|
432
464
|
return {
|
|
433
465
|
remove: () => subscription.remove()
|
|
434
466
|
};
|