@yuno-payments/yuno-sdk-react-native 1.0.16
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/LICENSE +22 -0
- package/README.md +621 -0
- package/android/build.gradle +131 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/yunosdkreactnative/YunoPaymentMethodsViewManager.kt +194 -0
- package/android/src/main/java/com/yunosdkreactnative/YunoSdkModule.kt +777 -0
- package/android/src/main/java/com/yunosdkreactnative/YunoSdkPackage.kt +24 -0
- package/ios/YunoSdk.m +65 -0
- package/ios/YunoSdk.podspec +48 -0
- package/ios/YunoSdk.swift +442 -0
- package/lib/commonjs/YunoPaymentMethods.js +145 -0
- package/lib/commonjs/YunoPaymentMethods.js.map +1 -0
- package/lib/commonjs/YunoSdk.js +455 -0
- package/lib/commonjs/YunoSdk.js.map +1 -0
- package/lib/commonjs/core/enums/CardFlow.js +26 -0
- package/lib/commonjs/core/enums/CardFlow.js.map +1 -0
- package/lib/commonjs/core/enums/YunoLanguage.js +58 -0
- package/lib/commonjs/core/enums/YunoLanguage.js.map +1 -0
- package/lib/commonjs/core/enums/YunoStatus.js +40 -0
- package/lib/commonjs/core/enums/YunoStatus.js.map +1 -0
- package/lib/commonjs/core/enums/index.js +27 -0
- package/lib/commonjs/core/enums/index.js.map +1 -0
- package/lib/commonjs/core/index.js +28 -0
- package/lib/commonjs/core/index.js.map +1 -0
- package/lib/commonjs/core/types/AndroidConfig.js +2 -0
- package/lib/commonjs/core/types/AndroidConfig.js.map +1 -0
- package/lib/commonjs/core/types/EnrollmentArguments.js +2 -0
- package/lib/commonjs/core/types/EnrollmentArguments.js.map +1 -0
- package/lib/commonjs/core/types/IosConfig.js +2 -0
- package/lib/commonjs/core/types/IosConfig.js.map +1 -0
- package/lib/commonjs/core/types/OneTimeTokenInfo.js +2 -0
- package/lib/commonjs/core/types/OneTimeTokenInfo.js.map +1 -0
- package/lib/commonjs/core/types/SeamlessArguments.js +6 -0
- package/lib/commonjs/core/types/SeamlessArguments.js.map +1 -0
- package/lib/commonjs/core/types/StartPayment.js +2 -0
- package/lib/commonjs/core/types/StartPayment.js.map +1 -0
- package/lib/commonjs/core/types/YunoConfig.js +6 -0
- package/lib/commonjs/core/types/YunoConfig.js.map +1 -0
- package/lib/commonjs/core/types/index.js +2 -0
- package/lib/commonjs/core/types/index.js.map +1 -0
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/YunoPaymentMethods.js +138 -0
- package/lib/module/YunoPaymentMethods.js.map +1 -0
- package/lib/module/YunoSdk.js +448 -0
- package/lib/module/YunoSdk.js.map +1 -0
- package/lib/module/core/enums/CardFlow.js +20 -0
- package/lib/module/core/enums/CardFlow.js.map +1 -0
- package/lib/module/core/enums/YunoLanguage.js +52 -0
- package/lib/module/core/enums/YunoLanguage.js.map +1 -0
- package/lib/module/core/enums/YunoStatus.js +34 -0
- package/lib/module/core/enums/YunoStatus.js.map +1 -0
- package/lib/module/core/enums/index.js +4 -0
- package/lib/module/core/enums/index.js.map +1 -0
- package/lib/module/core/index.js +3 -0
- package/lib/module/core/index.js.map +1 -0
- package/lib/module/core/types/AndroidConfig.js +2 -0
- package/lib/module/core/types/AndroidConfig.js.map +1 -0
- package/lib/module/core/types/EnrollmentArguments.js +2 -0
- package/lib/module/core/types/EnrollmentArguments.js.map +1 -0
- package/lib/module/core/types/IosConfig.js +2 -0
- package/lib/module/core/types/IosConfig.js.map +1 -0
- package/lib/module/core/types/OneTimeTokenInfo.js +2 -0
- package/lib/module/core/types/OneTimeTokenInfo.js.map +1 -0
- package/lib/module/core/types/SeamlessArguments.js +2 -0
- package/lib/module/core/types/SeamlessArguments.js.map +1 -0
- package/lib/module/core/types/StartPayment.js +2 -0
- package/lib/module/core/types/StartPayment.js.map +1 -0
- package/lib/module/core/types/YunoConfig.js +2 -0
- package/lib/module/core/types/YunoConfig.js.map +1 -0
- package/lib/module/core/types/index.js +2 -0
- package/lib/module/core/types/index.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/package.json +142 -0
- package/src/YunoPaymentMethods.tsx +196 -0
- package/src/YunoSdk.ts +518 -0
- package/src/core/enums/CardFlow.ts +18 -0
- package/src/core/enums/YunoLanguage.ts +50 -0
- package/src/core/enums/YunoStatus.ts +32 -0
- package/src/core/enums/index.ts +3 -0
- package/src/core/index.ts +2 -0
- package/src/core/types/AndroidConfig.ts +17 -0
- package/src/core/types/EnrollmentArguments.ts +32 -0
- package/src/core/types/IosConfig.ts +17 -0
- package/src/core/types/OneTimeTokenInfo.ts +207 -0
- package/src/core/types/SeamlessArguments.ts +42 -0
- package/src/core/types/StartPayment.ts +59 -0
- package/src/core/types/YunoConfig.ts +55 -0
- package/src/core/types/index.ts +7 -0
- package/src/index.ts +17 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package com.yunosdkreactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Yuno SDK React Native Package.
|
|
10
|
+
*
|
|
11
|
+
* This class registers the Yuno SDK module with React Native.
|
|
12
|
+
*/
|
|
13
|
+
class YunoSdkPackage : ReactPackage {
|
|
14
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
15
|
+
return listOf(YunoSdkModule(reactContext))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
19
|
+
return listOf(
|
|
20
|
+
YunoPaymentMethodsViewManager(reactContext)
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
package/ios/YunoSdk.m
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(YunoSdk, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(
|
|
7
|
+
initialize:(NSString *)apiKey
|
|
8
|
+
countryCode:(NSString *)countryCode
|
|
9
|
+
yunoConfig:(NSDictionary *)yunoConfig
|
|
10
|
+
iosConfig:(NSDictionary *)iosConfig
|
|
11
|
+
androidConfig:(NSDictionary *)androidConfig
|
|
12
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
13
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
RCT_EXTERN_METHOD(
|
|
17
|
+
enrollmentPayment:(NSDictionary *)arguments
|
|
18
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
19
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
RCT_EXTERN_METHOD(
|
|
23
|
+
startPaymentLite:(NSDictionary *)arguments
|
|
24
|
+
countryCode:(NSString *)countryCode
|
|
25
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
26
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
RCT_EXTERN_METHOD(
|
|
30
|
+
startPayment:(BOOL)showPaymentStatus
|
|
31
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
32
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
RCT_EXTERN_METHOD(
|
|
36
|
+
continuePayment:(BOOL)showPaymentStatus
|
|
37
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
38
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
RCT_EXTERN_METHOD(
|
|
42
|
+
startPaymentSeamlessLite:(NSDictionary *)arguments
|
|
43
|
+
language:(NSString *)language
|
|
44
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
45
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
RCT_EXTERN_METHOD(
|
|
49
|
+
hideLoader:(RCTPromiseResolveBlock)resolver
|
|
50
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
RCT_EXTERN_METHOD(
|
|
54
|
+
receiveDeeplink:(NSString *)url
|
|
55
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
56
|
+
rejecter:(RCTPromiseRejectBlock)rejecter
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
+ (BOOL)requiresMainQueueSetup
|
|
60
|
+
{
|
|
61
|
+
return YES;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@end
|
|
65
|
+
|
|
@@ -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 = "*.{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
|
+
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import YunoSDK
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Yuno SDK React Native Module for iOS.
|
|
6
|
+
*
|
|
7
|
+
* This module provides a bridge between React Native JavaScript code and the native Yuno iOS SDK.
|
|
8
|
+
*/
|
|
9
|
+
@objc(YunoSdk)
|
|
10
|
+
class YunoSdk: RCTEventEmitter {
|
|
11
|
+
|
|
12
|
+
private var isInitialized = false
|
|
13
|
+
private var currentCountryCode: String?
|
|
14
|
+
private var currentLanguage: String?
|
|
15
|
+
private var customerSession: String = ""
|
|
16
|
+
private var checkoutSession: String = ""
|
|
17
|
+
|
|
18
|
+
override init() {
|
|
19
|
+
super.init()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override func supportedEvents() -> [String]! {
|
|
27
|
+
return [
|
|
28
|
+
"YunoPaymentStatus",
|
|
29
|
+
"YunoEnrollmentStatus",
|
|
30
|
+
"YunoOneTimeToken"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Initialize the Yuno SDK with configuration.
|
|
36
|
+
*/
|
|
37
|
+
@objc
|
|
38
|
+
func initialize(
|
|
39
|
+
_ apiKey: String,
|
|
40
|
+
countryCode: String,
|
|
41
|
+
yunoConfig: NSDictionary,
|
|
42
|
+
iosConfig: NSDictionary?,
|
|
43
|
+
androidConfig: NSDictionary?,
|
|
44
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
45
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
46
|
+
) {
|
|
47
|
+
DispatchQueue.main.async { [weak self] in
|
|
48
|
+
guard let self = self else { return }
|
|
49
|
+
|
|
50
|
+
do {
|
|
51
|
+
self.currentCountryCode = countryCode
|
|
52
|
+
|
|
53
|
+
// Parse language
|
|
54
|
+
if let lang = yunoConfig["lang"] as? String {
|
|
55
|
+
self.currentLanguage = lang
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Parse card flow
|
|
59
|
+
var cardFlow: YunoCardFlow = .oneStep
|
|
60
|
+
if let flow = yunoConfig["cardFlow"] as? String {
|
|
61
|
+
cardFlow = self.mapToCardFlow(flow)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Parse other config options
|
|
65
|
+
let saveCardEnabled = yunoConfig["saveCardEnabled"] as? Bool ?? false
|
|
66
|
+
let keepLoader = yunoConfig["keepLoader"] as? Bool ?? false
|
|
67
|
+
|
|
68
|
+
// Initialize Yuno SDK
|
|
69
|
+
Yuno.initialize(
|
|
70
|
+
apiKey: apiKey,
|
|
71
|
+
config: YunoConfig(
|
|
72
|
+
cardFlow: cardFlow,
|
|
73
|
+
saveCardEnabled: saveCardEnabled,
|
|
74
|
+
keepLoader: keepLoader
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
self.isInitialized = true
|
|
79
|
+
resolver(nil)
|
|
80
|
+
} catch {
|
|
81
|
+
rejecter("INITIALIZATION_ERROR", "Failed to initialize Yuno SDK: \(error.localizedDescription)", error)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Start enrollment payment flow.
|
|
88
|
+
*/
|
|
89
|
+
@objc
|
|
90
|
+
func enrollmentPayment(
|
|
91
|
+
_ arguments: NSDictionary,
|
|
92
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
93
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
94
|
+
) {
|
|
95
|
+
guard isInitialized else {
|
|
96
|
+
rejecter("NOT_INITIALIZED", "Yuno SDK is not initialized", nil)
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
DispatchQueue.main.async { [weak self] in
|
|
101
|
+
guard let self = self else { return }
|
|
102
|
+
|
|
103
|
+
do {
|
|
104
|
+
guard let customerSession = arguments["customerSession"] as? String, !customerSession.isEmpty else {
|
|
105
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "customerSession is required"])
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let showPaymentStatus = arguments["showPaymentStatus"] as? Bool ?? true
|
|
109
|
+
|
|
110
|
+
var countryCode = arguments["countryCode"] as? String
|
|
111
|
+
if countryCode == nil || countryCode!.isEmpty {
|
|
112
|
+
countryCode = self.currentCountryCode
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
guard let safeCountryCode = countryCode, !safeCountryCode.isEmpty else {
|
|
116
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "countryCode is required"])
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
self.customerSession = customerSession
|
|
120
|
+
self.currentCountryCode = safeCountryCode
|
|
121
|
+
|
|
122
|
+
Yuno.enrollPayment(with: self, showPaymentStatus: showPaymentStatus)
|
|
123
|
+
|
|
124
|
+
resolver(nil)
|
|
125
|
+
} catch {
|
|
126
|
+
rejecter("ENROLLMENT_ERROR", "Failed to start enrollment: \(error.localizedDescription)", error)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Start payment lite flow.
|
|
133
|
+
*/
|
|
134
|
+
@objc
|
|
135
|
+
func startPaymentLite(
|
|
136
|
+
_ arguments: NSDictionary,
|
|
137
|
+
countryCode: String,
|
|
138
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
139
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
140
|
+
) {
|
|
141
|
+
guard isInitialized else {
|
|
142
|
+
rejecter("NOT_INITIALIZED", "Yuno SDK is not initialized", nil)
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
DispatchQueue.main.async { [weak self] in
|
|
147
|
+
guard let self = self else { return }
|
|
148
|
+
|
|
149
|
+
do {
|
|
150
|
+
guard let checkoutSession = arguments["checkoutSession"] as? String, !checkoutSession.isEmpty else {
|
|
151
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "checkoutSession is required"])
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
guard let methodSelected = arguments["methodSelected"] as? NSDictionary else {
|
|
155
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "methodSelected is required"])
|
|
156
|
+
}
|
|
157
|
+
|
|
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
|
+
guard let paymentMethodType = methodSelected["paymentMethodType"] as? String, !paymentMethodType.isEmpty else {
|
|
163
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "paymentMethodType is required"])
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let showPaymentStatus = arguments["showPaymentStatus"] as? Bool ?? true
|
|
167
|
+
|
|
168
|
+
self.checkoutSession = checkoutSession
|
|
169
|
+
self.currentCountryCode = countryCode
|
|
170
|
+
|
|
171
|
+
let paymentSelected = Yuno.PaymentSelected(
|
|
172
|
+
paymentMethodType: paymentMethodType,
|
|
173
|
+
vaultedToken: vaultedToken
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
Yuno.startPaymentLite(
|
|
177
|
+
with: self,
|
|
178
|
+
paymentSelected: paymentSelected,
|
|
179
|
+
showPaymentStatus: showPaymentStatus
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
resolver(nil)
|
|
183
|
+
} catch {
|
|
184
|
+
rejecter("PAYMENT_LITE_ERROR", "Failed to start payment lite: \(error.localizedDescription)", error)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Start full payment flow.
|
|
191
|
+
*/
|
|
192
|
+
@objc
|
|
193
|
+
func startPayment(
|
|
194
|
+
_ showPaymentStatus: Bool,
|
|
195
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
196
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
197
|
+
) {
|
|
198
|
+
guard isInitialized else {
|
|
199
|
+
rejecter("NOT_INITIALIZED", "Yuno SDK is not initialized", nil)
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
DispatchQueue.main.async {
|
|
204
|
+
do {
|
|
205
|
+
Yuno.startPayment(showPaymentStatus: showPaymentStatus)
|
|
206
|
+
resolver(nil)
|
|
207
|
+
} catch {
|
|
208
|
+
rejecter("PAYMENT_ERROR", "Failed to start payment: \(error.localizedDescription)", error)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Continue payment flow.
|
|
215
|
+
*/
|
|
216
|
+
@objc
|
|
217
|
+
func continuePayment(
|
|
218
|
+
_ showPaymentStatus: Bool,
|
|
219
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
220
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
221
|
+
) {
|
|
222
|
+
guard isInitialized else {
|
|
223
|
+
rejecter("NOT_INITIALIZED", "Yuno SDK is not initialized", nil)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
DispatchQueue.main.async {
|
|
228
|
+
do {
|
|
229
|
+
Yuno.continuePayment()
|
|
230
|
+
resolver(nil)
|
|
231
|
+
} catch {
|
|
232
|
+
rejecter("CONTINUE_PAYMENT_ERROR", "Failed to continue payment: \(error.localizedDescription)", error)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Start seamless payment lite flow.
|
|
239
|
+
*/
|
|
240
|
+
@objc
|
|
241
|
+
func startPaymentSeamlessLite(
|
|
242
|
+
_ arguments: NSDictionary,
|
|
243
|
+
language: String,
|
|
244
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
245
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
246
|
+
) {
|
|
247
|
+
guard isInitialized else {
|
|
248
|
+
rejecter("NOT_INITIALIZED", "Yuno SDK is not initialized", nil)
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
DispatchQueue.main.async { [weak self] in
|
|
253
|
+
guard let self = self else { return }
|
|
254
|
+
|
|
255
|
+
do {
|
|
256
|
+
guard let checkoutSession = arguments["checkoutSession"] as? String, !checkoutSession.isEmpty else {
|
|
257
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "checkoutSession is required"])
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
guard let methodSelected = arguments["methodSelected"] as? NSDictionary else {
|
|
261
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "methodSelected is required"])
|
|
262
|
+
}
|
|
263
|
+
|
|
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
|
+
guard let paymentMethodType = methodSelected["paymentMethodType"] as? String, !paymentMethodType.isEmpty else {
|
|
269
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "paymentMethodType is required"])
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let showPaymentStatus = arguments["showPaymentStatus"] as? Bool ?? true
|
|
273
|
+
|
|
274
|
+
var countryCode = arguments["countryCode"] as? String
|
|
275
|
+
if countryCode == nil || countryCode!.isEmpty {
|
|
276
|
+
countryCode = self.currentCountryCode
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
guard let safeCountryCode = countryCode, !safeCountryCode.isEmpty else {
|
|
280
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "countryCode is required"])
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
self.checkoutSession = checkoutSession
|
|
284
|
+
self.currentCountryCode = safeCountryCode
|
|
285
|
+
|
|
286
|
+
let paymentSelected = Yuno.PaymentSelected(
|
|
287
|
+
paymentMethodType: paymentMethodType,
|
|
288
|
+
vaultedToken: vaultedToken
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
Yuno.startPaymentLite(
|
|
292
|
+
with: self,
|
|
293
|
+
paymentSelected: paymentSelected,
|
|
294
|
+
showPaymentStatus: showPaymentStatus
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
// Return initial processing status
|
|
298
|
+
resolver("PROCESSING")
|
|
299
|
+
} catch {
|
|
300
|
+
rejecter("SEAMLESS_ERROR", "Failed to start seamless payment: \(error.localizedDescription)", error)
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Hide loader.
|
|
307
|
+
*/
|
|
308
|
+
@objc
|
|
309
|
+
func hideLoader(
|
|
310
|
+
_ resolver: @escaping RCTPromiseResolveBlock,
|
|
311
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
312
|
+
) {
|
|
313
|
+
DispatchQueue.main.async {
|
|
314
|
+
do {
|
|
315
|
+
Yuno.hideLoader()
|
|
316
|
+
resolver(nil)
|
|
317
|
+
} catch {
|
|
318
|
+
rejecter("HIDE_LOADER_ERROR", "Failed to hide loader: \(error.localizedDescription)", error)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Receive deeplink for payment resumption.
|
|
325
|
+
*/
|
|
326
|
+
@objc
|
|
327
|
+
func receiveDeeplink(
|
|
328
|
+
_ url: String,
|
|
329
|
+
resolver: @escaping RCTPromiseResolveBlock,
|
|
330
|
+
rejecter: @escaping RCTPromiseRejectBlock
|
|
331
|
+
) {
|
|
332
|
+
DispatchQueue.main.async {
|
|
333
|
+
do {
|
|
334
|
+
guard !url.isEmpty, let deeplink = URL(string: url) else {
|
|
335
|
+
throw NSError(domain: "YunoSdk", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
Yuno.receiveDeeplink(deeplink)
|
|
339
|
+
resolver(nil)
|
|
340
|
+
} catch {
|
|
341
|
+
rejecter("DEEPLINK_ERROR", "Failed to process deeplink: \(error.localizedDescription)", error)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// MARK: - Helper Methods
|
|
347
|
+
|
|
348
|
+
private func mapToCardFlow(_ cardFlow: String) -> YunoCardFlow {
|
|
349
|
+
switch cardFlow {
|
|
350
|
+
case "STEP_BY_STEP":
|
|
351
|
+
return .multiStep
|
|
352
|
+
default:
|
|
353
|
+
return .oneStep
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private func mapStatusToString(_ status: YunoPaymentStatus) -> String {
|
|
358
|
+
switch status {
|
|
359
|
+
case .rejected:
|
|
360
|
+
return "REJECTED"
|
|
361
|
+
case .succeeded:
|
|
362
|
+
return "SUCCEEDED"
|
|
363
|
+
case .failed:
|
|
364
|
+
return "FAILED"
|
|
365
|
+
case .processing:
|
|
366
|
+
return "PROCESSING"
|
|
367
|
+
case .internalError:
|
|
368
|
+
return "INTERNAL_ERROR"
|
|
369
|
+
case .cancelledByUser:
|
|
370
|
+
return "CANCELLED_BY_USER"
|
|
371
|
+
@unknown default:
|
|
372
|
+
return "INTERNAL_ERROR"
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// MARK: - Event Emitters
|
|
377
|
+
|
|
378
|
+
private func sendPaymentStatusEvent(status: YunoPaymentStatus, token: String? = nil) {
|
|
379
|
+
var params: [String: Any] = ["status": mapStatusToString(status)]
|
|
380
|
+
if let token = token {
|
|
381
|
+
params["token"] = token
|
|
382
|
+
}
|
|
383
|
+
sendEvent(withName: "YunoPaymentStatus", body: params)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private func sendEnrollmentStatusEvent(status: YunoPaymentStatus) {
|
|
387
|
+
let params: [String: Any] = ["status": mapStatusToString(status)]
|
|
388
|
+
sendEvent(withName: "YunoEnrollmentStatus", body: params)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
private func sendOneTimeTokenEvent(token: String) {
|
|
392
|
+
sendEvent(withName: "YunoOneTimeToken", body: token)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// MARK: - YunoPaymentDelegate Extension
|
|
397
|
+
extension YunoSdk: YunoPaymentDelegate {
|
|
398
|
+
func yunoCreatePayment(with token: String) {
|
|
399
|
+
sendOneTimeTokenEvent(token: token)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
func yunoPaymentResult(_ result: Yuno.Result) {
|
|
403
|
+
sendPaymentStatusEvent(status: mapResultToStatus(result))
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
var countryCode: String {
|
|
407
|
+
return currentCountryCode ?? ""
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
var checkoutSession: String {
|
|
411
|
+
return self.checkoutSession
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private func mapResultToStatus(_ result: Yuno.Result) -> YunoPaymentStatus {
|
|
415
|
+
switch result {
|
|
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
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// MARK: - YunoEnrollmentDelegate Extension
|
|
433
|
+
extension YunoSdk: YunoEnrollmentDelegate {
|
|
434
|
+
func yunoEnrollmentResult(_ result: Yuno.Result) {
|
|
435
|
+
sendEnrollmentStatusEvent(status: mapResultToStatus(result))
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
var customerSession: String {
|
|
439
|
+
return self.customerSession
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|