Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0a246a7
Oppretter EksempelApp
ErlendStokkeMonstadKS Mar 3, 2026
46a3326
Legger til manglene ressurser
ErlendStokkeMonstadKS Mar 3, 2026
aa108bc
Oppdatere pom.xml
ErlendStokkeMonstadKS Mar 3, 2026
935408f
Legger til flere config filer og dummy eksempel config filer
ErlendStokkeMonstadKS Mar 3, 2026
55bd5b8
Fikset pom
ErlendStokkeMonstadKS Mar 4, 2026
fe1f59a
Merge branch 'main' into FO-434-eksempel-app
ErlendStokkeMonstadKS Mar 4, 2026
9e71f58
Merge branch 'refs/heads/main' into FO-434-eksempel-app
ErlendStokkeMonstadKS Mar 5, 2026
21f040b
Fikser feil med stenging av FiksIOKlient
ErlendStokkeMonstadKS Mar 5, 2026
259a811
Pynter på output og legger til commando for å sjekke kontostatus
ErlendStokkeMonstadKS Mar 5, 2026
8619f2d
Fikser skrivefeil integrasjon
ErlendStokkeMonstadKS Mar 6, 2026
43fdbd1
Legger på mottaker på logg meldinger
ErlendStokkeMonstadKS Mar 6, 2026
a2ef46f
Bruker enum til å definere meldingstyper og bruker mer fullstendig part
ErlendStokkeMonstadKS Mar 6, 2026
c63ebe7
Legg til README.md for eksemepel klienten
ErlendStokkeMonstadKS Mar 9, 2026
95d81e7
Setter opp mulighet for å hente Maskinporten token
ErlendStokkeMonstadKS Mar 10, 2026
3bdfbb3
Dokumentere bruk av maskinporten token
ErlendStokkeMonstadKS Mar 10, 2026
0683d17
Fjern tekst om levetid på token, denne kan være noe annet enn 2 minut…
ErlendStokkeMonstadKS Mar 17, 2026
7f2ed6a
Fjern tekst som anntar at levetid på token er 2 minutt.
ErlendStokkeMonstadKS Mar 17, 2026
b7e29fa
Legger til støtte for private key som .pem fil
ErlendStokkeMonstadKS Mar 17, 2026
daec6cc
Legger til instruksjoner for kjøring av EksempelApp
ErlendStokkeMonstadKS Mar 17, 2026
8e0dca2
Oppdatere properties til å flytte virksomhetsertifikat ting over til …
ErlendStokkeMonstadKS Mar 17, 2026
fe6cd87
Fiks feil i metodekall
ErlendStokkeMonstadKS Mar 17, 2026
908ffc5
Fikser feil med avslutting av Java app
ErlendStokkeMonstadKS Mar 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions fiks-io-eksempel-klient/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Fiks IO Java Eksempel Applikasjon

Eksempel applikasjon som viser hvordan man bruker Fiks IO Java-klienten til å sende og motta meldinger.

## Om eksempel applikasjonen

Eksempel applikasjonen er en Java-konsollapplikasjon som demonstrerer følgende funksjoner:
- Opprettelse av en Fiks IO-klient
- Abonnering på meldinger
- Sending av meldinger
- Svar på meldinger
- Henting av kontoinformasjon

Applikasjonen kjører som en interaktiv konsolloop som lytter etter brukerinput for å sende meldinger og hente kontoinformasjon. Når applikasjonen mottar en PING-melding, svarer den automatisk med en PONG-melding.

## Forutsetninger

For å kunne bruke Fiks IO må du ha:
- En aktiv Fiks IO-konto med en tilknyttet integrasjon
- Virksomhetssertifikat
- Privat nøkkel for Fiks IO-kontoen
- Integrasjons-ID og passord

