Nhảy tới nội dung

Tích hợp React Native

Yêu cầu
  • Yêu cầu iOS >= 13.0
  • Yêu cầu Android >= 21

Cài đặt cho Android

Bước 1: Tải SDK và cấu hình project

  • Thực hiện các Bước 1 theo hướng dẫn tại đây

Bước 2: Tạo Native Modules (https://reactnative.dev/docs/native-modules-android)

  • Tạo file SmartCAModule.kt ngang hàng với MainApplication.kt như sau
package com.reactnativeapp
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.util.Log
import android.widget.Toast
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.vnpt.smartca.ConfigSDK
import com.vnpt.smartca.SmartCAEnvironment
import com.vnpt.smartca.SmartCALanguage
import com.vnpt.smartca.SmartCAResultCode
import com.vnpt.smartca.VNPTSmartCASDK
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.vnpt.smartca.EkycService

class SmartCAModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

override fun getName() = "SmartCAModule"

private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit(eventName, params)
}

@ReactMethod
fun addListener(type: String?) {
// Keep: Required for RN built in Event Emitter Calls.
}

@ReactMethod
fun removeListeners(type: Int?) {
// Keep: Required for RN built in Event Emitter Calls.
}

@ReactMethod(isBlockingSynchronousMethod = true)
private fun getAuth() {
currentActivity?.runOnUiThread {
try {
VNPTSmartCA.getAuthentication { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// SDK trả lại token, credential của khách hàn
val params = Arguments.createMap().apply {
putInt("code", 0) // 0 is success
putString("statusCode", result.status.toString())
putString("statusDesc", result.statusDesc)
putString("data", result.data.toString())
}

sendEvent(this.reactApplicationContext, "EventReminder", params)
}

else -> {
val params = Arguments.createMap().apply {
putInt("code", 1) // 1 is error
putString("statusCode", result.status.toString())
putString("statusDesc", result.statusDesc)
}
sendEvent(this.reactApplicationContext, "EventReminder", params)

}
}
}
} catch (ex: Exception) {
throw ex;
}
}
}

@ReactMethod(isBlockingSynchronousMethod = true)
private fun getMainInfo() {
currentActivity?.runOnUiThread {
try {
VNPTSmartCA.getMainInfo { result ->
when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// Xử lý khi confirm thành công
}

else -> {
// Xử lý khi confirm thất bại
}
}
}
} catch (ex: java.lang.Exception) {
throw ex;
}
}
}

@ReactMethod(isBlockingSynchronousMethod = true)
private fun getWaitingTransaction(transId: String) {
currentActivity?.runOnUiThread {
try {
VNPTSmartCA.getWaitingTransaction(transId) { result ->
val params = Arguments.createMap().apply {
putInt("code", 0) // 0 is success
putString("statusCode", result.status.toString())
putString("statusDesc", result.statusDesc)
}

sendEvent(this.reactApplicationContext, "EventReminder", params)

when (result.status) {
SmartCAResultCode.SUCCESS_CODE -> {
// Xử lý khi thành công
}

else -> {
// Xử lý khi thất bại
}
}

}
} catch (ex: Exception) {
throw ex;
}
}
}


companion object {

private var VNPTSmartCA = VNPTSmartCASDK()

@SuppressLint("StaticFieldLeak")
private lateinit var context: Context

fun init(context: Context) {
this.context = context
val config = ConfigSDK()
config.context = context
config.partnerId = "<YOUR PARTNER ID>"
config.environment = SmartCAEnvironment.DEMO_ENV
config.lang = SmartCALanguage.VI
config.isFlutter = false
VNPTSmartCA.initSDK(config)
VNPTSmartCA.initEkycService(EkycService(vnptSmartCA = VNPTSmartCA))
val x = mutableListOf<Int>()
x.add(Intent.FLAG_ACTIVITY_NEW_TASK)
VNPTSmartCA.initCustomIntentFlag(x)
}

fun onDestroy() {
VNPTSmartCA.destroySDK();
}
}

}
  • Tạo file MyAppPackage.kt ngang hàng với MainApplication.kt
import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class MyAppPackage : ReactPackage {
override fun createViewManagers(
reactContext: ReactApplicationContext
): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()

override fun createNativeModules(
reactContext: ReactApplicationContext
): MutableList<NativeModule> = listOf(SmartCAModule(reactContext)).toMutableList()
}
  • Kết nối MyAppPackage vào function getPackages trong MainApplication
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
add(MyAppPackage())
}
  • Trong MainActivity thêm hai function sau
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
SmartCAModule.init(this)
}

override fun onDestroy() {
super.onDestroy()
SmartCAModule.onDestroy()
}

Bước 3: Chi tiết các hàm chính

Cài đặt cho iOS

Bước 1: Tải SDK và cấu hình Project

  • Thực hiện các Bước 1 theo hướng dẫn tại đây

