Pengambilan di React Native
Buka pengambilan dari aplikasi React Native dengan native module.
Back-end Anda membuat proses di Human Plugin dengan alur Journey dan callbackUri yang menggunakan URL scheme aplikasi Anda. Sebuah native module membuka link dari respons di ASWebAuthenticationSession pada iOS dan di Custom Tabs pada Android. Saat pengambilan berakhir, module menyelesaikan promise-nya dan aplikasi mengambil alih.
Simpan id Human Plugin dari respons pembuatan. Back-end Anda membaca hasilnya dengannya.
Prasyarat
- React Native 0.71 atau lebih baru
- Xcode 14 atau lebih baru untuk iOS
- Android Studio untuk Android
- URL scheme yang unik untuk aplikasi Anda, seperti
myapp
1. Buat proses dengan scheme Anda
Back-end Anda mengirim scheme sebagai callbackUri:
{
"flow": "humantoken",
"clientId": "client-a",
"correlationId": "order-1001",
"credential": { "type": "DUI_TYPE_NG_BVN", "value": "<document number>" },
"callbackUri": "myapp://callback"
}
dan mengembalikan id serta link ke aplikasi.
2. Buat bridge TypeScript
// src/modules/CaptureModule.ts
import { NativeModules } from 'react-native';
const { CaptureModule } = NativeModules;
if (!CaptureModule) {
throw new Error('CaptureModule not found. Make sure the native module is linked correctly.');
}
export const Capture = {
openSession: (url: string): Promise<string> => CaptureModule.openSession(url),
};
3. Implementasikan module iOS
- Bridge Objective-C
- Implementasi Swift
// ios/CaptureModule.m
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(CaptureModule, NSObject)
RCT_EXTERN_METHOD(openSession:(NSString *)url
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
@end
// ios/CaptureModule.swift
import AuthenticationServices
@objc(CaptureModule)
class CaptureModule: NSObject, ASWebAuthenticationPresentationContextProviding {
private var session: ASWebAuthenticationSession?
@objc func openSession(_ url: String,
resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock) {
guard let sessionURL = URL(string: url) else {
reject("INVALID_URL", "Invalid URL", nil)
return
}
DispatchQueue.main.async {
let newSession = ASWebAuthenticationSession(
url: sessionURL,
callbackURLScheme: "myapp"
) { callbackURL, error in
self.session = nil
if let callbackURL = callbackURL {
resolve(callbackURL.absoluteString)
} else {
reject("SESSION_ERROR", error?.localizedDescription ?? "Session cancelled", error)
}
}
newSession.presentationContextProvider = self
newSession.prefersEphemeralWebBrowserSession = true
newSession.start()
self.session = newSession
}
}
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first else {
return ASPresentationAnchor()
}
return window
}
@objc static func requiresMainQueueSetup() -> Bool { return true }
}
4. Implementasikan module Android
Tambahkan dependensi ke android/app/build.gradle:
implementation("androidx.browser:browser:1.5.0")
// android/app/src/main/java/<your.package>/CaptureModule.kt
package com.yourapp
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import com.facebook.react.bridge.*
class CaptureModule(private val reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
private var pendingPromise: Promise? = null
override fun getName() = "CaptureModule"
@ReactMethod
fun openSession(url: String, promise: Promise) {
pendingPromise = promise
currentActivity?.runOnUiThread {
CustomTabsIntent.Builder().build()
.launchUrl(currentActivity!!, Uri.parse(url))
} ?: promise.reject("NO_ACTIVITY", "No current activity")
}
fun handleRedirectUrl(uri: Uri) {
if (uri.scheme == "myapp") {
pendingPromise?.resolve(uri.toString())
pendingPromise = null
}
}
}
// CapturePackage.kt
package com.yourapp
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class CapturePackage : ReactPackage {
override fun createNativeModules(ctx: ReactApplicationContext): List<NativeModule> =
listOf(CaptureModule(ctx))
override fun createViewManagers(ctx: ReactApplicationContext): List<ViewManager<*, *>> =
emptyList()
}
Daftarkan di MainApplication.kt:
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(CapturePackage())
}
Tangani kembalinya pengguna di MainActivity.kt:
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
intent.data?.let { uri ->
if (uri.scheme == "myapp") {
val module = reactInstanceManager
.currentReactContext
?.getNativeModule(CaptureModule::class.java)
module?.handleRedirectUrl(uri)
}
}
}
5. Daftarkan scheme Anda di Android
Di AndroidManifest.xml:
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<activity android:name=".MainActivity" ...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="callback" />
</intent-filter>
</activity>
6. Mulai pengambilan
import { Capture } from './modules/CaptureModule';
try {
await Capture.openSession(link);
// Pengambilan berakhir. Minta back-end Anda membaca hasilnya
// dengan GET /v1/processes/{id}, menggunakan id Human Plugin.
} catch {
// Orang tersebut menutup sesi.
}
Ringkasan
| File | Tujuan |
|---|---|
src/modules/CaptureModule.ts | Bridge TypeScript |
ios/CaptureModule.m | Deklarasi Objective-C |
ios/CaptureModule.swift | iOS: ASWebAuthenticationSession |
android/.../CaptureModule.kt | Android: Custom Tabs |
android/.../CapturePackage.kt | Pendaftaran package |
android/.../MainApplication.kt | Menambahkan package |
android/.../MainActivity.kt | Menangani kembalinya pengguna |
AndroidManifest.xml | Intent filter |