Saltar al contenido principal
Captura en Ionic

Abre la captura desde una app Ionic con un plugin local de Capacitor.

Markdown

Tu backend crea el proceso en Human Plugin con un flujo Journey y un callbackUri que usa el esquema de URL de tu app. Un plugin local de Capacitor abre el link de la respuesta en Custom Tabs en Android y en ASWebAuthenticationSession en iOS. Cuando la captura termina, el plugin se resuelve y la app retoma el control.

Conserva el id de Human Plugin de la respuesta de la creación. Tu backend lee el resultado con él.

Requisitos previos​

  • Ionic con Capacitor 4 o posterior
  • Xcode 14 o posterior, y Android Studio
  • Un esquema de URL único para tu app, como myapp

1. Crea el proceso con tu esquema​

Tu backend envía el esquema como callbackUri:

{
"flow": "humantoken",
"clientId": "client-a",
"correlationId": "order-1001",
"credential": { "type": "DUI_TYPE_NG_BVN", "value": "<document number>" },
"callbackUri": "myapp://callback"
}

y devuelve id y link a la app.

2. Define la interfaz del plugin​

// src/plugins/capture-plugin.ts
import { registerPlugin } from '@capacitor/core';

export interface CapturePlugin {
openSession(options: { url: string }): Promise<{ callbackUrl: string }>;
}

const Capture = registerPlugin<CapturePlugin>('CapturePlugin');
export default Capture;

3. Implementa el plugin de iOS​

import Capacitor
import AuthenticationServices

@objc(CapturePlugin)
public class CapturePlugin: CAPPlugin, ASWebAuthenticationPresentationContextProviding {
private var session: ASWebAuthenticationSession?

@objc func openSession(_ call: CAPPluginCall) {
guard let urlString = call.getString("url"),
let url = URL(string: urlString) else {
call.reject("Invalid URL")
return
}

DispatchQueue.main.async {
let newSession = ASWebAuthenticationSession(
url: url,
callbackURLScheme: "myapp"
) { callbackURL, error in
self.session = nil
if let callbackURL = callbackURL {
call.resolve(["callbackUrl": callbackURL.absoluteString])
} else {
call.reject(error?.localizedDescription ?? "Session cancelled")
}
}
newSession.presentationContextProvider = self
newSession.prefersEphemeralWebBrowserSession = true
newSession.start()
self.session = newSession
}
}

public 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
}
}

4. Implementa el plugin de Android​

import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import com.getcapacitor.JSObject
import com.getcapacitor.Plugin
import com.getcapacitor.PluginCall
import com.getcapacitor.PluginMethod
import com.getcapacitor.annotation.CapacitorPlugin

@CapacitorPlugin(name = "CapturePlugin")
class CapturePlugin : Plugin() {

private var pendingCall: PluginCall? = null

@PluginMethod
fun openSession(call: PluginCall) {
val url = call.getString("url") ?: return call.reject("Missing URL")
pendingCall = call

activity.runOnUiThread {
CustomTabsIntent.Builder().build()
.launchUrl(activity, Uri.parse(url))
}
}

override fun handleOnNewIntent(intent: Intent) {
super.handleOnNewIntent(intent)
intent.data?.let { uri ->
if (uri.scheme == "myapp") {
pendingCall?.resolve(JSObject().put("callbackUrl", uri.toString()))
pendingCall = null
}
}
}
}

5. Registra tu esquema​

En Info.plist:

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>

6. Inicia la captura​

Un servicio de Angular alrededor del plugin:

import { Injectable } from '@angular/core';
import Capture from '../plugins/capture-plugin';

@Injectable({ providedIn: 'root' })
export class CaptureService {
/** Se resuelve con true cuando la captura terminó, con false cuando la persona la cerró. */
async open(link: string): Promise<boolean> {
try {
await Capture.openSession({ url: link });
return true;
} catch {
return false;
}
}
}
const ended = await this.captureService.open(link);
if (ended) {
// La captura terminó. Pide a tu backend que lea el resultado
// con GET /v1/processes/{id}, usando el id de Human Plugin.
}

Resumen​

ArchivoPropósito
capture-plugin.tsInterfaz del plugin de Capacitor
CapturePlugin.swiftiOS: ASWebAuthenticationSession
CapturePlugin.ktAndroid: Custom Tabs
Info.plistEsquema de URL de iOS
AndroidManifest.xmlIntent filter de Android
capture.service.tsServicio de Angular