Skip to content

Commit

Permalink
Merge pull request #172 from digipost/shared-document-request-state
Browse files Browse the repository at this point in the history
Functionality related to datatype ShareDocumentsRequest
  • Loading branch information
hermanwh authored Nov 13, 2023
2 parents 8c13103 + 8c5ae21 commit 3721ca5
Show file tree
Hide file tree
Showing 17 changed files with 816 additions and 8 deletions.
82 changes: 82 additions & 0 deletions docs/_v15_x/2_send.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,88 @@ client.createMessage(message)
.send();
```

### Datatype ShareDocumentsRequest

This datatype enables sharing of documents between an organisation and a Digipost end user. The organisation
first sends a message of datatype ShareDocumentsRequest, to which the end user can attach a list of documents. When
new documents are shared, a DocumentEvent is generated. The organisation can retrieve the status of their
ShareDocumentsRequest. If documents are shared and the sharing is not cancelled, the documents can either be downloaded
or viewed on the digipostdata.no domain. Active requests can be cancelled both by the end user and the organisation.

The `purpose` attribute of the ShareDocumentsRequest should briefly explain why the sender organisation want to gain
access to the relevant documents. This text will be displayed prominently, and should contain the information necessary
for the user to make an informed choice. The primary document should contain a more detailed explanation.

#### Send ShareDocumentsRequest
```java
PersonalIdentificationNumber pin = new PersonalIdentificationNumber("26079833787");
UUID messageUUID = UUID.randomUUID();

ShareDocumentsRequest shareDocumentsRequest = new ShareDocumentsRequest(
Duration.ofDays(60).toSeconds(),
"We require to see your six latest pay slips in order to give you a loan."
);

Document primaryDocument = new Document(messageUUID, "Request to access your latest payslips", FileType.PDF, shareDocumentsRequest);

Message message = Message.newMessage("messageId", primaryDocument)
.recipient(pin)
.build();

