- Created by Unknown User (thomas.guenter), last modified by Miriam Stettler on Nov 25, 2021
You are viewing an old version of this page. View the current version.
Compare with Current View Page History
« Previous Version 38 Next »
Release Information | 1.3.3 |
---|---|
Target audience | This documentation is intended for developers and system integrators which enable customer systems for interaction with the ZSR Webservice. |
Summary | The ZSR Webservice is the public API to connect customer specific solutions to the SASIS care provider register in a well structured an secured manner. The reader of this documentation will find the API description in detail as well as further information about the access and authorization mechanisms. |
Introduction
The ZSR Webservice provides a possibility to connect enterprise systems to SASIS internal data structures to maintain and interrogate care providers and their clearing numbers.
The ZSR Webservice is designed to replace existing file based data exchange with a high performance and secure online interface. The API itself is REST based and supports tenant specific requests which is handled based on the authentication of the API client.
The main functionality is:
- Interrogation of clearing number (ZSR/RCC/CPR number) or employee number (K-Nummer/Numéro C/Numero di controllo) overviews and details.
- Interrogation of comments on health services.
- Interrogation of filtered clearing numbers and/or employee numbers based on subscription search options.
- Maintenance of care provider certification periods (mainly used by health service certifiers).
ZSR Webservice Specification
Status codes
The SASIS Regis uses standard http status codes.
The following status codes will generally be used by the API:
Status Code | Description |
---|---|
200 | Success |
202 | Accepted; Request is valid and business process could be triggered successfully. |
400 | Bad Request; The request data is invalid. |
401 | Unauthorized; The caller does not have sufficient privileges to perform the call. |
403 | Forbidden; The server is refusing the action. |
500 | Internal Server Error; Any unexpected internal failure. |
Referenced Algorithms
Clearing number check digit
The clearing number has the following structure:
- A leading char as check digit
- A four digit sequential number
- A two digit number circle / canton number
The leading char of the clearing number is created and validated as follows:
- Each number is multiplied with its position (calculate from the right end).
- All products are summarized into one sum.
- Modulo 26 of the sum denotes the char in the alphabet (result 0 results in char 'Z').
Example L248519:(9*1)+(1*2)+(5*3)+(8*4)+(4*5)+(2*6) = 90
90 mod 26 = 12
12th char in the alphabet = L
UID ECH0097 check digit
The ECH0097 enterprise identification number (Unternehmensidentifikationsnummer UID, Numéro d’identification des entreprises IDE, Numero d’identificazione delle imprese IDI) has the following structure:
- ISO-Alpha-3 Code (ISO 3166-1) of Switzerland (CHE)
- 8 digit pseudo random number
- check digit
The check digit is created and validated as follows:
- Each digit of the pseudo-random number is multiplied with a predefined multiplier: 54327654
- All products are summarized into one sum.
- 11 minus Modulo 11 of the sum defines the check digit.
Example CHE-114.617.288:(1*5)+(1*4)+(4*3)+(6*2)+(1*7)+(7*6)+(2*5)+(8*4) = 124
124 mod 11 = 3
11 - 3 = 8
Authentication / Autorisation
The authentication is based on OpenID Connect, an identity layer on top of OAuth 2.0 and its corresponding flows/grants. For application integration, the resource owner password flow using the OAuth 2.0 password grant is to be used.
The SASIS IAM infrastructure acts a OpenID provider / authorization server.
- The API Client requests the token endpoint from the auth server.
- The token endpoint is returned to the API Client.
- Request an access token from the auth server by providing the following post request parameters:
- grant_type: set to 'password'
- client_id: provided individually by SASIS
- client_secret: provided individually by SASIS
- username: provided individually by SASIS
- password: provided individually by SASIS
- scope: set constantly to 'openid profile email offline_access roles c1s_profile cpr'
- The access token as well as the refresh token is returned to the API Client.
- The specific API resource is called providing the access token in as bearer in the Authorization http header:
'Authorization: Bearer <access token>'
- The API responds to the request.
- Once the access token expired, the previously received refresh token is used to request a new access token from the auth server by providing the following parameters:
- grant_type: set to 'refresh_token'
- client_id: provided individually by SASIS
- client_secret: provided individually by SASIS
- scope: set constantly to 'openid profile email offline_access roles c1s_profile cpr'
- refresh_token: The refresh token received with the last access token.
- A new access token as well as a new refresh token is returned to the API Client.
- The specific API resource is called providing the new access token in as bearer in the Authorization http header:
'Authorization: Bearer <access token>'
- The API responds to the request.
Access token
The access token response contains additional information:
{ "access_token": "MTQ0NjOkZmQ5OTM5NDE9ZTZjNGZmZjI3", "refresh_token": "GEbRxBNZmQOTM0NjOkZ5NDE9ZedjnXbL", "token_type": "bearer", "expires_in": 300, "scope": "openid profile email offline_access roles c1s_profile cpr" }
The token itself is a JWT and can therefore be decoded on the JWT website.
The expires_in field defines the validity period of the token in seconds. Afterwards, a new token must be retrieved.
Code samples
A complete c# sample shows how to access one specific API resource (numbers):
Authentication in other languages follows the same procedure.
The following code snippets explain the procedure on a step-by-step basis:
/// <summary> /// Loads the IAM configuration. /// </summary> private async Task<DiscoveryResponse> GetDiscoveryDocumentAsync(CancellationToken ct) { using (var client = new HttpClient()) { var discoveryResponse = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { Address = "[AuthorityUrl]" }, ct).ConfigureAwait(false); if (discoveryResponse.IsError) throw new Exception(discoveryResponse.Error); return discoveryResponse; } }
/// <summary> /// Gets a new token response with a username and password. /// </summary> private async Task<TokenResponse> RequestTokenAsync(CancellationToken ct) { using (var client = new HttpClient()) { var discoveryResponse = await GetDiscoveryDocumentAsync(ct).ConfigureAwait(false); var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest { ClientId = "[ClientId]", ClientSecret = "[ClientSecret]", UserName = "[UserName]", Password = "[Password]", Address = discoveryResponse.TokenEndpoint, GrantType = OidcConstants.GrantTypes.Password, Scope = string.Join(" ", _scopes), }, ct).ConfigureAwait(false); if (tokenResponse.IsError) throw new Exception(tokenResponse.Error); return tokenResponse; } }
/// <summary> /// Gets the access token by either requesting a new token or by using the refresh token of an already existing token. /// </summary> private async Task<string> GetAccessTokenAsync(CancellationToken ct) { if (_tokenResponse == null) { // Creates a new token response _tokenResponse = await RequestTokenAsync(ct).ConfigureAwait(false); } else { var jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); // Parses JWT access token var jwtSecurityToken = jwtSecurityTokenHandler.ReadToken(_tokenResponse.AccessToken) as JwtSecurityToken; // The access token might be valid now, but expired the very next millisecond. // Thus, add a reasonable reserve in minutes for the validity time comparison below. var comparisionCorrectionInMinutes = 1; // Compares the access token life time with the current time, modified by the comparison correction value. if (jwtSecurityToken.ValidTo < DateTime.UtcNow.AddMinutes(comparisionCorrectionInMinutes)) { // Updates the existing token response _tokenResponse = await RefreshTokenAsync(_tokenResponse.RefreshToken, ct).ConfigureAwait(false); } } return _tokenResponse.AccessToken; } /// <summary> /// Gets an updated token response by using a refresh token. /// </summary> private async Task<TokenResponse> RefreshTokenAsync(string refreshToken, CancellationToken ct) { using (var client = new HttpClient()) { var discoveryResponse = await GetDiscoveryDocumentAsync(ct).ConfigureAwait(false); var tokenResponse = await client.RequestTokenAsync(new TokenRequest { ClientId = "[ClientId]", ClientSecret = "[ClientSecret]", Address = discoveryResponse.TokenEndpoint, ClientCredentialStyle = ClientCredentialStyle.AuthorizationHeader, GrantType = OidcConstants.GrantTypes.RefreshToken, Parameters = { { "refresh_token", refreshToken }, { "scope", string.Join(" ", _scopes) } } }); if (tokenResponse.IsError) throw new Exception(tokenResponse.Error); return tokenResponse; } }
/// <summary> /// A simple CPR API number search request. /// </summary> private async Task<BulkResponse> CprApiSampleRequestAsync(string accessToken, CancellationToken ct) { BulkResponse bulkResponse = new BulkResponse(); using (var client = new HttpClient()) { client.SetBearerToken(accessToken); var response = await client.GetAsync($"https://[CprBaseUrl]/ApiGateway/api/v1/numbers?searchOptions=Okp&offset=0&limit=10", ct).ConfigureAwait(false); if (!response.IsSuccessStatusCode) throw new Exception("There was a problem with the request"); string content = await response.Content.ReadAsStringAsync(); if (content != null && content.Length > 0) { bulkResponse = JsonConvert.DeserializeObject<BulkResponse>(content); } } return bulkResponse; }
var accessToken = await GetAccessTokenAsync(ct).ConfigureAwait(false); var cprApiResponse = await CprApiSampleRequestAsync(accessToken, ct).ConfigureAwait(false);
Connection Settings
Setting | Test Environment | Live Environment |
---|---|---|
AuthorityUrl | https://openid-test.santesuisse.ch | https://openid.santesuisse.ch |
CprBaseUrl | https://stagecurrent.zsrnext.ch/ | https://www.zsrnext.ch |
ClientId | 1) | 1) |
ClientSecret | 1) | 1) |
UserName | 1) | 1) |
Password | 1) | 1) |
1) To be provided individually by SASIS. Please contact: support@sasis.ch
- No labels