Antrag senden
TL;DR – Aus Klartext-Antragsdaten in wenigen Builder-Zeilen eine signierte, verschlüsselte Einreichung machen und an einen Zustellpunkt senden. Das SDK übernimmt intern Verschlüsselung, Metadaten-Erzeugung und das Ankündigen / Hochladen der Anhänge.
- Java
- .NET (C#)
// onlineService = sdk.onlineService(myDestinationId) — Ihr eigener Onlinedienst, Typ C
Participant recipient = Participant.of(
destinationId, Addressing.toService(leikaKey, "FIT-Connect Demo"));
OutgoingSubmission submission = OutgoingSubmission.to(recipient)
.setData(SubmissionData.json(jsonData, schemaUri))
.build();
SentSubmission sent = onlineService.send(submission);
// onlineService = client.AsOnlineService() — Ihr eigener Onlinedienst, Typ C
OutgoingSubmission submission = OutgoingSubmissionBuilder.Builder()
.WithDestinationId(destinationId)
.WithServiceType(leikaKey, "FIT-Connect Demo")
.WithMetadataVersion(new Version(1, 5, 0))
.WithJsonData(jsonData, schemaUri)
.Build();
SentSubmission sent = await onlineService.SendSubmission(submission);
Zwei Wege, eine Einreichung zu bauen
Beide SDKs bieten zwei Builder, je nachdem, ob die Antragsdaten beim Eintreffen im Backend noch im Klartext oder bereits verschlüsselt vorliegen:
Wenn möglich, verschlüsseln Sie die Antragsdaten bereits im Browser/Frontend mit dem JavaScript-SDK und übergeben dem Backend lediglich JWE-Strings. Damit hat Ihr Server keinen Zugriff auf die Klartext-Daten – das senkt die Anforderungen an Datenschutz und IT-Sicherheit deutlich.
Unverschlüsselte Daten übergeben
Der einfachere Weg: Sie übergeben Klartext-Fachdaten und Anhänge an das SDK, das die Verschlüsselung intern erledigt.
- Java
- .NET (C#)
Zuerst den Empfänger adressieren – Destination-ID plus die Verwaltungsleistung, für die der Antrag bestimmt ist:
OnlineService onlineService = sdk.onlineService(myDestinationId);
Participant recipient = Participant.of(
UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"),
Addressing.toService(
"urn:de:fim:leika:leistung:99400048079000",
"FIT-Connect Demo"));
Dann die Submission bauen: Pflicht sind Empfänger und Fachdaten, alles Weitere ist optional und in beliebiger Reihenfolge ergänzbar:
OutgoingSubmission submission = OutgoingSubmission.to(recipient)
.setData(SubmissionData.json(
"{\"message\":\"Hello World\"}",
URI.create("https://schema.example.net/schemas/demo.json")))
.addAttachment(Attachment.fromFile(
Paths.get("anlage.pdf"), "application/pdf"))
.setAuthenticationInformation(List.of(authInfo))
.setPaymentInformation(paymentInfo)
.setReplyChannel(ReplyChannels.email("buerger@example.com"))
.build();
Und schließlich senden:
SentSubmission sent = onlineService.send(submission);
System.out.println("submissionId: " + sent.submissionId());
System.out.println("caseId: " + sent.caseId());
Den Empfänger liefert das Verzeichnis als Route; der Builder braucht
davon die DestinationId plus die Verwaltungsleistung:
IOnlineServiceClient onlineService = client.AsOnlineService();
OutgoingSubmission submission = OutgoingSubmissionBuilder.Builder()
.WithDestinationId(Guid.Parse("d2d43892-9d9c-4630-980a-5af341179b14"))
.WithServiceType(
"urn:de:fim:leika:leistung:99400048079000",
"FIT-Connect Demo")
.WithMetadataVersion(new Version(1, 5, 0))
.WithJsonData(
"{\"message\":\"Hello World\"}",
new Uri("https://schema.example.net/schemas/demo.json"))
.WithAttachment(
Attachment.FromFile("./anlage.pdf", "application/pdf"),
shouldBeChunked: false)
.WithAuthenticationInformation(authInfo)
.WithPaymentInformation(paymentInfo)
.WithReplyChannel(ReplyChannel.OfEmail())
.Build();
SentSubmission sent = await onlineService.SendSubmission(submission);
Console.WriteLine($"submissionId: {sent.SubmissionId}");
Console.WriteLine($"caseId: {sent.CaseId}");
Der .NET-Builder ist ein Step-Builder: Jeder Schritt gibt ein Interface zurück, das nur den
nächsten erlaubten Schritt kennt — wie ein Formular mit Pflichtfeldern. Build() existiert erst,
wenn Ziel (WithDestinationId), Leistung (WithServiceType oder WithProcessMessage),
Metadaten-Version und Daten gesetzt sind. Deshalb lautet die IntelliSense-Meldung bei falscher
Reihenfolge „Methode nicht gefunden“, nicht „Argument fehlt“.
Reihenfolge der Builder-Aufrufe (Fluent API)
Die Builder beider SDKs sind als Fluent API mit Step-Interfaces gestaltet. Pflichtaufrufe
müssen in dieser Reihenfolge erfolgen; optionale Aufrufe (addAttachment / WithAttachment,
setReplyChannel / WithReplyChannel …) können in beliebiger Reihenfolge ergänzt werden. Java
macht den Fortschritt am Rückgabetyp jedes Aufrufs sichtbar: to(...) liefert einen
SubmissionDataStep, setData(...) einen SubmissionOptionalPropertiesStep — was gerade nicht
erlaubt ist, ist gar nicht erst als Methode sichtbar.
Vorverschlüsselte Daten durchreichen
Wenn das Frontend die Daten bereits mit dem PublicKey des Zustellpunkts verschlüsselt
hat (typisch beim Einsatz des JavaScript-SDKs), übergeben Sie die fertigen JWE-Strings an
einen separaten Builder. Das SDK fungiert dann als reiner Transporteur ohne Zugriff auf
die Klardaten.
Public Encryption Key des Zustellpunkts abrufen
Bevor das Frontend verschlüsseln kann, benötigt es den öffentlichen Schlüssel. Den holen Sie im Backend und leiten ihn an den Browser weiter:
- Java
- .NET (C#)
UUID destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
EncryptionKey publicKey = sdk.directory().activeEncryptionKeyOf(destinationId);
var destinationId = Guid.Parse("d2d43892-9d9c-4630-980a-5af341179b14");
ApiJwk publicKey = await client.Directory.GetActiveEncryptionKey(destinationId);
Beide SDKs validieren den Schlüssel automatisch gegen die kryptographischen Vorgaben (Algorithmus, Schlüssellänge, V-PKI-Zertifikatskette).
Verschlüsselte Submission zusammenstellen und senden
- Java
- .NET (C#)
Auch hier zuerst der Empfänger, wie oben:
Participant recipient = Participant.of(destinationId, Addressing.toService(
"urn:de:fim:leika:leistung:99400048079000", "FIT-Connect Demo"));
Die eigentliche Submission nutzt einen eigenen Builder: EncryptedOutgoingSubmission statt
OutgoingSubmission. Case-Adressierung (openingCase), Fachdaten (setEncryptedData) und Anhänge
(addEncryptedAttachment) erwarten hier jeweils bereits verschlüsseltes Material – plus einen
SHA-512-Hash je Nutzlast (Sha512Hash.ofHex(...)), mit dem die Empfängerseite die Integrität
prüfen kann, da die Daten für das SDK selbst undurchsichtig sind:
EncryptedOutgoingSubmission encrypted = EncryptedOutgoingSubmission.to(recipient)
.openingCase(
"urn:de:fim:leika:leistung:99400048079000",
"FIT-Connect Demo")
.setEncryptedData(
jweData, Sha512Hash.ofHex(dataHashHex), schemaUri, MimeType.APPLICATION_JSON)
.addEncryptedAttachment(new EncryptedAttachmentMetadata(
UUID.fromString("02c925b2-1234-4abc-9def-c39aaa0bc0c"),
jweAttachment, attachmentHash, "anlage.pdf",
"application/pdf", Purpose.ATTACHMENT, "Anlage"))
.build();
Gesendet wird wie gewohnt über onlineService.send(...):
SentSubmission sent = onlineService.send(encrypted);
Organisation bietet dieses Overload bewusst nicht — vorverschlüsseltes Senden ist ein
Typ-C-Szenario (nur OnlineService).
EncryptedOutgoingSubmission encrypted = EncryptedOutgoingSubmission.Builder()
.SetDestination(destinationId)
.SetServiceType(
"urn:de:fim:leika:leistung:99400048079000",
"FIT-Connect Demo")
.SetEncryptedMetadata(jweMetadata)
.SetEncryptedData(jweData)
.AddEncryptedAttachment(
Guid.Parse("02c925b2-1234-4abc-9def-c39aaa0bc0c"),
jweAttachment)
.Build();
SentSubmission sent = await onlineService.SendEncryptedSubmission(encrypted);
Wie in Java ist das ein Typ-C-Szenario: SendEncryptedSubmission gibt es nur auf
IOnlineServiceClient, nicht auf IOrganisationClient.
- Destination und Service-Identifier aus dem Frontend müssen serverseitig auf Zulässigkeit geprüft werden – beide SDKs übernehmen diese Validierung intern.
- Keine ZIP-Kompression: Weder Java- noch .NET-SDK fügen einen ZIP-Compression-Header
hinzu. Bei Eigenimplementierungen mit
nimbus-jose-jwtdarauf achten, dass keine doppelte Kompression erfolgt.
Referenz: Felder von SentSubmission
| Feld (Java) / Property (.NET) | Bedeutung |
|---|---|
submissionId() / SubmissionId | Eindeutiges Kennzeichen dieser Einreichung (UUID/Guid). |
caseId() / CaseId | Vorgangs-ID, die mehrere zusammenhängende Submissions klammert. |
Wie Sie damit den Status verfolgen, zeigt Status verfolgen — im Java-SDK über
onlineService.cases().logOf(sent), im .NET-SDK über onlineService.GetSubmissionState(sent).
Häufige Stolperfallen
- Falsches Schema: Stimmt der
serviceIdentifiernicht mit den Schemata des Zustellpunkts überein, wirft das SDK eine Exception. Im Self-Service-Portal sehen Sie, welche Schemata ein Zustellpunkt akzeptiert. - Großer Anhang: Die Standard-Attachment-Methoden laden die Datei komplett in den RAM. Für sehr große Dateien siehe Große Anhänge senden.
- Schlüssel zu kurz: Beide SDKs lehnen Schlüssel ab, die nicht den
Vorgaben entsprechen. In Tests hilft das
TEST-Environment oder ein Custom-Environment mitallowInsecureKeys: true(Java). - Falsche Rolle: Ein Zustellpunkt vom Typ A/B kann ebenfalls senden (
Organisation/AsOrganisation()), aber nicht vorverschlüsselt. Das .NET-SDK meldet eine falsche Fassade beim Start (FitConnectConfigurationException), wennVerifyDestinationOnStartupaktiv ist.
Weiter geht's
- Status verfolgen — wurde der Antrag angenommen?
- Antworten senden und lesen — einen Rückkanal mitgeben, um den Bescheid zu lesen
- Große Anhänge senden
- Empfänger finden
- Konzept: Der Weg eines Antrags