Zum Hauptinhalt springen

FIT-Connect und das Zentrale Bürgerpostfach (ZBP)

Das Zentrale Bürgerpostfach (ZBP) als Teil der BundID-Infrastruktur ermöglicht es Fachverfahren, Bürgern Nachrichten (wie z.B. Bescheide) sicher zu übermitteln. Des Weiteren ist es möglich, sog. Antragstatusmeldungen zu versenden, um über den Bearbeitungsstatus eines Antrags via Statusmonitor zu informieren. Dieses Angebot ist von FIT-Connect unabhängig. Dennoch kann Sie FIT-Connect bei der technischen Integration weitreichend unterstützen. Die Möglichkeiten zur technischen Integration hängen dabei davon ab, ob Ihre Anwendung innerhalb der Netze des Bundes (NdB) betrieben wird, oder aber außerhalb davon.

Anbindung des ZBP innerhalb der Netze des Bundes (NdB)

Wird ihre Anwendung innerhalb der NdB betrieben, können Sie die REST-Schnittstelle des ZBP direkt aufrufen. Dazu können Sie auf eine eigene Implementierung zurückgreifen, die Sie anhand der ZBP-Dokumentation entwickeln. Einfacher ist es jedoch, die dafür bereitgestellte Funktion der FIT-Connect-SDKs zu verwenden. Eine Beispiel-Implementierung mit dem Java-SDK finden Sie unten, wobei beim Instanziieren Pfade zu ihrem privaten BPKI-Schlüssel und ihrem BPKI-Zertifikat angegeben werden müssen:

// ----- Setup configuration that can be reused -----
final var privateKeyPath = Path.of("/path/to/clientPrivateKey.key");
final var clientCertPath = Path.of("/path/to/clientCertificate.crt");

final ZBPCertConfig certConfig = new ZBPCertConfig(privateKeyPath, clientCertPath)
final ZBPClient zbpClient = ClientFactory.createZBPClient(certConfig, ZBPEnvironment.INT_INTERNET); // INT_INTERNET = Integrationsumgebung for testing purposes
// ------End Setup ----------------------------------

final CreateMessage message = CreateMessage.builder()
.content("Hi there from FIT-Connect !")
.sender("FIT-Connect")
.service("FIT-Connect Test")
.title("plain message without attachment")
.retrievalConfirmationAddress("retrieval@mail.net")
.replyAddress("reply@mail.net")
.mailboxUuid(UUID.fromString("d0996589-508c-499c-bb26-a97fed704669"))
.stork_qaa_level(AuthenticationLevel.ONE)
.build();

final CreateMessageResponse response;
try {
response = zbpClient.sendMessage(message);
System.out.println("Sent message successfully. messageUUID = " + response.getMessageUuid());
} catch (Exception e) {
throw new RuntimeException("Failed to send message to ZBP", e);
}

Das Beispiel kann auf eine Nachricht mit Attachments folgendermaßen erweitert werden:

// ----- Setup configuration that can be reused -----
final var privateKeyPath = Path.of("/path/to/clientPrivateKey.key");
final var clientCertPath = Path.of("/path/to/clientCertificate.crt");

final ZBPCertConfig certConfig = new ZBPCertConfig(privateKeyPath, clientCertPath);
final ZBPClient zbpClient = ClientFactory.createZBPClient(certConfig, ZBPEnvironment.INT_INTERNET); // INT_INTERNET = Integrationsumgebung for testing purposes
// ------End Setup ----------------------------------

final byte[] attachmentData = loadFileAsByteArray();
final ZBPApiAttachment attachment = new ZBPApiAttachment(attachmentData, "test-attachment.pdf", "application/pdf");
final ZBPAttachmentMetadata attachmentMetadata = ZBPAttachmentMetadataBuilder.from(attachment);

final CreateMessage message = CreateMessage.builder()
.content("Hi there from FIT-Connect !")
.sender("FIT-Connect")
.service("FIT-Connect Test")
.title("plain message with attachment")
.retrievalConfirmationAddress("retrieval@mail.net")
.replyAddress("reply@mail.net")
.mailboxUuid(UUID.fromString("d0996589-508c-499c-bb26-a97fed704669"))
.stork_qaa_level(AuthenticationLevel.ONE)
.attachmentMetadata(List.of(attachmentMetadata))
.build();

final CreateMessageResponse response;
try {
response = zbpClient.sendMessageWithAttachments(message, List.of(attachment));
System.out.println("Sent message successfully. messageUUID = " + response.getMessageUuid());
} catch (Exception e) {
throw new RuntimeException("Failed to send message to ZBP", e);
}

Die Übermittlung einer Statusmeldung wird wie folgt durchgeführt:

// ----- Setup configuration that can be reused -----
final var privateKeyPath = Path.of("/path/to/clientPrivateKey.key");
final var clientCertPath = Path.of("/path/to/clientCertificate.crt");

final ZBPCertConfig certConfig = new ZBPCertConfig(privateKeyPath, clientCertPath);
final ZBPClient zbpClient = ClientFactory.createZBPClient(certConfig, ZBPEnvironment.INT_INTERNET); // INT_INTERNET = Integrationsumgebung for testing purposes
// ------End Setup ----------------------------------

