/// <summary> /// Antrag versenden /// </summary> /// <param name="application">Antrag</param> /// <param name="p10Data">PKCS#10-Daten</param> /// <param name="certStore">Zertifikat-Speicher für die Bildung der Zertifikatskette und die Abfrage des Empfänger-Zertifikats</param> /// <param name="pfx">Zertifikat für die Verschlüsselung - wenn nicht gesetzt, dann wird ein Erstantrag erstellt</param> /// <param name="validator">The validator for the OSTC certificate request document</param> /// <returns>Das Ergebnis der Antragstellung</returns> public async Task <OstcApplicationResult> SendApplicationAsync([NotNull] OstcAntrag application, [NotNull] Pkcs10Data p10Data, [CanBeNull] IOstcCertificateStore certStore, [CanBeNull] Pkcs12Store pfx, [CanBeNull] IValidator validator) { var senderId = SenderId.FromBnrOrIk(application.Antragsteller.IK_BN); var applicationData = OstcUtils.Serialize(application, Iso88591); string mimeType; if (pfx == null) { mimeType = "text/xml"; } else { var alias = pfx.Aliases.Cast <string>().FirstOrDefault(pfx.IsKeyEntry); if (alias != null) { var certEntry = pfx.GetCertificate(alias); var keyEntry = pfx.GetKey(alias); var certificate = certEntry.Certificate; var key = keyEntry.Key; if (certStore == null) { throw new ArgumentNullException(nameof(certStore)); } var certChain = certStore.GetChain(certificate).ToList(); Debug.Assert(certChain[0].SubjectDN.Equivalent(certificate.SubjectDN)); certChain.RemoveAt(0); applicationData = OstcUtils.SignData(applicationData, key, certificate, certChain); var receiverCert = certStore.GetCertificate(senderId.CommunicationServerReceiver); applicationData = OstcUtils.EncryptData(applicationData, receiverCert); mimeType = "application/octet-stream"; } else { mimeType = "text/xml"; } } var date = DateTime.ParseExact(application.Antragsinfo.Datum, "dd.MM.yyyy", CultureDe); var p10FileName = $"{senderId.Id}.p10"; var xmlFileName = $"{senderId}_{date:ddMMyyyy}.xml"; var reqSendAppContent = new MultipartFormDataContent { { new StringContent("4000"), "MAX_FILE_SIZE_XML" }, { new ByteArrayContent(applicationData) { Headers = { ContentType = MediaTypeHeaderValue.Parse(mimeType), } }, "xml_Datei", xmlFileName }, { new StringContent("4000"), "MAX_FILE_SIZE_P10" }, { new ByteArrayContent(p10Data.CertRequestDer) { Headers = { ContentType = MediaTypeHeaderValue.Parse("application/octet-stream"), } }, "p10_Datei", p10FileName } }; var requestSendApp = new HttpRequestMessage(HttpMethod.Post, Network.Requests.Upload) { Content = reqSendAppContent, }; var responseSendApp = await _client.SendAsync(requestSendApp); responseSendApp.EnsureSuccessStatusCode(); var responseHtml = DecodeResponse(await responseSendApp.Content.ReadAsStreamAsync()); var responseFileUrl = GetResponseFileUrl(responseHtml); if (responseFileUrl == null) { throw new OstcException("Von der ITSG wurde kein Pfad zu einer Rückmeldungs-Datei geliefert."); } var downloadResponse = await _client.GetAsync(responseFileUrl); downloadResponse.EnsureSuccessStatusCode(); var resultData = await downloadResponse.Content.ReadAsByteArrayAsync(); var resultXml = XDocument.Load(new MemoryStream(resultData)); var trustCenterNode = resultXml .Elements("OSTCAntrag") .Elements("Trustcenter") .FirstOrDefault(); if (trustCenterNode == null) { throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor."); } var returnCodeNode = trustCenterNode .Elements("Returncode") .FirstOrDefault(); if (returnCodeNode == null) { throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor."); } var returnCode = Convert.ToInt32(returnCodeNode.Value.Trim(), 10); var errorCodeNode = trustCenterNode.Elements("Fehlercode").FirstOrDefault(); if (errorCodeNode == null) { throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor."); } var errorCodes = errorCodeNode.Value.Trim() .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => Convert.ToInt32(x.Trim(), 10)) .ToList(); var inputNumberNode = trustCenterNode.Elements("Eingangsnummer").FirstOrDefault(); if (inputNumberNode == null) { throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor."); } var inputNumber = inputNumberNode.Value.Trim(); var result = new OstcApplicationResult() { OrderId = inputNumber, ReturnCode = returnCode, ErrorCodes = errorCodes, }; return(result); }