Business Logik Beispiele
Bankdaten-Agent
Automatisierte Bearbeitung von Bankverbindungsänderungen
Tip
Der Bankdaten-Agent ist ein spezialisierter KI-Agent für die effiziente Bearbeitung von Änderungswünschen zu Bankverbindungen. Er validiert und verarbeitet Kundenanfragen zur Aktualisierung von Bankdaten automatisch und sorgt für eine nahtlose Integration in bestehende Zahlungssysteme. Durch intelligente Prüfmechanismen und strukturierte Prozesse werden Bankdatenänderungen präzise, sicher und mit minimalem manuellem Aufwand durchgeführt.
Zentrale Funktionen
Der Bankdaten-Agent übernimmt den kompletten Prozess der Bankdatenaktualisierung und bietet dabei folgende Kernfunktionalitäten:
- IBAN-Validierung: Automatische Prüfung der Format- und Prüfsummenkonformität neuer Bankverbindungen
- Identitätsprüfung: Abgleich des Kontoinhabers mit Vertragsinformationen zur Sicherstellung der Legitimität
- Systemintegration: Nahtlose Aktualisierung der Bankdaten in allen relevanten Systemen
- Kundenkommunikation: Automatisierte Bestätigungen über erfolgreiche Änderungen oder Rückfragen bei Unklarheiten
Prozessablauf
Der Agent arbeitet nach einem klar definierten Prozess, der maximale Sicherheit bei gleichzeitig hoher Benutzerfreundlichkeit gewährleistet:
- Extraktion relevanter Daten aus der Kundenanfrage (neue IBAN, Kontoinhaber, gewünschtes Datum)
- Validierung der neuen Bankverbindung anhand internationaler Standards
- Prüfung der Berechtigung zur Änderung der Bankdaten
- Durchführung der Änderung in allen verknüpften Systemen
- Bestätigung an den Kunden mit den relevanten Informationen zur neuen Bankverbindung
Durch die regelbasierte Logik werden alle Eingaben systematisch geprüft und verarbeitet, sodass Fehler minimiert und gleichzeitig der manuelle Bearbeitungsaufwand deutlich reduziert wird.
<?php
use EnneoSDK\Api;
use EnneoSDK\Helpers;
use EnneoSDK\IntentInfo;
use EnneoSDK\IntentOption;
use EnneoSDK\Interaction;
require(getenv()['SDK'] ?? 'sdk.php');
/** @var stdClass $in */
######### Expected Input:
// date -> Date for deposit change (optional)
// channel -> ticket channel. Voice and chat can be handled synchronously (required)
// newIBAN -> IBAN of the new bank account (required)
// oldIBAN -> IBAN of the old bank account (optional)
// payoutOnly -> true if only payout should be changed (optional)
// Initialize variables
if ($in->date ?? false) {
$in->date = Helpers::parseDateToYMD($in->date);
} else {
$in->date = date('Y-m-d', strtotime('+1 day'));
}
$interaction = new Interaction(data: $in);
$interaction->data->oldIBAN = formatIban($in->oldIBAN ?: "");
$interaction->data->newIBAN = formatIban($in->newIBAN ?: "");
// Handle actual change of bank data in the backend system
if ($in->_action == 'enter_into_system') {
$response = Api::call(
method: 'POST',
url: 'https://echo.enneo.ai',
params: json_decode(json_encode($interaction), true)
);
echo json_encode($interaction);
exit();
}
// Business logic
if ($in->oldIBAN == $in->newIBAN && $in->newIBAN) {
$interaction->infos[] = new IntentInfo(
type: 'warning',
message: 'IBAN ist schon im System',
);
$interaction->options[] = new IntentOption(
type: 'iban_already_in_system',
name: 'Kunden darauf hinweisen',
recommended: true,
);
} elseif (!validateIbanFormatting($in->newIBAN)) {
$interaction->infos[] = new IntentInfo(
type: 'warning',
message: 'IBAN nicht im korrekten Format',
);
$interaction->options[] = new IntentOption(
type: 'ask_for_verification_iban_invalid_format',
name: 'Kunden darauf hinweisen',
recommended: true,
);
} elseif (!validateIbanChecksum($in->newIBAN)) {
$interaction->infos[] = new IntentInfo(
type: 'warning',
message: 'IBAN-Prüfsumme ungültig',
);
$interaction->options[] = new IntentOption(
type: 'ask_for_verification_iban_invalid_checksum',
name: 'Kunden darauf hinweisen',
recommended: true,
);
} else {
if ($in->date < date('Y-m-d')) {
// If the customer wants to use an IBAN effective in the past, we default to tomorrow
$interaction->infos[] = new IntentInfo(
type: 'warning',
message: 'Gewünschtes Gültigkeitsdatum '.EnneoSDK\Helpers::formatDate($in->date).' liegt in der Vergangenheit. Gültigkeit auf morgen gesetzt'
);
$interaction->data->date = date('Y-m-d', strtotime('+1 day'));
}
$interaction->infos[] = new IntentInfo(
type: 'success',
message: 'IBAN gültig',
);
if ($in->payoutOnly) {
$msg = 'Im System nur für Guthaben hinterlegen';
} else {
$msg = 'Im System hinterlegen';
}
$interaction->options[] = new IntentOption(
type: 'enter_into_system',
name: $msg,
recommended: true,
);
}
// Return result
echo json_encode($interaction);
// Format IBAN for readability
function formatIban(string $iban): string
{
$iban = str_replace(' ', '', $iban);
// Split the input string into 4-character chunks for readability
$formatted_iban = '';
$chunk_size = 4;
$num_chunks = ceil(strlen($iban) / $chunk_size);
for ($i = 0; $i < $num_chunks; ++$i) {
$chunk = substr($iban, $i * $chunk_size, $chunk_size);
$formatted_iban .= $chunk . ' ';
}
// Trim any trailing spaces and return the formatted IBAN
return trim($formatted_iban);
}
// Check integrity of IBAN (modified from original source: https://stackoverflow.com/questions/20983339/validate-iban-php)
function validateIbanChecksum(string $iban): bool
{
$iban = strtolower(str_replace(' ', '', $iban));
$Countries = ['al' => 28, 'ad' => 24, 'at' => 20, 'az' => 28, 'bh' => 22, 'be' => 16, 'ba' => 20, 'br' => 29, 'bg' => 22, 'cr' => 21, 'hr' => 21, 'cy' => 28, 'cz' => 24, 'dk' => 18, 'do' => 28, 'ee' => 20, 'fo' => 18, 'fi' => 18, 'fr' => 27, 'ge' => 22, 'de' => 22, 'gi' => 23, 'gr' => 27, 'gl' => 18, 'gt' => 28, 'hu' => 28, 'is' => 26, 'ie' => 22, 'il' => 23, 'it' => 27, 'jo' => 30, 'kz' => 20, 'kw' => 30, 'lv' => 21, 'lb' => 28, 'li' => 21, 'lt' => 20, 'lu' => 20, 'mk' => 19, 'mt' => 31, 'mr' => 27, 'mu' => 30, 'mc' => 27, 'md' => 24, 'me' => 22, 'nl' => 18, 'no' => 15, 'pk' => 24, 'ps' => 29, 'pl' => 28, 'pt' => 25, 'qa' => 29, 'ro' => 24, 'sm' => 27, 'sa' => 24, 'rs' => 22, 'sk' => 24, 'si' => 19, 'es' => 24, 'se' => 24, 'ch' => 21, 'tn' => 24, 'tr' => 26, 'ae' => 23, 'gb' => 22, 'vg' => 24];
$Chars = ['a' => 10, 'b' => 11, 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17, 'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23, 'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29, 'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35];
if (!array_key_exists(substr($iban, 0, 2), $Countries)) {
return false;
}
if (strlen($iban) == $Countries[substr($iban, 0, 2)]) {
$MovedChar = substr($iban, 4) . substr($iban, 0, 4);
$MovedCharArray = str_split($MovedChar);
$NewString = '';
foreach ($MovedCharArray as $key => $value) {
if (!is_numeric($MovedCharArray[$key])) {
$MovedCharArray[$key] = $Chars[$MovedCharArray[$key]];
}
$NewString .= $MovedCharArray[$key];
}
if (bcmod($NewString, '97') == 1) {
return true;
}
}
return false;
}
// Check formatting of IBAN
function validateIbanFormatting(string $str): bool
{
// Note: German IBAN definition allows for slack
// Correct IBAN definition: DE[0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
if (str_starts_with($str,'DE')) {
$re = 'DE\s?[0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?';
// Find all IBAN addresses
if (preg_match_all('/' . $re . '/', $str, $m)) {
return true;
} else {
return false;
}
} else {
// International IBANs are validated in the validateIbanChecksum() function
return true;
}
}import importlib.util
import os
import json
import re
from datetime import datetime, timedelta
file_path = os.getenv('SDK', 'sdk.py')
spec = importlib.util.spec_from_file_location('sdk', file_path)
sdk = importlib.util.module_from_spec(spec)
spec.loader.exec_module(sdk)
######### Expected Input:
# date -> Date for deposit change (optional)
# channel -> ticket channel. Voice and chat can be handled synchronously (required)
# newIBAN -> IBAN of the new bank account (required)
# oldIBAN -> IBAN of the old bank account (optional)
# payoutOnly -> true if only payout should be changed (optional)
def parse_date_to_ymd(date_str):
"""
Parse a textual date into yyyy-mm-dd format.
Matches the PHP parseDateToYMD function.
"""
if not date_str:
return None
# Try standard date parsing first
try:
parsed_date = datetime.strptime(date_str, '%Y-%m-%d')
return parsed_date.strftime('%Y-%m-%d')
except ValueError:
pass
# Try other common formats
formats = ['%d.%m.%Y', '%d.%m.%y', '%d.%m.%Y', '%d.%m.%y']
for fmt in formats:
try:
parsed_date = datetime.strptime(date_str, fmt)
return parsed_date.strftime('%Y-%m-%d')
except ValueError:
continue
return None
# Format IBAN for readability
def format_iban(iban):
if not iban:
return ''
iban = str(iban).replace(' ', '')
# Split the input string into 4-character chunks for readability
formatted_iban = ''
chunk_size = 4
num_chunks = (len(iban) + chunk_size - 1) // chunk_size
for i in range(num_chunks):
chunk = iban[i * chunk_size:(i + 1) * chunk_size]
formatted_iban += chunk + ' '
# Trim any trailing spaces and return the formatted IBAN
return formatted_iban.strip()
# Check integrity of IBAN (modified from original source: https://stackoverflow.com/questions/20983339/validate-iban-php)
def validate_iban_checksum(iban):
if not iban:
return False
iban = str(iban).lower().replace(' ', '')
countries = {
'al': 28, 'ad': 24, 'at': 20, 'az': 28, 'bh': 22, 'be': 16, 'ba': 20, 'br': 29, 'bg': 22, 'cr': 21,
'hr': 21, 'cy': 28, 'cz': 24, 'dk': 18, 'do': 28, 'ee': 20, 'fo': 18, 'fi': 18, 'fr': 27, 'ge': 22,
'de': 22, 'gi': 23, 'gr': 27, 'gl': 18, 'gt': 28, 'hu': 28, 'is': 26, 'ie': 22, 'il': 23, 'it': 27,
'jo': 30, 'kz': 20, 'kw': 30, 'lv': 21, 'lb': 28, 'li': 21, 'lt': 20, 'lu': 20, 'mk': 19, 'mt': 31,
'mr': 27, 'mu': 30, 'mc': 27, 'md': 24, 'me': 22, 'nl': 18, 'no': 15, 'pk': 24, 'ps': 29, 'pl': 28,
'pt': 25, 'qa': 29, 'ro': 24, 'sm': 27, 'sa': 24, 'rs': 22, 'sk': 24, 'si': 19, 'es': 24, 'se': 24,
'ch': 21, 'tn': 24, 'tr': 26, 'ae': 23, 'gb': 22, 'vg': 24
}
chars = {
'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15, 'g': 16, 'h': 17, 'i': 18, 'j': 19,
'k': 20, 'l': 21, 'm': 22, 'n': 23, 'o': 24, 'p': 25, 'q': 26, 'r': 27, 's': 28, 't': 29,
'u': 30, 'v': 31, 'w': 32, 'x': 33, 'y': 34, 'z': 35
}
if iban[:2] not in countries:
return False
if len(iban) == countries[iban[:2]]:
moved_char = iban[4:] + iban[:4]
new_string = ''
for char in moved_char:
if char.isdigit():
new_string += char
else:
new_string += str(chars[char])
if int(new_string) % 97 == 1:
return True
return False
# Check formatting of IBAN
def validate_iban_formatting(iban_str):
if not iban_str:
return False
iban_str = str(iban_str)
# Note: German IBAN definition allows for slack
# Correct IBAN definition: DE[0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
if iban_str.startswith('DE'):
pattern = r'DE\s?[0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?'
if re.match(pattern, iban_str):
return True
else:
return False
else:
# International IBANs are validated in the validate_iban_checksum() function
return True
input_data = sdk.load_input_data()
# Initialize variables
if input_data.get('date'):
input_data['date'] = parse_date_to_ymd(input_data['date'])
else:
input_data['date'] = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d')
interaction = sdk.Interaction(data=input_data)
interaction.data['oldIBAN'] = format_iban(input_data.get('oldIBAN', ''))
interaction.data['newIBAN'] = format_iban(input_data.get('newIBAN', ''))
# Handle actual change of bank data in the backend system
if input_data.get('_action') == 'enter_into_system':
response = sdk.Api.call(
method='POST',
url='https://echo.enneo.ai',
params=json.loads(json.dumps(interaction.model_dump()))
)
print(json.dumps(interaction.model_dump()))
exit()
# Business logic
if input_data.get('oldIBAN') == input_data.get('newIBAN') and input_data.get('newIBAN'):
interaction.infos.append(
sdk.IntentInfo(
type='warning',
message='IBAN ist schon im System'
)
)
interaction.options.append(
sdk.IntentOption(
type='iban_already_in_system',
name='Kunden darauf hinweisen',
recommended=True
)
)
elif not validate_iban_formatting(input_data.get('newIBAN', '')):
interaction.infos.append(
sdk.IntentInfo(
type='warning',
message='IBAN nicht im korrekten Format'
)
)
interaction.options.append(
sdk.IntentOption(
type='ask_for_verification_iban_invalid_format',
name='Kunden darauf hinweisen',
recommended=True
)
)
elif not validate_iban_checksum(input_data.get('newIBAN', '')):
interaction.infos.append(
sdk.IntentInfo(
type='warning',
message='IBAN-Prüfsumme ungültig'
)
)
interaction.options.append(
sdk.IntentOption(
type='ask_for_verification_iban_invalid_checksum',
name='Kunden darauf hinweisen',
recommended=True
)
)
else:
if input_data['date'] < datetime.now().strftime('%Y-%m-%d'):
# If the customer wants to use an IBAN effective in the past, we default to tomorrow
interaction.infos.append(
sdk.IntentInfo(
type='warning',
message=f'Gewünschtes Gültigkeitsdatum {sdk.Helpers.format_date(input_data["date"])} liegt in der Vergangenheit. Gültigkeit auf morgen gesetzt'
)
)
interaction.data['date'] = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d')
interaction.infos.append(
sdk.IntentInfo(
type='success',
message='IBAN gültig'
)
)
if input_data.get('payoutOnly'):
msg = 'Im System nur für Guthaben hinterlegen'
else:
msg = 'Im System hinterlegen'
interaction.options.append(
sdk.IntentOption(
type='enter_into_system',
name=msg,
recommended=True
)
)
# Return result
print(json.dumps(interaction.model_dump()))