final CreateState createState = CreateState.builder()
.applicationId(UUID.fromString("d0996589-508c-499c-bb26-a97fed704669"))
.state(State.PROCESSING)
.createdDate(Instant.now())
.senderName("FIT-Connect")
.publicServiceName(new PublicServiceName("Bundeswahlscheinverfahren"))
.additionalInformation(new AdditionalInformation("Ihr Antrag wird von einem Sachbearbeiter bearbeitet."))
.statusDetails(new StatusDetails("Antrag wird bearbeitet"))
.build();

try {
zbpClient.createState(createState);
System.out.println("Sent state successfully.");
} catch (Exception e) {
throw new RuntimeException("Failed to send state to ZBP", e);
}

Anbindung des ZBP außerhalb der Netze des Bundes (NdB)

Wird ihre Anwendung außerhalb der NdB betrieben, können Sie auf eine von FIT-Connect bereitgestellte "Brückenkopf"-Anwendung zurückgreifen.

Verfügbarkeit der "Brückenkopf"-Anwendung

Derzeit steht die "Brückenkopf"-Anwendung nur auf der FIT-Connect TEST-Umgebung zur Verfügung. Diese integriert mit der Integrationsumgebung des ZBP und kann für Implementierung und Ende-zu-Ende-Tests verwendet werden. Die "Brückenkopf"-Anwendung wird zeitnah auch auf den Umgebungen STAGE und PROD zur Verfügung gestellt werden.

Dazu müssen sie lediglich eine Einreichung (Submission) mit dem Inhalt der ZBP-Nachricht oder der ZBP-Statusmeldung an einen speziellen Zustellpunkt (Destination) senden. Die "Brückenkopf"-Anwendung wird diese Einreichung zeitnah verarbeiten und an das ZBP weiterleiten, sowie mit einem accept-submission oder reject-submission-Event antworten. Dazu sind folgende Konventionen einzuhalten:

Die Felder des Fachdatenkranzes (authorCertificate, authorToken, content, sha512sum) sind dabei so zu bilden, wie in der ZBP-Dokumentation beschrieben.

Das Senden einer ZBP-Nachricht über die "Brückenkopf"-Anwendung wird durch die FIT-Connect-SDKs dabei deutlich vereinfacht. Dazu zunächst ein Beispiel ohne Attachments:

// ----- Setup configuration that can be reused -----
final ApplicationConfig config = ApplicationConfigLoader.loadConfigFromPath(Path.of("/path/to/config.yml"));
final SenderClient senderClient = ClientFactory.createSenderClient(config);

final AuthorKeyPair authorKeyPair = AuthorKeyPair.builder()
.authorCertificatePath(Path.of("/path/to/clientCertificate.crt"))
.authorPrivateKeyPath(Path.of("/path/to/clientPrivateKey.key"))
.build();

final String destinationId = "TODO"; // depends on the environment: TEST / STAGE / PROD
final String serviceIdentifier = "urn:schema-fitko-de:fit-connect:id.bund.de:message_v6"; // constant
// ------End Setup ----------------------------------

final CreateMessage message = CreateMessage.builder()
.content("Hi there from FIT-Connect !")
.sender("FIT-Connect")
.service("FIT-Connect Test")
.title("plain message without attachment")
.retrievalConfirmationAddress("retrieval@mail.net")
.replyAddress("reply@mail.net")
.mailboxUuid(UUID.fromString("d0996589-508c-499c-bb26-a97fed704669"))
.stork_qaa_level(AuthenticationLevel.ONE)
.build();

// send to FIT-Connect backend that will process the message and confirm the result via the event log
final SendableSubmission submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(destinationId))
.setServiceType(serviceIdentifier, "ZBP Message Forwarding")
.setZBPMessage(message, authorKeyPair)
.build();
// the following call will only fail, if FIT-Connect can not be reached, but a successful call does NOT
// imply that the message was already accepted by ZBP. the process is asynchronous!
final SentSubmission sentSubmission = senderClient.send(submission);

// we can then poll repeatedly for the status of this submission.
// it will start as EventState.SUBMITTED and will eventually transition to EventState.ACCEPTED or EventState.REJECTED
final Status submissionStatus = senderClient.getSubmissionStatus(sentSubmission);

Attachments zu der ZBP-Nachricht können als Anlagen (Attachments) der FIT-Connect-Einreichung (Submission) abgebildet werden. Die Attachments müssen in der ZBP-Nachricht korrekt beschrieben sein und die Dateinamen von Submission-Attachments und ZBP-Nachricht müssen übereinstimmen. Mit dem Java-SDK lassen sich Attachments folgendermaßen anhängen:

// ----- Setup configuration that can be reused -----
final ApplicationConfig config = ApplicationConfigLoader.loadConfigFromPath(Path.of("/path/to/config.yml"));
final SenderClient senderClient = ClientFactory.createSenderClient(config);

