nimbbl-mobile-react-native-sdk 1.0.0-alpha.5
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 +21 -0
- package/README.md +569 -0
- package/android/build.gradle +86 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
- package/android/gradle.properties +4 -0
- package/android/gradlew +185 -0
- package/android/gradlew.bat +89 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +19 -0
- package/android/src/main/java/com/nimbbl/reactnative/NimbblCheckoutActivity.kt +224 -0
- package/android/src/main/java/com/nimbbl/reactnative/NimbblReactNativeSDKModule.kt +428 -0
- package/android/src/main/java/com/nimbbl/reactnative/NimbblReactNativeSDKPackage.kt +16 -0
- package/android/src/main/java/com/nimbbl/reactnative/TestActivity.kt +28 -0
- package/index.tsx +8 -0
- package/ios/NimbblReactNativeSDK.m +20 -0
- package/ios/NimbblReactNativeSDK.podspec +38 -0
- package/ios/NimbblReactNativeSDK.swift +199 -0
- package/lib/NimbblSDK.d.ts +108 -0
- package/lib/NimbblSDK.d.ts.map +1 -0
- package/lib/NimbblSDK.js +256 -0
- package/lib/NimbblSDK.js.map +1 -0
- package/lib/__tests__/__mocks__/react-native.d.ts +26 -0
- package/lib/__tests__/__mocks__/react-native.d.ts.map +1 -0
- package/lib/__tests__/__mocks__/react-native.js +23 -0
- package/lib/__tests__/__mocks__/react-native.js.map +1 -0
- package/lib/__tests__/setup.d.ts +1 -0
- package/lib/__tests__/setup.d.ts.map +1 -0
- package/lib/__tests__/setup.js +4 -0
- package/lib/__tests__/setup.js.map +1 -0
- package/lib/constants.d.ts +35 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/constants.js +44 -0
- package/lib/constants.js.map +1 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +32 -0
- package/lib/index.js.map +1 -0
- package/lib/types.d.ts +100 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +8 -0
- package/lib/types.js.map +1 -0
- package/nimbbl-mobile-react-native-sdk.podspec +27 -0
- package/package.json +90 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
package com.nimbbl.reactnative
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.facebook.react.bridge.*
|
|
7
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
8
|
+
import tech.nimbbl.webviewsdk.core.NimbblCheckoutSDK
|
|
9
|
+
import tech.nimbbl.webviewsdk.core.NimbblOrderCreation
|
|
10
|
+
import tech.nimbbl.webviewsdk.models.NimbblCheckoutOptions
|
|
11
|
+
import tech.nimbbl.webviewsdk.models.interfaces.NimbblCheckoutPaymentListener
|
|
12
|
+
import kotlinx.coroutines.*
|
|
13
|
+
import retrofit2.Response
|
|
14
|
+
|
|
15
|
+
class NimbblReactNativeSDKModule(private val reactContext: ReactApplicationContext) :
|
|
16
|
+
ReactContextBaseJavaModule(reactContext), ActivityEventListener {
|
|
17
|
+
|
|
18
|
+
companion object {
|
|
19
|
+
private const val TAG = "NimbblReactNativeSDK"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private var config: MutableMap<String, Any> = mutableMapOf()
|
|
23
|
+
private var isInitialized = false
|
|
24
|
+
|
|
25
|
+
init {
|
|
26
|
+
reactContext.addActivityEventListener(this)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun getName(): String {
|
|
30
|
+
return "NimbblReactNativeSDK"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun getConstants(): MutableMap<String, Any> {
|
|
34
|
+
return mutableMapOf(
|
|
35
|
+
"SDK_VERSION" to "1.0.0",
|
|
36
|
+
"PLATFORM" to "android"
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ReactMethod
|
|
41
|
+
fun testModule(promise: Promise) {
|
|
42
|
+
try {
|
|
43
|
+
println("NimbblReactNativeSDK testModule called")
|
|
44
|
+
Log.d(TAG, "testModule called - Android native module is working")
|
|
45
|
+
val result = Arguments.createMap().apply {
|
|
46
|
+
putString("status", "success")
|
|
47
|
+
putString("message", "Module is working")
|
|
48
|
+
}
|
|
49
|
+
promise.resolve(result)
|
|
50
|
+
} catch (error: Exception) {
|
|
51
|
+
println("Error in testModule: ${error.message}")
|
|
52
|
+
Log.e(TAG, "Error in testModule: ${error.message}", error)
|
|
53
|
+
promise.reject("TEST_MODULE_FAILED", error.message, error)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@ReactMethod
|
|
58
|
+
fun initialize(config: ReadableMap, promise: Promise) {
|
|
59
|
+
try {
|
|
60
|
+
Log.d(TAG, "Initializing Nimbbl SDK")
|
|
61
|
+
|
|
62
|
+
if (config == null) {
|
|
63
|
+
promise.reject("INVALID_CONFIG", "Configuration is required")
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Extract configuration
|
|
68
|
+
this.config.clear()
|
|
69
|
+
this.config["environment"] = config.getString("environment") ?: "sandbox"
|
|
70
|
+
|
|
71
|
+
config.getMap("options")?.let { options ->
|
|
72
|
+
this.config["timeout"] = if (options.hasKey("timeout")) options.getInt("timeout") else 30000
|
|
73
|
+
this.config["enable_logging"] = if (options.hasKey("enable_logging")) options.getBoolean("enable_logging") else true
|
|
74
|
+
this.config["enable_analytics"] = if (options.hasKey("enable_analytics")) options.getBoolean("enable_analytics") else true
|
|
75
|
+
this.config["api_base_url"] = if (options.hasKey("api_base_url")) options.getString("api_base_url") ?: "https://api.nimbbl.tech" else "https://api.nimbbl.tech"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
isInitialized = true
|
|
79
|
+
|
|
80
|
+
val result = Arguments.createMap().apply {
|
|
81
|
+
putBoolean("success", true)
|
|
82
|
+
putString("message", "SDK initialized successfully")
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
promise.resolve(result)
|
|
86
|
+
|
|
87
|
+
} catch (e: Exception) {
|
|
88
|
+
Log.e(TAG, "Error initializing SDK", e)
|
|
89
|
+
promise.reject("INITIALIZATION_FAILED", e.message)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@ReactMethod
|
|
94
|
+
fun createShopOrder(orderData: ReadableMap, promise: Promise) {
|
|
95
|
+
Log.d(TAG, "=== CREATE SHOP ORDER METHOD CALLED ===")
|
|
96
|
+
println("NimbblReactNativeSDK createShopOrder method called")
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
if (!isInitialized) {
|
|
100
|
+
Log.e(TAG, "SDK not initialized")
|
|
101
|
+
promise.reject("NOT_INITIALIZED", "SDK must be initialized before creating orders")
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Log.d(TAG, "Creating shop order: $orderData")
|
|
106
|
+
println("Creating shop order with data: $orderData")
|
|
107
|
+
|
|
108
|
+
// Extract order data
|
|
109
|
+
val currency = orderData.getString("currency") ?: "INR"
|
|
110
|
+
val amountString = orderData.getString("amount") ?: "0"
|
|
111
|
+
val amount = amountString.toDoubleOrNull() ?: 0.0
|
|
112
|
+
val productId = orderData.getString("product_id") ?: "11"
|
|
113
|
+
val orderLineItems = orderData.getBoolean("orderLineItems")
|
|
114
|
+
val checkoutExperience = orderData.getString("checkout_experience") ?: "redirect"
|
|
115
|
+
val paymentMode = orderData.getString("payment_mode") ?: ""
|
|
116
|
+
val subPaymentMode = orderData.getString("subPaymentMode") ?: ""
|
|
117
|
+
|
|
118
|
+
Log.d(TAG, "Extracted order data:")
|
|
119
|
+
Log.d(TAG, " - currency: $currency")
|
|
120
|
+
Log.d(TAG, " - amount: $amount")
|
|
121
|
+
Log.d(TAG, " - productId: $productId")
|
|
122
|
+
Log.d(TAG, " - orderLineItems: $orderLineItems")
|
|
123
|
+
Log.d(TAG, " - checkoutExperience: $checkoutExperience")
|
|
124
|
+
Log.d(TAG, " - paymentMode: $paymentMode")
|
|
125
|
+
Log.d(TAG, " - subPaymentMode: $subPaymentMode")
|
|
126
|
+
|
|
127
|
+
// Validate required fields
|
|
128
|
+
if (amountString.isEmpty() || currency.isEmpty()) {
|
|
129
|
+
Log.e(TAG, "Amount or currency is empty")
|
|
130
|
+
promise.reject("INVALID_ORDER_DATA", "Amount and currency are required")
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Handle user parameter - it might be undefined, null, or valid data from React Native
|
|
135
|
+
val userMap = orderData.getMap("user")
|
|
136
|
+
val user: Map<String, Any>? = if (userMap != null && !userMap.toHashMap().isEmpty()) {
|
|
137
|
+
userMap.toHashMap()
|
|
138
|
+
} else {
|
|
139
|
+
null
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Log.d(TAG, "User data: $user")
|
|
143
|
+
|
|
144
|
+
// Use the actual Nimbbl Android SDK to create order
|
|
145
|
+
// Set environment URL if provided
|
|
146
|
+
val apiBaseUrl = config["api_base_url"] as? String
|
|
147
|
+
if (!apiBaseUrl.isNullOrEmpty()) {
|
|
148
|
+
Log.d(TAG, "Setting environment URL: $apiBaseUrl")
|
|
149
|
+
NimbblCheckoutSDK.instance?.setEnvironmentUrl(apiBaseUrl)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Extract user details for order creation
|
|
153
|
+
val userEmail = user?.get("email") as? String ?: ""
|
|
154
|
+
val userName = user?.get("name") as? String ?: ""
|
|
155
|
+
val userMobile = user?.get("mobile_number") as? String ?: ""
|
|
156
|
+
|
|
157
|
+
Log.d(TAG, "User details:")
|
|
158
|
+
Log.d(TAG, " - email: $userEmail")
|
|
159
|
+
Log.d(TAG, " - name: $userName")
|
|
160
|
+
Log.d(TAG, " - mobile: $userMobile")
|
|
161
|
+
|
|
162
|
+
Log.d(TAG, "About to attempt Android SDK call")
|
|
163
|
+
println("About to attempt Android SDK call")
|
|
164
|
+
|
|
165
|
+
// Try to use the actual Android SDK for order creation
|
|
166
|
+
try {
|
|
167
|
+
Log.d(TAG, "Attempting to use Android SDK for order creation...")
|
|
168
|
+
println("Attempting to use Android SDK for order creation...")
|
|
169
|
+
|
|
170
|
+
// Get the API base URL from config
|
|
171
|
+
val apiBaseUrl = config["api_base_url"] as? String ?: "https://api.nimbbl.tech/"
|
|
172
|
+
Log.d(TAG, "Using API base URL: $apiBaseUrl")
|
|
173
|
+
println("Using API base URL: $apiBaseUrl")
|
|
174
|
+
|
|
175
|
+
Log.d(TAG, "Calling createOrder with parameters:")
|
|
176
|
+
Log.d(TAG, " - apiBaseUrl: $apiBaseUrl")
|
|
177
|
+
Log.d(TAG, " - amountString: $amountString")
|
|
178
|
+
Log.d(TAG, " - userEmail: $userEmail")
|
|
179
|
+
Log.d(TAG, " - userName: $userName")
|
|
180
|
+
Log.d(TAG, " - userMobile: $userMobile")
|
|
181
|
+
Log.d(TAG, " - productId: $productId")
|
|
182
|
+
Log.d(TAG, " - paymentMode: $paymentMode")
|
|
183
|
+
println("Calling createOrder with parameters:")
|
|
184
|
+
println(" - apiBaseUrl: $apiBaseUrl")
|
|
185
|
+
println(" - amountString: $amountString")
|
|
186
|
+
println(" - userEmail: $userEmail")
|
|
187
|
+
println(" - userName: $userName")
|
|
188
|
+
println(" - userMobile: $userMobile")
|
|
189
|
+
println(" - productId: $productId")
|
|
190
|
+
println(" - paymentMode: $paymentMode")
|
|
191
|
+
|
|
192
|
+
// Use direct method call with coroutine (since createOrder is a suspend function)
|
|
193
|
+
// Convert amount string to int
|
|
194
|
+
val amountInt = amountString.toIntOrNull() ?: 0
|
|
195
|
+
|
|
196
|
+
// Use coroutine to call suspend function
|
|
197
|
+
val orderResult = runBlocking {
|
|
198
|
+
NimbblOrderCreation.createOrder(
|
|
199
|
+
apiBaseUrl,
|
|
200
|
+
amountInt, // Use amount as int
|
|
201
|
+
userEmail,
|
|
202
|
+
userName,
|
|
203
|
+
userMobile,
|
|
204
|
+
productId,
|
|
205
|
+
paymentMode, // Use paymentMode as paymentModeCode
|
|
206
|
+
"" // bankCode (empty for now)
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
Log.d(TAG, "Order creation result: $orderResult")
|
|
211
|
+
println("Order creation result: $orderResult")
|
|
212
|
+
|
|
213
|
+
// The result should be a Response object
|
|
214
|
+
if (orderResult != null) {
|
|
215
|
+
Log.d(TAG, "Order result is not null, checking if successful...")
|
|
216
|
+
println("Order result is not null, checking if successful...")
|
|
217
|
+
|
|
218
|
+
// Check if the response is successful
|
|
219
|
+
if (orderResult.isSuccessful) {
|
|
220
|
+
Log.d(TAG, "Response is successful, getting body...")
|
|
221
|
+
println("Response is successful, getting body...")
|
|
222
|
+
|
|
223
|
+
// Get the response body
|
|
224
|
+
val responseBody = orderResult.body()
|
|
225
|
+
|
|
226
|
+
Log.d(TAG, "Response body: $responseBody")
|
|
227
|
+
println("Response body: $responseBody")
|
|
228
|
+
|
|
229
|
+
if (responseBody != null) {
|
|
230
|
+
Log.d(TAG, "Response body is not null, extracting token...")
|
|
231
|
+
println("Response body is not null, extracting token...")
|
|
232
|
+
|
|
233
|
+
// Extract token from response body
|
|
234
|
+
val token = responseBody.token
|
|
235
|
+
val orderId = responseBody.orderId
|
|
236
|
+
|
|
237
|
+
Log.d(TAG, "Extracted token: $token")
|
|
238
|
+
Log.d(TAG, "Extracted order ID: $orderId")
|
|
239
|
+
println("Extracted token: $token")
|
|
240
|
+
println("Extracted order ID: $orderId")
|
|
241
|
+
|
|
242
|
+
if (!token.isNullOrEmpty()) {
|
|
243
|
+
val result = Arguments.createMap().apply {
|
|
244
|
+
putString("order_id", orderId ?: "order_${System.currentTimeMillis()}")
|
|
245
|
+
putString("token", token)
|
|
246
|
+
putString("status", "created")
|
|
247
|
+
putDouble("amount", amount)
|
|
248
|
+
putString("currency", currency)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
Log.d(TAG, "Order created successfully with real token: $result")
|
|
252
|
+
println("Order created successfully with real token: $result")
|
|
253
|
+
promise.resolve(result)
|
|
254
|
+
return
|
|
255
|
+
} else {
|
|
256
|
+
Log.e(TAG, "Token is null or empty in response")
|
|
257
|
+
println("Token is null or empty in response")
|
|
258
|
+
promise.reject("INVALID_RESPONSE", "Token is null or empty in response")
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
Log.e(TAG, "Response body is null")
|
|
263
|
+
println("Response body is null")
|
|
264
|
+
promise.reject("INVALID_RESPONSE", "Response body is null")
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
// Get error body for logging
|
|
269
|
+
val errorBody = orderResult.errorBody()
|
|
270
|
+
Log.e(TAG, "Order creation failed, error body: $errorBody")
|
|
271
|
+
println("Order creation failed, error body: $errorBody")
|
|
272
|
+
promise.reject("ORDER_CREATION_FAILED", "Order creation failed: $errorBody")
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
} else {
|
|
276
|
+
Log.e(TAG, "Order creation result is null")
|
|
277
|
+
println("Order creation result is null")
|
|
278
|
+
promise.reject("ORDER_CREATION_FAILED", "Order creation result is null")
|
|
279
|
+
return
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
} catch (e: Exception) {
|
|
283
|
+
Log.e(TAG, "Android SDK order creation failed: ${e.message}", e)
|
|
284
|
+
println("Android SDK order creation failed: ${e.message}")
|
|
285
|
+
e.printStackTrace()
|
|
286
|
+
promise.reject("ORDER_CREATION_FAILED", "Android SDK order creation failed: ${e.message}")
|
|
287
|
+
return
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
} catch (e: Exception) {
|
|
291
|
+
Log.e(TAG, "Error creating shop order", e)
|
|
292
|
+
println("Error creating shop order: ${e.message}")
|
|
293
|
+
e.printStackTrace()
|
|
294
|
+
promise.reject("ORDER_CREATION_FAILED", e.message)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
@ReactMethod
|
|
301
|
+
fun checkout(options: ReadableMap, promise: Promise) {
|
|
302
|
+
Log.d(TAG, "=== CHECKOUT METHOD CALLED ===")
|
|
303
|
+
println("NimbblReactNativeSDK checkout method called")
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
if (!isInitialized) {
|
|
307
|
+
promise.reject("NOT_INITIALIZED", "SDK must be initialized before checkout")
|
|
308
|
+
return
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
Log.d(TAG, "Opening checkout with options: $options")
|
|
312
|
+
|
|
313
|
+
val orderToken = options.getString("order_token")
|
|
314
|
+
val paymentModeCode = options.getString("payment_mode_code") ?: ""
|
|
315
|
+
val bankCode = options.getString("bank_code") ?: ""
|
|
316
|
+
val walletCode = options.getString("wallet_code") ?: ""
|
|
317
|
+
val paymentFlow = options.getString("payment_flow") ?: ""
|
|
318
|
+
|
|
319
|
+
if (orderToken.isNullOrEmpty()) {
|
|
320
|
+
promise.reject("INVALID_OPTIONS", "Order token is required")
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
Log.d(TAG, "Building checkout options...")
|
|
325
|
+
|
|
326
|
+
// Get the current Activity
|
|
327
|
+
val currentActivity = reactContext.currentActivity
|
|
328
|
+
Log.d(TAG, "Current activity: $currentActivity")
|
|
329
|
+
|
|
330
|
+
if (currentActivity == null) {
|
|
331
|
+
Log.e(TAG, "Current activity is null!")
|
|
332
|
+
promise.reject("ACTIVITY_ERROR", "Current activity is null")
|
|
333
|
+
return
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Start the custom NimbblCheckoutActivity instead of trying to use MainActivity
|
|
337
|
+
Log.d(TAG, "Starting NimbblCheckoutActivity...")
|
|
338
|
+
println("Starting NimbblCheckoutActivity...")
|
|
339
|
+
try {
|
|
340
|
+
Log.d(TAG, "Creating intent for NimbblCheckoutActivity...")
|
|
341
|
+
println("Creating intent for NimbblCheckoutActivity...")
|
|
342
|
+
|
|
343
|
+
// Use startActivityForResult to properly handle callbacks
|
|
344
|
+
val intent = Intent(currentActivity, NimbblCheckoutActivity::class.java).apply {
|
|
345
|
+
putExtra(NimbblCheckoutActivity.EXTRA_ORDER_TOKEN, orderToken)
|
|
346
|
+
putExtra(NimbblCheckoutActivity.EXTRA_PAYMENT_MODE_CODE, paymentModeCode)
|
|
347
|
+
putExtra(NimbblCheckoutActivity.EXTRA_BANK_CODE, bankCode)
|
|
348
|
+
putExtra(NimbblCheckoutActivity.EXTRA_WALLET_CODE, walletCode)
|
|
349
|
+
putExtra(NimbblCheckoutActivity.EXTRA_PAYMENT_FLOW, paymentFlow)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Use a request code to identify this activity result
|
|
353
|
+
val REQUEST_CHECKOUT = 1001
|
|
354
|
+
currentActivity.startActivityForResult(intent, REQUEST_CHECKOUT)
|
|
355
|
+
|
|
356
|
+
Log.d(TAG, "NimbblCheckoutActivity started successfully")
|
|
357
|
+
println("NimbblCheckoutActivity started successfully")
|
|
358
|
+
} catch (e: Exception) {
|
|
359
|
+
Log.e(TAG, "Error starting NimbblCheckoutActivity: ${e.message}", e)
|
|
360
|
+
println("Error starting NimbblCheckoutActivity: ${e.message}")
|
|
361
|
+
e.printStackTrace()
|
|
362
|
+
promise.reject("CHECKOUT_FAILED", "Error starting checkout activity: ${e.message}")
|
|
363
|
+
return
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
val result = Arguments.createMap().apply {
|
|
367
|
+
putString("status", "checkout_opened")
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
promise.resolve(result)
|
|
371
|
+
|
|
372
|
+
} catch (e: Exception) {
|
|
373
|
+
Log.e(TAG, "Error during checkout", e)
|
|
374
|
+
promise.reject("CHECKOUT_FAILED", e.message)
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
private fun sendEvent(eventName: String, params: WritableMap?) {
|
|
380
|
+
try {
|
|
381
|
+
reactContext
|
|
382
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
383
|
+
.emit(eventName, params)
|
|
384
|
+
} catch (e: Exception) {
|
|
385
|
+
Log.e(TAG, "Error sending event: $eventName", e)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
override fun onActivityResult(activity: Activity?, requestCode: Int, resultCode: Int, data: Intent?) {
|
|
390
|
+
// Handle NimbblCheckoutActivity results
|
|
391
|
+
if (requestCode == 1001 && data != null) {
|
|
392
|
+
val status = data.getStringExtra("status")
|
|
393
|
+
|
|
394
|
+
when (status) {
|
|
395
|
+
"success" -> {
|
|
396
|
+
val params = Arguments.createMap().apply {
|
|
397
|
+
putString("status", "success")
|
|
398
|
+
putString("order_id", data.getStringExtra("order_id") ?: "")
|
|
399
|
+
putString("payment_id", data.getStringExtra("payment_id") ?: "")
|
|
400
|
+
putString("data", data.getStringExtra("response") ?: "")
|
|
401
|
+
}
|
|
402
|
+
sendEvent("payment_success", params)
|
|
403
|
+
}
|
|
404
|
+
"failed" -> {
|
|
405
|
+
val params = Arguments.createMap().apply {
|
|
406
|
+
putString("status", "failed")
|
|
407
|
+
putString("data", data.getStringExtra("response") ?: "")
|
|
408
|
+
}
|
|
409
|
+
sendEvent("payment_failed", params)
|
|
410
|
+
}
|
|
411
|
+
"cancelled" -> {
|
|
412
|
+
// Don't send cancelled event since back button is blocked
|
|
413
|
+
// Only success and failure events should be sent to the sample app
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
override fun onNewIntent(intent: Intent?) {
|
|
420
|
+
// Handle new intents if needed
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
override fun onCatalystInstanceDestroy() {
|
|
424
|
+
super.onCatalystInstanceDestroy()
|
|
425
|
+
reactContext.removeActivityEventListener(this)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.nimbbl.reactnative
|
|
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
|
+
class NimbblReactNativeSDKPackage : ReactPackage {
|
|
9
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
+
return listOf(NimbblReactNativeSDKModule(reactContext))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
14
|
+
return emptyList()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package com.nimbbl.reactnative
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.os.Bundle
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import android.widget.TextView
|
|
7
|
+
|
|
8
|
+
class TestActivity : Activity() {
|
|
9
|
+
|
|
10
|
+
companion object {
|
|
11
|
+
private const val TAG = "TestActivity"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
15
|
+
super.onCreate(savedInstanceState)
|
|
16
|
+
|
|
17
|
+
Log.d(TAG, "TestActivity onCreate called")
|
|
18
|
+
println("TestActivity onCreate called")
|
|
19
|
+
|
|
20
|
+
// Create a simple TextView
|
|
21
|
+
val textView = TextView(this)
|
|
22
|
+
textView.text = "Test Activity is working!"
|
|
23
|
+
setContentView(textView)
|
|
24
|
+
|
|
25
|
+
Log.d(TAG, "TestActivity setup complete")
|
|
26
|
+
println("TestActivity setup complete")
|
|
27
|
+
}
|
|
28
|
+
}
|
package/index.tsx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_MODULE(NimbblReactNativeSDK, NSObject)
|
|
4
|
+
|
|
5
|
+
RCT_EXTERN_METHOD(testModule:(RCTPromiseResolveBlock)resolve
|
|
6
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
7
|
+
|
|
8
|
+
RCT_EXTERN_METHOD(initialize:(NSDictionary *)config
|
|
9
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
10
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
11
|
+
|
|
12
|
+
RCT_EXTERN_METHOD(createShopOrder:(NSDictionary *)orderData
|
|
13
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
14
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
15
|
+
|
|
16
|
+
RCT_EXTERN_METHOD(checkout:(NSDictionary *)options
|
|
17
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
18
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
19
|
+
|
|
20
|
+
@end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'NimbblReactNativeSDK'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.homepage = package['homepage']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.platform = :ios, "13.0"
|
|
13
|
+
s.source = { :git => "https://github.com/nimbbl-tech/nimbbl_mobile_kit_react_native_sdk.git", :tag => "#{s.version}" }
|
|
14
|
+
s.source_files = "*.{h,m,swift}"
|
|
15
|
+
s.swift_version = '5.0'
|
|
16
|
+
s.requires_arc = true
|
|
17
|
+
|
|
18
|
+
s.dependency "React-Core"
|
|
19
|
+
|
|
20
|
+
# Nimbbl WebView SDK dependency (includes all necessary dependencies)
|
|
21
|
+
s.dependency "nimbbl_mobile_kit_ios_webview_sdk", "~> 1.0.12"
|
|
22
|
+
|
|
23
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
24
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
25
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
26
|
+
s.pod_target_xcconfig = {
|
|
27
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
28
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
29
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
30
|
+
}
|
|
31
|
+
s.dependency "React-RCTFabric"
|
|
32
|
+
s.dependency "React-Codegen"
|
|
33
|
+
s.dependency "RCT-Folly"
|
|
34
|
+
s.dependency "RCTRequired"
|
|
35
|
+
s.dependency "RCTTypeSafety"
|
|
36
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
37
|
+
end
|
|
38
|
+
end
|