Ouvrez la capture depuis une application Ionic avec un plugin Capacitor local.
Votre back-end crée le processus dans Human Plugin avec un flux Journey et un callbackUri qui utilise le scheme d'URL de votre application. Un plugin Capacitor local ouvre le link de la réponse dans Custom Tabs sur Android et dans ASWebAuthenticationSession sur iOS. Lorsque la capture se termine, le plugin se résout et l'application reprend la main.
Conservez l'id Human Plugin de la réponse de création. Votre back-end lit le résultat avec cet id.
Prérequis
- Ionic avec Capacitor 4 ou version ultérieure
- Xcode 14 ou version ultérieure, et Android Studio
- Un scheme d'URL propre à votre application, tel que
myapp
1. Créer le processus avec votre scheme
Votre back-end envoie le scheme comme callbackUri :
{
"flow": "humantoken",
"clientId": "client-a",
"correlationId": "order-1001",
"credential": { "type": "DUI_TYPE_NG_BVN", "value": "<document number>" },
"callbackUri": "myapp://callback"
}
et renvoie id et link à l'application.
2. Définir l'interface du 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. Implémenter le plugin 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. Implémenter le plugin 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. Enregistrer votre scheme
- iOS
- Android
Dans Info.plist :
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Dans AndroidManifest.xml, à l'intérieur de votre <activity> principale :
<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>
Dans build.gradle :
implementation("androidx.browser:browser:1.5.0")
6. Démarrer la capture
Un service Angular autour du plugin :
import { Injectable } from '@angular/core';
import Capture from '../plugins/capture-plugin';
@Injectable({ providedIn: 'root' })
export class CaptureService {
/** Se résout à true lorsque la capture est terminée, à false lorsque la personne l'a fermée. */
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 capture est terminée. Demandez à votre back-end de lire le résultat
// avec GET /v1/processes/{id}, en utilisant l'id Human Plugin.
}
Récapitulatif
| Fichier | Rôle |
|---|---|
capture-plugin.ts | Interface du plugin Capacitor |
CapturePlugin.swift | iOS : ASWebAuthenticationSession |
CapturePlugin.kt | Android : Custom Tabs |
Info.plist | Scheme d'URL iOS |
AndroidManifest.xml | Intent filter Android |
capture.service.ts | Service Angular |