21. Oktober 2025 by Marvin
Fotoüberweisung einfach, schnell & sicher in Banking-Apps integriert
Sie wollen direkt zum Code springen?
Hier geht's zum Code
Docutain Photo Payment SDK
Mit dem Docutain Photo Payment SDK kann die Funktion der Fotoüberweisung in nur wenigen Minuten in Banking-Apps integriert werden.
Die Datenerkennung und Datenextraktion findet lokal auf dem Gerät des Nutzers statt. Keine Datenübertragung auf externe Server, wie es bei anderen Anbietern der Fall ist.
Dadurch erhalten Sie:
-
100% Datenschutz und keine Gefahren eines Serverhackings
-
100% Geschwindigkeit - Datenerkennung in Echtzeit
-
100% Verfügbarkeit - Die Fotoüberweisung steht 24/7 an 365 Tagen zur Verfügung
-
100% weniger sonstige Aufwände - Z.B. zu prüfende und überwachende Anforderungen bezüglich IKT-Dienstleitungen im Rahmen von DORA
In einigen Banking-Apps wie der Sparkasse, DKB oder Consorsbank ist die Funktion der Fotoüberweisung bereits integriert. Im Gegensatz zum Docutain Photo Payment SDK hat die dort integrierte Fotoüberweisungsfunktion einen entscheidenden Nachteil: Der Anbieter arbeitet serverbasiert, d.h. beim Scan der Rechnung mit der Banking-App wird der gesamte Scan an einen externen Server gesendet, um die Rechnungsdaten dort auszulesen. Rechnungen enthalten viele sensible Inhalte und lassen Rückschlüsse auf Vorlieben, Einstellungen, Krankheiten und mehr zu. Dies sind Informationen, die nicht für die Fotoüberweisung benötigt werden. Lediglich die IBAN, der Betrag, der Empfänger und ein Verwendungszweck sind entscheidende Informationen. Dennoch werden bei dem serverbasierten Anbieter alle Inhalte der Rechnung ausgelesen und vorgehalten. Neben dem Datenschutzrisiko kann auch das Risiko eines Serverausfalls oder Serverhackings nie 100% ausgeschlossen werden.
Mit der Fotoüberweisung des Docutain SDK werden Scans von Rechnungen gemacht und die Informationen in Echtzeit auf dem Gerät des Nutzers ausgelesen – ohne externe Server, sondern 100% lokal auf dem Gerät, um maximalen Datenschutz zu garantieren.
Kunden wie die PKO Bank Polski, Polens größte Bank, die Star Finanz GmbH mit StarMoney und SFirm und die 1822direkt Bank vertrauen bereits auf das Docutain SDK.
Im folgenden Artikel erklären wir, wie Sie das Docutain Photo Payment SDK in nur wenigen Minuten in Ihre Banking-App integrieren können.
Docutain Fotoüberweisungs-SDK
Erfahren Sie mehr zum Docutain Photo Payment SDK, welches Sie in nur wenigen Minuten integrieren können.
Testen Sie das Docutain SDK, ohne auch nur eine Zeile Code zu schreiben und laden Sie sich die Showcase App herunter.
Fotoüberweisung integrieren
Die Fotoüberweisung von Docutain steht für alle relevanten Plattformen und Frameworks zur Verfügung: Android, iOS, Windows, React Native,
.NET MAUI, Flutter, Capacitor (Ionic) und Cordova. In der Dokumentation wählen Sie einfach die
gewünschte Plattform aus und finden dort alle was Sie wissen müssen. In nachfolgendem Beispiel gehen wir von einem Android Kotlin Projekt aus.
Hinzufügen des Docutain Photo Payment SDK
Bevor Sie Docutain's Fotoüberweisung in Ihrer App nutzen können, müssen Sie zunächst die notwendigen Pakete zu Ihrer App hinzufügen.
Im Falle von Android geschieht dies klassisch über Maven Dependencies in der build.gradle
:
def docutainSdkVersion = '1.8.2.0'
implementation("de.docutain:Docutain-SDK-UI:$docutainSdkVersion")
implementation("de.docutain:Docutain-SDK-DataExtraction:$docutainSdkVersion")
Initialisieren des Docutain Photo Payment SDK
Bevor Sie die Fotoüberweisung starten können, muss das Docutain SDK zunächst initialisiert werden.
Zu Testzwecken können Sie den Lizenzschlüssel leer lassen. Beachten Sie jedoch, dass das SDK dann nur 60 Sekunden genutzt werden kann.
Anschließend müssen Sie die App neu starten um es wieder nutzen zu können. Wenn Sie länger testen möchten, können Sie sich eine
kostenlose Testlizenz erstellen.
import de.docutain.sdk.DocutainSDK;
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(!DocutainSDK.initSDK(this.application, "")){
//init of Docutain SDK failed, get the last error message
val error = DocutainSDK.getLastError()
//your logic to deactivate access to SDK functionality
}
}
}
Starten der Fotoüberweisung
Um die Fotoüberweisung zu starten, müssen Sie nur einen ActivityResultLauncher
mit unserem vordefinierten
PhotoPaymentResult
starten. Übergeben Sie dem Launcher eine PhotoPaymentConfiguration
. Darüber haben Sie
die Möglichkeit, die Fotoüberweisung an Ihren Bedarf und das Corporate Branding anzupassen. Details dazu finden Sie in der
Dokumentation.
Zu Testzwecken nutzen wir die Standardeinstellungen.
import de.docutain.sdk.ui.PhotoPaymentResult
val photoPaymentResult = registerForActivityResult(PhotoPaymentResult()) { data ->
if(data != null){
if(data.isNotEmpty()){
// data is a JSON string containing the information
// extract the fields you need and pass it on to your payment sheet
} else{
// no data was extracted at all
// Note: this case is only reachable, if you disabled the Empty Result Screen
}
} else{
// user canceled scan process
}
}
myButton.setOnClickListener {
val paymentConfig = PhotoPaymentConfiguration()
photoPaymentResult.launch(paymentConfig)
}
Wenn Sie nun den ActivityResultLauncher
starten, sollten Sie die Rechnung wie in nachfolgendem Video scannen können.
Möglicherweise wird Ihnen vor dem ersten Scan ein Onboarding angezeigt. Die Anzeige der erkannten Daten wie am Ende des Video ist bis
hierhin noch nicht Bestandteil des Codes. Dies finden Sie am Ende des Tutorials.
Zahlungsdaten extrahieren
Die erkannten Daten der Rechnung werden als JSON
string zurückgegeben. Nachfolgend ein Beispiel der extrahierten
Daten, die zu einer Bahncard Rechnung gehören:
{
"Address":
{
"Name1": "DB Fernverkehr AG",
"Name2": "",
"Name3": "",
"Zipcode": "60643",
"City": "Frankfurt am Main",
"Street": "BahnCard-Service",
"Phone": "0302970",
"CustomerId": "",
"Bank": [{"BIC": "PBNKDEFFXXX",
"IBAN": "DE02100100100152517108"}]
},
"Date": "2024-10-14",
"Amount": "244.00",
"InvoiceId": "2023174086",
"Reference": "RNr:2023174086 vom 14.10.2024",
"SEPACreditor": "DB Vertrieb GmbH"
}
Optional kann auch der Bezahlstatus ausgelesen werden, der angibt, ob die Rechnung bereits gezahlt wurde oder nicht.
Details dazu finden Sie in der Dokumentation.
Leerer Ergebnisbildschirm
Sollten keinerlei Zahldaten extrahiert werden können, wird standardmäßig ein Bildschirm mit einigen Tipps und einer Option zum Abbrechen oder Wiederholen des Scans angezeigt.
Sie können diesen Bildschirm nach Ihren Bedürfnissen anpassen oder vollständig deaktivieren. Details dazu finden Sie in der
Dokumentation.
Onboarding
Sie möchten Ihren App Nutzern vielleicht den Einstieg in die Fotoüberweisungsfunktion erleichtern und ihnen einige Erläuterungen
& Tipps geben. Zu diesem Zweck bietet das Docutain SDK zwei Onboarding-UI-Komponenten. Sie können entweder die
Standardeinstellungen verwenden oder die Inhalte nach Ihren Bedürfnissen anpassen, bzw. auch komplett deaktivieren.
Details finden Sie im Dokumentatiosabschnitt: Onboarding.
Scan Tipps
Auch wenn das Docutain SDK in sämtlichen Szenarien die bestmöglichen Scanergebnisse liefert, möchten Sie Ihren App Nutzern
möglicherweise dennoch einen Bildschirm mit Tipps zur Erzielung der besten Scanergebnisse anzeigen. Standardmäßig finden Sie
dazu eine entsprechendes Toolbar Item oben rechts im Scan-Bildschirm. Die Scan-Tipps können nach Ihrem Bedarf angepasst oder deaktiviert werden.
Weitere Informationen finden Sie hier: Scan Tipps.
Bonus: Erkannte Zahlungsdaten anzeigen
Da jede Banking App Ihr eigenes UI für das Überweisungsformular hat, beinhaltet das Docutain SDK entsprechend keine UI Komponenten
zur Anzeige der erkannten Zahldaten. Damit Sie im Sinne dieses Beispiels jedoch die erkannten Daten auch optisch anzeigen können, finden Sie
nachfolgend ein beispielhaftes Layout.
Legen Sie eine neue Layout Datei an und nennen Sie sie activity_photo_payment_result
. Fügen Sie den folgenden Code ein:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/materialToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/materialToolbar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_payment_recipient"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="Payment Recipient">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_IBAN"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="IBAN">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_BIC"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="BIC">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_Amount"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="Amount">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_customerId"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="CustomerId">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_InvoiceId"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="InvoiceId">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textField_reference"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="Reference">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Erstellen Sie nun eine neue AppCompatActivity
und nennen Sie sie PhotoPaymentResultActivity
.
Entfernen Sie den kompletten Code bis auf die oberste Zeile in der das package
definiert ist und fügen Sie den nachfolgenden Code ein.
import android.os.Bundle
import com.google.android.material.textfield.TextInputLayout
import org.json.JSONObject
internal class PhotoPaymentResultActivity : AppCompatActivity() {
private lateinit var textViewRecipient: TextInputLayout
private lateinit var textViewCustomerID: TextInputLayout
private lateinit var textViewIBAN: TextInputLayout
private lateinit var textViewBIC: TextInputLayout
private lateinit var textViewAmount: TextInputLayout
private lateinit var textViewInvoiceId: TextInputLayout
private lateinit var textViewReference: TextInputLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_photo_payment_result)
supportToolbar()
initTextfields()
val data = intent.getStringExtra("data")
loadData(data!!)
}
private fun initTextfields() {
textViewRecipient = findViewById(R.id.textField_payment_recipient)
textViewCustomerID = findViewById(R.id.textField_customerId)
textViewIBAN = findViewById(R.id.textField_IBAN)
textViewBIC = findViewById(R.id.textField_BIC)
textViewAmount = findViewById(R.id.textField_Amount)
textViewInvoiceId = findViewById(R.id.textField_InvoiceId)
textViewReference = findViewById(R.id.textField_reference)
}
private fun loadData(data: String) {
try {
val jsonArray = JSONObject(data)
val address = JSONObject(jsonArray.getString("Address"))
val customerId = address.getString("CustomerId")
val bank = address.optJSONArray("Bank")
var sIBAN = ""
var sBIC = ""
if (bank != null) {
(0 until bank.length()).forEach {
if (sIBAN.isNotEmpty())
sIBAN += "\n"
if (sBIC.isNotEmpty())
sBIC += "\n"
val item = bank.getJSONObject(it)
sIBAN += item.getString("IBAN")
sBIC += item.getString("BIC")
}
}
val amount = jsonArray.getString("Amount")
val invoiceId = jsonArray.getString("InvoiceId")
val reference = jsonArray.getString("Reference")
val recipient = jsonArray.optString("SEPACreditor")
if (recipient.isNotEmpty()) {
textViewRecipient.editText!!.setText(recipient)
}
if (customerId.isNotEmpty()) {
textViewCustomerID.editText!!.setText(customerId)
}
if (sIBAN.isNotEmpty()) {
val regex = ".{4}".toRegex()
textViewIBAN.editText!!.setText(sIBAN.replace(regex, "\$0 "))
}
if (sBIC.isNotEmpty()) {
textViewBIC.editText!!.setText(sBIC)
}
if (amount.isNotEmpty() && (amount != "0.00")) {
textViewAmount.editText!!.setText(amount)
}
if (invoiceId.isNotEmpty()) {
textViewInvoiceId.editText!!.setText(invoiceId)
}
if (reference.isNotEmpty()) {
textViewReference.editText!!.setText(reference)
}
} catch (ex: Exception) {
// TODO: error handling
}
}
}
Starten Sie nun die PhotoPaymentResultActivity
, nachdem die Fotoüberweisung erfolgreich war.
Passen Sie dazu den Code zum Starten der Fotoüberweisung wie folgt an:
private val photoPaymentResult = registerForActivityResult(PhotoPaymentResult()) { data ->
if (data != null) {
val intent = Intent(this@MainActivity, PhotoPaymentResultActivity::class.java).apply {
putExtras(bundleOf("data" to data))
}
startActivity(intent)
}
}
myButton.setOnClickListener {
val paymentConfig = PhotoPaymentConfiguration()
photoPaymentResult.launch(paymentConfig)
}
Docutain Scanner & Datenextraktions-SDK
Erfahren Sie mehr zum Docutain SDK. Neben dem Photo Payment SDK
gibt es auch ein Barcode Scanner SDK und ein Document Scanner SDK. Alle SDKs sind für alle gängigen Plattformen & Frameworks verfügbar.
Testen Sie das Docutain SDK, ohne auch nur eine Zeile Code zu schreiben und laden Sie sich die Showcase App herunter.
Folgende Artikel könnten Sie auch interessieren