Add ZIP-wrapped CAMT parsing and real bank file tests
Playwright Tests / test (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
- Support parsing camt.052 ZIP archives in CamtParser and BankingService
- Add CamtZipParserTests for ZIP parsing (single/multi/malformed/empty cases)
- Add CamtRealFileTests: integration tests for real bank exports (ZIP, XML, CAMT, MT940, STA) in git-ignored test data dir
- Update .gitignore and add README.md for test data usage
- Copy test data files in Fuchs.Tests.csproj; add .gitkeep
- Refactor BankingService CAMT mapping logic
- Overhaul connection string config: use {username}/{password} tokens, resolve from secrets at runtime, update appsettings and Key Vault keys
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Globalization;
|
||||
using System.Globalization;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -32,6 +33,14 @@ public sealed class CamtParser
|
||||
xml.Contains("camt.05", StringComparison.OrdinalIgnoreCase) ||
|
||||
xml.Contains("BkToCstmr", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Cheap content sniff: is this payload a ZIP archive? Some banks deliver
|
||||
/// camt.052 intraday reports wrapped in a ZIP containing one or more XML files.
|
||||
/// Checks for the universal PK magic bytes (0x50 0x4B).
|
||||
/// </summary>
|
||||
public static bool LooksLikeZip(ReadOnlySpan<byte> bytes) =>
|
||||
bytes.Length >= 2 && bytes[0] == 0x50 && bytes[1] == 0x4B;
|
||||
|
||||
public List<CamtStatement> Parse(Stream stream)
|
||||
{
|
||||
using var reader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, leaveOpen: true);
|
||||
@@ -40,6 +49,39 @@ public sealed class CamtParser
|
||||
|
||||
public List<CamtStatement> Parse(byte[] bytes) => Parse(Encoding.UTF8.GetString(bytes));
|
||||
|
||||
/// <summary>
|
||||
/// Parses all CAMT XML files found inside a ZIP archive and returns
|
||||
/// the combined list of statements. Non-XML entries and malformed XML
|
||||
/// entries are silently skipped. Used for camt.052 deliveries where the
|
||||
/// bank wraps one or more intraday reports in a single ZIP file.
|
||||
/// </summary>
|
||||
public List<CamtStatement> ParseZip(byte[] bytes)
|
||||
{
|
||||
using var ms = new MemoryStream(bytes);
|
||||
return ParseZip(ms);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ParseZip(byte[])"/>
|
||||
public List<CamtStatement> ParseZip(Stream stream)
|
||||
{
|
||||
var result = new List<CamtStatement>();
|
||||
using var archive = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen: true);
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (!entry.Name.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
using var entryStream = entry.Open();
|
||||
using var buffer = new MemoryStream();
|
||||
entryStream.CopyTo(buffer);
|
||||
var entryBytes = buffer.ToArray();
|
||||
if (!LooksLikeXml(entryBytes))
|
||||
continue;
|
||||
try { result.AddRange(Parse(entryBytes)); }
|
||||
catch (FormatException) { /* skip malformed XML entries */ }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<CamtStatement> Parse(string xml)
|
||||
{
|
||||
var result = new List<CamtStatement>();
|
||||
|
||||
Reference in New Issue
Block a user