client.createMessage(message)
.addContent(primaryDocument, Files.newInputStream(Path.of("longer-desc-of-sharing-purpose.pdf")))
.send();
```

#### Discover new shared documents
The sender organisation can discover new shared documents by polling document events regularly. Use the `uuid` attribute
of the DocumentEvent to match with the `messageUUID` of the origin ShareDocumentsRequest:

```java
List<DocumentEvent> sharedDocumentEvents = digipostClient.getDocumentEvents(brokerId.asSenderId(), ZonedDateTime.now().minus(Duration.ofDays(1)), ZonedDateTime.now(), 0, 100);
.getEvents()
.stream()
.filter(event -> DocumentEventType.SHARE_DOCUMENTS_REQUEST_DOCUMENTS_SHARED.equals(event.getType()))
.toList()
```

NB: events are attached to the broker, _not_ each individual sender.

#### Get state of ShareDocumentsRequest

```java
ShareDocumentsRequestState sharedDocumentsRequestState = sendClient.getShareDocumentsRequestState(senderId, uuid);
```

#### Get documents

Each `SharedDocument` has attributes describing the document and its origin. If `SharedDocumentOrigin` is of type
`OrganisationOrigin`, the corresponding document was received by the end user through Digipost from the organisation
with the provided organisation number. If the origin is of type `PrivatePersonOrigin`, the document was received either
from another end user or uploaded by the user itself.

Get a single document as stream:

```java
SharedDocument doc1 = sharedDocumentsRequestState.getSharedDocuments().get(0);
InputStream inputStream = sendClient.getSharedDocumentContentStream(doc1.getSharedDocumentContentStream());
```

Get link to view a single document on digipostdata.no

```java
SharedDocumentContent sharedDocumentContent = sendClient.getSharedDocumentContent(doc1.getSharedDocumentContent());
String uri = sharedDocumentContent.getUri();
```

#### Stop sharing

```java
client.stopSharing(senderId, sharedDocumentsRequestState.stopSharing())
```



## Send message with request for registration

It is possible to send a message to a person, who does not have a Digipost account, where the message triggers an SMS notification with a request for registration. The SMS notification says that if they register for a Digipost account the document will be delivered digitally. The actual content of the SMS notification is set manually by Digipost. If the user does not register for a Digipost account within the defined deadline, the document will either be delivered as physical mail or not at all.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
<dependency>
<groupId>no.digipost</groupId>
<artifactId>digipost-data-types</artifactId>
<version>0.38</version>
<version>0.39</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
Expand Down
25 changes: 23 additions & 2 deletions src/main/java/no/digipost/api/client/DigipostClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@
import no.digipost.api.client.representations.inbox.Inbox;
import no.digipost.api.client.representations.inbox.InboxDocument;
import no.digipost.api.client.representations.sender.SenderInformation;
import no.digipost.api.client.representations.shareddocuments.ShareDocumentsRequestState;
import no.digipost.api.client.representations.shareddocuments.SharedDocumentContent;
import no.digipost.api.client.security.CryptoUtil;
import no.digipost.api.client.security.Signer;
import no.digipost.api.client.shareddocuments.SharedDocumentsApi;
import no.digipost.api.client.tag.TagApi;
import no.digipost.api.client.util.JAXBContextUtils;
import no.digipost.http.client3.DigipostHttpClientFactory;
Expand Down Expand Up @@ -91,6 +94,7 @@ public class DigipostClient {
private final ArchiveApi archiveApi;
private final BatchApi batchApi;
private final TagApi tagApi;
private final SharedDocumentsApi sharedDocumentsApi;


public DigipostClient(DigipostClientConfig config, BrokerId brokerId, Signer signer) {
Expand All @@ -102,16 +106,17 @@ public DigipostClient(DigipostClientConfig config, BrokerId brokerId, Signer sig
}

private DigipostClient(DigipostClientConfig config, ApiServiceImpl apiService) {
this(config, apiService, apiService, apiService, apiService, apiService, apiService);
this(config, apiService, apiService, apiService, apiService, apiService, apiService, apiService);
}

public DigipostClient(DigipostClientConfig config, MessageDeliveryApi apiService, InboxApi inboxApiService, DocumentApi documentApi, ArchiveApi archiveApi, BatchApi batchApi, TagApi tagApi) {
public DigipostClient(DigipostClientConfig config, MessageDeliveryApi apiService, InboxApi inboxApiService, DocumentApi documentApi, ArchiveApi archiveApi, BatchApi batchApi, TagApi tagApi, SharedDocumentsApi sharedDocumentsApi) {
this.messageApi = apiService;
this.inboxApiService = inboxApiService;
this.documentApi = documentApi;
this.archiveApi = archiveApi;
this.batchApi = batchApi;
this.tagApi = tagApi;
this.sharedDocumentsApi = sharedDocumentsApi;

this.messageSender = new MessageDeliverer(config, apiService);
this.archiveSender = new ArchiveDeliverer(config, archiveApi);
Expand Down Expand Up @@ -313,6 +318,22 @@ public Tags getTags(PersonalIdentificationNumber personalIdentificationNumber) {
return tagApi.getTags(personalIdentificationNumber);
}

public ShareDocumentsRequestState getShareDocumentsRequestState(SenderId senderId, UUID shareDocumentsRequestUuid) {
return sharedDocumentsApi.getShareDocumentsRequestState(senderId, shareDocumentsRequestUuid);
}

public InputStream getSharedDocumentContentStream(URI uri) {
return sharedDocumentsApi.getSharedDocumentContentStream(uri);
}

public SharedDocumentContent getSharedDocumentContent(URI uri) {
return sharedDocumentsApi.getSharedDocumentContent(uri);
}

public CloseableHttpResponse stopSharing(SenderId senderId, URI uri) {
return sharedDocumentsApi.stopSharing(senderId, uri);
}

public ArchiveApi.ArchivingDocuments archiveDocuments(final Archive archive) {
return archiveSender.createArchive(archive);
}
Expand Down
39 changes: 36 additions & 3 deletions src/main/java/no/digipost/api/client/internal/ApiServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,15 @@
import no.digipost.api.client.representations.sender.AuthorialSender;
import no.digipost.api.client.representations.sender.AuthorialSender.Type;
import no.digipost.api.client.representations.sender.SenderInformation;
import no.digipost.api.client.representations.shareddocuments.SharedDocumentContent;
import no.digipost.api.client.representations.shareddocuments.ShareDocumentsRequestState;
import no.digipost.api.client.security.Digester;
import no.digipost.api.client.security.Signer;
import no.digipost.api.client.shareddocuments.SharedDocumentsApi;
import no.digipost.api.client.tag.TagApi;
import no.digipost.api.client.util.JAXBContextUtils;
import no.digipost.api.datatypes.DataType;
import no.digipost.api.datatypes.types.share.ShareDocumentsRequestSharingStopped;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
Expand Down Expand Up @@ -111,7 +116,7 @@
import static no.digipost.api.client.util.JAXBContextUtils.marshal;
import static no.digipost.api.client.util.JAXBContextUtils.unmarshal;

public class ApiServiceImpl implements MessageDeliveryApi, InboxApi, DocumentApi, ArchiveApi, BatchApi, TagApi {
public class ApiServiceImpl implements MessageDeliveryApi, InboxApi, DocumentApi, ArchiveApi, BatchApi, TagApi, SharedDocumentsApi {

private static final Logger LOG = LoggerFactory.getLogger(ApiServiceImpl.class);

Expand Down Expand Up @@ -292,7 +297,6 @@ public Autocomplete searchSuggest(String searchString) {
return requestEntity(httpGet, Autocomplete.class);
}


@Override
public CloseableHttpResponse identifyRecipient(Identification identification) {
return sendDigipostMedia(identification, getEntryPoint().getIdentificationUri().getPath());
Expand Down Expand Up @@ -495,7 +499,36 @@ public Tags getTags(PersonalIdentificationNumber personalIdentificationNumber) {
queryParams.put("personal-identification-number", personalIdentificationNumber.asString());
return getEntity(Tags.class, getEntryPoint().getTagsUri().getPath(), queryParams);
}


@Override
public ShareDocumentsRequestState getShareDocumentsRequestState(SenderId senderId, UUID shareDocumentsRequestUuid) {
return getEntity(ShareDocumentsRequestState.class, getEntryPoint(senderId).getShareDocumentsRequestStateUri().getPath() + shareDocumentsRequestUuid.toString());
}

@Override
public InputStream getSharedDocumentContentStream(URI uri) {
HttpGet httpGet = new HttpGet(uri);
httpGet.setHeader(HttpHeaders.ACCEPT, ContentType.WILDCARD.toString());
final HttpCoreContext httpCoreContext = HttpCoreContext.create();
httpCoreContext.setAttribute(ResponseSignatureInterceptor.NOT_SIGNED_RESPONSE, true);
return requestStream(httpGet);
}

@Override
public SharedDocumentContent getSharedDocumentContent(URI uri) {
return getEntity(SharedDocumentContent.class, uri.getPath());
}

@Override
public CloseableHttpResponse stopSharing(SenderId senderId, URI uri) {
DataType dataType = new ShareDocumentsRequestSharingStopped();
AdditionalData data = AdditionalData.Builder
.newAdditionalData(dataType)
.setSenderId(senderId)
.build();
return addData(new AddDataLink(uri.getPath()), data);
}

private static String pathWithQuery(URI uri){
return uri.getPath() + ((uri.getQuery() != null) ? "?" + uri.getQuery() : "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public enum DocumentEventType {
PRINT_FAILED,
PEPPOL_FAILED,
PEPPOL_DELIVERED,
SHREDDED;
SHREDDED,
SHARE_DOCUMENTS_REQUEST_DOCUMENTS_SHARED

}
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public URI getSenderInformationUri() {

public URI getTagsUri() { return getLinkByRelationName(GET_TAGS).getUri(); }

public URI getShareDocumentsRequestStateUri() { return getLinkByRelationName(GET_SHARE_DOCUMENTS_REQUEST_STATE).getUri(); }

public URI getCreateOrActivateUserAccountUri() { return getLinkByRelationName(CREATE_OR_ACTIVATE_USER_ACCOUNT).getUri(); }

public String getCertificate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@ public enum Relation {
ADD_TAG,
REMOVE_TAG,
GET_TAGS,
GET_SHARE_DOCUMENTS_REQUEST_STATE,
GET_SHARED_DOCUMENT_CONTENT,
GET_SHARED_DOCUMENT_CONTENT_STREAM,
STOP_SHARING,

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) Posten Norge AS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package no.digipost.api.client.representations.shareddocuments;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "shared-document-origin-organisation")
public class OrganisationOrigin {

@XmlAttribute(name = "organisation-number")
protected String organisationNumber;
@XmlAttribute(name = "name")
protected String name;

public OrganisationOrigin() {
}

public OrganisationOrigin(String organisationNumber, String name) {
this.organisationNumber = organisationNumber;
this.name = name;
}

public String getOrganisationNumber() {
return organisationNumber;
}

public void setOrganisationNumber(String organisationNumber) {
this.organisationNumber = organisationNumber;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "OrganisationOrigin{" +
"organisationNumber='" + organisationNumber + '\'' +
", name='" + name + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) Posten Norge AS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package no.digipost.api.client.representations.shareddocuments;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "shared-document-origin-private-person")
public class PrivatePersonOrigin {

@XmlAttribute(name = "name")
protected String name;

public PrivatePersonOrigin() {
}

public PrivatePersonOrigin(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "PrivatePersonOrigin{" +
"name='" + name + '\'' +
'}';
}
}
Loading

0 comments on commit 3721ca5

Please sign in to comment.