1
Kapitel
Indledning
Kapitel
Nærværende dokument beskriver hvorledes man kan udvikle en applikation der anvender den publicerede SOAP webservice til at aflevere XBRL regnskaber, og den publicerede REST webservice til at aflevere inline XBRL (iXBRL) regnskaber.
Beskrivelsen tager udgangspunkt i et eksempel på en webservice klient der derved kan anvendes som udgangspunkt/inspiration.
Dokumentet beskriver dels generelle forhold omkring denne udvikling og dernæst specifikke forhold om hhv. udvikling i Java.
Ændringer til version 3.7 af dokumentet:
- Fejlkode 75 ang. Grønland udgår som følge af at indberetning for Grønlandske virksomheder bliver muligt
Ændringer til version 3.8 af dokumentet:
af Java. Det angivne afspejler de versioner vi har testet med.
- Fejl i URL til hentning af testcertifikater rettet
- Afsnit om testdata tilrettet med information om hvor de kan hentes
- Tilføjet information om ændringer til TLS og kryptering. Da Erhvervsstyrelsen ikke længere tillader TLS 1.0 og 1.1 eller kryptering med 128 bit, er der krav om visse minimumsversioner
Ændringer til version 3.9 af dokumentet:
- Tilføjet højere versionsnummer af .NET Framework, af hensyn til understøttelse af nyere versioner af TLS.
Ændringer til version 4.0 af dokumentet:
- URL’er til SOAP webservice er blevet opdaterede.
- Beskrivelse af indberetning af inline XBRL regnskaber, gennem ny REST webservice.
- Beskrivelse af fejlkode 80, 81 og 82 tilføjet. Disse fejlkoder knytter sig alle til den nye REST webservice.
1.1. Værktøjer
Der er i denne beskrivelse anvendt følgende C
Java:
- Eclipse version 3.5
- OpenJDK 1.8.0_152
- OpenOCES 1.8.0 (www.openoces.org/opensign/download.html)
1.2. Anskaffelse af nødvendige certifikater
For at kunne anvende den integrerede XBRL løsning er det nødvendigt at have certifikater til rådighed, dels for at kunne anvende disse til signering af det indsendte XBRL regnskab, og dels for at kunne indgå i TLS kommunikation ved SOAP- og REST webservicekald.
Løsningen anvender de fælles offentlige OCES certifikater til virksomheder.
Der kan anvendes FOCES (funktionscertifikat) og VOCES (virksomhedscertifikat) certifikater, til både SOAP- og REST webservicekald. SOAP webservicen accepterer desuden MOCES (medarbejdercertifikat) certifikater.
2
Kapitel
Generering af webservice stubs
Kapitel
Kaldet af SOAP webservices foregår som en HTTP POST mod webservicens URL med et XML dokument og et PDF dokument afhængig af modtager, hvor argumenterne til webservicen er pakket ind i en SOAP envelope struktur.
Da det kan være vanskeligt at arbejde direkte med denne XML/SOAP struktur, indeholder de fleste udviklingsværktøjer en kodegenerering, der på baggrund af webservicens publicerede WSDL, kan generere klasser der gør det nemmere, dels at opbygge argument strukturen, og dels at udføre selve kaldet med argumenterne til webservicen.
Fælles for disse kodegenereringsværktøjer er, at de skal have en URL til WSDL’en for den publicerede webservice.
For XBRL webservicen er URL’en til WSDL’en:
http://erst<env>.virk.dk/ri/s2s/RegisterXbrlEksternWS?wsdl
eller
https: //erst<env>.virk.dk/ri/s2s /RegisterXbrlEksternWS?wsdl, hvor <env> er hhv. dev, test eller preprod
URL’en til prod WSDL’en er:
BEMÆRK: Adgang til dev og test miljøerne er forbeholdt udviklere der er på Erhvervsstyrelsens eget netværk. Det er ikke muligt at anvende disse miljøer udefra.
2.1. Generel struktur for eksempel klient
Eksempel klienterne har følgende struktur:
En simpel grænseflade til at prompte brugeren for de nødvendige data der skal anvendes som argumenter til kaldet af webservicen. Disse nødvendige data er:
- Et XBRL regnskab
- Regnskabet som PDF (for destination ERST).
- Afsender certifikat i form af PKCS#12 fil inkl. password til generering af digitale signaturer for XBRL dokumentet.
- Destination for data – Erhvervsstyrelsen (ERST), Danmarks Statistik (DST), og SKAT (SKAT)
En angivelse af om transporten skal foregå via HTTP eller HTTPS. En egentlig produktions implementering vil altid anvende HTTPS til kaldet af webservicen, men i eksempel klienterne kan man vælge begge former for transport.
- Valg af webservice der kaldes – der kan kaldes webservice lokalt eller på preprod miljøet (med mindre man er på styrelsens eget netværk hvor dev og test også er tilgængelige..
2.1.1 En klasse til indpakning af de indsamlede argumenter.
En klasse der anvender de genererede klasser til at opbygge den nødvendige argument struktur og derefter kalder webservicen med argument strukturen via en genereret webservice stub.
Når der skal laves en produktionsklar implementering, der anvender webservicen, skal denne naturligvis anvende produktionsversionen af webservicen.
URL’en for produktionsversionen er:
https://erst.virk.dk/ri/s2s/RegisterXbrlEksternWS
2.1.2 Klasser til generering af digitale signaturer.
Webservicens API kræver, at XBRL regnskabet pakkes ind i et XML dokument der er signeret med afsenderens certifikat, jf. XML Digitale Signaturer ( www.w3.org/TR/xmldsigcore ).
Den digitale signatur der skal medsendes, er en OpenOCES ( www.openoces.org ) signatur med namespace “http://www.openoces.org/2006/07/signature#”.
Der er i eksempel-klienten inkluderet klasser, der sikrer at der genereres en sådan signatur. Dette er uddybet under beskrivelsen af klienten.
I det efterfølgende gennemgås Java klienten.
3
Kapitel
Beskrivelse af REST webservice
Kapitel
3.1. Basis URL
Basis-URL for REST webservices findes på:
https://erst-api<env>.virk.dk/ri/api, hvor <env> er hhv. dev, test eller preprod.
URL’en til produktionssystemet (prod) er:
BEMÆRK: Adgang til dev og test miljøerne er forbeholdt udviklere, der er på Erhvervsstyrelsens eget netværk. Det er ikke muligt at anvende disse miljøer udefra.
3.2. Endpoints
Inline XBRL REST webservicen findes på
/ixbrl/indberet
Endpoint’et understøtter GET og POST
3.2.1 GET
Det accepterede dataskema, som benyttes i forbindelse med ovenstående post, returneres ved en http GET til ovenstående endpoint. Der returneres følgende JSON skema:
{
"$id": "ri/api/ixbrl/indberet.json/v1",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Indberetning af ixbrl",
"type": "object",
"required": true,
"properties": {
"destinationErst": {
"type": "boolean",
"required": true
},
"iXbrl": {
"type": "string",
"required": true,
"minLength": 10
},
"token": {
"type": "string"
}
}
}
Property | Krævet | |
---|---|---|
destinationErst | Ja |
Feltet skal altid være der, og have værdien ’true’ |
iXbrl | Ja |
Indeholder inline XBRL. Værdien er Base64 kodet |
token | Nej |
Medsendes, hvis første kald til REST webservicen returnerede en advis og en token. Denne token medsendes, for at indberette trods advis’en |
3.2.2 POST
Kaldet af REST webservicen, når et inline XBRL regnskab skal indberettes, foregår som en HTTP POST.
3.2.2.1 Returværdier – skema
REST webservicen svarer med data på følgende JSON skema:
{
"$id": "ri/api/ixbrl/indberet_response.json/v1",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Response fra indberetning af ixbrl",
"type": "object",
"required": true,
"properties": {
"statusCode": {
"type": "string",
"required": true
},
"statusText": {
"type": "string",
},
"statusDetail": {
"type": "string",
},
"companyCvr": {
"type": "string",
},
"companyName": {
"type": "string",
},
"registrationDate": {
"type": "string",
},
"reportPeriod": {
"type": "string",
},
"uniqueReportIdentifier": {
"type": "string",
},
"token": {
"type": "string"
},
"validationErrors": {
"type": "array",
"items": { "$ref": "#/definitions/validationError" }
}
},
"definitions": {
"validationError" : {
"type": "object",
"required": ["path", "instance", "message", "schema"],
"properties": {
"path": {
"type": "string",
"description": "Hvad kunne ikke valideres? f.eks. this.iXbrl"
}
"instance": {
"type": "string",
"description": "Værdien som ikke kunne valideres"
},
"message": {
"type": "string",
"description": "Beskrivelse af valideringsfejlen"
},
"schema": {
"type": "object",
"required": ["type", "required"],
"properties": {
"type": {
"type": "string",
"description": "Datatypen (f.eks. string)"
}
"required": {
"type": "boolean",
"description": "Er datafeltet krævet"
},
"minLength": {
"type": "integer",
"description": "Minimum længde af datafeltet"
}
}
}
}
}
}
}
4
Kapitel
Generel struktur for eksempel klient
Kapitel
Eksempel klienterne har følgende struktur:
En simpel grænseflade til at prompte brugeren for de nødvendige data der skal anvendes som argumenter til kaldet af SOAP og REST webservicen.
4.1. SOAP webservicen
De nødvendige data er:
- Et XBRL regnskab
- Regnskabet som PDF (for destination ERST).
- Afsendercertifikat i form af PKCS#12 fil inkl. password til generering af digitale signaturer for XBRL dokumentet.
- Destination for data – Erhvervsstyrelsen (ERST), Danmarks Statistik (DST), og SKAT (SKAT)
- En angivelse af om transporten skal foregå via HTTP eller HTTPS.
En egentlig produktions implementering vil altid anvende HTTPS til kaldet af webservicen, men i eksempel klienterne kan man vælge begge former for transport. - Valg af webservice der kaldes – der kan kaldes webservice på prod eller preprod miljøet (med mindre man er på styrelsens eget netværk hvor dev og test også er tilgængelige.
En klasse til indpakning af de indsamlede argumenter for SOAP webservices.
En klasse der anvender de genererede klasser til at opbygge den nødvendige argument struktur og derefter kalder webservicen med argument strukturen via en genereret webservice stub.
Når der skal laves en produktionsklar implementering der anvender webservicen, skal denne naturligvis anvende produktionsversionen af webservicen.
URL’en for produktionsversionen er: https://erst.virk.dk/ri/s2s/RegisterXbrlEksternWS
4.1.1 Klasser til generering af digitale signaturer.
SOAP webservicens API kræver, at XBRL regnskabet pakkes ind i et XML dokument der er signeret med afsenderens certifikat, jf. XML Digitale Signaturer www.w3.org/TR/xmldsig-core
Den digitale signatur der skal medsendes, er en OpenOCES (www.openoces.org) signatur med namespace “http://www.openoces.org/2006/07/signature#”.
Der er i de to eksempel klienter inkluderet klasser, der sikrer at der genereres en sådan signatur. Dette er uddybet under beskrivelsen af de to eksempel klienter.
4.2. REST webservicen
De nødvendige data er:
- Et inline XBRL (iXBRL) regnskab
- Afsendercertifikat i form af PKCS#12 fil inkl. password . Certifikatet benyttes til TLS kommunikation med webservicen
- Destination for data – kun ERST er understøttet
- En angivelse af om transporten skal foregå via http eller HTTPS (TLS). I produktion vil det altid være HTTPS
- Valg af REST webservice der kaldes
- Valg af webservice der kaldes – der kan kaldes webservice på prod eller preprod miljøet (med mindre man er på styrelsens eget netværk hvor dev og test også er tilgængelige)
- En klasse til indkapsling af de indsamlede argumenter for REST webservicen
5
Kapitel
Java Eksempel Klient
Kapitel
Denne sektion beskriver hvorledes Java Eksempel Klienten kan anvendes og hvordan den er lavet.
Klasse navne etc. refererer til specifikke klasser der kan findes i zip filen der indeholder Java Eksempel Klienten.
Denne zip fil indeholder et Eclipse projekt, der kan importeres til et lokalt Eclipse workspace.
5.1. Installation og kørsel af eksempel klient
Java eksempel klienten installeres og køres ved at:
- Pakke zip filen 's2s_xbrl_eksempel_java_klient_Maj2019.zip' ud i en passende folder
- Afvikle filen 'run_klient.bat' (windows) eller 'run_klient.sh' (MacOS/Linux).
Testfiler kan hentes på følgende steder:
- XBRL regnskaber kan downloades via https://datacvr.virk.dk/data/. Vi kan dog ikke garantere at alle CVR numre er tilgængelige i preproduktion. Desuden kan man modtage fejlbeskeden at der allerede er registreret et regnskab for dette CVR nummer og periode hvis andre tester på dette CVR nummer.
- Regnskabets pdf (dette er blot en tilfældig pdf fil som ikke er password-beskyttet)
- Testcertifikat kan downloades fra Nets, jævnfør afsnittet ”Værktøjer”.
5.2. Generering af Webservice stub og klasser
Først oprettes et nyt Java projekt i Eclipse. Vælg derefter projektet, højreklik og vælg ”New → Other ...” for at vælge den rigtige wizard.
Vælg ”Web Service Client” og tryk ”Next >”

Dette vil bringe en dialog hvori webservicen skal vælges

Vælg ”Browse...” og i den fremkomne dialog, indtast placeringen af webservicens WSDL.

Vælg ”Ok” for at komme tilbage til den forrige dialog, nu med webservicen valgt:
Træk i ”slideren” så man blot opretter klienten (Develop Client) og klik ”Finish”. Dette vil generere stubs og hjælpeklasser til at kalde webservicen.

Følgende klasser vil blive genereret:

5.3. Wsimport til generering af Webservice stub og klasser
Java har også et værktøj (wsimport), som følger med i JDK’et, til generering af klasser ud fra et WSDL dokument.
Følgende kommando genererer klasser og interfaces, ud fra dev miljøets WSDL:
wsimport -keep -p webservice_xbrl.registerXbrlEkstern -s src/main/java
https://erstdev.virk.dk/ri/s2s/RegisterXbrlEksternWS?wsdl -verbosewsimport -keep -p
webservice_xbrl.registerXbrlEkstern -s src/main/java
https://erstdev.virk.dk/ri/s2s/RegisterXbrlEksternWS?wsdl -verbose
Nedenstående kodeeksempler benytter dog de klasser, som blev genereret af Eclipse.
5.4. Kald af webservice – RegisterXBRLInvoker
Klassen 'eksempel.RegisterXBRLInvoker' foretager kaldet til webservicen, ved hjælp af de genererede klasser.
Følgende detaljer kan fremhæves:
- Denne klasse modtager et argument der angiver om webservicen skal kaldes via http eller https. Dette påvirker justeringen af endpoint til at anvende hhv. http eller https.
- Ved hjælp af de generede klasser opbygges argument strukturen til kaldet af webservicen samt modtages resultatet af kaldet til webservicen.
5.5. Brugergrænseflade
Klassen 'eksempel.RegisterXBRLFront' indeholder en simpel brugergræseflade, der prompter brugeren for de nødvendige data.
Indholdet varierer lidt, afhængig af om der er valgt XBRL eller inline XBRL.
5.5.1 XBRL
Samler data sammen, signerer XBRL’en med det valgte certifikat, og kalder metoden registerXBRL i 'eksempel.RegisterXBRLInvoker'.

5.5.2 Inline XBRL
Samler data sammen, kalder 'registerInlineXbrl' i klassen 'RegisterInlineXBRLInvoker', og bruger det valgte certifikat til at instantiere en TLS 1.2 forbindelse til serveren.

5.6. Generering af Signeret XML dokument
Java implementeringen anvender funktionaliteten fra OpenOCES – OpenSign til at generere det Digitalt Signerede XML dokument i OpenOCES formatet.
De nødvendige klasser findes ikke som en selvstændig jar fil der kan downloades, men findes i stedet som en del af de plugin klasser, der er tiltænkt anvendelse ved brug af OpenSign appletten.
For at lette pakningen af Java eksempel klienten, er de nødvendige klasser samlet og pakket sammen i en openoces-1.8.0.jar fil.
Procedureren i signatur genereringen er følgende:
- Opret en 'Pkcs12CertificateHandler' på baggrund af den valgte PKCS#12 fil samt det tilhørende password.
- Modificer CallBackHandleren på den oprettede 'Pkcs12CertificateHandler' – dette er nødvendigt, da den normale 'CallBackHandler' er lavet til at få password’et via en bruger interaktion – hvilket ikke sker her.
- Generer det signerede XML dokument via metoden 'SignatureGenerator.sign' – denne metode returnerer en Enveloping signatur, dvs. at det signerede dokument er indeholdt i signaturen.
- XML prologen fjernes og den resterende XML Signatur er nu klar til at blive brugt som argument til webservicen.
6
Kapitel
Statusbeskeder fra webservicen
Kapitel
Hvert kald til webservicen returnerer en status kode, tekst og evt. detaljer, der beskriver resultatet af behandlingen af det foretagne kald.
Kode 0 betyder OK, øvrige koder er fejlkoder. Ved kode 0 kan tekst og detaljer indeholder advis.
Siden version 3.2 af dette dokument blev udsendt, er den tekniske platform for webservicen blevet opdateret og en del af fejlkoderne er ikke længere relevante. Disse er derfor fjernet fra oversigten.
Bemærk at fejlkode 73 tidligere fejlagtigt var angivet som “CVR-nummer ikke fundet”.
Kode | Tekst |
---|---|
10 | XBRL dokumentet kan ikke valideres |
23 | XBRL dokumentet opfylder ikke Erhvervsstyrelsens krav |
24 | XBRL dokumentet er valideret med Advis |
30 | Årsrapportens PDF dokument kan ikke valideres |
31 | Årsrapportens PDF overstiger den maksimale størrelse på 20 Mb |
40 | Det signerede XML dokuments signatur kan ikke valideres |
41 | Certifikatet der har signeret XML dokumentet er ikke validt |
43 | Det signerede XML dokument kan ikke valideres |
44 | Der kan kun anvendes medarbejder- eller virksomhedscertifikat ved indberetning til SKAT |
50 | Der er allerede registreret et regnskab for dette CVR nummer i denne periode – der kan ikke |
51 | Der skal angives netop een destination |
55 | XBRL dokumentet til Erhvervsstyrelsen skal være en Årsrapport eller Likvidationsregnskab |
56 | XBRL dokumentet til Danmarks Statistik skal være en Regnskabsstatistik |
57 | XBRL dokumentet til SKAT skal være en Selskabsselvangivelse |
58 | Mangler registerXbrlEkstern i SOAP |
59 | PDF dokumentet mangler |
60 | PDF dokumentet overholder ikke størrelsesbegræsningen på 20 Mb |
72 | CVR-nummer ikke fundet |
73 | Danmarks Statistik svarer at der er fejl i den indberettede selskabsstatistik. |
74 | Vi kan i øjeblikket ikke få forbindelse til Danmarks Statistiks systemer |
80 | REST-kaldets JSON data kunne valideres imod skemaet |
81 | Kun ERST er understøttet som destination i REST-kaldet |
82 | Inline XBRL (IXBRL) er ikke Base64 kodet i REST-kaldet |
98 | Systemet er optaget - prøv venligst senere |
99 | Der er opstået en fejl - kontakt venligst Erhvervs- og Selskabsstyrelsen |
7
Kapitel
Appendix A: Advis håndtering i Erhvervsstyrelsens System-til-system service
Kapitel
Erhvervsstyrelsen indfører fra 23/8 2016 et nyt niveau i sin modtagekontrol kaldet 'Advis'. En advis adskiller sig fra en fejl ved at indberetter har mulighed for at fortsætte indberetningen efter at have accepteret den.
Fremover vil alle indberetninger i system-til-system som har fået en advis få et svar tilbage indeholdende en ”token”. Såfremt brugeren vælger at indberette trods advis’en da gentages indberetningen, sammen med den modtagede token.
Token kan kun anvendes hvis der er tale om en indberetning der er identisk med den indberetning der adstedkom advis’en. Tilsvarende løsningen indarbejdes i styrelsens løsninger på virk.dk.
Både SOAP webserviceløsningen og REST webserviceløsningen understøtter brugen af token.
7.1. Skal eksisterende SOAP webserviceløsninger lave deres kode om til at bruge en ny service?
Nej, Erhvervsstyrelsen har haft som mål at bevare den eksisterende service, derfor er der kun tale om et ekstra valgfrit felt i det der sendes frem og tilbage. Indtil en indberetninger får en advis, vil der ikke kunne mærkes forskel.
7.2. En ny opdateret WSDL
Til formålet er der tilføjet en linje i WSDL’en; i henholdsvist registerXbrlEkstern og registerXbrlEksternResponse og begge ser sådan her ud:
<xs:element minOccurs="0" name="token" type="xs:string" />
Det nye element er et token; en streng som løsningen sender til dig og som du kan sende tilbage. Men den behøver ikke at være der.
7.3. Kodeeksempel
Det efterfølgende kodeeksempel tager udgangspunkt i den eksisterende eksempel-klient til Java, hvor vi har brugt wsdl2java til at lave en java-klasse ud af vores WSDL. Derfra kan man finde sit token hvis der er blevet sendt et med tilbage:
RegisterXbrlEksternWS stub = stubLocator.getRegisterXbrlEksternWSPort();
WsReturnRegister returnStatus;
returnStatus = stub.registerXbrlEkstern(registerXbrlInput.getSignedXbrl(), registerXbrlInput.getPdf(),
String result = invocationTime+
"Code: "+returnStatus.getStatusCode()+
"\nText: "+returnStatus.getStatusText()+
"\nDetail:\n"+returnStatus.getStatusDetail() + skatKvitMsg +
"\nToken: " + returnStatus.getToken() +
"\nSagsnummer: " + returnStatus.getUniqueReportIdentifier();
Tilsvarende hvis man vil acceptere sin advis, så skal token bare tilføjes til det indsendte:
// Saml input
RegisterXBRLInput input = new RegisterXBRLInput();
input.setSendDst(dstBox.isSelected() ? "Y" : "N");
input.setSendEogS(eogsBox.isSelected() ? "Y" : "N");
input.setSendSkat(skatBox.isSelected() ? "Y" : "N");
input.setPdf(pdf);
input.setSignedXbrl(xmlDSigSender);
input.setToken(token.getText());
8
Kapitel
Appendix B: Omgørelse og berigtigelse
Kapitel
Da det ikke er muligt at omgøre og berigtige regnskaber via via System-til-system servicen skal udviklere og testere som anvender klienten være opmærksom på at når der er indberettet korrekt på et CVR-nummer for en periode vil det ikke være muligt at indberette igen på samme CVR-nummer og regnskabsperiode.
Da Erhvervsstyrelsen anvender preproduktions-miljøet til forskellige andre tests af systemet kan der forekomme løbende ændringer i testdata.