<?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;
}
}