Bước 2: Tạo Native Modules (https://reactnative.dev/docs/native-modules-ios)

  • Sử dụng xcode để tạo và mở project ios (*.xcworkspace)
  • Tạo file swift với tên là SmartCAModule.swift, lúc này xcode sẽ gợi ý tạo file để configure an Objective-C Bridging Header, chọn Create Bridging Header
//
// SmartCAModule.swift
//

import Foundation
import SmartCASDK

@objc(SmartCAModule)
class SmartCAModule: RCTEventEmitter {

private var manager: SmartCAManager?
private var hasListeners = false

override init() {
super.init()
self.manager = SmartCAManager.shared
}

override func startObserving() {
hasListeners = true
}

override func stopObserving() {
hasListeners = false
}

@objc func getAuth() {
// SDK tự động xử lý các trường hợp về token: Hết hạn, chưa kích hoạt...
self.manager?.vnptSmartCASDK?.getAuthentication(callback: { result in
if result.status == SmartCAResultCode.SUCCESS_CODE {
// Xử lý khi thành công
if self.hasListeners {
self.sendEvent(withName: "EventReminder", body: ["code": 0, "statusCode": result.status, "statusDesc": result.statusDesc, "data": result.data])
}

} else {
// Xử lý khi thất bại
if self.hasListeners {
self.sendEvent(withName: "EventReminder", body: ["code": 1, "statusCode": result.status, "statusDesc": result.statusDesc])
}
}
});
}

@objc func getMainInfo(){
DispatchQueue.main.async {
self.manager?.vnptSmartCASDK?.getMainInfo(callback: { result in

})
}
}

@objc func getWaitingTransaction(_ tranId: String) {
// self.tranId = "xxxx"; // tạo giao dịch từ backend, lấy tranId từ hệ thống VNPT SmartCA trả về

DispatchQueue.main.async {
self.manager?.vnptSmartCASDK?.getWaitingTransaction(tranId: tranId, callback: { result in
if result.status == SmartCAResultCode.SUCCESS_CODE {
print("Giao dịch thành công: \(result.status) - \(result.statusDesc) - \(result.data)");

if self.hasListeners {
self.sendEvent(withName: "EventReminder", body: ["code": 0, "statusCode": result.status, "statusDesc": result.statusDesc])
}


} else {
if self.hasListeners {
self.sendEvent(withName: "EventReminder", body: ["code": 1, "statusCode": result.status, "statusDesc": result.statusDesc])
}
}
});
}
}

// we need to override this method and
// return an array of event names that we can listen to
override func supportedEvents() -> [String]! {
return ["EventReminder"]
}


@objc
override func constantsToExport() -> [AnyHashable : Any]! {
return ["initialCount": 0]
}

override static func requiresMainQueueSetup() -> Bool {
return true
}


}

class SmartCAManager: NSObject {
static let shared = SmartCAManager()

@objc class func getInstance() -> SmartCAManager {
return SmartCAManager.shared
}

var vnptSmartCASDK: VNPTSmartCASDK?

@objc
func initSDK() {
if let ab = RCTPresentedViewController() {
self.vnptSmartCASDK = VNPTSmartCASDK(
viewController: ab,
partnerId: "CLIENT_ID",
environment: VNPTSmartCASDK.ENVIRONMENT.DEMO,
lang: VNPTSmartCASDK.LANG.VI,
isFlutterApp: false)
}
}

@objc
func destroySDK() {
self.vnptSmartCASDK?.destroySDK();
}
}
  • Cấu hình file *-Bridging-Header.h
//

// Use this file to import your target's public headers that you would like to expose to Swift.

//

#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"
#import <React/RCTUtils.h>
  • Tạo file SmartCAModule.m
// RCTSmartCAModule.m
#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"

@interface RCT_EXTERN_MODULE(SmartCAModule, RCTEventEmitter)
RCT_EXTERN_METHOD(getAuth)
RCT_EXTERN_METHOD(getMainInfo)
RCT_EXTERN_METHOD(getWaitingTransaction: String)
@end

Sử dụng trong React Native

  • Import native module
import {NativeModules} from 'react-native';
  • Khởi tạo
const {SmartCAModule} = NativeModules;
  • Viết hàm lắng nghe sự kiện EventReminder (có thể tạo nhiều sự kiện)
useEffect(() => {
const eventEmitter = new NativeEventEmitter(SmartCAModule)
let eventListener = eventEmitter.addListener('EventReminder', event => {
let code = event.code
let statusCode = event.statusCode
let statusDesc = event.statusDesc
let data = event.data

// todo

// other event if need
let testIOSEvent = eventEmitter.addListener('onIncrement', event => {
console.log('onIncrement event', event);
});

// Removes the listener once unmounted

return () => {
eventListener.remove();
testIOSEvent.remove();
};
}, []);
  • Sử dụng các hàm chính
// get auth
SmartCAModule.getAuth();

// get main info
SmartCAModule.getMainInfo();

// get waiting transaction
let transactionId = 'xxx';
SmartCAModule.getWaitingTransaction(transactionId);

Bước 3: Chi tiết các hàm chính