Capacitor · TypeScript
→
Recognized locally
Payment data
RecipientSanitär Krause
AmountEUR 359.44
IBANDE58 5705 0120 0094 7103 28
PurposeInvoice 2026-0417
IBAN validated by Docutain
Updated 9 min readBy Jonas Richter
Integrate Photo Payment with Capacitor
This guide connects an Ionic or Capacitor UI to Docutain's native Photo Payment flow on Android and iOS.
The Capacitor plugin launches native invoice capture, recognizes GiroCode or invoice data locally and returns structured JSON in result.data. The web layer then maps the result into the application's controlled payment workflow.
- Targets
- Android and iOS
- Language
- TypeScript
- Result
- JSON in result.data
- Processing
- Local in the native SDK
Jump to the Capacitor setup
The Capacitor-to-native payment workflow
- An Ionic or web component invokes the Docutain plugin from a user action.
- The plugin presents native Android or iOS capture and review UI.
- Docutain reads a GiroCode when available or extracts payment fields from invoice text.
- The Promise resolves with an object whose
data property contains JSON, or rejects on cancellation/error. - The web layer maps the JSON to a payment draft before native banking controls continue.
Prepare both native targets
| Area | Requirement |
|---|
| Package | @docutain/capacitor-plugin-docutain-sdk |
| Android | compileSdk 34+, Jetifier enabled and Kotlin 1.8.10+ |
| iOS | An NSCameraUsageDescription for invoice scanning |
| License | A key matching Android applicationId and iOS CFBundleIdentifier |
| Evaluation | Installed native builds on representative physical devices |
Browser preview is useful for the surrounding Ionic UI, but it cannot evaluate the native Docutain capture and recognition flow.
Install, synchronize and initialize the plugin
1. Add the package and update native projects
npm install @docutain/capacitor-plugin-docutain-sdk
npx cap sync
2. Initialize before enabling Photo Payment
import { DocutainSDK } from
'@docutain/capacitor-plugin-docutain-sdk';
async function initializeDocutain(): Promise<boolean> {
try {
await DocutainSDK.initSDK({
licenseKey: '<YOUR-LICENSE-KEY>',
});
return true;
} catch (error) {
// Keep Photo Payment disabled and surface a support path.
reportInitializationError(error);
return false;
}
}
Launch the native UI and classify failures
import { DocutainSDK } from
'@docutain/capacitor-plugin-docutain-sdk';
type DocutainError = { code?: string; message?: string };
async function startPhotoPayment(): Promise<void> {
try {
const result = await DocutainSDK.startPhotoPayment({
// Customize scan, analysis and theming when required.
});
if (result.data === '') {
// No data was found. This is reachable when the
// Empty Result Screen has been disabled.
showManualEntry();
return;
}
processPaymentData(result.data);
} catch (unknownError) {
const error = unknownError as DocutainError;
if (error.code === 'CANCELED') {
return; // Expected user cancellation.
}
reportPhotoPaymentError(error);
}
}
Keep the launch action single-flight until the Promise settles. Handle CANCELED separately so user cancellation does not pollute production error monitoring.
Map result.data into a payment draft
{
"Address": {
"Name1": "Sanitär Krause",
"Zipcode": "56068",
"City": "Koblenz",
"Street": "Musterstraße 17",
"Bank": [{
"BIC": "MALADE51KOB",
"IBAN": "DE58570501200094710328"
}]
},
"Date": "2026-04-17",
"Amount": "359.44",
"InvoiceId": "2026-0417",
"Reference": "Invoice 2026-0417",
"PaymentState": "ToBePaid",
"SEPACreditor": "Sanitär Krause"
}
SEPACreditor is the payment recipient. Keep the DTO fields optional, because documents may omit values. Docutain returns only valid IBANs, but the host application must still confirm recipient, IBAN, amount and reference before authorization.
Configure analysis and fallback behavior
The start options also cover capture behavior, page editing, onboarding, Scan Tips, colors and the Empty Result Screen. Add optional analysis fields only when the target payment model uses them.
const result = await DocutainSDK.startPhotoPayment({
analyzeConfig: {
// Add the optional paid/to-be-paid classification.
readPaymentState: true,
},
// Keep the default retry screen during evaluation.
});
Disabling BIC changes the bank-data shape to an IBAN list. Coordinate configuration and mapper changes. GiroCode and invoice OCR use the same Photo Payment entry point, avoiding a separate barcode choice in the Ionic interface.
Test the web layer and both native shells
- Start with the Android and iOS Showcase Apps, then use a trial license in the installed Capacitor app.
- Test the same approved invoice corpus on representative physical devices.
- Include paper invoices, files and GiroCodes under realistic lighting.
- Measure correct, missing and incorrect results per field and the required manual corrections.
- Verify empty data,
CANCELED, initialization failure, bridge failure and retry/manual entry. - Test repeated navigation, app backgrounding, native project updates after
cap sync and double-tap prevention. - Check accessibility in both the web-based payment screen and native capture UI.
Official resources
Technical sources last checked on September 13, 2026.
FREQUENTLY ASKED QUESTIONS
Capacitor Photo Payment integration
Yes. Supported payment data is recognized on the Android or iOS device without an external recognition server. The host app controls any subsequent storage or transfer.
DocutainSDK.startPhotoPayment returns a response whose data property contains the payment JSON.
A rejected promise with error code CANCELED means the user canceled the flow.
No. It returns structured payment data. The banking app remains responsible for review, business rules, authorization and execution.