From d41a303f6ad307009975d7964925ea3a3e392063 Mon Sep 17 00:00:00 2001 From: 25harsh Date: Fri, 14 Aug 2026 16:39:16 +0530 Subject: [PATCH] chore: turbo support --- .../android/build.gradle | 142 +++++++----------- .../android/gradle.properties | 7 +- .../android/src/main/AndroidManifestNew.xml | 2 + .../HyperswitchNetcetera3dsModule.kt | 20 +-- .../HyperswitchNetcetera3dsPackage.kt | 32 +++- .../HyperswitchNetcetera3dsSpec.kt | 6 + .../HyperswitchNetcetera3dsSpec.kt | 32 ++++ .../Source/HyperswitchChallengeManager.swift | 14 +- .../HyperswitchNetcetera3ds-Bridging-Header.h | 2 - .../ios/Source/HyperswitchNetcetera3ds.m | 31 ---- .../ios/Source/HyperswitchNetcetera3ds.mm | 100 ++++++++++++ .../ios/Source/HyperswitchNetcetera3ds.swift | 54 +++---- .../package.json | 51 ++++--- ...t-native-hyperswitch-netcetera-3ds.podspec | 41 ++--- .../src/NativeHyperswitchNetcetera3ds.ts | 43 ++++++ .../src/index.tsx | 60 ++++---- .../android/build.gradle | 31 ++++ ...ager.kt => PaypalButtonViewManagerImpl.kt} | 24 +-- .../ReactNativeHyperswitchPaypalModule.kt | 5 +- .../ReactNativeHyperswitchPaypalPackage.kt | 36 ++++- .../PaypalButtonViewManager.kt | 55 +++++++ .../ReactNativeHyperswitchPaypalSpec.kt | 6 + .../PaypalButtonViewManager.kt | 43 ++++++ .../ReactNativeHyperswitchPaypalSpec.kt | 11 ++ .../ios/PaypalButtonComponentView.mm | 75 +++++++++ .../ios/PaypalButtonView.swift | 18 +-- .../ios/ReactNativeHyperswitchPaypal.mm | 54 ++++++- .../ios/ReactNativeHyperswitchPaypal.swift | 12 +- .../package.json | 17 ++- .../src/NativeHyperswitchPaypal.ts | 18 +++ .../PaypalButtonNativeComponent.android.ts | 10 -- .../src/PaypalButtonNativeComponent.ts | 19 +++ .../src/codegen-shims.d.ts | 28 ++++ .../src/index.tsx | 16 +- .../android/build.gradle | 124 ++++++--------- .../android/src/main/AndroidManifestNew.xml | 2 + .../HyperswitchScancardModule.kt | 13 +- .../HyperswitchScancardPackage.kt | 34 ++++- .../HyperswitchScancardSpec.kt | 6 + .../HyperswitchScancardSpec.kt | 11 ++ .../HyperswitchScancard-Bridging-Header.h | 2 - .../ios/Source/HyperswitchScancard.m | 12 -- .../ios/Source/HyperswitchScancard.mm | 65 ++++++++ .../ios/Source/HyperswitchScancard.swift | 47 +++--- .../package.json | 18 ++- .../react-native-hyperswitch-scancard.podspec | 23 +-- .../src/NativeHyperswitchScancard.ts | 20 +++ .../src/index.tsx | 47 +++--- yarn.lock | 21 ++- 49 files changed, 1058 insertions(+), 502 deletions(-) create mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/AndroidManifestNew.xml create mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/newarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt create mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/oldarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt delete mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds-Bridging-Header.h delete mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.m create mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.mm create mode 100644 packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/NativeHyperswitchNetcetera3ds.ts rename packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/{PaypalButtonViewManager.kt => PaypalButtonViewManagerImpl.kt} (63%) create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonComponentView.mm create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/src/NativeHyperswitchPaypal.ts delete mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.android.ts create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.ts create mode 100644 packages/@juspay-tech/react-native-hyperswitch-paypal/src/codegen-shims.d.ts create mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/AndroidManifestNew.xml create mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/newarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt create mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/oldarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt delete mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard-Bridging-Header.h delete mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.m create mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.mm create mode 100644 packages/@juspay-tech/react-native-hyperswitch-scancard/src/NativeHyperswitchScancard.ts diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/build.gradle b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/build.gradle index 2fba887c..c8806404 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/build.gradle +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/build.gradle @@ -1,28 +1,29 @@ buildscript { - // Buildscript is evaluated before everything else so we can't use getExtOrDefault - def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['HyperswitchNetcetera3ds_kotlinVersion'] + ext.getExtOrDefault = {name -> + return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['HyperswitchNetcetera3ds_' + name] + } repositories { - google() - mavenCentral() + google() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath "com.android.tools.build:gradle:8.7.2" // noinspection DifferentKotlinGradleVersion - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}" } } def isNewArchitectureEnabled() { - return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" + return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" } -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' +apply plugin: "com.android.library" +apply plugin: "kotlin-android" if (isNewArchitectureEnabled()) { - apply plugin: 'com.facebook.react' + apply plugin: "com.facebook.react" } def getExtOrDefault(name) { @@ -33,14 +34,38 @@ def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['HyperswitchNetcetera3ds_' + name]).toInteger() } +def supportsNamespace() { + def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') + def major = parsed[0].toInteger() + def minor = parsed[1].toInteger() + + // Namespace support was added in 7.3.0 + return (major == 7 && minor >= 3) || major >= 8 +} + android { - compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') + if (supportsNamespace()) { + namespace "com.reactnativehyperswitchnetcetera3ds" + + sourceSets { + main { + manifest.srcFile "src/main/AndroidManifestNew.xml" + } + } + } + + compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") defaultConfig { - minSdkVersion getExtOrIntegerDefault('minSdkVersion') - targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') + minSdkVersion getExtOrIntegerDefault("minSdkVersion") + targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() } + + buildFeatures { + buildConfig true + } + buildTypes { release { minifyEnabled false @@ -48,96 +73,37 @@ android { } lintOptions { - disable 'GradleCompatible' + disable "GradleCompatible" } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ["src/newarch"] + } else { + java.srcDirs += ["src/oldarch"] + } + } } } repositories { mavenCentral() google() - - def found = false - def defaultDir = null - def androidSourcesName = 'React Native sources' - - if (rootProject.ext.has('reactNativeAndroidRoot')) { - defaultDir = rootProject.ext.get('reactNativeAndroidRoot') - } else { - defaultDir = new File( - projectDir, - '/../../../node_modules/react-native/android' - ) - } - - if (defaultDir.exists()) { - maven { - url defaultDir.toString() - name androidSourcesName - } - - logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}") - found = true - } else { - def parentDir = rootProject.projectDir - - 1.upto(5, { - if (found) return true - parentDir = parentDir.parentFile - - def androidSourcesDir = new File( - parentDir, - 'node_modules/react-native' - ) - - def androidPrebuiltBinaryDir = new File( - parentDir, - 'node_modules/react-native/android' - ) - - if (androidPrebuiltBinaryDir.exists()) { - maven { - url androidPrebuiltBinaryDir.toString() - name androidSourcesName - } - - logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}") - found = true - } else if (androidSourcesDir.exists()) { - maven { - url androidSourcesDir.toString() - name androidSourcesName - } - - logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}") - found = true - } - }) - } - - if (!found) { - throw new GradleException( - "${project.name}: unable to locate React Native android sources. " + - "Ensure you have you installed React Native as a dependency in your project and try again." - ) - } } -def kotlin_version = getExtOrDefault('kotlinVersion') +def kotlin_version = getExtOrDefault("kotlinVersion") dependencies { - //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:+" + implementation "com.facebook.react:react-android" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'io.hyperswitch:netcetra-3ds:2.5.2.0' - // TODO remove this + implementation "io.hyperswitch:netcetra-3ds:2.5.2.0" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.0" - -// From node_modules } if (isNewArchitectureEnabled()) { diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/gradle.properties b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/gradle.properties index 4d814534..65d832d9 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/gradle.properties +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/gradle.properties @@ -1,5 +1,4 @@ -HyperswitchNetcetera3ds_kotlinVersion=1.7.0 +HyperswitchNetcetera3ds_kotlinVersion=1.9.22 HyperswitchNetcetera3ds_minSdkVersion=21 -HyperswitchNetcetera3ds_targetSdkVersion=31 -HyperswitchNetcetera3ds_compileSdkVersion=31 -HyperswitchNetcetera3ds_ndkversion=21.4.7075529 +HyperswitchNetcetera3ds_targetSdkVersion=34 +HyperswitchNetcetera3ds_compileSdkVersion=35 diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/AndroidManifestNew.xml b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/AndroidManifestNew.xml new file mode 100644 index 00000000..a2f47b60 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/AndroidManifestNew.xml @@ -0,0 +1,2 @@ + + diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsModule.kt b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsModule.kt index 191b9909..04458d58 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsModule.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsModule.kt @@ -2,26 +2,24 @@ package com.reactnativehyperswitchnetcetera3ds import android.app.Activity import android.app.Application -import androidx.annotation.Nullable import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Callback import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod class HyperswitchNetcetera3dsModule(reactContext: ReactApplicationContext) : - ReactContextBaseJavaModule(reactContext) { + HyperswitchNetcetera3dsSpec(reactContext) { val hsNetceteraUtils = HsNetceteraUtils() val applicationContext = reactApplicationContext.applicationContext as Application private fun getActivity(): Activity? { return currentActivity ?: reactApplicationContext.currentActivity } override fun getName(): String { - return "HyperswitchNetcetera3ds" + return NAME } @ReactMethod - fun initialiseNetceteraSDK( + override fun initialiseNetceteraSDK( apiKey: String, hsSDKEnvironment: String, callback: Callback ) { @@ -40,18 +38,18 @@ class HyperswitchNetcetera3dsModule(reactContext: ReactApplicationContext) : } @ReactMethod - fun generateAReqParams( + override fun generateAReqParams( messageVersion: String, directoryServerId: String, callback: Callback ) { hsNetceteraUtils.generateAReqParams(getActivity(), messageVersion, directoryServerId, callback) } @ReactMethod - fun recieveChallengeParamsFromRN( + override fun recieveChallengeParamsFromRN( acsSignedContent: String, acsRefNumber: String, acsTransactionId: String, - @Nullable threeDSRequestorAppURL: String?, + threeDSRequestorAppURL: String?, threeDSServerTransId: String, callback: Callback ) { @@ -66,7 +64,11 @@ class HyperswitchNetcetera3dsModule(reactContext: ReactApplicationContext) : } @ReactMethod - fun generateChallenge(callback: Callback) { + override fun generateChallenge(callback: Callback) { hsNetceteraUtils.generateChallenge(getActivity(), 5, callback) } + + companion object { + const val NAME = "HyperswitchNetcetera3ds" + } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsPackage.kt b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsPackage.kt index d50626e2..26b1cc87 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsPackage.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/main/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsPackage.kt @@ -1,16 +1,34 @@ package com.reactnativehyperswitchnetcetera3ds -import com.facebook.react.ReactPackage +import com.facebook.react.TurboReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.uimanager.ViewManager +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.module.model.ReactModuleInfoProvider -class HyperswitchNetcetera3dsPackage : ReactPackage { - override fun createNativeModules(reactContext: ReactApplicationContext): List { - return listOf(HyperswitchNetcetera3dsModule(reactContext)) +class HyperswitchNetcetera3dsPackage : TurboReactPackage() { + override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { + return if (name == HyperswitchNetcetera3dsModule.NAME) { + HyperswitchNetcetera3dsModule(reactContext) + } else { + null } + } - override fun createViewManagers(reactContext: ReactApplicationContext): List> { - return emptyList() + override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { + return ReactModuleInfoProvider { + val moduleInfos: MutableMap = HashMap() + val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + moduleInfos[HyperswitchNetcetera3dsModule.NAME] = ReactModuleInfo( + HyperswitchNetcetera3dsModule.NAME, + HyperswitchNetcetera3dsModule.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule + ) + moduleInfos } + } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/newarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/newarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt new file mode 100644 index 00000000..c9b46e93 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/newarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt @@ -0,0 +1,6 @@ +package com.reactnativehyperswitchnetcetera3ds + +import com.facebook.react.bridge.ReactApplicationContext + +abstract class HyperswitchNetcetera3dsSpec internal constructor(context: ReactApplicationContext) : + NativeHyperswitchNetcetera3dsSpec(context) diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/oldarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/oldarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt new file mode 100644 index 00000000..3eaea3a0 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/android/src/oldarch/java/com/reactnativehyperswitchnetcetera3ds/HyperswitchNetcetera3dsSpec.kt @@ -0,0 +1,32 @@ +package com.reactnativehyperswitchnetcetera3ds + +import com.facebook.react.bridge.Callback +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule + +abstract class HyperswitchNetcetera3dsSpec internal constructor(context: ReactApplicationContext) : + ReactContextBaseJavaModule(context) { + + abstract fun initialiseNetceteraSDK( + apiKey: String, + hsSDKEnvironment: String, + callback: Callback + ) + + abstract fun generateAReqParams( + messageVersion: String, + directoryServerId: String, + callback: Callback + ) + + abstract fun recieveChallengeParamsFromRN( + acsSignedContent: String, + acsRefNumber: String, + acsTransactionId: String, + threeDSRequestorAppURL: String?, + threeDSServerTransId: String, + callback: Callback + ) + + abstract fun generateChallenge(callback: Callback) +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchChallengeManager.swift b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchChallengeManager.swift index 99fab6f1..127ac401 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchChallengeManager.swift +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchChallengeManager.swift @@ -10,10 +10,10 @@ import ThreeDS_SDK class HyperswitchChallengeManager: ChallengeStatusReceiver { - var postChallengeCallback: RCTResponseSenderBlock? + var postChallengeCallback: (([String: Any]) -> Void)? var map: [String: Any] = [:] - func setPostHSChallengeCallback(_ callback: @escaping RCTResponseSenderBlock) { + func setPostHSChallengeCallback(_ callback: @escaping ([String: Any]) -> Void) { self.postChallengeCallback = callback } @@ -21,21 +21,21 @@ class HyperswitchChallengeManager: ChallengeStatusReceiver { // Handle successful or unsuccessful completion of challenge flow map["status"] = "success"; map["message"] = "challenge completed successfully"; - postChallengeCallback?([map]); + postChallengeCallback?(map); } func cancelled() { // Handle challenge canceled by the user map["status"] = "error"; map["message"] = "challenge cancelled by user"; - postChallengeCallback?([map]); + postChallengeCallback?(map); } func timedout() { // Handle challenge timeout map["status"] = "error"; map["message"] = "challenge timeout"; - postChallengeCallback?([map]); + postChallengeCallback?(map); } func protocolError(protocolErrorEvent: ProtocolErrorEvent) { @@ -69,7 +69,7 @@ class HyperswitchChallengeManager: ChallengeStatusReceiver { map["status"] = "error"; map["message"] = message; - postChallengeCallback?([map]); + postChallengeCallback?(map); } func runtimeError(runtimeErrorEvent: RuntimeErrorEvent) { @@ -83,7 +83,7 @@ class HyperswitchChallengeManager: ChallengeStatusReceiver { map["status"] = "error"; map["message"] = message; - postChallengeCallback?([map]); + postChallengeCallback?(map); } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds-Bridging-Header.h b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds-Bridging-Header.h deleted file mode 100644 index dea7ff6b..00000000 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds-Bridging-Header.h +++ /dev/null @@ -1,2 +0,0 @@ -#import -#import diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.m b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.m deleted file mode 100644 index 1db39e92..00000000 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.m +++ /dev/null @@ -1,31 +0,0 @@ -#import - -@interface RCT_EXTERN_MODULE(HyperswitchNetcetera3ds, NSObject) - - -RCT_EXTERN_METHOD(initialiseNetceteraSDK: - (NSString *)apiKey: - (NSString *)hsSDKEnvironment: - (RCTResponseSenderBlock)callback) - -RCT_EXTERN_METHOD(generateAReqParams: - (NSString *)messageVersion: - (NSString *)directoryServerId: - (RCTResponseSenderBlock)callback) - -RCT_EXTERN_METHOD(recieveChallengeParamsFromRN: - (NSString *)acsSignedContent: - (NSString *)acsRefNumber: - (NSString *)acsTransactionId: - (nullable NSString *)threeDSRequestorAppURL: - (NSString *)threeDSServerTransId: - (RCTResponseSenderBlock)callback) - -RCT_EXTERN_METHOD(generateChallenge: (RCTResponseSenderBlock)callback) - -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} - -@end diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.mm b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.mm new file mode 100644 index 00000000..ceb6a285 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.mm @@ -0,0 +1,100 @@ +#import +#import + +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNHyperswitchNetcetera3dsSpec.h" +#endif + +#if __has_include() +#import +#else +#import "react_native_hyperswitch_netcetera_3ds-Swift.h" +#endif + +@interface HyperswitchNetcetera3ds : NSObject +@end + +#ifdef RCT_NEW_ARCH_ENABLED +@interface HyperswitchNetcetera3ds () +@end +#endif + +@implementation HyperswitchNetcetera3ds { + HyperswitchNetcetera3dsImpl *_impl; +} + +RCT_EXPORT_MODULE() + +- (instancetype)init +{ + if (self = [super init]) { + _impl = [HyperswitchNetcetera3dsImpl new]; + } + return self; +} + ++ (BOOL)requiresMainQueueSetup +{ + return NO; +} + +RCT_EXPORT_METHOD(initialiseNetceteraSDK:(NSString *)apiKey + hsSDKEnvironment:(NSString *)hsSDKEnvironment + callback:(RCTResponseSenderBlock)callback) +{ + [self->_impl initialiseNetceteraSDK:apiKey + hsSDKEnvironment:hsSDKEnvironment + callback:^(NSDictionary *status) { + callback(@[ status ]); + }]; +} + +RCT_EXPORT_METHOD(generateAReqParams:(NSString *)messageVersion + directoryServerId:(NSString *)directoryServerId + callback:(RCTResponseSenderBlock)callback) +{ + dispatch_async(dispatch_get_main_queue(), ^{ + UIViewController *presentedViewController = RCTPresentedViewController(); + [self->_impl generateAReqParams:messageVersion + directoryServerId:directoryServerId + from:presentedViewController + callback:^(NSDictionary *status, + NSDictionary *aReqParams) { + callback(aReqParams ? @[ status, aReqParams ] : @[ status ]); + }]; + }); +} + +RCT_EXPORT_METHOD(recieveChallengeParamsFromRN:(NSString *)acsSignedContent + acsRefNumber:(NSString *)acsRefNumber + acsTransactionId:(NSString *)acsTransactionId + threeDSRequestorAppURL:(nullable NSString *)threeDSRequestorAppURL + threeDSServerTransId:(NSString *)threeDSServerTransId + callback:(RCTResponseSenderBlock)callback) +{ + [self->_impl recieveChallengeParamsFromRN:acsSignedContent + acsRefNumber:acsRefNumber + acsTransactionId:acsTransactionId + threeDSRequestorAppURL:threeDSRequestorAppURL + threeDSServerTransId:threeDSServerTransId + callback:^(NSDictionary *status) { + callback(@[ status ]); + }]; +} + +RCT_EXPORT_METHOD(generateChallenge:(RCTResponseSenderBlock)callback) +{ + [self->_impl generateChallenge:^(NSDictionary *status) { + callback(@[ status ]); + }]; +} + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif + +@end diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.swift b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.swift index 0df444f2..715d4b83 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.swift +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/ios/Source/HyperswitchNetcetera3ds.swift @@ -6,10 +6,10 @@ // import Foundation +import UIKit import ThreeDS_SDK -@objc(HyperswitchNetcetera3ds) -class HyperswitchNetcetera3ds: NSObject { +@objc public class HyperswitchNetcetera3dsImpl: NSObject { private let challengeStatusReceiver: HyperswitchChallengeManager = HyperswitchChallengeManager() private let threeDS2Service: ThreeDS2Service = ThreeDS2ServiceSDK() @@ -22,9 +22,9 @@ class HyperswitchNetcetera3ds: NSObject { private var hsSDKEnvironment: String? @objc - func initialiseNetceteraSDK(_ apiKey: String, - _ hsSDKEnvironment: String, - _ callback: @escaping RCTResponseSenderBlock) { + public func initialiseNetceteraSDK(_ apiKey: String, + hsSDKEnvironment: String, + callback: @escaping ([String: Any]) -> Void) { var initStatus: [String:Any] = [:]; do { @@ -66,7 +66,7 @@ class HyperswitchNetcetera3ds: NSObject { guard let configParams = self.configParams else { initStatus["status"] = "failure"; initStatus["message"] = "netcetera sdk initialization failed"; - callback([initStatus]); + callback(initStatus) return } @@ -76,18 +76,18 @@ class HyperswitchNetcetera3ds: NSObject { success: { initStatus["status"] = "success" initStatus["message"] = "netcetera sdk initialization successful" - callback([initStatus]) + callback(initStatus) }, failure: { error in if (error.localizedDescription == "The SDK is already initialized") { initStatus["status"] = "success"; initStatus["message"] = "netcetera sdk initialization successful"; - callback([initStatus]); + callback(initStatus) } else{ initStatus["status"] = "failure"; initStatus["message"] = "netcetera sdk initialization failed"; - callback([initStatus]); + callback(initStatus) } }) } @@ -95,23 +95,23 @@ class HyperswitchNetcetera3ds: NSObject { var errMap: [String:Any] = [:]; errMap["status"] = "failure"; errMap["message"] = "Initialization failed:" + error.localizedDescription; - callback([errMap]); + callback(errMap) return } } @objc - func generateAReqParams(_ messageVersion: String, - _ directoryServerId: String, - _ callback: @escaping RCTResponseSenderBlock) { - + public func generateAReqParams(_ messageVersion: String, + directoryServerId: String, + from viewController: UIViewController?, + callback: @escaping ([String: Any], [String: String]?) -> Void) { DispatchQueue.main.async { do { //MARK: dont send nil here try [:] let transaction = try self.threeDS2Service.createTransaction(directoryServerId: directoryServerId, messageVersion: messageVersion) self.transaction = transaction - self.vc = RCTPresentedViewController() + self.vc = viewController self.progressView = try self.transaction?.getProgressView() let authenticationParameters = try transaction.getAuthenticationRequestParameters() @@ -126,23 +126,23 @@ class HyperswitchNetcetera3ds: NSObject { var statusMap: [String: Any] = [:] statusMap["status"] = "success" statusMap["message"] = "AReq Params generation successful" - callback([statusMap, authReqMap]) + callback(statusMap, authReqMap) } catch let error as NSError { //MARK: don't send nil here try [:] var statusMap: [String: Any] = [:] statusMap["status"] = "error" statusMap["message"] = "AReq Params generation failure. Error: \(error)" - callback([statusMap]) + callback(statusMap, nil) } } } @objc - func recieveChallengeParamsFromRN(_ acsSignedContent: String, - _ acsRefNumber: String, - _ acsTransactionId: String, - _ threeDSRequestorAppURL: String?, - _ threeDSServerTransId: String, - _ callback: @escaping RCTResponseSenderBlock) { + public func recieveChallengeParamsFromRN(_ acsSignedContent: String, + acsRefNumber: String, + acsTransactionId: String, + threeDSRequestorAppURL: String?, + threeDSServerTransId: String, + callback: @escaping ([String: Any]) -> Void) { let challengeParameters = ChallengeParameters( threeDSServerTransactionID: threeDSServerTransId, acsTransactionID: acsTransactionId, @@ -157,11 +157,11 @@ class HyperswitchNetcetera3ds: NSObject { var statusMap: [String:Any] = [:] statusMap["status"] = "success" statusMap["message"] = "challenge params receive successful" - callback([statusMap]) + callback(statusMap) } @objc - func generateChallenge(_ callback: @escaping RCTResponseSenderBlock) { + public func generateChallenge(_ callback: @escaping ([String: Any]) -> Void) { challengeStatusReceiver.setPostHSChallengeCallback(callback) DispatchQueue.global().async { @@ -173,7 +173,7 @@ class HyperswitchNetcetera3ds: NSObject { var map: [String: String] = [:] map["status"] = "error" map["message"] = "doChallenge call unsuccessful" - callback([map]) + callback(map) return } @@ -187,7 +187,7 @@ class HyperswitchNetcetera3ds: NSObject { var map: [String: String] = [:] map["status"] = "error" map["message"] = err.localizedDescription - callback([map]) + callback(map) } } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/package.json b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/package.json index d5a57bc9..4179280c 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/package.json +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/package.json @@ -1,10 +1,10 @@ { "name": "@juspay-tech/react-native-hyperswitch-netcetera-3ds", - "version": "0.2.2", + "version": "0.3.0", "description": "React Native Hyperswitch Netcetera 3DS", - "main": "lib/commonjs/index", - "module": "lib/module/index", - "types": "lib/typescript/index.d.ts", + "main": "./lib/module/index.js", + "module": "./lib/module/index.js", + "types": "./lib/typescript/src/index.d.ts", "react-native": "src/index", "source": "src/index", "files": [ @@ -49,24 +49,21 @@ "author": "Hyperswitch", "license": "Apache-2.0", "devDependencies": { - "@arkweid/lefthook": "^0.7.7", - "@babel/eslint-parser": "^7.18.2", "@commitlint/config-conventional": "^17.0.2", - "@react-native-community/eslint-config": "^3.0.2", + "@react-native/babel-preset": "0.81.1", "@release-it/conventional-changelog": "^10.0.1", - "@types/jest": "^28.1.2", - "@types/react": "~17.0.21", - "@types/react-native": "0.68.0", + "@types/jest": "^29.5.14", + "@types/react": "^19.1.0", "commitlint": "^17.0.2", "eslint": "^8.4.1", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", - "jest": "^28.1.1", + "jest": "^29.7.0", "pod-install": "^0.1.0", "prettier": "^2.0.5", - "react": "17.0.2", - "react-native": "0.68.2", - "react-native-builder-bob": "^0.18.3", + "react": "19.1.0", + "react-native": "0.81.1", + "react-native-builder-bob": "^0.40.13", "release-it": "^19.0.5", "typescript": "^5.9.2" }, @@ -75,7 +72,7 @@ }, "peerDependencies": { "react": "*", - "react-native": "*" + "react-native": ">=0.72.0" }, "jest": { "preset": "react-native", @@ -88,8 +85,12 @@ "source": "src", "output": "lib", "targets": [ - "commonjs", - "module", + [ + "module", + { + "esm": true + } + ], [ "typescript", { @@ -100,5 +101,21 @@ }, "publishConfig": { "access": "public" + }, + "exports": { + ".": { + "source": "./src/index.tsx", + "types": "./lib/typescript/src/index.d.ts", + "default": "./lib/module/index.js" + }, + "./package.json": "./package.json" + }, + "codegenConfig": { + "name": "RNHyperswitchNetcetera3dsSpec", + "type": "modules", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.reactnativehyperswitchnetcetera3ds" + } } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/react-native-hyperswitch-netcetera-3ds.podspec b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/react-native-hyperswitch-netcetera-3ds.podspec index 1c893566..f82d66e9 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/react-native-hyperswitch-netcetera-3ds.podspec +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/react-native-hyperswitch-netcetera-3ds.podspec @@ -1,36 +1,21 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' Pod::Spec.new do |s| - s.name = "react-native-hyperswitch-netcetera-3ds" - s.version = package["version"] - s.summary = package["description"] - s.homepage = package["homepage"] - s.license = package["license"] - s.authors = package["author"] + s.name = "react-native-hyperswitch-netcetera-3ds" + s.version = package["version"] + s.summary = package["description"] + s.homepage = package["homepage"] + s.license = package["license"] + s.authors = package["author"] - s.platforms = { :ios => "10.0" } - s.source = { :git => "https://github.com/juspay/react-native-hyperswitch-libraries.git", :branch => "main" } - - s.source_files = "ios/Source/**/*.{h,m,mm,swift}" - s.vendored_frameworks = "ios/Frameworks/ThreeDS_SDK.xcframework" + s.platforms = { :ios => "13.4" } + s.swift_version = '5.0' + s.requires_arc = true + s.source = { :git => "https://github.com/juspay/react-native-hyperswitch-libraries.git", :branch => "main" } + s.source_files = "ios/Source/**/*.{h,m,mm,swift}" + s.vendored_frameworks = "ios/Frameworks/ThreeDS_SDK.xcframework" - s.dependency "React-Core" - - # Don't install the dependencies when we run `pod install` in the old architecture. - if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then - s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" - s.pod_target_xcconfig = { - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", - "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" - } - - s.dependency "React-Codegen" - s.dependency "RCT-Folly" - s.dependency "RCTRequired" - s.dependency "RCTTypeSafety" - s.dependency "ReactCommon/turbomodule/core" - end + install_modules_dependencies(s) end diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/NativeHyperswitchNetcetera3ds.ts b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/NativeHyperswitchNetcetera3ds.ts new file mode 100644 index 00000000..72b17f3b --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/NativeHyperswitchNetcetera3ds.ts @@ -0,0 +1,43 @@ +import type {TurboModule} from 'react-native'; +import {TurboModuleRegistry} from 'react-native'; + +export type NetceteraStatus = { + status: string; + message: string; +}; + +export type NetceteraAReqParams = { + deviceData: string; + messageVersion: string; + sdkTransId: string; + sdkAppId: string; + sdkEphemeralKey: string; + sdkReferenceNo: string; +}; + +export interface Spec extends TurboModule { + initialiseNetceteraSDK( + apiKey: string, + hsSDKEnvironment: string, + callback: (status: NetceteraStatus) => void + ): void; + // Native invokes the callback with (status, aReqParams) in that order. + generateAReqParams( + messageVersion: string, + directoryServerId: string, + callback: (status: NetceteraStatus, aReqParams: NetceteraAReqParams) => void + ): void; + // Parameter order matches the native method (threeDSRequestorAppURL comes + // before threeDSServerTransId); the public JS wrapper reorders. + recieveChallengeParamsFromRN( + acsSignedContent: string, + acsRefNumber: string, + acsTransactionId: string, + threeDSRequestorAppURL: string | null, + threeDSServerTransId: string, + callback: (status: NetceteraStatus) => void + ): void; + generateChallenge(callback: (status: NetceteraStatus) => void): void; +} + +export default TurboModuleRegistry.get('HyperswitchNetcetera3ds'); diff --git a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/index.tsx b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/index.tsx index 725ebccc..a42e3f6e 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/index.tsx +++ b/packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds/src/index.tsx @@ -1,15 +1,30 @@ -import { NativeModules } from 'react-native'; +import NativeHyperswitchNetcetera3ds from './NativeHyperswitchNetcetera3ds'; -const HyperswitchNetcetera3ds = NativeModules.HyperswitchNetcetera3ds || null; -const isAvailable = - HyperswitchNetcetera3ds && HyperswitchNetcetera3ds.initialiseNetceteraSDK; +// TurboModuleRegistry.get resolves the TurboModule on the new architecture +// and falls back to the legacy NativeModules entry on the old architecture, +// so this single code path supports both. +const isAvailable = NativeHyperswitchNetcetera3ds != null; + +export type statusType = { + status: string; + message: string; +}; + +export type AReqParams = { + deviceData: string; + messageVersion: string; + sdkTransId: string; + sdkAppId: string; + sdkEphemeralKey: any; + sdkReferenceNo: string; +}; function initialiseNetceteraSDK( apiKey: string, hsSDKEnvironment: string, callback: (status: statusType) => void ) { - return HyperswitchNetcetera3ds.initialiseNetceteraSDK( + return NativeHyperswitchNetcetera3ds?.initialiseNetceteraSDK( apiKey, hsSDKEnvironment, callback @@ -19,9 +34,9 @@ function initialiseNetceteraSDK( function generateAReqParams( messageVersion: string, directoryServerId: string, - callback: (aReqParams: AReqParams, status: statusType) => void + callback: (status: statusType, aReqParams: AReqParams) => void ) { - return HyperswitchNetcetera3ds.generateAReqParams( + return NativeHyperswitchNetcetera3ds?.generateAReqParams( messageVersion, directoryServerId, callback @@ -29,40 +44,27 @@ function generateAReqParams( } function recieveChallengeParamsFromRN( - acsSignedContent: String, - acsRefNumber: String, - acsTransactionId: String, - threeDSServerTransId: String, + acsSignedContent: string, + acsRefNumber: string, + acsTransactionId: string, + threeDSServerTransId: string, callback: (status: statusType) => void, - threeDSRequestorAppURL?: String + threeDSRequestorAppURL?: string ) { - return HyperswitchNetcetera3ds.recieveChallengeParamsFromRN( + return NativeHyperswitchNetcetera3ds?.recieveChallengeParamsFromRN( acsSignedContent, acsRefNumber, acsTransactionId, - threeDSRequestorAppURL, + threeDSRequestorAppURL ?? null, threeDSServerTransId, callback ); } + function generateChallenge(callback: (status: statusType) => void) { - return HyperswitchNetcetera3ds.generateChallenge(callback); + return NativeHyperswitchNetcetera3ds?.generateChallenge(callback); } -export type statusType = { - status: string; - message: string; -}; - -export type AReqParams = { - deviceData: string; - messageVersion: string; - sdkTransId: string; - sdkAppId: string; - sdkEphemeralKey: any; - sdkReferenceNo: string; -}; - export { isAvailable, initialiseNetceteraSDK, diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/build.gradle b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/build.gradle index 868fdd50..3c7f4b34 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/build.gradle +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/build.gradle @@ -16,9 +16,17 @@ buildscript { } +def isNewArchitectureEnabled() { + return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" +} + apply plugin: "com.android.library" apply plugin: "kotlin-android" +if (isNewArchitectureEnabled()) { + apply plugin: "com.facebook.react" +} + def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeHyperswitchPaypal_" + name]).toInteger() @@ -32,6 +40,11 @@ android { defaultConfig { minSdkVersion getExtOrIntegerDefault("minSdkVersion") targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + } + + buildFeatures { + buildConfig true } buildTypes { @@ -52,6 +65,16 @@ android { kotlinOptions { jvmTarget = '17' } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ["src/newarch"] + } else { + java.srcDirs += ["src/oldarch"] + } + } + } } repositories { @@ -67,3 +90,11 @@ dependencies { implementation "com.paypal.android:paypal-web-payments:2.3.0" implementation "com.paypal.android:payment-buttons:2.3.0" } + +if (isNewArchitectureEnabled()) { + react { + jsRootDir = file("../src/") + libraryName = "HyperswitchPaypal" + codegenJavaPackageName = "com.juspaytech.reactnativehyperswitchpaypal" + } +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManagerImpl.kt similarity index 63% rename from packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt rename to packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManagerImpl.kt index 741bc780..e58a4eff 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManagerImpl.kt @@ -1,30 +1,21 @@ package com.juspaytech.reactnativehyperswitchpaypal -import com.facebook.react.module.annotations.ReactModule -import com.facebook.react.uimanager.SimpleViewManager import com.facebook.react.uimanager.ThemedReactContext -import com.facebook.react.uimanager.annotations.ReactProp import com.paypal.android.paymentbuttons.PayPalButtonColor import com.paypal.android.paymentbuttons.PayPalButtonLabel import com.paypal.android.paymentbuttons.PaymentButtonSize -@ReactModule(name = PaypalButtonViewManager.NAME) -class PaypalButtonViewManager : SimpleViewManager() { +object PaypalButtonViewManagerImpl { + const val NAME = "PaypalButton" - override fun getName(): String { - return NAME - } - - public override fun createViewInstance(context: ThemedReactContext): PaypalButtonView { + fun createViewInstance(context: ThemedReactContext): PaypalButtonView { return PaypalButtonView(context) } - public override fun onAfterUpdateTransaction(view: PaypalButtonView) { - super.onAfterUpdateTransaction(view) + fun onAfterUpdateTransaction(view: PaypalButtonView) { view.addButton() } - @ReactProp(name = "buttonColor") fun setButtonColor(view: PaypalButtonView, value: String?) { view.buttonColor = when (value) { "GOLD" -> PayPalButtonColor.GOLD @@ -36,7 +27,6 @@ class PaypalButtonViewManager : SimpleViewManager() { } } - @ReactProp(name = "buttonLabel") fun setButtonLabel(view: PaypalButtonView, value: String?) { view.buttonLabel = when (value) { "CHECKOUT" -> PayPalButtonLabel.CHECKOUT @@ -46,7 +36,6 @@ class PaypalButtonViewManager : SimpleViewManager() { } } - @ReactProp(name = "buttonSize") fun setButtonSize(view: PaypalButtonView, value: String?) { view.buttonSize = when (value) { "SMALL" -> PaymentButtonSize.SMALL @@ -55,12 +44,7 @@ class PaypalButtonViewManager : SimpleViewManager() { } } - @ReactProp(name = "borderRadius", defaultDouble = 0.0) fun setBorderRadius(view: PaypalButtonView, value: Double) { view.customCornerRadius = value.toFloat() } - - companion object { - const val NAME = "PaypalButton" - } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalModule.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalModule.kt index bcf144c2..88b13604 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalModule.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalModule.kt @@ -6,13 +6,12 @@ import android.os.Looper import android.util.Log import com.facebook.react.bridge.Callback import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.WritableNativeMap import org.json.JSONObject class ReactNativeHyperswitchPaypalModule(reactContext: ReactApplicationContext) : - ReactContextBaseJavaModule(reactContext), + ReactNativeHyperswitchPaypalSpec(reactContext), PayPalPendingResult.PayPalResultCallback { private var currentCallback: Callback? = null @@ -21,7 +20,7 @@ class ReactNativeHyperswitchPaypalModule(reactContext: ReactApplicationContext) override fun getName(): String = NAME @ReactMethod - fun launchPayPal(requestObj: String, callback: Callback) { + override fun launchPayPal(requestObj: String, callback: Callback) { try { val json = JSONObject(requestObj) diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalPackage.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalPackage.kt index b140a2c5..2d4a9e62 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalPackage.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/main/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalPackage.kt @@ -1,17 +1,41 @@ package com.juspaytech.reactnativehyperswitchpaypal -import android.util.Log -import com.facebook.react.ReactPackage +import com.facebook.react.TurboReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.module.model.ReactModuleInfoProvider import com.facebook.react.uimanager.ViewManager -class ReactNativeHyperswitchPaypalPackage : ReactPackage { - override fun createNativeModules(reactContext: ReactApplicationContext): List { - return listOf(ReactNativeHyperswitchPaypalModule(reactContext)) +class ReactNativeHyperswitchPaypalPackage : TurboReactPackage() { + override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { + return if (name == ReactNativeHyperswitchPaypalModule.NAME) { + ReactNativeHyperswitchPaypalModule(reactContext) + } else { + null + } } - override fun createViewManagers(reactContext: ReactApplicationContext): List> { + override fun createViewManagers( + reactContext: ReactApplicationContext + ): List> { return listOf(PaypalButtonViewManager()) } + + override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { + return ReactModuleInfoProvider { + val moduleInfos: MutableMap = HashMap() + val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + moduleInfos[ReactNativeHyperswitchPaypalModule.NAME] = ReactModuleInfo( + ReactNativeHyperswitchPaypalModule.NAME, + ReactNativeHyperswitchPaypalModule.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule + ) + moduleInfos + } + } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt new file mode 100644 index 00000000..a3c73124 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt @@ -0,0 +1,55 @@ +package com.juspaytech.reactnativehyperswitchpaypal + +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.SimpleViewManager +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.ViewManagerDelegate +import com.facebook.react.uimanager.annotations.ReactProp +import com.facebook.react.viewmanagers.PaypalButtonManagerDelegate +import com.facebook.react.viewmanagers.PaypalButtonManagerInterface + +@ReactModule(name = PaypalButtonViewManagerImpl.NAME) +class PaypalButtonViewManager : + SimpleViewManager(), + PaypalButtonManagerInterface { + + private val delegate: ViewManagerDelegate = + PaypalButtonManagerDelegate(this) + + override fun getDelegate(): ViewManagerDelegate { + return delegate + } + + override fun getName(): String { + return PaypalButtonViewManagerImpl.NAME + } + + public override fun createViewInstance(context: ThemedReactContext): PaypalButtonView { + return PaypalButtonViewManagerImpl.createViewInstance(context) + } + + public override fun onAfterUpdateTransaction(view: PaypalButtonView) { + super.onAfterUpdateTransaction(view) + PaypalButtonViewManagerImpl.onAfterUpdateTransaction(view) + } + + @ReactProp(name = "buttonColor") + override fun setButtonColor(view: PaypalButtonView, value: String?) { + PaypalButtonViewManagerImpl.setButtonColor(view, value) + } + + @ReactProp(name = "buttonLabel") + override fun setButtonLabel(view: PaypalButtonView, value: String?) { + PaypalButtonViewManagerImpl.setButtonLabel(view, value) + } + + @ReactProp(name = "buttonSize") + override fun setButtonSize(view: PaypalButtonView, value: String?) { + PaypalButtonViewManagerImpl.setButtonSize(view, value) + } + + @ReactProp(name = "borderRadius", defaultDouble = 0.0) + override fun setBorderRadius(view: PaypalButtonView, value: Double) { + PaypalButtonViewManagerImpl.setBorderRadius(view, value) + } +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt new file mode 100644 index 00000000..5c4da2a3 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/newarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt @@ -0,0 +1,6 @@ +package com.juspaytech.reactnativehyperswitchpaypal + +import com.facebook.react.bridge.ReactApplicationContext + +abstract class ReactNativeHyperswitchPaypalSpec internal constructor(context: ReactApplicationContext) : + NativeHyperswitchPaypalSpec(context) diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt new file mode 100644 index 00000000..6d784ac3 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/PaypalButtonViewManager.kt @@ -0,0 +1,43 @@ +package com.juspaytech.reactnativehyperswitchpaypal + +import com.facebook.react.module.annotations.ReactModule +import com.facebook.react.uimanager.SimpleViewManager +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.annotations.ReactProp + +@ReactModule(name = PaypalButtonViewManagerImpl.NAME) +class PaypalButtonViewManager : SimpleViewManager() { + + override fun getName(): String { + return PaypalButtonViewManagerImpl.NAME + } + + public override fun createViewInstance(context: ThemedReactContext): PaypalButtonView { + return PaypalButtonViewManagerImpl.createViewInstance(context) + } + + public override fun onAfterUpdateTransaction(view: PaypalButtonView) { + super.onAfterUpdateTransaction(view) + PaypalButtonViewManagerImpl.onAfterUpdateTransaction(view) + } + + @ReactProp(name = "buttonColor") + fun setButtonColor(view: PaypalButtonView, value: String?) { + PaypalButtonViewManagerImpl.setButtonColor(view, value) + } + + @ReactProp(name = "buttonLabel") + fun setButtonLabel(view: PaypalButtonView, value: String?) { + PaypalButtonViewManagerImpl.setButtonLabel(view, value) + } + + @ReactProp(name = "buttonSize") + fun setButtonSize(view: PaypalButtonView, value: String?) { + PaypalButtonViewManagerImpl.setButtonSize(view, value) + } + + @ReactProp(name = "borderRadius", defaultDouble = 0.0) + fun setBorderRadius(view: PaypalButtonView, value: Double) { + PaypalButtonViewManagerImpl.setBorderRadius(view, value) + } +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt new file mode 100644 index 00000000..5984d963 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/android/src/oldarch/java/com/juspaytech/reactnativehyperswitchpaypal/ReactNativeHyperswitchPaypalSpec.kt @@ -0,0 +1,11 @@ +package com.juspaytech.reactnativehyperswitchpaypal + +import com.facebook.react.bridge.Callback +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule + +abstract class ReactNativeHyperswitchPaypalSpec internal constructor(context: ReactApplicationContext) : + ReactContextBaseJavaModule(context) { + + abstract fun launchPayPal(requestObj: String, callback: Callback) +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonComponentView.mm b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonComponentView.mm new file mode 100644 index 00000000..74b221f3 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonComponentView.mm @@ -0,0 +1,75 @@ +#ifdef RCT_NEW_ARCH_ENABLED + +#import +#import + +#import +#import + +#if __has_include() +#import +#else +#import "ReactNativeHyperswitchPaypal-Swift.h" +#endif + +using namespace facebook::react; + +@interface PaypalButtonComponentView : RCTViewComponentView +@end + +@implementation PaypalButtonComponentView { + PaypalButtonView *_view; +} + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _view = [[PaypalButtonView alloc] initWithFrame:frame]; + self.contentView = _view; + } + return self; +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + static const auto defaultProps = std::make_shared(); + _props = defaultProps; +} + +- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps +{ + const auto &oldViewProps = *std::static_pointer_cast(_props); + const auto &newViewProps = *std::static_pointer_cast(props); + + if (oldViewProps.buttonColor != newViewProps.buttonColor && !newViewProps.buttonColor.empty()) { + _view.buttonColor = RCTNSStringFromString(newViewProps.buttonColor); + } + if (oldViewProps.buttonLabel != newViewProps.buttonLabel && !newViewProps.buttonLabel.empty()) { + _view.buttonLabel = RCTNSStringFromString(newViewProps.buttonLabel); + } + if (oldViewProps.buttonSize != newViewProps.buttonSize && !newViewProps.buttonSize.empty()) { + _view.buttonSize = RCTNSStringFromString(newViewProps.buttonSize); + } + if (oldViewProps.borderRadius != newViewProps.borderRadius) { + _view.borderRadius = newViewProps.borderRadius; + } + + [super updateProps:props oldProps:oldProps]; +} + +@end + +Class PaypalButtonCls(void) +{ + return PaypalButtonComponentView.class; +} + +#endif // RCT_NEW_ARCH_ENABLED diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonView.swift b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonView.swift index efe9c117..9b6aa565 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonView.swift +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/PaypalButtonView.swift @@ -1,33 +1,33 @@ import UIKit import PayPal -class PaypalButtonView: UIView { +@objc public class PaypalButtonView: UIView { private var payPalButton: PayPalButton? private var containerView: UIView? - @objc dynamic var buttonColor: String = "gold" { + @objc public dynamic var buttonColor: String = "gold" { didSet { updateButton() } } - @objc dynamic var buttonLabel: String = "paypal" { + @objc public dynamic var buttonLabel: String = "paypal" { didSet { updateButton() } } - @objc dynamic var buttonSize: String = "medium" { + @objc public dynamic var buttonSize: String = "medium" { didSet { updateButton() } } - @objc dynamic var borderRadius: Double = 0 { + @objc public dynamic var borderRadius: Double = 0 { didSet { updateButton() } } - override init(frame: CGRect) { + public override init(frame: CGRect) { super.init(frame: frame) setupButton() } - required init?(coder: NSCoder) { + public required init?(coder: NSCoder) { super.init(coder: coder) setupButton() } @@ -119,11 +119,11 @@ class PaypalButtonView: UIView { reactView.reactSubviews().first?.perform(#selector(UIView.didMoveToWindow)) } - override var intrinsicContentSize: CGSize { + public override var intrinsicContentSize: CGSize { return CGSize(width: UIView.noIntrinsicMetric, height: 48) } - override func layoutSubviews() { + public override func layoutSubviews() { super.layoutSubviews() payPalButton?.layoutSubviews() } diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.mm b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.mm index 155a69ba..e1eb8804 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.mm +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.mm @@ -1,13 +1,61 @@ #import #import -@interface RCT_EXTERN_MODULE(HyperswitchPaypal, NSObject) +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNHyperswitchPaypalSpec.h" +#endif -RCT_EXTERN_METHOD(launchPayPal:(NSString *)requestObj +#if __has_include() +#import +#else +#import "ReactNativeHyperswitchPaypal-Swift.h" +#endif + +@interface HyperswitchPaypal : NSObject +@end + +#ifdef RCT_NEW_ARCH_ENABLED +@interface HyperswitchPaypal () +@end +#endif + +@implementation HyperswitchPaypal { + HyperswitchPaypalImpl *_impl; +} + +RCT_EXPORT_MODULE() + +- (instancetype)init +{ + if (self = [super init]) { + _impl = [HyperswitchPaypalImpl new]; + } + return self; +} + ++ (BOOL)requiresMainQueueSetup +{ + return YES; +} + +RCT_EXPORT_METHOD(launchPayPal:(NSString *)requestObj callback:(RCTResponseSenderBlock)callback) +{ + [self->_impl launchPayPal:requestObj callback:callback]; +} + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif @end +#ifndef RCT_NEW_ARCH_ENABLED + @interface RCT_EXTERN_MODULE(PaypalButton, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(buttonColor, NSString) @@ -16,3 +64,5 @@ @interface RCT_EXTERN_MODULE(PaypalButton, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(borderRadius, double) @end + +#endif // !RCT_NEW_ARCH_ENABLED diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.swift b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.swift index c0c80913..d7b59a00 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.swift +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/ios/ReactNativeHyperswitchPaypal.swift @@ -1,17 +1,11 @@ +import Foundation import PayPal -@objc(HyperswitchPaypal) -class ReactNativeHyperswitchPaypal: NSObject { +@objc public class HyperswitchPaypalImpl: NSObject { private static let TAG = "HyperswitchPaypal" - @objc - static func requiresMainQueueSetup() -> Bool { - return true - } - - @objc(launchPayPal:callback:) - func launchPayPal(_ requestObj: String, callback: @escaping RCTResponseSenderBlock) { + @objc public func launchPayPal(_ requestObj: String, callback: @escaping ([Any]) -> Void) { guard let data = requestObj.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/package.json b/packages/@juspay-tech/react-native-hyperswitch-paypal/package.json index 10d9cb18..6ec16d77 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/package.json +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/package.json @@ -1,6 +1,6 @@ { "name": "@juspay-tech/react-native-hyperswitch-paypal", - "version": "1.0.2", + "version": "1.1.0", "description": "react native hyperswitch paypal", "source": "./src/index.tsx", "main": "./lib/module/index.js", @@ -84,7 +84,7 @@ }, "peerDependencies": { "react": "*", - "react-native": "*" + "react-native": ">=0.72.0" }, "workspaces": [ "../../../example" @@ -150,5 +150,18 @@ "type": "legacy-module", "languages": "kotlin-swift", "version": "0.49.8" + }, + "codegenConfig": { + "name": "RNHyperswitchPaypalSpec", + "type": "all", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.juspaytech.reactnativehyperswitchpaypal" + }, + "ios": { + "componentProvider": { + "PaypalButton": "PaypalButtonComponentView" + } + } } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/NativeHyperswitchPaypal.ts b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/NativeHyperswitchPaypal.ts new file mode 100644 index 00000000..d74af7a7 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/NativeHyperswitchPaypal.ts @@ -0,0 +1,18 @@ +import type {TurboModule} from 'react-native'; +import {TurboModuleRegistry} from 'react-native'; + +export type PayPalNativeResult = { + status: string; + orderId?: string; + payerId?: string; + error_message?: string; +}; + +export interface Spec extends TurboModule { + launchPayPal( + requestObj: string, + callback: (result: PayPalNativeResult) => void + ): void; +} + +export default TurboModuleRegistry.get('HyperswitchPaypal'); diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.android.ts b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.android.ts deleted file mode 100644 index 05c531c3..00000000 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.android.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { requireNativeComponent, type ViewProps } from 'react-native'; - -interface NativeProps extends ViewProps { - buttonColor?: string; - buttonLabel?: string; - buttonSize?: string; - borderRadius?: number; -} - -export default requireNativeComponent('PaypalButton'); diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.ts b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.ts new file mode 100644 index 00000000..bf426d07 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/PaypalButtonNativeComponent.ts @@ -0,0 +1,19 @@ +// Deep imports keep the compiled output loadable on old-architecture React +// Native consumers down to 0.72, where the root exports for +// codegenNativeComponent/CodegenTypes do not exist at runtime. +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type {Double} from 'react-native/Libraries/Types/CodegenTypes'; +import type {HostComponent, ViewProps} from 'react-native'; + +export interface NativeProps extends ViewProps { + buttonColor?: string; + buttonLabel?: string; + buttonSize?: string; + borderRadius?: Double; +} + +// codegenNativeComponent works on both architectures: static view config + +// Fabric on the new architecture, Paper view config lookup on the old one. +export default codegenNativeComponent( + 'PaypalButton' +) as HostComponent; diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/codegen-shims.d.ts b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/codegen-shims.d.ts new file mode 100644 index 00000000..979f212e --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/codegen-shims.d.ts @@ -0,0 +1,28 @@ +// Ambient declarations for react-native deep imports used by the codegen +// specs. The runtime modules exist on every supported React Native version, +// but the strict TypeScript API of newer versions does not expose their +// types. This file is not part of any codegen spec (name matches neither +// Native* nor *NativeComponent). +declare module 'react-native/Libraries/Utilities/codegenNativeComponent' { + import type {HostComponent} from 'react-native'; + + type Options = { + interfaceOnly?: boolean; + paperComponentName?: string; + paperComponentNameDeprecated?: string; + excludedPlatforms?: ReadonlyArray<'iOS' | 'android'>; + }; + + export default function codegenNativeComponent( + componentName: string, + options?: Options + ): HostComponent; +} + +declare module 'react-native/Libraries/Types/CodegenTypes' { + export type Double = number; + export type Float = number; + export type Int32 = number; + export type UnsafeObject = object; + export type WithDefault = T | undefined; +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/index.tsx b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/index.tsx index 6f3dcb29..35bfa233 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-paypal/src/index.tsx +++ b/packages/@juspay-tech/react-native-hyperswitch-paypal/src/index.tsx @@ -1,8 +1,14 @@ -import { NativeModules } from 'react-native'; +import NativeHyperswitchPaypal from './NativeHyperswitchPaypal'; -const { HyperswitchPaypal } = NativeModules; +// TurboModuleRegistry.get resolves the TurboModule on the new architecture +// and falls back to the legacy NativeModules entry on the old architecture, +// so this single code path supports both. +export const isAvailable = NativeHyperswitchPaypal != null; -export const isAvailable = !!HyperswitchPaypal; +import PaypalButtonNativeComponent from './PaypalButtonNativeComponent'; + +export const PaypalButton = PaypalButtonNativeComponent; +export type {NativeProps as PaypalButtonProps} from './PaypalButtonNativeComponent'; export type PayPalResult = { status: string; @@ -23,12 +29,12 @@ export function launchPayPal( requestObj: string, callback: (result: PayPalResult) => void ): void { - if (!HyperswitchPaypal) { + if (!NativeHyperswitchPaypal) { callback({ status: 'failed', error_message: 'PayPal module not available', }); return; } - return HyperswitchPaypal.launchPayPal(requestObj, callback); + return NativeHyperswitchPaypal.launchPayPal(requestObj, callback); } diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/build.gradle b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/build.gradle index a82d41cc..66fb5734 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/build.gradle +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/build.gradle @@ -1,18 +1,17 @@ buildscript { - // Buildscript is evaluated before everything else so we can't use getExtOrDefault - def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['HyperswitchScancard_kotlinVersion'] + ext.getExtOrDefault = {name -> + return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['HyperswitchScancard_' + name] + } repositories { google() mavenCentral() } - dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath "com.android.tools.build:gradle:8.7.2" // noinspection DifferentKotlinGradleVersion - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}" } } @@ -20,12 +19,11 @@ def isNewArchitectureEnabled() { return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" } -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - +apply plugin: "com.android.library" +apply plugin: "kotlin-android" if (isNewArchitectureEnabled()) { - apply plugin: 'com.facebook.react' + apply plugin: "com.facebook.react" } def getExtOrDefault(name) { @@ -36,19 +34,42 @@ def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['HyperswitchScancard_' + name]).toInteger() } +def supportsNamespace() { + def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') + def major = parsed[0].toInteger() + def minor = parsed[1].toInteger() + + // Namespace support was added in 7.3.0 + return (major == 7 && minor >= 3) || major >= 8 +} + android { + if (supportsNamespace()) { + namespace "com.reactnativehyperswitchscancard" + + sourceSets { + main { + manifest.srcFile "src/main/AndroidManifestNew.xml" + } + } + } viewBinding { enabled = true } - compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') + compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") defaultConfig { - minSdkVersion getExtOrIntegerDefault('minSdkVersion') - targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') + minSdkVersion getExtOrIntegerDefault("minSdkVersion") + targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() } + + buildFeatures { + buildConfig true + } + buildTypes { release { minifyEnabled false @@ -56,81 +77,34 @@ android { } lintOptions { - disable 'GradleCompatible' + disable "GradleCompatible" } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ["src/newarch"] + } else { + java.srcDirs += ["src/oldarch"] + } + } } } repositories { mavenCentral() google() - - def found = false - def defaultDir = null - def androidSourcesName = 'React Native sources' - - if (rootProject.ext.has('reactNativeAndroidRoot')) { - defaultDir = rootProject.ext.get('reactNativeAndroidRoot') - } else { - defaultDir = new File(projectDir, - '/../../../node_modules/react-native/android') - } - - if (defaultDir.exists()) { - maven { - url defaultDir.toString() - name androidSourcesName - } - - logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}") - found = true - } else { - def parentDir = rootProject.projectDir - - 1.upto(5, { - if (found) return true - parentDir = parentDir.parentFile - - def androidSourcesDir = new File(parentDir, - 'node_modules/react-native') - - def androidPrebuiltBinaryDir = new File(parentDir, - 'node_modules/react-native/android') - - if (androidPrebuiltBinaryDir.exists()) { - maven { - url androidPrebuiltBinaryDir.toString() - name androidSourcesName - } - - logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}") - found = true - } else if (androidSourcesDir.exists()) { - maven { - url androidSourcesDir.toString() - name androidSourcesName - } - - logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}") - found = true - } - }) - } - - if (!found) { - throw new GradleException("${project.name}: unable to locate React Native android sources. " + "Ensure you have you installed React Native as a dependency in your project and try again.") - } } -def kotlin_version = getExtOrDefault('kotlinVersion') +def kotlin_version = getExtOrDefault("kotlinVersion") dependencies { - //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:+" + implementation "com.facebook.react:react-android" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "io.hyperswitch:hyperswitch-sdk-android-scancard:1.0.0" } diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/AndroidManifestNew.xml b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/AndroidManifestNew.xml new file mode 100644 index 00000000..a2f47b60 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/AndroidManifestNew.xml @@ -0,0 +1,2 @@ + + diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardModule.kt b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardModule.kt index e6d6e78b..d05bf434 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardModule.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardModule.kt @@ -4,20 +4,19 @@ import androidx.fragment.app.FragmentActivity import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Callback import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import io.hyperswitch.scancard.ScanCardCallback import io.hyperswitch.scancard.ScanCardManager class HyperswitchScancardModule(reactContext: ReactApplicationContext) : - ReactContextBaseJavaModule(reactContext) { + HyperswitchScancardSpec(reactContext) { override fun getName(): String { - return "HyperswitchScancard" + return NAME } @ReactMethod - fun launchScanCard(scanCardRequest: String, callBack: Callback) { + override fun launchScanCard(scanCardRequest: String, callback: Callback) { (currentActivity as? FragmentActivity)?.let { ScanCardManager.launch(it, object : ScanCardCallback { override fun onScanResult(result: Map) { @@ -34,9 +33,13 @@ class HyperswitchScancardModule(reactContext: ReactApplicationContext) : val map = Arguments.createMap() map.putString("status", result["status"] as String? ?: "Failed") map.putMap("data", dataMap) - callBack.invoke(map) + callback.invoke(map) } }) } } + + companion object { + const val NAME = "HyperswitchScancard" + } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardPackage.kt b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardPackage.kt index 13903cc3..80ac340c 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardPackage.kt +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/main/java/com/reactnativehyperswitchscancard/HyperswitchScancardPackage.kt @@ -1,16 +1,34 @@ package com.reactnativehyperswitchscancard -import com.facebook.react.ReactPackage + +import com.facebook.react.TurboReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.uimanager.ViewManager - +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.module.model.ReactModuleInfoProvider -class HyperswitchScancardPackage : ReactPackage { - override fun createNativeModules(reactContext: ReactApplicationContext): List { - return listOf(HyperswitchScancardModule(reactContext)) +class HyperswitchScancardPackage : TurboReactPackage() { + override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { + return if (name == HyperswitchScancardModule.NAME) { + HyperswitchScancardModule(reactContext) + } else { + null } + } - override fun createViewManagers(reactContext: ReactApplicationContext): List> { - return emptyList() + override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { + return ReactModuleInfoProvider { + val moduleInfos: MutableMap = HashMap() + val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + moduleInfos[HyperswitchScancardModule.NAME] = ReactModuleInfo( + HyperswitchScancardModule.NAME, + HyperswitchScancardModule.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule + ) + moduleInfos } + } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/newarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/newarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt new file mode 100644 index 00000000..0ee92ddf --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/newarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt @@ -0,0 +1,6 @@ +package com.reactnativehyperswitchscancard + +import com.facebook.react.bridge.ReactApplicationContext + +abstract class HyperswitchScancardSpec internal constructor(context: ReactApplicationContext) : + NativeHyperswitchScancardSpec(context) diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/oldarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/oldarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt new file mode 100644 index 00000000..96857fc4 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/android/src/oldarch/java/com/reactnativehyperswitchscancard/HyperswitchScancardSpec.kt @@ -0,0 +1,11 @@ +package com.reactnativehyperswitchscancard + +import com.facebook.react.bridge.Callback +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule + +abstract class HyperswitchScancardSpec internal constructor(context: ReactApplicationContext) : + ReactContextBaseJavaModule(context) { + + abstract fun launchScanCard(scanCardRequest: String, callback: Callback) +} diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard-Bridging-Header.h b/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard-Bridging-Header.h deleted file mode 100644 index dea7ff6b..00000000 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard-Bridging-Header.h +++ /dev/null @@ -1,2 +0,0 @@ -#import -#import diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.m b/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.m deleted file mode 100644 index 468ffa37..00000000 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.m +++ /dev/null @@ -1,12 +0,0 @@ -#import - -@interface RCT_EXTERN_MODULE(HyperswitchScancard, NSObject) - -RCT_EXTERN_METHOD(launchScanCard: (NSString)rnMessage :(RCTResponseSenderBlock)rnCallback) - -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} - -@end diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.mm b/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.mm new file mode 100644 index 00000000..a9367e25 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.mm @@ -0,0 +1,65 @@ +#import +#import + +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNHyperswitchScancardSpec.h" +#endif + +#if __has_include() +#import +#else +#import "react_native_hyperswitch_scancard-Swift.h" +#endif + +@interface HyperswitchScancard : NSObject +@end + +#ifdef RCT_NEW_ARCH_ENABLED +@interface HyperswitchScancard () +@end +#endif + +@implementation HyperswitchScancard { + HyperswitchScancardImpl *_impl; +} + +RCT_EXPORT_MODULE() + +- (instancetype)init +{ + if (self = [super init]) { + _impl = [HyperswitchScancardImpl new]; + } + return self; +} + ++ (BOOL)requiresMainQueueSetup +{ + return NO; +} + +RCT_EXPORT_METHOD(launchScanCard:(NSString *)scanCardRequest + callback:(RCTResponseSenderBlock)callback) +{ + dispatch_async(dispatch_get_main_queue(), ^{ + UIViewController *presentedViewController = RCTPresentedViewController(); + if (presentedViewController == nil) { + callback(@[ @{@"status" : @"Failed"} ]); + return; + } + [self->_impl launchScanCardFrom:presentedViewController + callback:^(NSDictionary *response) { + callback(@[ response ]); + }]; + }); +} + +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif + +@end diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.swift b/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.swift index 4a393bda..5ad48027 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.swift +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/ios/Source/HyperswitchScancard.swift @@ -1,35 +1,30 @@ import Foundation +import UIKit import HyperswitchScanCard +@objc public class HyperswitchScancardImpl: NSObject { -@objc(HyperswitchScancard) -class HyperswitchScancard: NSObject { - - @objc - func launchScanCard(_ rnMessage: String, _ rnCallback: @escaping RCTResponseSenderBlock) { - - DispatchQueue.main.async { - var message: [String:Any] = [:] - var callback: [String:Any] = [:] - let cardScanSheet = CardScanSheet() - cardScanSheet.present(from: RCTPresentedViewController()!) { result in - - switch result { - case .completed(var card as ScannedCard?): - message["pan"] = card?.pan - message["expiryMonth"] = card?.expiryMonth - message["expiryYear"] = card?.expiryYear - callback["status"] = "Succeeded" - callback["data"] = message - case .canceled: - callback["status"] = "Cancelled" - case .failed(let error): - callback["status"] = "Failed" - } - rnCallback([callback]) + @objc public func launchScanCard(from viewController: UIViewController, + callback: @escaping ([String: Any]) -> Void) { + var message: [String: Any] = [:] + var response: [String: Any] = [:] + let cardScanSheet = CardScanSheet() + cardScanSheet.present(from: viewController) { result in + + switch result { + case .completed(let card as ScannedCard?): + message["pan"] = card?.pan + message["expiryMonth"] = card?.expiryMonth + message["expiryYear"] = card?.expiryYear + response["status"] = "Succeeded" + response["data"] = message + case .canceled: + response["status"] = "Cancelled" + case .failed: + response["status"] = "Failed" } + callback(response) } } } - diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/package.json b/packages/@juspay-tech/react-native-hyperswitch-scancard/package.json index 8a2b7b1c..090f23bc 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/package.json +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/package.json @@ -1,10 +1,10 @@ { "name": "@juspay-tech/react-native-hyperswitch-scancard", - "version": "0.2.3", + "version": "0.3.0", "description": "React Native Hyperswitch ScanCard", - "main": "lib/commonjs/index", - "module": "lib/module/index", - "types": "lib/typescript/src/index.d.ts", + "main": "./lib/module/index.js", + "module": "./lib/module/index.js", + "types": "./lib/typescript/src/index.d.ts", "exports": { ".": { "source": "./src/index.tsx", @@ -85,7 +85,7 @@ }, "peerDependencies": { "react": "*", - "react-native": "*", + "react-native": ">=0.72.0", "react-native-webview": "*" }, "jest": { @@ -148,5 +148,13 @@ "languages": "kotlin-objc", "type": "turbo-module", "version": "0.54.5" + }, + "codegenConfig": { + "name": "RNHyperswitchScancardSpec", + "type": "modules", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.reactnativehyperswitchscancard" + } } } diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/react-native-hyperswitch-scancard.podspec b/packages/@juspay-tech/react-native-hyperswitch-scancard/react-native-hyperswitch-scancard.podspec index 3541cb8d..2875fcb1 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/react-native-hyperswitch-scancard.podspec +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/react-native-hyperswitch-scancard.podspec @@ -1,7 +1,6 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' Pod::Spec.new do |s| s.name = "react-native-hyperswitch-scancard" @@ -11,7 +10,7 @@ Pod::Spec.new do |s| s.license = package["license"] s.authors = package["author"] - s.platforms = { :ios => "13.0" } + s.platforms = { :ios => "13.4" } s.swift_version = '5.0' s.requires_arc = true s.source = { :git => "https://github.com/juspay/react-native-hyperswitch-libraries.git", :branch => "main" } @@ -20,20 +19,8 @@ Pod::Spec.new do |s| s.source_files = "ios/Source/**/*.{h,m,mm,swift}" s.vendored_frameworks = "ios/Frameworks/HyperswitchScanCard.xcframework" - s.dependency "React-Core" - - # Don't install the dependencies when we run `pod install` in the old architecture. - if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then - s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" - s.pod_target_xcconfig = { - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", - "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" - } - - s.dependency "React-Codegen" - s.dependency "RCT-Folly" - s.dependency "RCTRequired" - s.dependency "RCTTypeSafety" - s.dependency "ReactCommon/turbomodule/core" - end + # Wires up React-Core plus, when the consumer enables the new architecture, + # codegen/Fabric/TurboModule dependencies and compiler flags + # (RCT_NEW_ARCH_ENABLED). Available on React Native >= 0.71. + install_modules_dependencies(s) end diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/src/NativeHyperswitchScancard.ts b/packages/@juspay-tech/react-native-hyperswitch-scancard/src/NativeHyperswitchScancard.ts new file mode 100644 index 00000000..a5ac4c19 --- /dev/null +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/src/NativeHyperswitchScancard.ts @@ -0,0 +1,20 @@ +import type {TurboModule} from 'react-native'; +import {TurboModuleRegistry} from 'react-native'; + +export type ScanCardResponse = { + status?: string; + data?: { + pan?: string; + expiryMonth?: string; + expiryYear?: string; + }; +}; + +export interface Spec extends TurboModule { + launchScanCard( + scanCardRequest: string, + callback: (response: ScanCardResponse) => void + ): void; +} + +export default TurboModuleRegistry.get('HyperswitchScancard'); diff --git a/packages/@juspay-tech/react-native-hyperswitch-scancard/src/index.tsx b/packages/@juspay-tech/react-native-hyperswitch-scancard/src/index.tsx index 11ab53c0..7b0d34d2 100644 --- a/packages/@juspay-tech/react-native-hyperswitch-scancard/src/index.tsx +++ b/packages/@juspay-tech/react-native-hyperswitch-scancard/src/index.tsx @@ -1,8 +1,10 @@ -import { NativeModules } from 'react-native'; +import NativeHyperswitchScancard from './NativeHyperswitchScancard'; +import type {ScanCardResponse} from './NativeHyperswitchScancard'; -const HyperswitchScancard = NativeModules.HyperswitchScancard || null; - -const isAvailable = HyperswitchScancard && HyperswitchScancard.launchScanCard; +// TurboModuleRegistry.get resolves the TurboModule on the new architecture +// and falls back to the legacy NativeModules entry on the old architecture, +// so this single code path supports both. +const isAvailable = NativeHyperswitchScancard != null; export interface ScanCardReturnType { status: string; @@ -16,26 +18,23 @@ interface ScanCardData { } function launchScanCard(callback: (s: ScanCardReturnType) => void): void { - if (isAvailable) { - return HyperswitchScancard.launchScanCard( - '', - (response: Record) => { - const status = response.status || 'Default'; - const data: ScanCardData | undefined = response.data; - const scanData: ScanCardReturnType = { - status, - data: data - ? { - pan: data.pan || '', - expiryMonth: data.expiryMonth || '', - expiryYear: data.expiryYear || '', - } - : undefined, - }; - callback(scanData); - } - ); + if (NativeHyperswitchScancard) { + NativeHyperswitchScancard.launchScanCard('', (response: ScanCardResponse) => { + const status = response.status || 'Default'; + const data = response.data; + const scanData: ScanCardReturnType = { + status, + data: data + ? { + pan: data.pan || '', + expiryMonth: data.expiryMonth || '', + expiryYear: data.expiryYear || '', + } + : undefined, + }; + callback(scanData); + }); } } -export { isAvailable, launchScanCard }; +export {isAvailable, launchScanCard}; diff --git a/yarn.lock b/yarn.lock index 5d9f816d..aed6c1ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4994,29 +4994,26 @@ __metadata: version: 0.0.0-use.local resolution: "@juspay-tech/react-native-hyperswitch-netcetera-3ds@workspace:packages/@juspay-tech/react-native-hyperswitch-netcetera-3ds" dependencies: - "@arkweid/lefthook": ^0.7.7 - "@babel/eslint-parser": ^7.18.2 "@commitlint/config-conventional": ^17.0.2 - "@react-native-community/eslint-config": ^3.0.2 + "@react-native/babel-preset": 0.81.1 "@release-it/conventional-changelog": ^10.0.1 - "@types/jest": ^28.1.2 - "@types/react": ~17.0.21 - "@types/react-native": 0.68.0 + "@types/jest": ^29.5.14 + "@types/react": ^19.1.0 commitlint: ^17.0.2 eslint: ^8.4.1 eslint-config-prettier: ^8.5.0 eslint-plugin-prettier: ^4.0.0 - jest: ^28.1.1 + jest: ^29.7.0 pod-install: ^0.1.0 prettier: ^2.0.5 - react: 17.0.2 - react-native: 0.68.2 - react-native-builder-bob: ^0.18.3 + react: 19.1.0 + react-native: 0.81.1 + react-native-builder-bob: ^0.40.13 release-it: ^19.0.5 typescript: ^5.9.2 peerDependencies: react: "*" - react-native: "*" + react-native: ">=0.72.0" languageName: unknown linkType: soft @@ -5164,7 +5161,7 @@ __metadata: typescript: ^5.9.2 peerDependencies: react: "*" - react-native: "*" + react-native: ">=0.72.0" react-native-webview: "*" languageName: unknown linkType: soft