Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
## [0.2.0] Initial release with working Android and iOS examples
## [0.2.1] Update internal SDK libraries to android 3.8.8 and iOS 3.8.5
## [0.2.2] Update internal SDK libraries to android 3.8.9 and iOS 3.8.8. Upgrade React Native version
3 changes: 1 addition & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")

dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.3")
implementation "com.ecommpay:msdk-ui:3.8.8"
implementation "com.ecommpay:msdk-core-android:0.12.4"
implementation "com.ecommpay:msdk-ui:3.8.9"

implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
Expand Down
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
247 changes: 126 additions & 121 deletions android/src/main/java/com/msdkreactnative/MsdkReactNativeModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@ import android.content.Intent
import android.util.Log
import com.ecommpay.msdk.ui.EcmpActionType
import com.ecommpay.msdk.ui.EcmpAdditionalField
import com.ecommpay.msdk.ui.EcmpAdditionalFieldType
import com.ecommpay.msdk.ui.EcmpPaymentInfo
import com.ecommpay.msdk.ui.EcmpPaymentOptions
import com.ecommpay.msdk.ui.EcmpPaymentSDK
import com.ecommpay.msdk.ui.EcmpRecipientInfo
import com.ecommpay.msdk.ui.EcmpRecurrentData
import com.ecommpay.msdk.ui.EcmpRecurrentDataSchedule
import com.ecommpay.msdk.ui.EcmpScreenDisplayMode
import com.facebook.react.bridge.ActivityEventListener
import com.facebook.react.bridge.Arguments
Expand All @@ -20,132 +15,142 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
import com.msdkreactnative.extensions.*

class MsdkReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), ActivityEventListener {

init {
reactContext.addActivityEventListener(this)
}

private var paymentPromise: Promise? = null

override fun getName(): String {
return "MsdkReactNative"
}

@ReactMethod
fun initializePaymentWithOptions(
params: ReadableMap,
promise: Promise
) {
val currentActivity = currentActivity ?: return

val ecmpPaymentInfo = params.getMap("paymentInfo")?.let { it.buildPaymentInfo() }

params.getMap("paymentInfo")?.let { Log.d("INFO", it.toString()) }

// Create payment options
val paymentOptions = EcmpPaymentOptions().apply {
if (ecmpPaymentInfo != null) {
paymentInfo = ecmpPaymentInfo
}

actionType = EcmpActionType.entries.toTypedArray()[params.getInt("actionType") - 1]

additionalFields {
params.getArray("additionalFields")?.let { array ->
mutableListOf<EcmpAdditionalField>().apply {
for (i in 0 until array.size()) {
add(array.getMap(i).buildAdditionalField())
}
}
} ?: listOf()
import com.msdkreactnative.extensions.buildAdditionalField
import com.msdkreactnative.extensions.buildPaymentInfo
import com.msdkreactnative.extensions.buildRecipientInfo
import com.msdkreactnative.extensions.buildRecurrentInfo
import com.msdkreactnative.extensions.safeGetBoolean
import com.msdkreactnative.extensions.safeGetInt

class MsdkReactNativeModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext), ActivityEventListener {

init {
reactContext.addActivityEventListener(this)
}

private var paymentPromise: Promise? = null

override fun getName(): String {
return "MsdkReactNative"
}

@ReactMethod
fun initializePaymentWithOptions(
params: ReadableMap,
promise: Promise,
) {
val currentActivity = currentActivity ?: return

val ecmpPaymentInfo = params.getMap("paymentInfo")?.let { it.buildPaymentInfo() }

params.getMap("paymentInfo")?.let { Log.d("INFO", it.toString()) }

// Create payment options
val paymentOptions = EcmpPaymentOptions().apply {
if (ecmpPaymentInfo != null) {
paymentInfo = ecmpPaymentInfo
}

actionType = EcmpActionType.entries.toTypedArray()[params.getInt("actionType") - 1]

additionalFields {
params.getArray("additionalFields")?.let { array ->
mutableListOf<EcmpAdditionalField>().apply {
for (i in 0 until array.size()) {
array.getMap(i)?.buildAdditionalField()?.let { add(it) }
}

screenDisplayModes {
params.getArray("screenDisplayModes")?.let { array ->
mutableSetOf<EcmpScreenDisplayMode>().apply {
for (i in 0 until array.size()) {
add(EcmpScreenDisplayMode.entries[array.getInt(i) - 1])
}
}
} ?: emptySet()
}

isDarkTheme = params.getBoolean("isDarkTheme")
recipientInfo = params.getMap("recipientInfo")?.let { it.buildRecipientInfo() }
recurrentData = params.getMap("recurrentData")?.let { it.buildRecurrentInfo() }
hideScanningCards = params.safeGetBoolean("hideScanningCards")

merchantId = params.getString("googleMerchantId") ?: ""
merchantName = params.getString("googleMerchantName") ?: ""
isTestEnvironment = params.safeGetBoolean("googleIsTestEnvironment")

// Brand customization
params.getString("brandColor")?.let { colorString ->
brandColor = colorString
}
} ?: listOf<EcmpAdditionalField>()
}

screenDisplayModes {
params.getArray("screenDisplayModes")?.let { array ->
mutableSetOf<EcmpScreenDisplayMode>().apply {
for (i in 0 until array.size()) {
add(EcmpScreenDisplayMode.entries[array.getInt(i) - 1])
}
}
} ?: emptySet<EcmpScreenDisplayMode>()
}

isDarkTheme = params.getBoolean("isDarkTheme")
recipientInfo = params.getMap("recipientInfo")?.let { it.buildRecipientInfo() }
recurrentData = params.getMap("recurrentData")?.let { it.buildRecurrentInfo() }
hideScanningCards = params.safeGetBoolean("hideScanningCards")

merchantId = params.getString("googleMerchantId") ?: ""
merchantName = params.getString("googleMerchantName") ?: ""
isTestEnvironment = params.safeGetBoolean("googleIsTestEnvironment")

// Brand customization
params.getString("brandColor")?.let { colorString ->
brandColor = colorString
}

// Stored card type
storedCardType = params.safeGetInt("storedCardType")
}

// Stored card type
storedCardType = params.safeGetInt("storedCardType")
}
val mockMode = EcmpPaymentSDK.EcmpMockModeType.entries[params.getInt("mockModeType")]

val mockMode = EcmpPaymentSDK.EcmpMockModeType.entries[params.getInt("mockModeType")]
// Initialize SDK and open payment form
val sdk = EcmpPaymentSDK(currentActivity.applicationContext, paymentOptions, mockMode)

// Initialize SDK and open payment form
val sdk = EcmpPaymentSDK(currentActivity.applicationContext, paymentOptions, mockMode)
paymentPromise = promise

paymentPromise = promise
val intent = sdk.intent
currentActivity.startActivityForResult(intent, 1001)
}

val intent = sdk.intent
currentActivity.startActivityForResult(intent, 1001)
}
@ReactMethod
fun getParamsForSignature(params: ReadableMap, promise: Promise) {
Log.d("MSDK", "getParamsForSignature called with: $params")
try {
val paymentInfoMap = params.getMap("paymentInfo") ?: params
val ecmpPaymentInfo = paymentInfoMap.buildPaymentInfo()
Log.d("MSDK", "Created EcmpPaymentInfo: $ecmpPaymentInfo")

@ReactMethod
fun getParamsForSignature(params: ReadableMap, promise: Promise) {
Log.d("MSDK", "getParamsForSignature called with: $params")
try {
val paymentInfoMap = params.getMap("paymentInfo") ?: params
val ecmpPaymentInfo = paymentInfoMap.buildPaymentInfo()
Log.d("MSDK", "Created EcmpPaymentInfo: $ecmpPaymentInfo")

val result = ecmpPaymentInfo.getParamsForSignature()
Log.d("MSDK", "getParamsForSignature result: $result")
promise.resolve(result)
} catch (e: Exception) {
Log.e("MSDK", "getParamsForSignature error: ${e.message}")
promise.reject("GET_PARAMS_ERROR", e.message, e)
}
val result = ecmpPaymentInfo.getParamsForSignature()
Log.d("MSDK", "getParamsForSignature result: $result")
promise.resolve(result)
} catch (e: Exception) {
Log.e("MSDK", "getParamsForSignature error: ${e.message}")
promise.reject("GET_PARAMS_ERROR", e.message, e)
}

override fun onActivityResult(activity: Activity?, requestCode: Int, resultCode: Int, data: Intent?) {
when (resultCode) {
EcmpPaymentSDK.RESULT_SUCCESS -> {
val paymentJson = data?.getStringExtra(EcmpPaymentSDK.EXTRA_PAYMENT)
val resultMap = Arguments.createMap()
resultMap.putString("paymentJson", paymentJson)
resultMap.putInt("resultCode", resultCode)
paymentPromise?.resolve(resultMap)
}

EcmpPaymentSDK.RESULT_ERROR -> {
val errorCode = data?.getStringExtra(EcmpPaymentSDK.EXTRA_ERROR_CODE)
val errorMessage = data?.getStringExtra(EcmpPaymentSDK.EXTRA_ERROR_MESSAGE)
val resultMap = Arguments.createMap()
resultMap.putString("errorCode", errorCode)
resultMap.putString("errorMessage", errorMessage)
paymentPromise?.resolve(resultMap)
}

else -> {
paymentPromise?.resolve(resultCode)
}
}
paymentPromise = null
}

override fun onActivityResult(
activity: Activity?,
requestCode: Int,
resultCode: Int,
data: Intent?,
) {
when (resultCode) {
EcmpPaymentSDK.RESULT_SUCCESS -> {
val paymentJson = data?.getStringExtra(EcmpPaymentSDK.EXTRA_PAYMENT)
val resultMap = Arguments.createMap()
resultMap.putString("paymentJson", paymentJson)
resultMap.putInt("resultCode", resultCode)
paymentPromise?.resolve(resultMap)
}

EcmpPaymentSDK.RESULT_ERROR -> {
val errorCode = data?.getStringExtra(EcmpPaymentSDK.EXTRA_ERROR_CODE)
val errorMessage = data?.getStringExtra(EcmpPaymentSDK.EXTRA_ERROR_MESSAGE)
val resultMap = Arguments.createMap()
resultMap.putString("errorCode", errorCode)
resultMap.putString("errorMessage", errorMessage)
paymentPromise?.resolve(resultMap)
}

else -> {
paymentPromise?.resolve(resultCode)
}
}
paymentPromise = null
}

override fun onNewIntent(data: Intent?) {}
override fun onNewIntent(data: Intent?) {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fun ReadableMap.safeGetInt(key: String): Int {
fun ReadableMap.buildPaymentInfo(): EcmpPaymentInfo {
val signature = getString("signature")
android.util.Log.d("PaymentInfo", "Signature from JS: $signature")

return EcmpPaymentInfo(
projectId = getInt("projectID"),
paymentId = getString("paymentID") ?: "",
Expand Down Expand Up @@ -81,7 +81,7 @@ fun ReadableMap.buildRecurrentInfo(): EcmpRecurrentData {
val schedule = getArray("schedule")?.let { array ->
mutableListOf<EcmpRecurrentDataSchedule>().apply {
for (i in 0 until array.size()) {
add(array.getMap(i).buildRecurrentInfoSchedule())
array.getMap(i)?.buildRecurrentInfoSchedule()?.let { add(it) }
}
}
} ?: listOf()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader

class MainApplication : Application(), ReactApplication {
Expand All @@ -34,7 +35,7 @@ class MainApplication : Application(), ReactApplication {

override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
SoLoader.init(this, OpenSourceMergedSoMapping)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
Expand Down
4 changes: 2 additions & 2 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
buildscript {
ext {
buildToolsVersion = "35.0.0"
minSdkVersion = 23
minSdkVersion = 24
compileSdkVersion = 35
targetSdkVersion = 35
ndkVersion = "26.1.10909125"
Expand All @@ -13,7 +13,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.1.1")
classpath('com.android.tools.build:gradle:8.11.1')
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Loading
Loading