@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/YunoSdk.podspec
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
|
+
|
|
6
|
+
Pod::Spec.new do |s|
|
|
7
|
+
s.name = "YunoSdk"
|
|
8
|
+
s.version = package["version"]
|
|
9
|
+
s.summary = package["description"]
|
|
10
|
+
s.homepage = package["homepage"]
|
|
11
|
+
s.license = package["license"]
|
|
12
|
+
s.authors = package["author"]
|
|
13
|
+
|
|
14
|
+
s.platforms = { :ios => "14.0" }
|
|
15
|
+
s.source = { :git => "https://github.com/yuno-payments/yuno-sdk-react-native.git", :tag => "#{s.version}" }
|
|
16
|
+
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
18
|
+
|
|
19
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
20
|
+
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
21
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
22
|
+
install_modules_dependencies(s)
|
|
23
|
+
else
|
|
24
|
+
s.dependency "React-Core"
|
|
25
|
+
|
|
26
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
27
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
28
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
29
|
+
s.pod_target_xcconfig = {
|
|
30
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
31
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
32
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
33
|
+
}
|
|
34
|
+
s.dependency "React-Codegen"
|
|
35
|
+
s.dependency "RCT-Folly"
|
|
36
|
+
s.dependency "RCTRequired"
|
|
37
|
+
s.dependency "RCTTypeSafety"
|
|
38
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Yuno iOS SDK
|
|
43
|
+
s.dependency "YunoSDK", "2.7.1"
|
|
44
|
+
|
|
45
|
+
s.swift_version = '5.0'
|
|
46
|
+
s.static_framework = true
|
|
47
|
+
end
|
|
48
|
+
|
|
@@ -2,6 +2,7 @@ package com.yunosdkreactnative
|
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
4
|
import android.content.Context
|
|
5
|
+
import android.util.Log
|
|
5
6
|
import androidx.activity.ComponentActivity
|
|
6
7
|
import com.facebook.react.bridge.*
|
|
7
8
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
@@ -51,6 +52,14 @@ class YunoSdkModule(private val reactContext: ReactApplicationContext) :
|
|
|
51
52
|
@Volatile
|
|
52
53
|
private var lastOneTimeTokenInfo: OneTimeTokenModel? = null
|
|
53
54
|
|
|
55
|
+
// Store the last payment status to prevent stale status from previous flows
|
|
56
|
+
@Volatile
|
|
57
|
+
private var lastPaymentStatus: String? = null
|
|
58
|
+
|
|
59
|
+
// Flag to track if we're starting a fresh payment flow
|
|
60
|
+
@Volatile
|
|
61
|
+
private var isPaymentFlowCleared: Boolean = false
|
|
62
|
+
|
|
54
63
|
// Gson instance for JSON serialization
|
|
55
64
|
private val gson = Gson()
|
|
56
65
|
|
|
@@ -612,6 +621,24 @@ class YunoSdkModule(private val reactContext: ReactApplicationContext) :
|
|
|
612
621
|
}
|
|
613
622
|
}
|
|
614
623
|
|
|
624
|
+
/**
|
|
625
|
+
* Clears the last stored payment status.
|
|
626
|
+
* This should be called at the start of each new payment flow
|
|
627
|
+
* to prevent stale status from previous flows.
|
|
628
|
+
*/
|
|
629
|
+
@ReactMethod
|
|
630
|
+
fun clearLastPaymentStatus(promise: Promise) {
|
|
631
|
+
try {
|
|
632
|
+
// Don't set to null - keep the last status to compare against stale events
|
|
633
|
+
// Just mark that we're starting a fresh flow
|
|
634
|
+
isPaymentFlowCleared = true
|
|
635
|
+
Log.d(TAG, "💫 Payment status cleared - fresh flow starting (last status was: $lastPaymentStatus)")
|
|
636
|
+
promise.resolve(true)
|
|
637
|
+
} catch (e: Exception) {
|
|
638
|
+
promise.reject("CLEAR_STATUS_ERROR", "Error clearing last payment status: ${e.message}", e)
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
615
642
|
// Lifecycle Methods
|
|
616
643
|
override fun onHostResume() {}
|
|
617
644
|
override fun onHostPause() {}
|
|
@@ -651,6 +678,26 @@ class YunoSdkModule(private val reactContext: ReactApplicationContext) :
|
|
|
651
678
|
|
|
652
679
|
internal fun sendPaymentStatusEvent(status: String?) {
|
|
653
680
|
val convertedStatus = convertPaymentStatus(status)
|
|
681
|
+
|
|
682
|
+
// If we just cleared the status and this is the same status as before,
|
|
683
|
+
// it's a stale event from the native SDK - ignore it
|
|
684
|
+
if (isPaymentFlowCleared && convertedStatus == lastPaymentStatus) {
|
|
685
|
+
Log.d(TAG, "🚫 Ignoring stale payment status: $convertedStatus (from previous flow)")
|
|
686
|
+
isPaymentFlowCleared = false
|
|
687
|
+
lastPaymentStatus = null // Clear it now that we've ignored the stale event
|
|
688
|
+
return
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Reset the cleared flag after processing first real new event
|
|
692
|
+
if (isPaymentFlowCleared) {
|
|
693
|
+
Log.d(TAG, "✅ First new status after clear: $convertedStatus (previous was: $lastPaymentStatus)")
|
|
694
|
+
isPaymentFlowCleared = false
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Store the current status for future comparison
|
|
698
|
+
lastPaymentStatus = convertedStatus
|
|
699
|
+
|
|
700
|
+
Log.d(TAG, "✅ Emitting payment status: $convertedStatus")
|
|
654
701
|
val params = Arguments.createMap().apply {
|
|
655
702
|
putString("status", convertedStatus)
|
|
656
703
|
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import React
|
|
5
|
+
import YunoSDK
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* ViewManager for YunoPaymentMethodsView.
|
|
9
|
+
*
|
|
10
|
+
* This component embeds the native Yuno SDK payment methods list view
|
|
11
|
+
* into React Native, allowing developers to display payment methods in their app.
|
|
12
|
+
*
|
|
13
|
+
* Uses UIHostingController to bridge SwiftUI to UIKit for React Native.
|
|
14
|
+
*/
|
|
15
|
+
@objc(YunoPaymentMethodsViewManager)
|
|
16
|
+
class YunoPaymentMethodsViewManager: RCTViewManager {
|
|
17
|
+
|
|
18
|
+
override func view() -> UIView! {
|
|
19
|
+
let view = YunoPaymentMethodsView()
|
|
20
|
+
// Tell React Native this view handles its own scrolling
|
|
21
|
+
view.clipsToBounds = true
|
|
22
|
+
return view
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Custom UIView that wraps the Yuno payment methods SwiftUI view using UIHostingController.
|
|
32
|
+
*/
|
|
33
|
+
class YunoPaymentMethodsView: UIView, YunoPaymentFullDelegate {
|
|
34
|
+
|
|
35
|
+
private var hostingController: UIHostingController<AnyView>?
|
|
36
|
+
private var _checkoutSession: String?
|
|
37
|
+
private var _countryCode: String?
|
|
38
|
+
|
|
39
|
+
// YunoPaymentDelegate properties
|
|
40
|
+
var checkoutSession: String {
|
|
41
|
+
return _checkoutSession ?? ""
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
var countryCode: String {
|
|
45
|
+
return _countryCode ?? ""
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var language: String? {
|
|
49
|
+
return nil // Use default language
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
var viewController: UIViewController? {
|
|
53
|
+
return self.findViewController()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
override init(frame: CGRect) {
|
|
57
|
+
super.init(frame: frame)
|
|
58
|
+
setupView()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
required init?(coder: NSCoder) {
|
|
62
|
+
super.init(coder: coder)
|
|
63
|
+
setupView()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private func setupView() {
|
|
67
|
+
self.backgroundColor = .clear
|
|
68
|
+
self.isUserInteractionEnabled = true
|
|
69
|
+
self.clipsToBounds = true
|
|
70
|
+
|
|
71
|
+
print("[YunoPaymentMethods] 🏗️ setupView called")
|
|
72
|
+
// Don't load immediately - wait for checkoutSession and countryCode props
|
|
73
|
+
// loadPaymentMethodsView() will be called from updateCheckoutSessionIfReady()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override func layoutSubviews() {
|
|
77
|
+
super.layoutSubviews()
|
|
78
|
+
print("[YunoPaymentMethods] 📐 layoutSubviews - frame: \(self.frame)")
|
|
79
|
+
// SwiftUI's Auto Layout constraints will handle the size
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
override func didMoveToWindow() {
|
|
84
|
+
super.didMoveToWindow()
|
|
85
|
+
if window != nil {
|
|
86
|
+
print("[YunoPaymentMethods] 🪟 View added to window, frame: \(self.frame)")
|
|
87
|
+
setNeedsLayout()
|
|
88
|
+
layoutIfNeeded()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Loads the payment methods view asynchronously from the Yuno SDK.
|
|
94
|
+
* Uses UIHostingController to convert SwiftUI View to UIView.
|
|
95
|
+
*
|
|
96
|
+
* The key is to use a separate async function with explicit return type
|
|
97
|
+
* to help Swift's type inference select the correct overload.
|
|
98
|
+
*/
|
|
99
|
+
private func loadPaymentMethodsView() {
|
|
100
|
+
print("[YunoPaymentMethods] 🔄 loadPaymentMethodsView called")
|
|
101
|
+
print("[YunoPaymentMethods] 📋 Current checkoutSession: \(self.checkoutSession)")
|
|
102
|
+
print("[YunoPaymentMethods] 🌍 Current countryCode: \(self.countryCode)")
|
|
103
|
+
|
|
104
|
+
Task { @MainActor in
|
|
105
|
+
// Get the SwiftUI view by calling the helper function
|
|
106
|
+
// that explicitly returns 'some View' type
|
|
107
|
+
print("[YunoPaymentMethods] 🎨 Getting SwiftUI view from Yuno SDK...")
|
|
108
|
+
let swiftUIView = await getYunoSwiftUIView()
|
|
109
|
+
print("[YunoPaymentMethods] ✅ SwiftUI view obtained")
|
|
110
|
+
|
|
111
|
+
// Wrap SwiftUI view in UIHostingController
|
|
112
|
+
let hostingController = UIHostingController(rootView: AnyView(swiftUIView))
|
|
113
|
+
hostingController.view.backgroundColor = .clear
|
|
114
|
+
self.hostingController = hostingController
|
|
115
|
+
|
|
116
|
+
guard let hostingView = hostingController.view else { return }
|
|
117
|
+
|
|
118
|
+
print("[YunoPaymentMethods] ➕ Adding SwiftUI hostingView")
|
|
119
|
+
|
|
120
|
+
// Add to view controller hierarchy for proper event handling
|
|
121
|
+
if let parentVC = self.findViewController() {
|
|
122
|
+
parentVC.addChild(hostingController)
|
|
123
|
+
hostingController.didMove(toParent: parentVC)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Add as subview and pin to edges
|
|
127
|
+
self.addSubview(hostingView)
|
|
128
|
+
hostingView.translatesAutoresizingMaskIntoConstraints = false
|
|
129
|
+
NSLayoutConstraint.activate([
|
|
130
|
+
hostingView.topAnchor.constraint(equalTo: self.topAnchor),
|
|
131
|
+
hostingView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
|
|
132
|
+
hostingView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
|
|
133
|
+
hostingView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
|
|
134
|
+
])
|
|
135
|
+
|
|
136
|
+
print("[YunoPaymentMethods] ✅ Payment methods view loaded")
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Helper function that explicitly returns SwiftUI View type.
|
|
142
|
+
* This helps Swift's type inference select the correct overload.
|
|
143
|
+
*/
|
|
144
|
+
@MainActor
|
|
145
|
+
private func getYunoSwiftUIView() async -> some View {
|
|
146
|
+
// By declaring the return type as 'some View', Swift knows to call
|
|
147
|
+
// the SwiftUI version of getPaymentMethodViewAsync
|
|
148
|
+
await Yuno.getPaymentMethodViewAsync(delegate: self)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Updates the checkout session.
|
|
153
|
+
*/
|
|
154
|
+
@objc func setCheckoutSession(_ checkoutSession: String) {
|
|
155
|
+
print("[YunoPaymentMethods] 📝 setCheckoutSession called with: \(checkoutSession)")
|
|
156
|
+
self._checkoutSession = checkoutSession
|
|
157
|
+
updateCheckoutSessionIfReady()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Updates the country code.
|
|
162
|
+
*/
|
|
163
|
+
@objc func setCountryCode(_ countryCode: String) {
|
|
164
|
+
print("[YunoPaymentMethods] 📝 setCountryCode called with: \(countryCode)")
|
|
165
|
+
self._countryCode = countryCode
|
|
166
|
+
updateCheckoutSessionIfReady()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Updates the checkout session in Yuno SDK if both checkoutSession and countryCode are available.
|
|
171
|
+
* Once both are set, loads the payment methods view.
|
|
172
|
+
*/
|
|
173
|
+
private func updateCheckoutSessionIfReady() {
|
|
174
|
+
guard let checkoutSession = _checkoutSession,
|
|
175
|
+
let countryCode = _countryCode,
|
|
176
|
+
!checkoutSession.isEmpty,
|
|
177
|
+
!countryCode.isEmpty else {
|
|
178
|
+
print("[YunoPaymentMethods] ⏳ Waiting for both checkoutSession and countryCode")
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check if view is already loaded
|
|
183
|
+
if hostingController != nil {
|
|
184
|
+
print("[YunoPaymentMethods] ✅ View already loaded, skipping reload")
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// The YunoPaymentDelegate protocol properties (checkoutSession, countryCode)
|
|
189
|
+
// are already implemented above and Yuno SDK will read them automatically
|
|
190
|
+
print("[YunoPaymentMethods] ✅✅ Checkout session ready: \(checkoutSession), country: \(countryCode)")
|
|
191
|
+
print("[YunoPaymentMethods] 🚀 Now loading payment methods view...")
|
|
192
|
+
|
|
193
|
+
// Now that we have both props, load the view
|
|
194
|
+
loadPaymentMethodsView()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// MARK: - YunoPaymentDelegate
|
|
198
|
+
|
|
199
|
+
func yunoCreatePayment(with token: String) {
|
|
200
|
+
print("[YunoPaymentMethods] yunoCreatePayment called with token: \(token)")
|
|
201
|
+
|
|
202
|
+
// Emit OTT token event to React Native
|
|
203
|
+
DispatchQueue.main.async {
|
|
204
|
+
if let bridge = RCTBridge.current() {
|
|
205
|
+
if let yunoModule = bridge.module(for: YunoSdk.self) as? YunoSdk {
|
|
206
|
+
yunoModule.sendOneTimeTokenEvent(token: token)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
func yunoCreatePayment(with token: String, information: [String : Any]) {
|
|
213
|
+
print("[YunoPaymentMethods] yunoCreatePayment called with token and information")
|
|
214
|
+
|
|
215
|
+
// Emit OTT token event with full information to React Native
|
|
216
|
+
DispatchQueue.main.async {
|
|
217
|
+
if let bridge = RCTBridge.current() {
|
|
218
|
+
if let yunoModule = bridge.module(for: YunoSdk.self) as? YunoSdk {
|
|
219
|
+
yunoModule.sendOneTimeTokenEvent(token: token)
|
|
220
|
+
// The information parameter contains additional token details
|
|
221
|
+
// It's already sent via sendOneTimeTokenEvent which emits both events
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
func yunoPaymentResult(_ result: Yuno.Result) {
|
|
228
|
+
print("[YunoPaymentMethods] yunoPaymentResult: \(result)")
|
|
229
|
+
|
|
230
|
+
// Emit payment status event to React Native
|
|
231
|
+
let statusString: String
|
|
232
|
+
switch result {
|
|
233
|
+
case .succeeded:
|
|
234
|
+
statusString = "SUCCEEDED"
|
|
235
|
+
case .fail:
|
|
236
|
+
statusString = "FAILED"
|
|
237
|
+
case .reject:
|
|
238
|
+
statusString = "REJECTED"
|
|
239
|
+
case .processing:
|
|
240
|
+
statusString = "PROCESSING"
|
|
241
|
+
case .internalError:
|
|
242
|
+
statusString = "INTERNAL_ERROR"
|
|
243
|
+
case .userCancelled:
|
|
244
|
+
statusString = "CANCELLED_BY_USER"
|
|
245
|
+
@unknown default:
|
|
246
|
+
statusString = "UNKNOWN"
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
DispatchQueue.main.async {
|
|
250
|
+
if let bridge = RCTBridge.current() {
|
|
251
|
+
if let yunoModule = bridge.module(for: YunoSdk.self) as? YunoSdk {
|
|
252
|
+
yunoModule.sendPaymentStatusEvent(status: statusString)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// MARK: - YunoPaymentFullDelegate
|
|
259
|
+
|
|
260
|
+
func yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected) {
|
|
261
|
+
// Emit event to React Native
|
|
262
|
+
print("[YunoPaymentMethods] Payment method selected")
|
|
263
|
+
emitPaymentSelectedEvent(isSelected: true)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
func yunoDidUnenrollSuccessfully(_ success: Bool) {
|
|
267
|
+
print("[YunoPaymentMethods] yunoDidUnenrollSuccessfully: \(success)")
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
func yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat) {
|
|
271
|
+
// Update view height if needed
|
|
272
|
+
print("[YunoPaymentMethods] yunoUpdatePaymentMethodsViewHeight: \(height)")
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// MARK: - Event Emission
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Emits a payment method selected event to React Native.
|
|
279
|
+
*/
|
|
280
|
+
private func emitPaymentSelectedEvent(isSelected: Bool) {
|
|
281
|
+
// Send event through YunoSdk module
|
|
282
|
+
DispatchQueue.main.async {
|
|
283
|
+
if let bridge = RCTBridge.current() {
|
|
284
|
+
if let yunoModule = bridge.module(for: YunoSdk.self) as? YunoSdk {
|
|
285
|
+
yunoModule.sendEvent(
|
|
286
|
+
withName: "onPaymentMethodSelected",
|
|
287
|
+
body: ["isSelected": isSelected]
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Emits an error event to React Native.
|
|
296
|
+
*/
|
|
297
|
+
private func emitErrorEvent(message: String) {
|
|
298
|
+
DispatchQueue.main.async {
|
|
299
|
+
if let bridge = RCTBridge.current() {
|
|
300
|
+
if let yunoModule = bridge.module(for: YunoSdk.self) as? YunoSdk {
|
|
301
|
+
yunoModule.sendEvent(
|
|
302
|
+
withName: "onPaymentMethodError",
|
|
303
|
+
body: ["message": message]
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// MARK: - UIView extension to find view controller
|
|
312
|
+
|
|
313
|
+
extension UIView {
|
|
314
|
+
func findViewController() -> UIViewController? {
|
|
315
|
+
if let nextResponder = self.next as? UIViewController {
|
|
316
|
+
return nextResponder
|
|
317
|
+
} else if let nextResponder = self.next as? UIView {
|
|
318
|
+
return nextResponder.findViewController()
|
|
319
|
+
} else {
|
|
320
|
+
return nil
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
package/ios/YunoSdk.m
CHANGED
|
@@ -33,7 +33,9 @@ RCT_EXTERN_METHOD(
|
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
RCT_EXTERN_METHOD(
|
|
36
|
-
continuePayment:(
|
|
36
|
+
continuePayment:(NSString *)checkoutSession
|
|
37
|
+
countryCode:(NSString *)countryCode
|
|
38
|
+
showPaymentStatus:(BOOL)showPaymentStatus
|
|
37
39
|
resolver:(RCTPromiseResolveBlock)resolver
|
|
38
40
|
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
39
41
|
)
|
|
@@ -56,10 +58,29 @@ RCT_EXTERN_METHOD(
|
|
|
56
58
|
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
57
59
|
)
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
RCT_EXTERN_METHOD(
|
|
62
|
+
getLastOneTimeToken:(RCTPromiseResolveBlock)resolver
|
|
63
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
RCT_EXTERN_METHOD(
|
|
67
|
+
getLastOneTimeTokenInfo:(RCTPromiseResolveBlock)resolver
|
|
68
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
RCT_EXTERN_METHOD(
|
|
72
|
+
clearLastOneTimeToken:(RCTPromiseResolveBlock)resolver
|
|
73
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
RCT_EXTERN_METHOD(
|
|
77
|
+
clearLastPaymentStatus:(RCTPromiseResolveBlock)resolver
|
|
78
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
RCT_EXTERN_METHOD(addListener:(NSString *)eventName)
|
|
82
|
+
|
|
83
|
+
RCT_EXTERN_METHOD(removeListeners:(double)count)
|
|
63
84
|
|
|
64
85
|
@end
|
|
65
86
|
|