diff --git a/android/build.gradle b/android/build.gradle index 2954a50..b8c5d62 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,3 +1,7 @@ +ext { + transactVersion = '3.18.3' +} + buildscript { // Buildscript is evaluated before everything else so we can't use getExtOrDefault // Prefer the library's declared Kotlin version to avoid root project mismatches @@ -49,7 +53,7 @@ android { minSdkVersion getExtOrIntegerDefault("minSdkVersion") targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() - buildConfigField "String", "TRANSACT_VERSION", "\"$TransactReactNative_transactVersion\"" + buildConfigField "String", "TRANSACT_VERSION", "\"$transactVersion\"" } buildTypes { release { @@ -83,7 +87,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // transact deps end - implementation "financial.atomic:transact:$TransactReactNative_transactVersion" + implementation "financial.atomic:transact:$transactVersion" } if (isNewArchitectureEnabled()) { diff --git a/android/gradle.properties b/android/gradle.properties index 15322d8..c9e662a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -16,6 +16,5 @@ TransactReactNative_kotlinVersion=2.1.21 TransactReactNative_minSdkVersion=24 TransactReactNative_ndkversion=21.4.7075529 TransactReactNative_targetSdkVersion=35 -TransactReactNative_transactVersion=3.18.2 android.enableJetifier=true android.useAndroidX=true diff --git a/android/src/main/java/com/atomicfi/transactreactnative/TransactReactNativeModule.kt b/android/src/main/java/com/atomicfi/transactreactnative/TransactReactNativeModule.kt index 40af765..08db1a3 100644 --- a/android/src/main/java/com/atomicfi/transactreactnative/TransactReactNativeModule.kt +++ b/android/src/main/java/com/atomicfi/transactreactnative/TransactReactNativeModule.kt @@ -1,6 +1,7 @@ package com.atomicfi.transactreactnative import android.content.Context +import android.util.Base64 import com.facebook.react.bridge.* import com.facebook.react.modules.core.DeviceEventManagerModule import financial.atomic.transact.Config @@ -31,10 +32,10 @@ class TransactReactNativeModule(reactContext: ReactApplicationContext) : } else { "production" } - + return when (environmentType) { "production" -> "https://transact.atomicfi.com" - "sandbox" -> "https://transact.atomicfi.com" + "sandbox" -> "https://transact.atomicfi.com" "custom" -> { if (environmentData.hasKey("transactPath")) { environmentData.getString("transactPath") ?: "https://transact.atomicfi.com" @@ -62,15 +63,31 @@ class TransactReactNativeModule(reactContext: ReactApplicationContext) : promise.resolve(result) } + private fun buildConfigToken(config: ReadableMap, wrapperVersion: String): String { + val configJson = JSONObject(config.toHashMap()) + val platformMap = Config.Platform.suffixed("react-$wrapperVersion").encode() + configJson.put("platform", JSONObject(platformMap as Map)) + return Base64.encodeToString( + configJson.toString().toByteArray(Charsets.UTF_8), + Base64.NO_WRAP, + ) + } + @ReactMethod - fun presentTransact(token: String, environment: ReadableMap, promise: Promise) { + fun presentTransact( + config: ReadableMap, + environment: ReadableMap, + wrapperVersion: String, + promise: Promise, + ) { val context = reactApplicationContext.currentActivity as Context val emitter = reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) val environmentURL = parseEnvironment(environment) - val config = Config(token = token, environment = "CUSTOM", environmentURL = environmentURL) + val token = buildConfigToken(config, wrapperVersion) + val sdkConfig = Config(token = token, environment = "CUSTOM", environmentURL = environmentURL) try { - Transact.present(context, config, object : TransactBroadcastReceiver() { + Transact.present(context, sdkConfig, object : TransactBroadcastReceiver() { override fun onClose(data: JSONObject) { handleCallbackEvent("onClose", data, "reason", emitter, promise) } @@ -104,7 +121,12 @@ class TransactReactNativeModule(reactContext: ReactApplicationContext) : } @ReactMethod - fun presentAction(id: String, environment: ReadableMap, promise: Promise) { + fun presentAction( + id: String, + environment: ReadableMap, + wrapperVersion: String, + promise: Promise, + ) { val context = reactApplicationContext.currentActivity as Context val emitter = reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) val environmentURL = parseEnvironment(environment) @@ -115,6 +137,7 @@ class TransactReactNativeModule(reactContext: ReactApplicationContext) : environment = Config.Environment.CUSTOM, environmentURL = environmentURL ) + config.platform = Config.Platform.suffixed("react-$wrapperVersion") Transact.presentAction(context, config) diff --git a/example/package.json b/example/package.json index 20c85f5..4c5f026 100644 --- a/example/package.json +++ b/example/package.json @@ -7,7 +7,7 @@ "android": "npx expo run:android", "ios": "npx expo run:ios", "web": "npx expo start --web", - "clean": "cd .. && yarn bob build && cd example && npx expo prebuild --clean", + "clean": "cd .. && yarn prepare && cd example && npx expo prebuild --clean", "lint": "expo lint" }, "dependencies": { diff --git a/ios/TransactReactNative.m b/ios/TransactReactNative.m index 8a24cc2..584082e 100644 --- a/ios/TransactReactNative.m +++ b/ios/TransactReactNative.m @@ -8,6 +8,7 @@ @interface RCT_EXTERN_MODULE(TransactReactNative, RCTEventEmitter) environment:(NSDictionary *)environment presentationStyle:(nullable NSString *)presentationStyle setDebug:(nullable NSNumber *)setDebug + wrapperVersion:(NSString *)wrapperVersion withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) diff --git a/ios/TransactReactNative.swift b/ios/TransactReactNative.swift index a4df37d..07e52c8 100644 --- a/ios/TransactReactNative.swift +++ b/ios/TransactReactNative.swift @@ -3,7 +3,7 @@ import UIKit @objc(TransactReactNative) class TransactReactNative: RCTEventEmitter { - + // Data request handler that will be called when the response arrives private var dataResponseHandler: ((Any) -> Void)? = nil @@ -37,8 +37,8 @@ class TransactReactNative: RCTEventEmitter { } } - @objc(presentTransact:environment:presentationStyle:setDebug:withResolver:withRejecter:) - func presentTransact(config: [String: Any], environment: [String: Any], presentationStyle: String?, setDebug: NSNumber?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { + @objc(presentTransact:environment:presentationStyle:setDebug:wrapperVersion:withResolver:withRejecter:) + func presentTransact(config: [String: Any], environment: [String: Any], presentationStyle: String?, setDebug: NSNumber?, wrapperVersion: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { let debugEnabled = setDebug?.boolValue ?? false Task { @MainActor in @@ -56,10 +56,7 @@ class TransactReactNative: RCTEventEmitter { let parsedPresentationStyle = self.parsePresentationStyle(presentationStyle) - if var platform = AtomicConfig.Platform().encode() as? [String: Any] { - platform["sdkVersion"] = platform["sdkVersion"] as! String + "-react" - json["platform"] = platform - } + json["platform"] = AtomicConfig.Platform(suffixed: "react-\(wrapperVersion)").encode() guard let data = try? JSONSerialization.data(withJSONObject: json, options: []) else { return } diff --git a/package.json b/package.json index 36ebaef..d3f4c0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@atomicfi/transact-react-native", - "version": "3.12.3", + "version": "3.16.0", "description": "React Native bridge for the Transact SDK", "main": "lib/commonjs/index.js", "module": "lib/module/index.js", @@ -48,7 +48,7 @@ "typecheck": "tsc", "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib", - "prepare": "bob build" + "prepare": "bob build && cp package.json lib/package.json" }, "keywords": [ "react-native", @@ -145,4 +145,4 @@ ] ] } -} +} \ No newline at end of file diff --git a/src/android.tsx b/src/android.tsx index beab6ac..49120d3 100644 --- a/src/android.tsx +++ b/src/android.tsx @@ -1,6 +1,5 @@ -import { DeviceEventEmitter, Platform } from 'react-native'; +import { DeviceEventEmitter } from 'react-native'; import * as CONSTANTS from './constants'; -import { utf8Base64 } from './utils'; function _eventHandler(request: string, func: Function) { return func(JSON.parse(request)); @@ -20,6 +19,7 @@ export const AtomicAndroid = { TransactReactNative, config, environment, + wrapperVersion, onInteraction, onTaskStatusUpdate, onAuthStatusUpdate, @@ -30,6 +30,7 @@ export const AtomicAndroid = { TransactReactNative: any; config: any; environment?: CONSTANTS.TransactEnvironment; + wrapperVersion: string; onInteraction?: Function; onTaskStatusUpdate?: Function; onAuthStatusUpdate?: Function; @@ -37,12 +38,6 @@ export const AtomicAndroid = { onFinish?: Function; onClose?: Function; }): void { - config.platform = { - name: 'android', - systemVersion: Platform.Version.toString(), - sdkVersion: TransactReactNative.getConstants().VERSION + '-react', - }; - _addEventListener('onClose', onClose); _addEventListener('onFinish', onFinish); _addEventListener('onInteraction', onInteraction); @@ -50,14 +45,13 @@ export const AtomicAndroid = { _addEventListener('onTaskStatusUpdate', onTaskStatusUpdate); _addEventListener('onAuthStatusUpdate', onAuthStatusUpdate); - const token = utf8Base64(JSON.stringify(config)); - - TransactReactNative.presentTransact(token, environment); + TransactReactNative.presentTransact(config, environment, wrapperVersion); }, presentAction({ TransactReactNative, id, environment, + wrapperVersion, onLaunch, onFinish, onClose, @@ -67,6 +61,7 @@ export const AtomicAndroid = { TransactReactNative: any; id: String; environment?: CONSTANTS.TransactEnvironment; + wrapperVersion: string; onLaunch?: Function; onFinish?: Function; onClose?: Function; @@ -79,6 +74,6 @@ export const AtomicAndroid = { _addEventListener('onTaskStatusUpdate', onTaskStatusUpdate); _addEventListener('onAuthStatusUpdate', onAuthStatusUpdate); - TransactReactNative.presentAction(id, environment); + TransactReactNative.presentAction(id, environment, wrapperVersion); }, }; diff --git a/src/index.tsx b/src/index.tsx index 5b19f84..679dc21 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,6 +3,9 @@ import { AtomicIOS } from './ios'; import { AtomicAndroid } from './android'; import * as CONSTANTS from './constants'; import type { PresentationStyleIOS, AppType, StepType } from './constants'; +import pkg from '../package.json'; + +const wrapperVersion: string = pkg.version; const LINKING_ERROR = `The package '@atomicfi/transact-react-native' doesn't seem to be linked. Make sure: \n\n` + @@ -126,6 +129,7 @@ export const Atomic = { TransactReactNative, config, environment: environment || CONSTANTS.Environment.production, + wrapperVersion, onInteraction, onFinish, onDataRequest, @@ -172,6 +176,7 @@ export const Atomic = { TransactReactNative, id, environment: environment || CONSTANTS.Environment.production, + wrapperVersion, presentationStyleIOS, onLaunch, onFinish, diff --git a/src/ios.tsx b/src/ios.tsx index de0ccf5..ef88a75 100644 --- a/src/ios.tsx +++ b/src/ios.tsx @@ -6,6 +6,7 @@ export const AtomicIOS = { TransactReactNative, config, environment, + wrapperVersion, onInteraction, onFinish, onDataRequest, @@ -18,6 +19,7 @@ export const AtomicIOS = { TransactReactNative: any; config: any; environment?: CONSTANTS.TransactEnvironment; + wrapperVersion: string; onInteraction?: Function; onDataRequest?: Function; onFinish?: Function; @@ -96,7 +98,8 @@ export const AtomicIOS = { config, environment, presentationStyleIOS, - setDebug + setDebug, + wrapperVersion ).then((event: any) => { if (event.finished && onFinish) { removeListeners(); @@ -122,6 +125,9 @@ export const AtomicIOS = { TransactReactNative: any; id: String; environment?: CONSTANTS.TransactEnvironment; + // iOS `presentAction` does not yet accept a platform suffix; accepted here + // for parity with Android callers but not forwarded to native. + wrapperVersion?: string; presentationStyleIOS?: CONSTANTS.PresentationStyleIOS; onLaunch?: Function; onFinish?: Function;