Disse kan settes opp for din organisasjon på:
- [FIKS-Konfigurasjon (test)](https://forvaltning.fiks.test.ks.no/fiks-konfigurasjon/)
- [FIKS-Konfigurasjon (produksjon)](https://forvaltning.fiks.ks.no/fiks-konfigurasjon/)

## Installasjon og konfigurering

### Konfigurer egenskaper

Applikasjonen trenger flere konfigurasjonsfiler. Kopier eksempelfiler og fyller inn dine verdier:

```bash
cp src/main/resources/config.properties.example.test src/main/resources/config.properties
cp src/main/resources/maskinporten.properties.example.test src/main/resources/maskinporten.properties
cp src/main/resources/fiks-api.properties.example.test src/main/resources/fiks-api.properties
cp src/main/resources/amqp.properties.example.test src/main/resources/amqp.properties
```

Se eksempelfiler (`fiks-io-eksempel-klient/src/main/resources/*.example.test`) for test-miljøkonfigurering.

Viktige egenskaper:
- **config.properties**: Inneholder sertifikat, nøkkel, konto-ID og integrasjonsdetaljer
- **maskinporten.properties**: Maskinporten-konfigurering for autentisering
- **fiks-api.properties**: API-verts (test: `api.fiks.test.ks.no`, prod: `api.fiks.ks.no`)
- **amqp.properties**: RabbitMQ-konfigurering (test: `io.fiks.test.ks.no`, prod: `io.fiks.ks.no`)

### Sertifikater og nøkler

Plassér ditt virksomhetssertifikat og privat nøkkel i `src/main/resources/`:

```bash
cp /path/to/virksomhetssertifikat.p12 src/main/resources/

cp /path/to/private.key src/main/resources/
```

## Kjøring av applikasjonen

Bygg prosjektet:
```bash
mvn clean install
```

Kjør applikasjonen:
```bash
mvn exec:java -Dexec.mainClass="no.ks.fiks.io.client.eksempel.EksempelApp" -f fiks-io-eksempel-klient/pom.xml
```

Kommandoene må kjøres fra `fiks-io-klient-java/` mappen for å fungere.

## Bruk

Etter oppstart av applikasjonen vil du se følgende meny:

```
Starter interaktiv konsoll:
P - Send PING melding
G - Send PONG melding
K - Hent konto informasjon og status
M - Hent Maskinporten token
Q - Avslutter applikasjonen
```

### Maskinporten Token og API-kall

Fiks IO API bruker Maskinporten for autentisering. Velg alternativ **M** i menyen for å hente en Maskinporten access token. Tokenet er en JWT (JSON Web Token) som genereres basert på din organisasjons virksomhetssertifikat og privatnøkkel.

**Viktig:** Maskinporten token har en begrenset levetid på typisk 2 minutt og må fornyes ved behov. Hvis det er behov for å gjøre mange API-kall manuelt så bør det settes opp en maskinporten klient med lengre levetid.

#### Eksempel API-kall med curl

Her er et eksempel på hvordan du kan hente konto-informasjon ved å bruke et Maskinporten token:

```bash
curl -X 'GET' \
'https://api.fiks.test.ks.no/fiks-protokoll/katalog/api/v1/kontoer/<kontoid>' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <maskinporten-token>' \
-H 'IntegrasjonId: <integrasjonid>' \
-H 'IntegrasjonPassord: <integrasjonpassord>'
```

**Parametre som må byttes:**
- `<kontoid>`: Din Fiks IO konto-ID
- `<maskinporten-token>`: Maskinporten access token fra kommando M
- `<integrasjonid>`: Din integrasjons-ID
- `<integrasjonpassord>`: Dit integrasjons-passord


## Ressurser

- [Fiks IO dokumentasjon](https://ks-no.github.io/fiks-plattform/tjenester/fiksprotokoll/fiksio/)
- [Maskinporten dokumentasjon](https://docs.digdir.no/docs/idporten/maskinporten/)
37 changes: 37 additions & 0 deletions fiks-io-eksempel-klient/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>no.ks.fiks</groupId>
<artifactId>fiks-io-klient-java-parent</artifactId>
<version>3.6.2-SNAPSHOT</version>
</parent>

<artifactId>fiks-io-eksempel-klient</artifactId>

<dependencies>
<dependency>
<groupId>no.ks.fiks</groupId>
<artifactId>fiks-io-klient-java</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>

<build>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package no.ks.fiks.io.client.eksempel;

/**
* ANSI fargemaner for terminal-output
*/
public enum AnsiColor {
RESET("\u001B[0m"),
RED("\u001B[31m"),
GREEN("\u001B[32m"),
YELLOW("\u001B[33m"),
BLUE("\u001B[34m"),
MAGENTA("\u001B[35m"),
CYAN("\u001B[36m"),
WHITE("\u001B[37m");

private final String code;

AnsiColor(String code) {
this.code = code;
}

@Override
public String toString() {
return code;
}

public final static String BOLD = "\u001B[1m";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package no.ks.fiks.io.client.eksempel;

import no.ks.fiks.io.client.FiksIOKlient;
import no.ks.fiks.io.client.eksempel.config.AmqpProperties;
import no.ks.fiks.io.client.eksempel.config.FiksApiProperties;
import no.ks.fiks.io.client.eksempel.config.FiksIOKlientProperties;
import no.ks.fiks.io.client.eksempel.config.MaskinportenProperties;
import no.ks.fiks.io.client.eksempel.utils.JavaClientUtils;
import no.ks.fiks.io.client.eksempel.utils.MeldingType;
import no.ks.fiks.io.client.eksempel.utils.TokenProvider;
import no.ks.fiks.io.client.model.Konto;
import no.ks.fiks.io.client.model.KontoId;
import no.ks.fiks.io.client.model.MeldingRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Scanner;

import static no.ks.fiks.io.client.eksempel.AnsiColor.*;
import static no.ks.fiks.io.client.eksempel.utils.MeldingType.PING;
import static no.ks.fiks.io.client.eksempel.utils.MeldingType.PONG;

public class EksempelApp {
private static final Logger logger = LoggerFactory.getLogger(EksempelApp.class);
private static final FiksIOKlientProperties klientProperties = FiksIOKlientProperties.loadProperties("config.properties");
private static final MaskinportenProperties maskinportenProperties = MaskinportenProperties.loadMaskinportenProperties("maskinporten.properties");
private static final FiksApiProperties fiksApiProperties = FiksApiProperties.loadProperties("fiks-api.properties");
private static final AmqpProperties amqpProperties = AmqpProperties.loadProperties("amqp.properties");

public static void main(String[] args) throws Exception {
final var kontoId = klientProperties.kontoId();

try (var javaKlient = JavaClientUtils.lagJavaKlient(klientProperties, maskinportenProperties, fiksApiProperties, amqpProperties)) {
final var tokenProvider = JavaClientUtils.lagTokenProvider(maskinportenProperties);

javaKlient.newSubscription(new MeldingHandler()::behandleMelding);

runInteractiveConsole(javaKlient, kontoId, tokenProvider);
System.exit(0);
}
}

private static void runInteractiveConsole(FiksIOKlient javaKlient, KontoId mottakerKontoId, TokenProvider tokenProvider) {
final var avsenderKontoId = javaKlient.getKontoId();
System.out.println("Starter interaktiv konsoll:");
System.out.println(" P - Send PING melding");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bør følge samme spor som .net example med reelle protokollnavn.

FiksIOPing = "ping";
FiksIOPong = "pong";
FiksArkivPing = "no.ks.fiks.arkiv.v1.ping";
FiksArkivPong = "no.ks.fiks.arkiv.v1.pong";
FiksPlanPing = "no.ks.fiks.plan.v2.ping";
FiksPlanPong = "no.ks.fiks.plan.v2.pong";
FiksMatrikkelfoeringPing = "no.ks.fiks.matrikkelfoering.v2.ping";
FiksMatrikkelfoeringPong = "no.ks.fiks.matrikkelfoering.v2.pong";

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La oss snakke om det direkte, jeg unngikk dette bevist.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brukt reelle protokollnavn, men tar ikke å inkluderer alle variantene her

System.out.println(" G - Send PONG melding");
System.out.println(" K - Hent konto informasjon og status");
System.out.println(" M - Hent maskinporten token");
System.out.println(" Q - Avslutter applikasjonen");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Få på plass en helesjekk...isOpen, getKonto, getKontoStatus, validerPublicKeyMotPrivateKey?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hent konto informasjon er egentlig getKontoStatus da status er med i konto informasjon.


try (Scanner scanner = new Scanner(System.in)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ingen demonstrasjon av payload-dekryptering / ASiC-E-lesing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La oss ta det direkte, ting er litt annerledes mellom Java og Dotnet.

String input = "";

while (scanner.hasNextLine() && !input.equalsIgnoreCase("Q")) {
input = scanner.nextLine().trim().toUpperCase();
switch (input) {
case "P":
logger.info(formatCommand("P trykket", "Sender PING melding fra konto: " + avsenderKontoId + " til konto: " + mottakerKontoId));
send(javaKlient, mottakerKontoId, PING, "Dette er en PING melding");
break;
case "G":
logger.info(formatCommand("G trykket", "Sender PONG melding fra konto: " + avsenderKontoId + " til konto: " + mottakerKontoId));
send(javaKlient, mottakerKontoId, PONG, "Dette er en PONG melding");
break;
case "K":
logger.info(formatCommand("K trykket", "Henter konto: " + mottakerKontoId));
final var konto = javaKlient.getKonto(mottakerKontoId);
konto.ifPresent(value -> logger.info(formatKonto(value)));
break;
case "M":
logger.info(formatCommand("M trykket", "Henter maskinporten token"));
hentOgVisMaskinportenToken(tokenProvider);
break;
case "Q":
logger.info(formatCommand("Q trykket", "Avslutter applikasjon"));
return;
default:
if (!input.isEmpty()) {
logger.info(formatCommand("Ukjent kommando", "Prøv P, G, K, M eller Q"));
}
}
}
}
}

public static void send(FiksIOKlient klient, KontoId mottakerKontoId, MeldingType meldingType, String innhold) {
final var avsenderKontoId = klient.getKontoId();
logger.info("Sender melding - Avsender: {}, Mottaker: {}, Type: {}", avsenderKontoId, mottakerKontoId, meldingType);
klient.send(MeldingRequest.builder().mottakerKontoId(mottakerKontoId).meldingType(meldingType.toString()).build(), innhold, "melding.txt");
}

private static void hentOgVisMaskinportenToken(TokenProvider tokenProvider) {
final var token = tokenProvider.getMaskinportenToken();
logger.info(formatMaskinportenToken(token));
}

private static String formatCommand(String command, String message) {
return String.format("%s[%s]%s %s%s%s",
BOLD + AnsiColor.MAGENTA, command, RESET,
AnsiColor.WHITE, message, RESET
);
}

private static String formatMaskinportenToken(String token) {
return String.format(
"""

%s════════════════════════════════════════%s
%s MASKINPORTEN TOKEN%s
%s════════════════════════════════════════%s
%sToken:%s
%s%s%s
%s════════════════════════════════════════%s
""",
BOLD + BLUE, RESET,
BOLD + GREEN, RESET,
BOLD + BLUE, RESET,
CYAN, RESET,
YELLOW, token, RESET,
BOLD + BLUE, RESET
);
}

private static String formatKonto(Konto konto) {
return String.format(
"""

%s════════════════════════════════════════%s
%s KONTO INFORMASJON%s
%s════════════════════════════════════════%s
%sKonto ID:%s %s%s%s
%sKonto Navn:%s %s%s%s
%sFiks Org Navn:%s %s%s%s
%sGyldig Avsender:%s %s%s%s
%sGyldig Mottaker:%s %s%s%s
%sUavhentede Meldinger:%s %s%d%s
%s════════════════════════════════════════%s
""",
BOLD + BLUE, RESET,
BOLD + GREEN, RESET,
BOLD + BLUE, RESET,
CYAN, RESET, YELLOW, konto.getKontoId(), RESET,
CYAN, RESET, YELLOW, konto.getKontoNavn(), RESET,
CYAN, RESET, YELLOW, konto.getFiksOrgNavn(), RESET,
CYAN, RESET, YELLOW, konto.isGyldigAvsender(), RESET,
CYAN, RESET, YELLOW, konto.isGyldigMottaker(), RESET,
CYAN, RESET, YELLOW, konto.getAntallUavhentedeMeldinger(), RESET,
BOLD + BLUE, RESET
);
}
}


Loading
Loading