Cześć, czy działa Wam może wysyłka wsadowa, co bym nie zrobił dostaję błąd: 21157 Nieprawidłowy rozmiar części pakietu. Zadeklarowany rozmiar części '1' nie zgadza się z rzeczywistym.
Co zrobiłem:
- Użyłem przykładowe request z dokumentacji online (Request sample) dostępny pod https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Wysylka-wsadowa/paths/~1api~1v2~1sessions~1batch/post
i wstawiłem do postmana, użyte endpointy:
a) https://ksef-test.mf.gov.pl/api/v2/sessions/batch
b) enpoint zwrócony z odpowiedzi z pkt. a
c) https://ksef-test.mf.gov.pl/api/v2/sessions/batch/{referenceNumber}/close
pkt. c zwraca błąd 21157
- Wyłuskałem kod z opasłej apki MF do jednej metody konsolowej w C# .net Core 5 i dalej ten sam błąd (nie oceniajcie proszę, kod jest mocno roboczy na potrzeby analizy na forum :))
< static void Main(string[] args)
{
string filePathName1 = @"C:...\FA_2_Example_1.xml";
string filePathName2 = @"C:...\FA_2_Example_2.xml";
var invoices = new List<string>();
invoices.Add(filePathName1);
invoices.Add(filePathName2);
// 1. Wczytaj pliki do pamięci
var files = invoices.Select(f => new { FileName = Path.GetFileName(f), Content = System.IO.File.ReadAllBytes(f) }).ToList();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 2. Stwórz ZIP w pamięci
byte[] zipBytes;
using var zipStream = new MemoryStream();
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, leaveOpen: true);
foreach (var file in files)
{
var entry = archive.CreateEntry(file.FileName, CompressionLevel.Optimal);
using var entryStream = entry.Open();
entryStream.Write(file.Content);
}
archive.Dispose();
zipBytes = zipStream.ToArray();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 3. Zrób skrót SHA256 pliku paczki, zakodowany w formacie Base64.
int zipLength = zipBytes.Length;
string zipHash = "";
using (var sha256 = SHA256.Create())
{
byte[] hash = sha256.ComputeHash(zipBytes);
zipHash = Convert.ToBase64String(hash);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 4. Wygeneruj Klucz symetryczny o długości 32 bajtów i wektor inicjalizujący (IV) o długości 16 bajtów
byte[] key = new byte[256 / 8];
RandomNumberGenerator rng1 = RandomNumberGenerator.Create();
rng1.GetBytes(key);
byte[] iv = new byte[16];
RandomNumberGenerator rng2 = RandomNumberGenerator.Create();
rng2.GetBytes(iv);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 5. Szyfruj 1 część (na ten moment bez dzielenia na kilka części)
int zipPartLength = 0;
string zipPartHash = "";
Aes aes = Aes.Create();
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.BlockSize = 16 * 8;
aes.Key = key;
aes.IV = iv;
ICryptoTransform encryptor = aes.CreateEncryptor();
using Stream input = BinaryData.FromBytes(zipBytes).ToStream();
using MemoryStream output = new();
using CryptoStream cryptoWriter = new(output, encryptor, CryptoStreamMode.Write);
input.CopyTo(cryptoWriter);
cryptoWriter.FlushFinalBlock();
output.Position = 0;
var encrypted = BinaryData.FromStream(output).ToArray();
zipPartLength = encrypted.Length;
using (var sha256 = SHA256.Create())
{
byte[] hash = sha256.ComputeHash(encrypted);
zipPartHash = Convert.ToBase64String(hash);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 6. Szyfruj kluczem publicznym Ministerstwa Finansów klucz symetryczny
// wartość z WS KSEF
string certificateDer = "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";
X509Certificate2 sym = new X509Certificate2(Convert.FromBase64String(certificateDer));
RSA rsa = sym.GetRSAPublicKey();
byte[] encryptedKey = rsa.Encrypt(key, RSAEncryptionPadding.OaepSHA256);
string EncryptedSymmetricKey = Convert.ToBase64String(encryptedKey);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 7. Koduj w Base64 wektor inicjalizujący
string InitializationVector = Convert.ToBase64String(iv);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 7. Buduj json do otwarcia sesji wsadowej
string jsonBatchFileName = @"C:\...\Examples\Json_Batch.txt";
string json = File.ReadAllText(jsonBatchFileName);
json = json.Replace("{0}", zipLength.ToString());
json = json.Replace("{1}", zipHash);
json = json.Replace("{2}", zipPartLength.ToString());
json = json.Replace("{3}", zipPartHash);
json = json.Replace("{4}", EncryptedSymmetricKey);
json = json.Replace("{5}", InitializationVector);
string stop = "END"; // :)
}/>
Zawartość pliku Json_Batch.txt
<{
"formCode": {
"systemCode": "FA (2)",
"schemaVersion": "1-0E",
"value": "FA"
},
"batchFile": {
"fileSize": {0},
"fileHash": "{1}",
"fileParts": [
{
"ordinalNumber": 1,
"fileName": "FA_Part_1.zip.aes",
"fileSize": {2},
"fileHash": "{3}"
}
]
},
"encryption": {
"encryptedSymmetricKey": "{4}",
"initializationVector": "{5}"
},
"offlineMode": false
}/>
Będę bardzo wdzięczny o pomoc / porady