4.3.1 Vermietungsdaten vom Produkt zum Partner
Dies ist der erste Schritt des Prozesses für Vermietungsdaten, zuerst muss die Datei/Dateien von der CloudApi heruntergeladen werden.
Details über die einzelnen Endpunkte können über das Developer Portal in der Swagger/OpenAPI Dokumentation nachgelesen werden.
Für alle folgenden Prozesse wird vorausgesetzt, dass eine Partner-Lizenz zur Übertragung der jeweiligen Daten existiert und diese bereits erfolgreich aktiviert wurde. (Siehe 5. Sicherheitsmechanismen unter Punkt a. Lizenzaktivierung)
1. Erstellung des Authentifizierungstokens
Um Daten aus der Cloud API empfangen zu können, ist es notwendig, zuvor ein Authentifizierungstoken zu übertragen, dass über den Endpunkt TokenCreate angefragt werden kann. Dafür müssen der grant_type (= „client_credentials“), requesttype (der zu übertragende Requesttype) und der scope (= LicenseIndicatorHash) im Body in URL-Encoded Form mit Content-Type: application/x-www-form-urlencoded übertragen werden.
Das Token ist grundsätzlich 30 Minuten gültig (sollte also ggf. für mehrere Requests wiederverwendet werden) und bezieht sich auf einen Requesttype (hier VermietungsdatenRequest) und dem jeweiligen Kunden mit dem man Daten austauschen möchte.
Der Auth-Token wird dann für weitere Requests im Header „Authentication: Bearer <token>“ genutzt.
POST TokenCreate
POST /CloudApi/V1/api//oauth2/token HTTP/1.1Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Content-Type: application/x-www-form-urlencodedAccept: */*Cache-Control: no-cacheHost: api.realestatehub.haufe.ioAccept-Encoding: gzip, deflate, brConnection: keep-aliveContent-Length: 116grant_type=client_credentials&scope=q92qdL0PcKxU2s2xFW0y2bqI-TZx0cupbnAmqgZdfmY1&requesttype=VermietungsdatenRequestHTTP/1.1 201 CreatedCache-Control: no-cachePragma: no-cacheContent-Length: 190Content-Type: application/json; charset=utf-8Expires: -1X-Powered-By: ASP.NETDate: Wed, 18 Nov 2020 07:41:42 GMT{ "access_token": "99b343dd-c29c-4da5-9281-3412b0060f08", "token_type": "Bearer", "expires_in": 1800, "scope": "q92qdL0PcKxU2s2xFW0y2bqI-TZx0cupbnAmqgZdfmY1", "requesttype": "VermietungsdatenRequest"}
2. Daten von einer Gegenstelle empfangen
Für den Empfang eines Datenpakets ist der Endpunkt FileJobsGetItems vorgesehen. Die Response kann hierbei mehrere Jobs auf einmal beinhalten und dementsprechend groß sein . Für den Aufruf des Endpunktes wird ein Authentifizierungstoken im Header benötigt.
GET FileJobsGetItems
GET /CloudApi/V1/api/filejobs HTTP/1.1Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Authorization: Bearer 68ead0ee-0f34-4619-af1f-e4fdb8fdfdeeAccept: */*Cache-Control: no-cacheHost: api.realestatehub.haufe.ioAccept-Encoding: gzip, deflate, brConnection: keep-aliveHTTP/1.1 200 OKCache-Control: no-cachePragma: no-cacheContent-Length: 1301Content-Type: application/json; charset=utf-8Content-Encoding: gzipExpires: -1Vary: Accept-EncodingX-Powered-By: ASP.NETDate: Tue, 09 Mar 2021 11:11:27 GMT{ "total_count": 1, "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs" } }, "_embedded": { "fileJobs": [ { "licenseownerid": "{ID}", "sequencenumber": "1", "licensecounterpartid": "{ID}", "deleteflag": false, "state": { "FileJobState": 1, "FileJobStateAsString": "UploadCompleted", "StateDateTime": "2021-03-09T11:10:38.0725218+00:00", "PreviousFileJobState": { "FileJobState": 0, "FileJobStateAsString": "Created", "StateDateTime": "2021-03-09T11:08:31.9481959+00:00", "PreviousFileJobState": null } }, "data": " ", "hasheddata": null, "response": null, "responsecode": null, "IsResponseOk": false, "LicenseIndicatorHashSender": "{LicenseIndicatorHash}", "TemporarySharedAccessSignatureUri": "https://prodcloudapifilejobs.blob.core.windows.net/2417147c-f867-40fb-8526-9e88ac6ec50e?sv=2017-04-17&sr=c&sig=b2gwhClrrrn37iUJjQXXa9GfokQAUv9L3kySM%2FwiXDc%3D&se=2021-03-09T11%3A41%3A27Z&sp=rl", "BlobContainerReference": "2417147c-f867-40fb-8526-9e88ac6ec50e", "id": "{JobId}", "requesttype": "VermietungsdatenRequest", "_links": { "self": { "href": null }, "confirm": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs/confirmations" } } } ] }}
3. Blobs auflisten
"Erklärungs-Text" Auflistung von Blobs in einem gegebenen container. Benötigt zusätzlich die query parameter restype=container und comp=list.
GET List Blobs
GET {TemporarySharedAccessSignatureUri aus FileJobGetIteams}&restype=container&comp=list HTTP/1.1Accept: */*Cache-Control: no-cacheHost: prodcloudapifilejobs.blob.core.windows.netAccept-Encoding: gzip, deflate, brConnection: keep-aliveHTTP/1.1 200 OKTransfer-Encoding: chunkedContent-Type: application/xmlServer: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0x-ms-request-id: 2b56ad48-501e-0000-63db-144157000000x-ms-version: 2017-04-17Date: Tue, 09 Mar 2021 12:00:04 GMT<?xml version="1.0" encoding="utf-8"?><EnumerationResults ServiceEndpoint="https://prodcloudapifilejobs.blob.core.windows.net/" ContainerName="2417147c-f867-40fb-8526-9e88ac6ec50e"> <Blobs> <Blob> <Name>TestDatei</Name> <Properties> <Last-Modified>Tue, 09 Mar 2021 12:00:04 GMT</Last-Modified> <Etag>0x8D8E2F8CCC7753E</Etag> <Content-Length>46</Content-Length> <Content-Type>text/plain</Content-Type> <Content-Encoding /> <Content-Language /> <Content-MD5>w6akDuFOQCw7y1baUhzGyg==</Content-MD5> <Cache-Control>no-cache</Cache-Control> <Content-Disposition /> <BlobType>BlockBlob</BlobType> <AccessTier>Hot</AccessTier> <AccessTierInferred>true</AccessTierInferred> <LeaseStatus>unlocked</LeaseStatus> <LeaseState>available</LeaseState> <ServerEncrypted>true</ServerEncrypted> </Properties> </Blob> </Blobs> <NextMarker /></EnumerationResults>
4. Blobs herunterladen
SharedAccessSignatureUri aus FileJobsGetItems als Request-Url einfügen.
Nach der GUID (Container-Bezeichnung) und vor dem "?" muss noch die Benennung der heruntergeladenen Datei erfolgen.
Dies geschieht mit einem "/" nach der GUID und die gewünschte Bezeichung der Datei oder aus der Auflistung von Blobs die gewünschte Datei auslesen und vor dem "?" einfügen.
GET
Blob Download
GET testcloudapifilejobs.blob.core.windows.net/1138eb61-8f00-4e35-bc13-b18e26276a96/Testdatei.png?sv=2017-04-17&sr=c&sig=9C88RICRluDv8ryjdvXfBj3MCJuW7NRoCPxma0JUa14%3D&se=2021-05-03T10%3A27%3A44Z&sp=cw HTTP/1.1{TemporarySharedAccessSignatureUri aus FileJobGetIteams mit resource identifier /dateiname aus ListBlobs} Accept: */*Cache-Control: no-cacheHost: prodcloudapifilejobs.blob.core.windows.netAccept-Encoding: gzip, deflate, brConnection: keep-aliveHTTP/1.1 200 OKCache-Control: no-cacheContent-Length: 46Content-Type: text/plainContent-MD5: w6akDuFOQCw7y1baUhzGyg==Last-Modified: Tue, 09 Mar 2021 12:42:28 GMTAccept-Ranges: bytesETag: "0x8D8E2F8CCC7753E"Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0x-ms-request-id: 5886c1e7-301e-0006-29e2-1472e8000000x-ms-version: 2017-04-17x-ms-lease-status: unlockedx-ms-lease-state: availablex-ms-blob-type: BlockBlobx-ms-server-encrypted: trueDate: Tue, 09 Mar 2021 12:46:53 GMT-> Testdatei.png "Hier ist das Test-Dokument(PDF,jpeg,txt.....)."
5. Datenempfang bestätigen
Bevor die abgeholten Daten verarbeitet werden, muss der Datenempfang in der Cloud API bestätigt werden, dies geschieht mit dem Endpunkt FileJobsConfirmationsCreate. Das soll verhindern, dass ggf. zwei Instanzen derselben Gegenstelle die Daten gleichzeitig bearbeiten. Außerdem wird ein Authentifizierungstoken im Header benötigt.
POST
FileJobsConfirmationsCreate
POST /CloudApi/V1/api/filejobs/confirmations HTTP/1.1Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Authorization: Bearer ca4d3bb5-d6b1-4067-a51e-01a626536c46Content-Type: application/jsonAccept: */*Cache-Control: no-cacheHost: api.realestatehub.haufe.ioAccept-Encoding: gzip, deflate, brConnection: keep-aliveContent-Length: 46[ "{JobId-GUID}", "{JobId-GUID}", "{JobId-GUID}", . , . , . , "{JobId-GUID}"]HTTP/1.1 201 CreatedCache-Control: no-cachePragma: no-cacheContent-Length: 383Content-Type: application/json; charset=utf-8Expires: -1X-Powered-By: ASP.NETDate: Tue, 09 Mar 2021 12:10:47 GMT{ "responseCollection": [ { "id": "{JobId}", "confirmationId": "{ConfirmationId}", "remark": "Job {JobId} confirmed." } ], "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs/confirmations" }, "respond": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs/responses" } }}
6. Beantwortung von Requests
Nach der Verarbeitung von Daten aus der Cloud API muss der Empfänger den Request beantworten, sodass der Absender die Information erhält, dass die Daten verarbeitet wurden. Dies geschieht über den Endpunkt FileJobsResponsesCreate. Dazu muss eine JobId mitgegeben werden, welches eine GUID ist. Außerdem wird ein Authentifizierungstoken im Header benötigt.
POST FileJobsResponsesCreate
POST /CloudApi/V1/api/filejobs/{JobId-GUID}/responses HTTP/1.1Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Content-Type: application/jsonAuthorization: Bearer ca4d3bb5-d6b1-4067-a51e-01a626536c46Accept: */*Cache-Control: no-cacheHost: api.realestatehub.haufe.ioAccept-Encoding: gzip, deflate, brConnection: keep-aliveContent-Length: 250{ "Response":"Download der Datei war erfolgreich", "Responsecode":"TestCode-0001", "ConfirmationToken": { "id": "{JobId-GUID}", "confirmationId": "{ConfirmationId-GUID}" }, "IsResponseOk" : "True"}HTTP/1.1 201 CreatedCache-Control: no-cachePragma: no-cacheContent-Length: 747Content-Type: application/json; charset=utf-8Expires: -1X-Powered-By: ASP.NETDate: Tue, 09 Mar 2021 12:23:57 GMT{ "id": "{JobId-GUID}", "requesttype": "VermietungsdatenRequest", "state": { "FileJobState": 3, "FileJobStateAsString": "Processed", "StateDateTime": "2021-03-09T12:23:58.2257078+00:00", "PreviousFileJobState": { "FileJobState": 2, "FileJobStateAsString": "Confirmed", "StateDateTime": "2021-03-09T12:10:47.8586793+00:00", "PreviousFileJobState": { "FileJobState": 1, "FileJobStateAsString": "UploadCompleted", "StateDateTime": "2021-03-09T11:10:38.0725218+00:00", "PreviousFileJobState": { "FileJobState": 0, "FileJobStateAsString": "Created", "StateDateTime": "2021-03-09T11:08:31.9481959+00:00", "PreviousFileJobState": null } } } }, "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/responses" } }}
Danach kommt der zweite Schritt des Prozesses für Vermietungsdaten, hier müssen die Vermietungsdaten selber abgeholt werden.
8. Daten von einer Gegenstelle empfangen
Für den Empfang eines Datenpakets ist der Endpunkt JobsGetItems vorgesehen.
Die Response kann hierbei mehrere Jobs auf einmal beinhalten und dementsprechend groß sein.
Für den Aufruf des Endpunktes wird ein Authentifizierungstoken im Header benötigt.
GET JobsGetItems
GET /CloudApi/V1/api/jobs HTTP/1.1Host: api.realestatehub.haufe.ioOcp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Authorization: Bearer 8a4267cb-d76e-4fd8-971a-9a1b2ebe448eAccept: */*Cache-Control: no-cacheAccept-Encoding: gzip, deflate, brConnection: keep-aliveHTTP/1.1 200 OKCache-Control: no-cachePragma: no-cacheContent-Length: 20827Content-Type: application/json; charset=utf-8Content-Encoding: gzipExpires: -1Vary: Accept-EncodingX-Powered-By: ASP.NETDate: Fri, 30 Oct 2020 09:24:42 GMT{ "total_count": 1, "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs" } }, "_embedded": { "jobs": [ { "sequencenumber": "1", "salt": "54zO/2bCBRXCi84yKe4WeYm3rbYp7Gb/3JjZvaXyxXM=", "licenseownerid": "37", "licensecounterpartid": "39", "deleteflag": false, "state": { "JobState": 0, "JobStateAsString": "New", "StateDateTime": "2020-10-30T09:25:14.82179+00:00", "PreviousJobState": { "JobState": -1, "JobStateAsString": "Queued", "StateDateTime": "2020-10-30T09:24:42.4295984+00:00", "PreviousJobState": null } }, "responseSalt": null, "data": "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", "hasheddata": "C5EEDDADA83CABADC88F2E54258418A068B1600525499B637B848CA769CF4E69DG312", "response": null, "responsecode": null, "IsResponseOk": true, "Entities": null, "EntitiesCount": { "MandantEntity": 1, "UnternehmenEntity": 1, "WirtschaftseinheitEntity": 1, "GebaeudeEntity": 1, "HausEntity": 1, "NutzungseinheitEntity": 1, "VermietungEntity": 1, "AusstattungsgruppeEntity": 1, "AusstattungselementEntity": 1, "RaumEntity": 1, "SachbearbeiterEntity": 1, "AdresseEntity": 1, "FotoEntity": 1, "EnergieausweisEntity": 1 }, "LicenseIndicatorHashSender": "{LicenseIndicatorHash}", "LicenseIndicatorHashReceiver": null, "AttachmentReference": "", "id": "{JobId-GUID}", "requesttype": "VermietungsdatenRequest", "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/responses" }, "confirm": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/confirmations" } } } ] }}
9. Datenempfang bestätigen
Bevor die abgeholten Daten verarbeitet werden, muss der Datenempfang in der Cloud API bestätigt werden, dies geschieht mit dem Endpunkt ConfirmationCreate.
Das soll verhindern, dass ggf. zwei Instanzen derselben Gegenstelle die Daten gleichzeitig bearbeiten.
Dazu muss eine JobId in der URL mitgegeben werden, welches eine GUID ist. Außerdem wird ein Authentifizierungstoken im Header benötigt.
POST ConfirmationCreate
POST /CloudApi/V1/api/jobs/{JobId}/confirmations HTTP/1.1Host: api.realestatehub.haufe.ioOcp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Authorization: Bearer 8a4267cb-d76e-4fd8-971a-9a1b2ebe448eAccept: */*Cache-Control: no-cacheAccept-Encoding: gzip, deflate, brConnection: keep-aliveContent-Length: 0HTTP/1.1 201 CreatedCache-Control: no-cachePragma: no-cacheContent-Length: 379Content-Type: application/json; charset=utf-8Expires: -1X-Powered-By: ASP.NETDate: Fri, 30 Oct 2020 10:37:08 GMT{ "id": "{JobId-GUID}", "confirmationId": "{ConfirmationId-GUID}", "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId}/confirmations" }, "respond": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId}/responses" } }}Das Bestätigen mehrerer Jobs kann mit dem Endpunkt ConfirmationsCreate durchgeführt werden. Hier entfällt außerdem die einzelne JobId in der URL:
POST ConfirmationsCreate
POST /CloudApi/V1/api//jobs/confirmations HTTP/1.1Host: api.realestatehub.haufe.ioOcp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Content-Type: application/jsonAuthorization: Bearer e98db7a5-7b78-4c25-9140-9920946894afAccept: */*Cache-Control: no-cacheAccept-Encoding: gzip, deflate, brConnection: keep-aliveContent-Length: 46[ "{JobId-GUID}", "{JobId-GUID}", "{JobId-GUID}", "{JobId-GUID}", "{JobId-GUID}", "{JobId-GUID}", . , . , . , . , "{JobId-GUID}"]HTTP/1.1 200 OKCache-Control: no-cachePragma: no-cacheContent-Length: 360Content-Type: application/json; charset=utf-8Content-Encoding: gzipExpires: -1Vary: Accept-EncodingX-Powered-By: ASP.NETDate: Fri, 30 Oct 2020 12:39:48 GMT{ "responseCollection": [ { "id": "{JobID-GUID}", "confirmationId": "{ConfirmationId-GUID}", "remark": "Job {JobID-GUID} confirmed." }, { "id": "{JobID-GUID}", "confirmationId": "{ConfirmationId-GUID}", "remark": "Job {JobID-GUID} confirmed." }, { "id": "{JobID-GUID}", "confirmationId": "{ConfirmationId-GUID}", "remark": "Job {JobID-GUID} confirmed." }, { . }, { . }, { . }, { "id": "{JobID-GUID}", "confirmationId": "{ConfirmationId-GUID}", "remark": "Job {JobID-GUID} confirmed." } ], "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/confirmations" }, "respond": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/responses" } }}
10. Beantwortung von Requests
Nach der Verarbeitung von Daten aus der Cloud API muss der Empfänger den Request beantworten, sodass der Absender die Information erhält, dass die Daten verarbeitet wurden.
Dies geschieht über den Endpunkt ResponsesCreate. Dazu muss eine JobId mitgegeben werden, welches eine GUID ist.
Außerdem wird ein Authentifizierungstoken im Header benötigt.
POST ResponsesCreate
POST /CloudApi/V1/api/jobs/{JobId}/responses HTTP/1.1Host: api.realestatehub.haufe.ioContent-Type: application/jsonOcp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••Content-Type: application/jsonAuthorization: Bearer d94fb9c4-8cb5-4e8c-bdd6-51fba2ceed44Accept: */*Cache-Control: no-cacheAccept-Encoding: gzip, deflate, brConnection: keep-aliveContent-Length: 342{ "Response":"{Verschlüsselte Antwort}", "Responsecode":"TestCode-0001", "IsResponseOk": true, "ConfirmationToken": { "id": "{JobId-GUID}", "confirmationId": "{ConfirmationId-GUID, welcher man vom Endpunkt ConfirmationCreate bekommt}" }, "ResponseSalt":"ChangeMeToTheRealSalt"}HTTP/1.1 201 CreatedCache-Control: no-cachePragma: no-cacheContent-Length: 698Content-Type: application/json; charset=utf-8Expires: -1X-Powered-By: ASP.NETDate: Fri, 30 Oct 2020 10:11:12 GMT{ "id": "{JobId-GUID}", "requesttype": "VermietungsdatenRequest", "state": { "JobState": 3, "JobStateAsString": "Processed", "StateDateTime": "2020-10-30T10:11:12.3078021+00:00", "PreviousJobState": { "JobState": 2, "JobStateAsString": "Confirmed", "StateDateTime": "2020-10-30T10:05:55.6473117+00:00", "PreviousJobState": { "JobState": 0, "JobStateAsString": "New", "StateDateTime": "2020-10-30T07:33:28.439343+00:00", "PreviousJobState": { "JobState": -1, "JobStateAsString": "Queued", "StateDateTime": "2020-10-30T07:33:27.1042678+00:00", "PreviousJobState": null } } } }, "_links": { "self": { "href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/responses" } }}