final AuthorKeyPair authorKeyPair = AuthorKeyPair.builder()
.authorCertificatePath(Path.of("/path/to/clientCertificate.crt"))
.authorPrivateKeyPath(Path.of("/path/to/clientPrivateKey.key"))
.build();

final String destinationId = "TODO"; // depends on the environment: TEST / STAGE / PROD
final String serviceIdentifier = "urn:schema-fitko-de:fit-connect:id.bund.de:message_v6"; // constant
// ------End Setup ----------------------------------

final byte[] attachmentData = loadFileAsByteArray();
final Attachment fitConnectAttachment = Attachment.fromByteArray(attachmentData, "application/pdf", "test-attachment.pdf", "test")
final ZBPAttachmentMetadata attachmentMetadata = ZBPAttachmentMetadataBuilder.from(fitConnectAttachment);

final CreateMessage message = CreateMessage.builder()
.content("Hi there from FIT-Connect !")
.sender("FIT-Connect")
.service("FIT-Connect Test")
.title("plain message with attachment")
.retrievalConfirmationAddress("retrieval@mail.net")
.replyAddress("reply@mail.net")
.mailboxUuid(UUID.fromString("d0996589-508c-499c-bb26-a97fed704669"))
.stork_qaa_level(AuthenticationLevel.ONE)
.attachmentMetadata(List.of(attachmentMetadata))
.build();

// send to FIT-Connect backend that will process the message and confirm the result via the event log
final SendableSubmission submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(destinationId))
.setServiceType(serviceIdentifier, "ZBP Message Forwarding")
.setZBPMessage(message, authorKeyPair)
.addAttachment(fitConnectAttachment)
.build();
// the following call will only fail, if FIT-Connect can not be reached, but a successful call does NOT
// imply that the message was already accepted by ZBP. the process is asynchronous!
final SentSubmission sentSubmission = senderClient.send(submission);

// we can then poll repeatedly for the status of this submission.
// it will start as EventState.SUBMITTED and will eventually transition to EventState.ACCEPTED or EventState.REJECTED
final Status submissionStatus = senderClient.getSubmissionStatus(sentSubmission);

Eine Statusmeldung lässt sich ebenfalls leicht in Form einer FIT-Connect-Einreichung übermitteln. Die Integration im Java-SDK ist wie folgt vorgesehen:

// ----- Setup configuration that can be reused -----
final ApplicationConfig config = ApplicationConfigLoader.loadConfigFromPath(Path.of("/path/to/config.yml"));
final SenderClient senderClient = ClientFactory.createSenderClient(config);

final AuthorKeyPair authorKeyPair = AuthorKeyPair.builder()
.authorCertificatePath(Path.of("/path/to/clientCertificate.crt"))
.authorPrivateKeyPath(Path.of("/path/to/clientPrivateKey.key"))
.build();

final String destinationId = "TODO"; // depends on the environment: TEST / STAGE / PROD
final String serviceIdentifier = "urn:schema-fitko-de:fit-connect:id.bund.de:status_v6"; // constant
// ------End Setup ----------------------------------

final CreateState createState = CreateState.builder()
.applicationId(UUID.fromString("d0996589-508c-499c-bb26-a97fed704669"))
.state(State.PROCESSING)
.createdDate(Instant.now())
.senderName("FIT-Connect")
.publicServiceName(new PublicServiceName("Bundeswahlscheinverfahren"))
.additionalInformation(new AdditionalInformation("Ihr Antrag wird von einem Sachbearbeiter bearbeitet."))
.statusDetails(new StatusDetails("Antrag wird bearbeitet"))
.build();

// send to FIT-Connect backend that will process the state and confirm the result via the event log
final SendableSubmission submission = SendableSubmission.Builder()
.setDestination(UUID.fromString(destinationId))
.setServiceType(serviceIdentifier, "ZBP State Forwarding")
.setZBPState(createState, authorKeyPair)
.build();
// the following call will only fail, if FIT-Connect can not be reached, but a successful call does NOT
// imply that the state was already accepted by ZBP. the process is asynchronous!
final SentSubmission sentSubmission = senderClient.send(submission);

// we can then poll repeatedly for the status of this submission.
// it will start as EventState.SUBMITTED and will eventually transition to EventState.ACCEPTED or EventState.REJECTED
final Status submissionStatus = senderClient.getSubmissionStatus(sentSubmission);

Zusammenfassung

Wie an den SDK-Beispielen zu sehen ist, ähnelt sich die Implementierung von Anwendungen innerhalb und außerhalb der NdB und das Erzeugen der CreateMessage- bzw. CreateState-Payload ist sogar identisch. Es ist also möglich, eine Anwendung so zu implementieren, dass sie in beiden Umgebungen lauffähig ist. Zum Beispiel kann über einen Konfigurationsparameter zwischen den beiden gezeigten Aufrufen einigermaßen nahtlos umgeschaltet werden. Zu Beachten ist dabei aber, dass der Aufruf innerhalb der NdB synchron ist, während bei der Verwendung von FIT-Connect das Ergebnis zeitversetzt abgeholt werden muss.