Compare commits
145 Commits
feature/OV
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| c45f2059f4 | |||
| 53185d10b1 | |||
| f237f677e3 | |||
| 9bb7320299 | |||
| 1bf9fa2fd0 | |||
| 903adbe238 | |||
| b6586891fc | |||
| 8b148b22ac | |||
| 44dae159b8 | |||
| a7e32f6122 | |||
| 513045c146 | |||
| 8c4542a151 | |||
| 0749e927dc | |||
| 2b02e52c22 | |||
| 2cb6f910df | |||
| 1269f8916f | |||
| c3af1e9adf | |||
| 5d307d9808 | |||
| 105e81b5c4 | |||
| 24b4832c69 | |||
| 03372074d9 | |||
| bf0ebee435 | |||
| 541b0662f1 | |||
| 594475331f | |||
| 42c49693f1 | |||
| 62f001c902 | |||
| a71aa2e4df | |||
| 5e2b646a30 | |||
| 7ab0de07c4 | |||
|
|
39e5042350 | ||
| 2d742ca3f1 | |||
| 97c58dc3fe | |||
| d06da1401e | |||
| 04d46e0891 | |||
| c31554a526 | |||
| 9d9039d732 | |||
| 93efb6b8f7 | |||
| 77953a726a | |||
|
|
bbf21e61f7 | ||
| 681e9f7671 | |||
| c9b54a095d | |||
| e3139fdd6d | |||
| 4b932a0628 | |||
| 43bf7bfff3 | |||
| 007cf4bdef | |||
| baee1e8622 | |||
| ba314674a3 | |||
| 1f51eaadc6 | |||
| 5838b14ac5 | |||
| 14817cc621 | |||
| c1fbc0dc90 | |||
| 9b8cf65525 | |||
| 8f907896be | |||
| 591347e080 | |||
| da7afd63fc | |||
| 2c88fac238 | |||
| 6a24636d50 | |||
| c7fa48b554 | |||
| 5133903efb | |||
| 447912e081 | |||
| e2d78ec969 | |||
| c6facc5a70 | |||
| cf0d24632f | |||
| aa4721c651 | |||
| 46bf7874d9 | |||
| 1a14918f4a | |||
| 7147318900 | |||
| e0f78d2e38 | |||
| ab57e27c1d | |||
| 68c7ccc279 | |||
| 80c9fe7599 | |||
| 8946026860 | |||
| e6b2146706 | |||
| fb8723124a | |||
| 6d7c260e9e | |||
| 292588b7ba | |||
| 4bd216bd37 | |||
| bfaa1ddcb1 | |||
| 55bac27561 | |||
|
|
715a9668fc | ||
| b4f20a9758 | |||
| 22cb3ddd92 | |||
| 1f3e2289dc | |||
| 3ff55e5888 | |||
| 987f64a081 | |||
| 00448486f3 | |||
| ed61633579 | |||
| d34ba20d19 | |||
| 3e1f23afe3 | |||
|
|
6260cc5d63 | ||
| d9157d04ef | |||
| f57f17e645 | |||
| 3ae52206fc | |||
| a52dfcab93 | |||
| 80b0de274e | |||
| 38cfec81c8 | |||
|
|
3ffc525d48 | ||
|
|
105a18c0ac | ||
| 7732ae13a6 | |||
| 4084a574c9 | |||
| 3ebdf0090f | |||
| b898288632 | |||
| dce4d5ea17 | |||
| e4b3ab4ccf | |||
| 01aa8a9f1a | |||
| bb917c3635 | |||
| e0e70af138 | |||
| ed40c1d546 | |||
| f990a9844e | |||
| 235ec95edb | |||
| 76f6ed9c9f | |||
| e6b34176c2 | |||
| 959ed1cd96 | |||
| d7f4cefca8 | |||
| 270217238f | |||
| 04be5e5fbd | |||
| cd9a2f1683 | |||
| 8db879c589 | |||
| 8c3ad923f7 | |||
| b8ad7c4ebf | |||
| de884764bd | |||
|
|
403b336522 | ||
| 8f93fb03fd | |||
| 6f95cee75e | |||
| b0360c22be | |||
| bfa400820f | |||
| 62ab18b8e8 | |||
| 361d194bc4 | |||
| 207c6961a8 | |||
| 70842ca9dc | |||
| b51ce9cee1 | |||
| 0b91eae4fa | |||
| 482911d717 | |||
| a4f33c5439 | |||
| 3230465cbb | |||
| 6e3aa3a04b | |||
| b1bbe6b0cb | |||
| e47464f4a6 | |||
| 6de1d6f22b | |||
| 61332e38c6 | |||
| bdfff9377b | |||
|
|
1eec7eab28 | ||
| ba8a31c94f | |||
| 5e79d30c7c | |||
| 343b74c038 |
614
src/dotnet/padp-reference-web/PadpReferenceApi/ApimHelper.cs
Normal file
614
src/dotnet/padp-reference-web/PadpReferenceApi/ApimHelper.cs
Normal file
@ -0,0 +1,614 @@
|
||||
using System.Text;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
|
||||
class ApimHelper
|
||||
{
|
||||
private readonly string _apimBaseUri;
|
||||
private readonly string _b2bApiUri;
|
||||
private readonly string _padp1201Uri;
|
||||
private readonly string _padp1202Uri;
|
||||
private readonly string _padp1204Uri;
|
||||
private readonly string _padp1205Uri;
|
||||
private readonly string _padp1206V2Uri;
|
||||
private readonly string _padp1207V2Uri;
|
||||
private readonly string _padp1206V3Uri;
|
||||
private readonly string _padp1207V3Uri;
|
||||
|
||||
private readonly string _padp1210Uri;
|
||||
private readonly string _padp1211Uri;
|
||||
|
||||
private readonly string _b2bApiKey;
|
||||
private readonly string _padApiKey;
|
||||
private readonly string _clientId;
|
||||
private readonly string _clientSecret;
|
||||
private CryptoHelper cryptoHelper;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
private Dictionary<string, UserAuthInfo> userAuthInfoMap = new Dictionary<string, UserAuthInfo>();
|
||||
|
||||
public ApimHelper(UserProperties userProperties)
|
||||
{
|
||||
_apimBaseUri = userProperties.Uris.ApimBaseUri;
|
||||
_b2bApiUri = userProperties.Uris.B2bApiUri;
|
||||
_padp1201Uri = userProperties.Uris.Padp1201Uri;
|
||||
_padp1202Uri = userProperties.Uris.Padp1202Uri;
|
||||
_padp1204Uri = userProperties.Uris.Padp1204Uri;
|
||||
_padp1205Uri = userProperties.Uris.Padp1205Uri;
|
||||
_padp1206V2Uri = userProperties.Uris.Padp1206V2Uri;
|
||||
_padp1207V2Uri = userProperties.Uris.Padp1207V2Uri;
|
||||
_padp1206V3Uri = userProperties.Uris.Padp1206V3Uri;
|
||||
_padp1207V3Uri = userProperties.Uris.Padp1207V3Uri;
|
||||
_padp1210Uri = userProperties.Uris.Padp1210Uri;
|
||||
_padp1211Uri = userProperties.Uris.Padp1211Uri;
|
||||
|
||||
_b2bApiKey = userProperties.Credentials.B2bApiKey;
|
||||
_padApiKey = userProperties.Credentials.PadApiKey;
|
||||
_clientId = userProperties.Credentials.ClientId;
|
||||
_clientSecret = userProperties.Credentials.ClientSecret;
|
||||
|
||||
cryptoHelper = new CryptoHelper(userProperties);
|
||||
|
||||
HttpClientHandler handler = new HttpClientHandler();
|
||||
string clientCertPath = Environment.CurrentDirectory + userProperties.Credentials.ClientCertFile;
|
||||
Console.WriteLine("Loading client cert from: {0}", clientCertPath);
|
||||
handler.ClientCertificates.Add(new X509Certificate2(clientCertPath, userProperties.Credentials.ClientCertPassword));
|
||||
|
||||
_httpClient = new HttpClient(handler);
|
||||
_httpClient.BaseAddress = new Uri(_apimBaseUri);
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<B2bAccessToken>, JsonHttpResult<ErrorResponse>>> GetB2bAccessToken()
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, _b2bApiUri);
|
||||
request.Headers.Add("APIKey", _b2bApiKey);
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
request.Content = new StringContent($"grant_type=client_credentials&client_id={_clientId}&client_secret={_clientSecret}", Encoding.UTF8, "application/x-www-form-urlencoded");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", _b2bApiUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK) {
|
||||
return TypedResults.Ok(await response.Content.ReadFromJsonAsync<B2bAccessToken>());
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetB2bAccessTokenAsString()
|
||||
{
|
||||
var b2bAccessToken = GetB2bAccessToken();
|
||||
return ((Ok<B2bAccessToken>)b2bAccessToken.Result.Result).Value.accessToken;
|
||||
}
|
||||
|
||||
public IResult GetImageFromBase64(string base64Image)
|
||||
{
|
||||
byte[] imageBytes = Convert.FromBase64String(base64Image);
|
||||
return TypedResults.File(imageBytes, "image/jpeg");
|
||||
}
|
||||
|
||||
public async Task<Results<Created, JsonHttpResult<ErrorResponse>>> CreatePersonalData(string xTat, string email, string? name, string? birthDate, IFormFile? photo)
|
||||
{
|
||||
UserAuthInfo userAuthInfo;
|
||||
if (userAuthInfoMap.TryGetValue(xTat, out UserAuthInfo? authInfo) && authInfo.encryptedEphemeralKey != null) {
|
||||
userAuthInfo = authInfo;
|
||||
} else {
|
||||
var errorResponse = new ErrorResponse("No ephemeral key found for xTAT " + xTat + " - generate and validate OTP first using API 1210!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
var b2bAccessToken = await GetB2bAccessToken();
|
||||
|
||||
var requestUri = _padp1201Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + ((Ok<B2bAccessToken>)b2bAccessToken.Result).Value.accessToken);
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
var createPersonalDataRequest = new CreatePersonalDataRequest();
|
||||
createPersonalDataRequest.metadata.email = email;
|
||||
createPersonalDataRequest.metadata.ephemeralKeyAlias = userAuthInfo.ephemeralKeyAlias;
|
||||
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(userAuthInfo.encryptedEphemeralKey);
|
||||
|
||||
if (name != null) {
|
||||
createPersonalDataRequest.data.personalAccountData.name = cryptoHelper.EncryptText(decryptedEphemeralKey, name);
|
||||
}
|
||||
if (birthDate != null) {
|
||||
createPersonalDataRequest.data.personalAccountData.birthdate = cryptoHelper.EncryptText(decryptedEphemeralKey, birthDate);;
|
||||
}
|
||||
if (photo != null) {
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
photo.CopyTo(memoryStream);
|
||||
byte[] photoBytes = memoryStream.ToArray();
|
||||
createPersonalDataRequest.data.personalAccountData.photo = cryptoHelper.EncryptPhoto(decryptedEphemeralKey, photoBytes);
|
||||
}
|
||||
}
|
||||
request.Content = JsonContent.Create(createPersonalDataRequest);
|
||||
|
||||
Console.WriteLine("Sending request to {0} with request body {1}...", requestUri, request.Content.ReadAsStringAsync().Result);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.Created) {
|
||||
return TypedResults.Created();
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Created, JsonHttpResult<ErrorResponse>>> CreatePersonalDataWithEmailVerification(string xTat, string email, string? userAccessToken, string? name, string? birthDate, IFormFile? photo)
|
||||
{
|
||||
UserAuthInfo userAuthInfo;
|
||||
if (userAuthInfoMap.TryGetValue(xTat, out UserAuthInfo? authInfo)) {
|
||||
if (authInfo.encryptedEphemeralKey == null) {
|
||||
var errorResponse = new ErrorResponse("No ephemeral key found for xTAT " + xTat + " - generate an ephemeral key first, using API 1210!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
} else if (authInfo.UserAccessToken == null && userAccessToken == null) {
|
||||
var errorResponse = new ErrorResponse("No User Access Token found for xTAT " + xTat + " - provide one in the request, or generate and validate OTP using API 1206 and 1207!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
userAuthInfo = authInfo;
|
||||
} else {
|
||||
var errorResponse = new ErrorResponse("No ephemeral key found for xTAT " + xTat + " - generate an ephemeral key first, using API 1210!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
var requestUri = _padp1201Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
|
||||
if (userAccessToken != null) {
|
||||
Console.WriteLine("Using provided User Access Token {0}...", userAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAccessToken);
|
||||
} else {
|
||||
Console.WriteLine("Using stored User Access Token {0}...", userAuthInfo.UserAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAuthInfo.UserAccessToken);
|
||||
}
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
var createPersonalDataRequest = new CreatePersonalDataRequest();
|
||||
createPersonalDataRequest.metadata.email = email;
|
||||
createPersonalDataRequest.metadata.ephemeralKeyAlias = userAuthInfo.ephemeralKeyAlias;
|
||||
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(userAuthInfo.encryptedEphemeralKey);
|
||||
|
||||
if (name != null) {
|
||||
createPersonalDataRequest.data.personalAccountData.name = cryptoHelper.EncryptText(decryptedEphemeralKey, name);
|
||||
}
|
||||
if (birthDate != null) {
|
||||
createPersonalDataRequest.data.personalAccountData.birthdate = cryptoHelper.EncryptText(decryptedEphemeralKey, birthDate);;
|
||||
}
|
||||
if (photo != null) {
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
photo.CopyTo(memoryStream);
|
||||
byte[] photoBytes = memoryStream.ToArray();
|
||||
createPersonalDataRequest.data.personalAccountData.photo = cryptoHelper.EncryptPhoto(decryptedEphemeralKey, photoBytes);
|
||||
}
|
||||
}
|
||||
request.Content = JsonContent.Create(createPersonalDataRequest);
|
||||
|
||||
Console.WriteLine("Sending request to {0} with request body {1}...", requestUri, request.Content.ReadAsStringAsync().Result);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.Created) {
|
||||
return TypedResults.Created();
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<PersonalData>, JsonHttpResult<ErrorResponse>>> GetPersonalData(string xTat, string? userAccessToken)
|
||||
{
|
||||
UserAuthInfo? userAuthInfo = null;
|
||||
if (userAuthInfoMap.TryGetValue(xTat, out UserAuthInfo? authInfo) && authInfo.UserAccessToken != null)
|
||||
{
|
||||
userAuthInfo = authInfo;
|
||||
} else if (userAccessToken == null) {
|
||||
var errorResponse = new ErrorResponse("No User Access Token found for xTAT " + xTat + " - provide one in the request, or generate and validate OTP using API 1206 and 1207!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
var requestUri = _padp1202Uri.Replace("{xtat}", xTat) + "?pemRsaPublicKey=" + cryptoHelper.GetPublicKeyRsa();
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
|
||||
|
||||
if (userAccessToken != null)
|
||||
{
|
||||
Console.WriteLine("Using provided User Access Token {0}...", userAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAccessToken);
|
||||
} else {
|
||||
Console.WriteLine("Using stored User Access Token {0}...", userAuthInfo.UserAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAuthInfo.UserAccessToken);
|
||||
}
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
return TypedResults.Ok(await response.Content.ReadFromJsonAsync<PersonalData>());
|
||||
}
|
||||
else
|
||||
{
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<DecryptedPersonalData>, JsonHttpResult<ErrorResponse>>> GetDecryptedPersonalData(string xTat, string? userAccessToken)
|
||||
{
|
||||
var personalData = await GetPersonalData(xTat, userAccessToken);
|
||||
if (personalData.Result.GetType() == typeof(JsonHttpResult<ErrorResponse>)) {
|
||||
return (JsonHttpResult<ErrorResponse>)personalData.Result;
|
||||
} else {
|
||||
var decryptedPersonalData = await DecryptPersonalData(((Ok<PersonalData>)personalData.Result).Value);
|
||||
return TypedResults.Ok(decryptedPersonalData);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<DeletePersonalDataResponse>, JsonHttpResult<ErrorResponse>>> DeletePersonalData(string xTat, string? userAccessToken)
|
||||
{
|
||||
UserAuthInfo? userAuthInfo = null;
|
||||
if (userAuthInfoMap.TryGetValue(xTat, out UserAuthInfo? authInfo) && authInfo.UserAccessToken != null)
|
||||
{
|
||||
userAuthInfo = authInfo;
|
||||
} else if (userAccessToken == null) {
|
||||
var errorResponse = new ErrorResponse("No User Access Token found for xTAT " + xTat + " - provide one in the request, or generate and validate OTP using API 1206 and 1207!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
var requestUri = _padp1204Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Delete, requestUri);
|
||||
|
||||
if (userAccessToken != null) {
|
||||
Console.WriteLine("Using provided User Access Token {0}...", userAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAccessToken);
|
||||
} else {
|
||||
Console.WriteLine("Using stored User Access Token {0}...", userAuthInfo.UserAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAuthInfo.UserAccessToken);
|
||||
}
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK) {
|
||||
return TypedResults.Ok(await response.Content.ReadFromJsonAsync<DeletePersonalDataResponse>());
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok, JsonHttpResult<ErrorResponse>>> UpdatePersonalData(string xTat, string? userAccessToken, bool skipUpdateCounter, string? name, string? birthDate, IFormFile? photo)
|
||||
{
|
||||
UserAuthInfo userAuthInfo;
|
||||
if (userAuthInfoMap.TryGetValue(xTat, out UserAuthInfo? authInfo)) {
|
||||
if (authInfo.encryptedEphemeralKey == null) {
|
||||
var errorResponse = new ErrorResponse("No ephemeral key found for xTAT " + xTat + " - generate an ephemeral key first, using API 1210!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
} else if (authInfo.UserAccessToken == null && userAccessToken == null) {
|
||||
var errorResponse = new ErrorResponse("No User Access Token found for xTAT " + xTat + " - provide one in the request, or generate and validate OTP using API 1206 and 1207!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
userAuthInfo = authInfo;
|
||||
} else {
|
||||
var errorResponse = new ErrorResponse("No User Access Token found for xTAT " + xTat + " - provide one in the request, or generate and validate OTP using API 1206 and 1207!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
var requestUri = _padp1205Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Put, requestUri);
|
||||
|
||||
if (userAccessToken != null) {
|
||||
Console.WriteLine("Using provided User Access Token {0}...", userAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAccessToken);
|
||||
} else {
|
||||
Console.WriteLine("Using stored User Access Token {0}...", userAuthInfo.UserAccessToken);
|
||||
request.Headers.Add("Authorization", "Bearer " + userAuthInfo.UserAccessToken);
|
||||
}
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
var updatePersonalDataRequest = new UpdatePersonalDataRequest();
|
||||
updatePersonalDataRequest.metadata.skipUpdateCounter = skipUpdateCounter;
|
||||
updatePersonalDataRequest.metadata.ephemeralKeyAlias = userAuthInfo.ephemeralKeyAlias;
|
||||
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(userAuthInfo.encryptedEphemeralKey);
|
||||
|
||||
if (name != null) {
|
||||
updatePersonalDataRequest.data.personalAccountData.name = cryptoHelper.EncryptText(decryptedEphemeralKey, name);
|
||||
}
|
||||
if (birthDate != null) {
|
||||
updatePersonalDataRequest.data.personalAccountData.birthdate = cryptoHelper.EncryptText(decryptedEphemeralKey, birthDate);;
|
||||
}
|
||||
if (photo != null) {
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
photo.CopyTo(memoryStream);
|
||||
byte[] photoBytes = memoryStream.ToArray();
|
||||
updatePersonalDataRequest.data.personalAccountData.photo = cryptoHelper.EncryptPhoto(decryptedEphemeralKey, photoBytes);
|
||||
}
|
||||
}
|
||||
request.Content = JsonContent.Create(updatePersonalDataRequest);
|
||||
|
||||
Console.WriteLine("Sending request to {0} with request body {1}...", requestUri, request.Content.ReadAsStringAsync().Result);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK) {
|
||||
return TypedResults.Ok();
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<JsonHttpResult<OtpResponse>, JsonHttpResult<ErrorResponse>>> GenerateOtpV2(string xTat)
|
||||
{
|
||||
var requestUri = _padp1206V2Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + GetB2bAccessTokenAsString());
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
request.Content = new StringContent("{\"channel\": \"EMAIL\"}", Encoding.UTF8, "application/json");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.Accepted) {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<OtpResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<UserAccessToken>, JsonHttpResult<ErrorResponse>>> ValidateOtpV2(string xTat, string otp)
|
||||
{
|
||||
var requestUri = _padp1207V2Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + GetB2bAccessTokenAsString());
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
request.Content = new StringContent("{\"otp\": \"" + otp + "\"}", Encoding.UTF8, "application/json");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK) {
|
||||
var content = await response.Content.ReadFromJsonAsync<UserAccessToken>();
|
||||
Console.WriteLine("Successfully retrieved User Access Token for xTAT {0} - storing for use in following calls...", xTat);
|
||||
|
||||
if (!userAuthInfoMap.ContainsKey(xTat)) {
|
||||
userAuthInfoMap.Add(xTat, new UserAuthInfo());
|
||||
}
|
||||
UserAuthInfo userAuthInfo = userAuthInfoMap[xTat];
|
||||
userAuthInfo.UserAccessToken = content.accessToken;
|
||||
|
||||
return TypedResults.Ok(content);
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<JsonHttpResult<OtpResponse>, JsonHttpResult<ErrorResponse>>> GenerateOtpV3(string? email, string? xTat)
|
||||
{
|
||||
var requestUri = _padp1206V3Uri;
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + GetB2bAccessTokenAsString());
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
var generateOtpRequest = new GenerateOtpRequestV3();
|
||||
|
||||
generateOtpRequest.channel = "EMAIL";
|
||||
if (email != null) {
|
||||
generateOtpRequest.source = "EMAIL";
|
||||
generateOtpRequest.recipient = email;
|
||||
} else if (xTat != null) {
|
||||
generateOtpRequest.source = "XTAT";
|
||||
generateOtpRequest.recipient = xTat;
|
||||
} else if (email != null && xTat != null){
|
||||
var errorResponse = new ErrorResponse("Both e-mail and xTAT filled, only one should be filled in the request!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
request.Content = JsonContent.Create(generateOtpRequest);
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.Accepted) {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<OtpResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<UserAccessToken>, JsonHttpResult<ErrorResponse>>> ValidateOtpV3(string? email, string? xTat, string otp)
|
||||
{
|
||||
var requestUri = _padp1207V3Uri;
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + GetB2bAccessTokenAsString());
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
var validateOtpRequest = new ValidateOtpRequestV3();
|
||||
|
||||
validateOtpRequest.otp = otp;
|
||||
if (email != null)
|
||||
{
|
||||
validateOtpRequest.source = "EMAIL";
|
||||
validateOtpRequest.recipient = email;
|
||||
}
|
||||
else if (xTat != null)
|
||||
{
|
||||
validateOtpRequest.source = "XTAT";
|
||||
validateOtpRequest.recipient = xTat;
|
||||
}
|
||||
else if (email != null && xTat != null)
|
||||
{
|
||||
var errorResponse = new ErrorResponse("Both e-mail and xTAT filled, only one should be filled in the request!", 400);
|
||||
return TypedResults.Json(errorResponse, JsonSerializerOptions.Default, "application/json", 400);
|
||||
}
|
||||
|
||||
request.Content = JsonContent.Create(validateOtpRequest);
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK) {
|
||||
var content = await response.Content.ReadFromJsonAsync<UserAccessToken>();
|
||||
|
||||
if (xTat != null) {
|
||||
Console.WriteLine("Successfully retrieved User Access Token for xTAT {0} - storing for use in following calls...", xTat);
|
||||
|
||||
if (!userAuthInfoMap.ContainsKey(xTat))
|
||||
{
|
||||
userAuthInfoMap.Add(xTat, new UserAuthInfo());
|
||||
}
|
||||
UserAuthInfo userAuthInfo = userAuthInfoMap[xTat];
|
||||
userAuthInfo.UserAccessToken = content.accessToken;
|
||||
}
|
||||
else {
|
||||
Console.WriteLine("Successfully retrieved User Access Token for e-mail {0} - we don't know the xTAT (yet), so we don't cannot the user access token for later use...");
|
||||
}
|
||||
|
||||
|
||||
return TypedResults.Ok(content);
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<AdministrativeData>, JsonHttpResult<ErrorResponse>>> GetAdministrativeData(string xTat)
|
||||
{
|
||||
var requestUri = _padp1211Uri.Replace("{xtat}", xTat);
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + GetB2bAccessTokenAsString());
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
return TypedResults.Ok(await response.Content.ReadFromJsonAsync<AdministrativeData>());
|
||||
}
|
||||
else
|
||||
{
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public string EncryptDecryptPoc(string textToEncrypt, string encryptedEphemeralKey)
|
||||
{
|
||||
Console.WriteLine("Encrypting, then decrypting text {0} using encrypted ephemeral key {1}...", textToEncrypt, encryptedEphemeralKey);
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(encryptedEphemeralKey);
|
||||
var encryptedText = cryptoHelper.EncryptText(decryptedEphemeralKey, textToEncrypt);
|
||||
Console.WriteLine($"Encrypted text: {encryptedText}");
|
||||
|
||||
Console.WriteLine("Decrypting text {0}...", encryptedText);
|
||||
var decryptedText = cryptoHelper.DecryptTextAsync(decryptedEphemeralKey, encryptedText);
|
||||
Console.WriteLine($"Decrypted text: {decryptedText.Result}");
|
||||
|
||||
return "Encrypted text: " + encryptedText + "\nDecrypted text: " + decryptedText.Result;
|
||||
}
|
||||
|
||||
public string EncryptPoc(string textToEncrypt, string encryptedEphemeralKey)
|
||||
{
|
||||
Console.WriteLine("Encrypting text {0} using encrypted ephemeral key {1}...", textToEncrypt, encryptedEphemeralKey);
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(encryptedEphemeralKey);
|
||||
var encryptedText = cryptoHelper.EncryptText(decryptedEphemeralKey, textToEncrypt);
|
||||
Console.WriteLine($"Encrypted text: {encryptedText}");
|
||||
|
||||
return "Encrypted text: " + encryptedText;
|
||||
}
|
||||
|
||||
public string DecryptPoc(string textToDecrypt, string encryptedEphemeralKey)
|
||||
{
|
||||
Console.WriteLine("Decrypting text {0} using ephemeral key {1}...", textToDecrypt, encryptedEphemeralKey);
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(encryptedEphemeralKey);
|
||||
var decryptedText = cryptoHelper.DecryptTextAsync(decryptedEphemeralKey, textToDecrypt);
|
||||
Console.WriteLine($"Decrypted text: {decryptedText.Result}");
|
||||
|
||||
return "Decrypted text: " + decryptedText.Result;
|
||||
}
|
||||
|
||||
public async Task<Results<Ok<EphemeralKey>, JsonHttpResult<ErrorResponse>>> CreateEphemeralKey(string xTat)
|
||||
{
|
||||
var requestUri = _padp1210Uri + "?pemRsaPublicKey=" + cryptoHelper.GetPublicKeyRsa();
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
|
||||
request.Headers.Add("Authorization", "Bearer " + GetB2bAccessTokenAsString());
|
||||
request.Headers.Add("APIKey", _padApiKey);
|
||||
request.Headers.Add("requestId", Guid.NewGuid().ToString());
|
||||
request.Headers.Add("Accept", "application/json");
|
||||
|
||||
Console.WriteLine("Sending request to {0}...", requestUri);
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.Created) {
|
||||
var content = await response.Content.ReadFromJsonAsync<EphemeralKey>();
|
||||
Console.WriteLine("Successfully created Ephemeral Key for xTAT {0} - storing for use in following calls...", xTat);
|
||||
if (!userAuthInfoMap.ContainsKey(xTat)) {
|
||||
userAuthInfoMap.Add(xTat, new UserAuthInfo());
|
||||
}
|
||||
UserAuthInfo userAuthInfo = userAuthInfoMap[xTat];
|
||||
userAuthInfo.ephemeralKeyAlias = content.ephemeralKeyAlias;
|
||||
userAuthInfo.encryptedEphemeralKey = content.encryptedEphemeralKey;
|
||||
|
||||
return TypedResults.Ok(content);
|
||||
} else {
|
||||
return TypedResults.Json(await response.Content.ReadFromJsonAsync<ErrorResponse>(), JsonSerializerOptions.Default, "application/json", (int)response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<DecryptedPersonalData> DecryptPersonalData(PersonalData personalData)
|
||||
{
|
||||
var decryptedEphemeralKey = cryptoHelper.DecryptEphemeralKey(personalData.metadata.encryptedEphemeralKey);
|
||||
Console.WriteLine("Decrypted encryptedEphemeralKey: {0}", Convert.ToBase64String(decryptedEphemeralKey));
|
||||
|
||||
var decryptedData = new DecryptedPersonalData.DecryptedData();
|
||||
|
||||
if (personalData.data.name != null) {
|
||||
decryptedData.decryptedName = await cryptoHelper.DecryptTextAsync(decryptedEphemeralKey, personalData.data.name);
|
||||
Console.WriteLine($"Decrypted name: {decryptedData.decryptedName}");
|
||||
}
|
||||
|
||||
if (personalData.data.birthdate != null) {
|
||||
decryptedData.decryptedBirthdate = await cryptoHelper.DecryptTextAsync(decryptedEphemeralKey, personalData.data.birthdate);
|
||||
Console.WriteLine($"Decrypted birthDate: {decryptedData.decryptedBirthdate}");
|
||||
}
|
||||
|
||||
if (personalData.data.photo != null) {
|
||||
decryptedData.decryptedPhoto = await cryptoHelper.DecryptPhotoAsync(decryptedEphemeralKey, personalData.data.photo);
|
||||
Console.WriteLine($"Decrypted photo: {decryptedData.decryptedPhoto}");
|
||||
}
|
||||
|
||||
return new DecryptedPersonalData(decryptedData, personalData);
|
||||
}
|
||||
}
|
||||
124
src/dotnet/padp-reference-web/PadpReferenceApi/CryptoHelper.cs
Normal file
124
src/dotnet/padp-reference-web/PadpReferenceApi/CryptoHelper.cs
Normal file
@ -0,0 +1,124 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
public class CryptoHelper
|
||||
{
|
||||
private RSA rsa;
|
||||
private string _publicKeyRsa;
|
||||
|
||||
public CryptoHelper(UserProperties userProperties)
|
||||
{
|
||||
string publicKeyPath = Environment.CurrentDirectory + userProperties.Rsa.PublicKeyFile;
|
||||
string privateKeyPath = Environment.CurrentDirectory + userProperties.Rsa.PrivateKeyFile;
|
||||
|
||||
Console.WriteLine("Loading public key from: {0}", publicKeyPath);
|
||||
Console.WriteLine("Loading private key from: {0}", privateKeyPath);
|
||||
|
||||
rsa = RSA.Create();
|
||||
rsa.ImportFromPem(File.ReadAllText(publicKeyPath));
|
||||
rsa.ImportFromPem(File.ReadAllText(privateKeyPath));
|
||||
|
||||
_publicKeyRsa = Convert.ToBase64String(rsa.ExportSubjectPublicKeyInfo());
|
||||
}
|
||||
|
||||
public string GetPublicKeyRsa() => _publicKeyRsa;
|
||||
|
||||
public byte[] DecryptEphemeralKey(string encryptedEphemeralKey)
|
||||
{
|
||||
return rsa.Decrypt(Convert.FromBase64String(encryptedEphemeralKey), RSAEncryptionPadding.OaepSHA512);
|
||||
}
|
||||
|
||||
public async Task<string> DecryptTextAsync(byte[] decryptedEphemeralKey, string encryptedText)
|
||||
{
|
||||
var decryptedBytes = await DecryptContentAsync(decryptedEphemeralKey, encryptedText);
|
||||
return Encoding.UTF8.GetString(decryptedBytes);
|
||||
}
|
||||
|
||||
public async Task<string> DecryptPhotoAsync(byte[] decryptedEphemeralKey, string encryptedPhoto)
|
||||
{
|
||||
var decryptedBytes = await DecryptContentAsync(decryptedEphemeralKey, encryptedPhoto);
|
||||
return Convert.ToBase64String(decryptedBytes);
|
||||
}
|
||||
|
||||
public string EncryptText(byte[] decryptedEphemeralKey, string textValue)
|
||||
{
|
||||
return EncryptContent(decryptedEphemeralKey, Encoding.UTF8.GetBytes(textValue));
|
||||
}
|
||||
|
||||
public string EncryptPhoto(byte[] decryptedEphemeralKey, byte[] photoBytes)
|
||||
{
|
||||
return EncryptContent(decryptedEphemeralKey, photoBytes);
|
||||
}
|
||||
|
||||
private async Task<byte[]> DecryptContentAsync(byte[] decryptedEphemeralKey, string encryptedData)
|
||||
{
|
||||
byte[] encryptedDataByteArray = Convert.FromBase64String(encryptedData);
|
||||
using MemoryStream memoryStream = new(encryptedDataByteArray);
|
||||
using Aes aes = Aes.Create();
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
|
||||
byte[] iv = new byte[aes.IV.Length];
|
||||
int numBytesToRead = aes.IV.Length;
|
||||
int numBytesRead = 0;
|
||||
while (numBytesToRead > 0)
|
||||
{
|
||||
int n = memoryStream.Read(iv, numBytesRead, numBytesToRead);
|
||||
if (n == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
numBytesRead += n;
|
||||
numBytesToRead -= n;
|
||||
}
|
||||
|
||||
byte[] key = decryptedEphemeralKey;
|
||||
|
||||
await using CryptoStream cryptoStream = new(memoryStream,
|
||||
aes.CreateDecryptor(key, iv),
|
||||
CryptoStreamMode.Read);
|
||||
|
||||
using MemoryStream ms = new();
|
||||
await cryptoStream.CopyToAsync(ms);
|
||||
var bytes = ms.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private string EncryptContent(byte[] decryptedEphemeralKey, byte[] content)
|
||||
{
|
||||
byte[] encrypted;
|
||||
byte[] iv;
|
||||
|
||||
using (var aesAlg = Aes.Create())
|
||||
{
|
||||
aesAlg.Key = decryptedEphemeralKey;
|
||||
|
||||
aesAlg.GenerateIV();
|
||||
iv = aesAlg.IV;
|
||||
|
||||
aesAlg.Mode = CipherMode.CBC;
|
||||
aesAlg.Padding = PaddingMode.PKCS7;
|
||||
|
||||
// Create an encryptor to perform the stream transform.
|
||||
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
|
||||
|
||||
// Create the streams used for encryption.
|
||||
using (MemoryStream msEncrypt = new())
|
||||
{
|
||||
using (CryptoStream csEncrypt = new(msEncrypt, encryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
|
||||
//Write all data to the stream.
|
||||
csEncrypt.Write(content, 0, content.Length);
|
||||
|
||||
}
|
||||
encrypted = msEncrypt.ToArray();
|
||||
}
|
||||
}
|
||||
var combinedIvCt = new byte[iv.Length + encrypted.Length];
|
||||
Array.Copy(iv, 0, combinedIvCt, 0, iv.Length);
|
||||
Array.Copy(encrypted, 0, combinedIvCt, iv.Length, encrypted.Length);
|
||||
var encryptedData = Convert.ToBase64String(combinedIvCt);
|
||||
return encryptedData;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.14" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
250
src/dotnet/padp-reference-web/PadpReferenceApi/Program.cs
Normal file
250
src/dotnet/padp-reference-web/PadpReferenceApi/Program.cs
Normal file
@ -0,0 +1,250 @@
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(setupAction =>
|
||||
{
|
||||
setupAction.EnableAnnotations();
|
||||
setupAction.SchemaFilter<SwaggerSchemaExampleFilter>();
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
var group = app.MapGroup("/").DisableAntiforgery().WithTags("PADP Reference API");
|
||||
var pocGroup = app.MapGroup("/poc").DisableAntiforgery().WithTags("Encrypt/decrypt POC");
|
||||
|
||||
UserProperties userProperties = app.Configuration.GetSection("UserProperties").Get<UserProperties>();
|
||||
|
||||
ApimHelper apimHelper = new ApimHelper(userProperties);
|
||||
|
||||
group.MapGet("/idp/b2b-access-token", () =>
|
||||
{
|
||||
return apimHelper.GetB2bAccessToken();
|
||||
})
|
||||
.Produces<B2bAccessToken>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("GetB2bAccessToken")
|
||||
.WithSummary("API 1020 - Get B2B Access Token")
|
||||
.WithDescription("Returns a client access token, needed for most other PADP APIs.")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/get-image-from-base64", ([FromHeader]string base64String) =>
|
||||
{
|
||||
return apimHelper.GetImageFromBase64(base64String);
|
||||
})
|
||||
.Produces<FileContentHttpResult>(200, "image/jpeg")
|
||||
.WithName("GetImageFromBase64")
|
||||
.WithSummary("Get rendered image from Base64 encoded String")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapPost("/personal-data/{xtat}", (string xTat, [SwaggerParameter("Email address to be used for OTP challenges")] string email, [SwaggerParameter("Should be at least two words (first name and last name)")] string? name, [SwaggerParameter("Should be a date between 1900-01-01 and now, in the format YYYY-MM-DD")] string? birthDate, [SwaggerSchema("Should be a JPG image, of max. 512KB and resolution between 520x520 and 720x720")] IFormFile? photo) =>
|
||||
{
|
||||
Console.WriteLine("Creating personal data for xTAT: " + xTat);
|
||||
return apimHelper.CreatePersonalData(xTat, email, name, birthDate, photo);
|
||||
})
|
||||
.Produces(201)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("CreatePersonalData")
|
||||
.WithSummary("API 1201 - Create Personal Data - First create an ephemeral key using API 1210!")
|
||||
.WithDescription("First create an ephemeral key using API 1210!")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapPost("/personal-data/{xtat}/with-email-verification", (string xTat, [SwaggerParameter("Email address to be used for OTP challenges")]string email, [SwaggerParameter("This user access token will be used for e-mail verification if provided - otherwise, the internally stored one (based on previous V3 1206+1207 calls) will be used")]string? userAccessToken, [SwaggerParameter("Should be at least two words (first name and last name)")]string? name, [SwaggerParameter("Should be a date between 1900-01-01 and now, in the format YYYY-MM-DD")]string? birthDate, [SwaggerSchema("Should be a JPG image, of max. 512KB and resolution between 520x520 and 720x720")]IFormFile? photo) =>
|
||||
{
|
||||
Console.WriteLine("Creating personal data with e-mail verification for xTAT: " + xTat);
|
||||
return apimHelper.CreatePersonalDataWithEmailVerification(xTat, email, userAccessToken,name, birthDate, photo);
|
||||
})
|
||||
.Produces(201)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("CreatePersonalDataWithEmailVerification")
|
||||
.WithSummary("API 1201 - Create Personal Data with e-mail verification - First create an ephemeral key using API 1210!")
|
||||
.WithDescription("Performs extra e-mail verification using OTP flow; using internally stored (after 1206+1207 call) or explicitly provided user access token. First create an ephemeral key using API 1210!")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/personal-data/{xtat}", (string xTat, [SwaggerParameter("If provided, this user access token will be used over the internally stored one (that was restrieved via earlier 1206+1207 calls)")]string? userAccessToken) =>
|
||||
{
|
||||
Console.WriteLine("Retrieving personal data for xTAT: " + xTat);
|
||||
return apimHelper.GetPersonalData(xTat, userAccessToken);
|
||||
})
|
||||
.Produces<PersonalData>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("GetPersonalData")
|
||||
.WithSummary("API 1202 - Get Personal Data - First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithDescription("First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/personal-data/{xtat}/decrypted", (string xTat, [SwaggerParameter("If provided, this user access token will be used over the internally stored one (that was restrieved via earlier 1206+1207 calls)")]string? userAccessToken) =>
|
||||
{
|
||||
Console.WriteLine("Retrieving decrypted personal data for xTAT: " + xTat);
|
||||
return apimHelper.GetDecryptedPersonalData(xTat, userAccessToken);
|
||||
})
|
||||
.Produces<DecryptedPersonalData>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("GetDecryptedPersonalData")
|
||||
.WithSummary("API 1202 - Get Personal Data AND decrypt response - First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithDescription("First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapDelete("/personal-data/{xtat}", (string xTat, [SwaggerParameter("If provided, this user access token will be used over the internally stored one (that was restrieved via earlier 1206+1207 calls)")]string? userAccessToken) =>
|
||||
{
|
||||
Console.WriteLine("Deleting personal data for xTAT: " + xTat);
|
||||
return apimHelper.DeletePersonalData(xTat, userAccessToken);
|
||||
})
|
||||
.Produces<DeletePersonalDataResponse>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("DeletePersonalData")
|
||||
.WithSummary("API 1204 - Delete Personal Data - First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithDescription("First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapPut("/personal-data/{xtat}", (string xTat, [SwaggerParameter("If provided, this user access token will be used over the internally stored one (that was restrieved via earlier 1206+1207 calls)")]string? userAccessToken, bool skipUpdateCounter, [SwaggerParameter("Should be at least two words (first name and last name)")]string? name, [SwaggerParameter("Should be a date between 1900-01-01 and now, in the format YYYY-MM-DD")]string? birthDate, [SwaggerSchema("Should be a JPG image, of max. 512KB and resolution between 520x520 and 720x720")]IFormFile? photo) =>
|
||||
{
|
||||
Console.WriteLine("Replacing personal data for xTAT: " + xTat);
|
||||
return apimHelper.UpdatePersonalData(xTat, userAccessToken, skipUpdateCounter, name, birthDate, photo);
|
||||
})
|
||||
.WithName("UpdatePersonalData")
|
||||
.WithSummary("API 1205 - Update Personal Data - First perform an OTP challenge using API 1206 and 1207 or explicitly provide user access token!")
|
||||
.WithDescription("Performs a complete replacement; empty request parameters will result in the corresponding PADP attribute being deleted.")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/v2/personal-data/{xtat}/generate-otp", (string xTat) =>
|
||||
{
|
||||
Console.WriteLine("Generating OTP for xTAT: " + xTat);
|
||||
return apimHelper.GenerateOtpV2(xTat);
|
||||
})
|
||||
.Produces<OtpResponse>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("GenerateOtpV2")
|
||||
.WithSummary("API 1206 V2 - Generate OTP")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/v2/personal-data/{xtat}/validate-otp", (string xTat, string otp) =>
|
||||
{
|
||||
Console.WriteLine("Validating OTP {0} for xTAT: {1}", otp, xTat);
|
||||
return apimHelper.ValidateOtpV2(xTat, otp);
|
||||
})
|
||||
.Produces<UserAccessToken>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("ValidateOtpV2")
|
||||
.WithSummary("API 1207 V2 - Validate OTP")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/v3/personal-data/generate-otp", (string? email, string? xTat) =>
|
||||
{
|
||||
if (email != null){
|
||||
Console.WriteLine("Generating OTP for e-mail: " + email);
|
||||
} else if (xTat != null){
|
||||
Console.WriteLine("Generating OTP for xTAT: " + xTat);
|
||||
}
|
||||
return apimHelper.GenerateOtpV3(email, xTat);
|
||||
})
|
||||
.Produces<OtpResponse>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("GenerateOtpV3")
|
||||
.WithSummary("API 1206 V3 - Generate OTP")
|
||||
.WithDescription("If e-mail is provided, the OTP is generated for the e-mail address. If xTAT is provided, the OTP is generated for the xTAT.")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/v3/personal-data/validate-otp", (string? email, string? xTat, string otp) =>
|
||||
{
|
||||
if (email != null){
|
||||
Console.WriteLine("Validating OTP {0} for e-mail: {1}", otp, email);
|
||||
} else if (xTat != null){
|
||||
Console.WriteLine("Validating OTP {0} for xTAT: {1}", otp, xTat);
|
||||
}
|
||||
return apimHelper.ValidateOtpV3(email, xTat, otp);
|
||||
})
|
||||
.Produces<UserAccessToken>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("ValidateOtpV3")
|
||||
.WithSummary("API 1207 V3 - Validate OTP")
|
||||
.WithDescription("If e-mail is provided, the OTP is validated for the e-mail address. If xTAT is provided, the OTP is validated for the xTAT.")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/personal-data/{xtat}/encrypted-update-init", (string xTat) =>
|
||||
{
|
||||
return apimHelper.CreateEphemeralKey(xTat);
|
||||
})
|
||||
.Produces<EphemeralKey>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("CreateEphemeralKey")
|
||||
.WithSummary("API 1210 - Create Ephemeral Key")
|
||||
.WithOpenApi();
|
||||
|
||||
group.MapGet("/personal-data/{xtat}/administrative-data", (string xTat) =>
|
||||
{
|
||||
Console.WriteLine("Retrieving administrative data for xTAT: {0}", xTat);
|
||||
return apimHelper.GetAdministrativeData(xTat);
|
||||
})
|
||||
.Produces<AdministrativeData>(200)
|
||||
.Produces<ErrorResponse>(400)
|
||||
.Produces<ErrorResponse>(404)
|
||||
.Produces<ErrorResponse>(500)
|
||||
.WithName("GetAdministrativeData")
|
||||
.WithSummary("API 1211 - Get Administrative Data")
|
||||
.WithOpenApi();
|
||||
|
||||
pocGroup.MapGet("/encrypt-decrypt-poc", ([FromHeader]string textToEncrypt, string encryptedEphemeralKey) =>
|
||||
{
|
||||
Console.WriteLine("Text to encrypt: {0}", textToEncrypt);
|
||||
return apimHelper.EncryptDecryptPoc(textToEncrypt, encryptedEphemeralKey);
|
||||
})
|
||||
.WithName("EncryptDecryptPoc")
|
||||
.WithSummary("Encrypt/Decrypt POC")
|
||||
.WithOpenApi();
|
||||
|
||||
pocGroup.MapGet("/encrypt-poc", ([FromHeader]string textToEncrypt, string encryptedEphemeralKey) =>
|
||||
{
|
||||
Console.WriteLine("Text to encrypt: {0}", textToEncrypt);
|
||||
return apimHelper.EncryptPoc(textToEncrypt, encryptedEphemeralKey);
|
||||
})
|
||||
.WithName("EncryptPoc")
|
||||
.WithSummary("Encrypt POC")
|
||||
.WithOpenApi();
|
||||
|
||||
pocGroup.MapGet("/decrypt-poc", ([FromHeader]string textToDecrypt, string encryptedEphemeralKey) =>
|
||||
{
|
||||
Console.WriteLine("Text to decrypt: {0}", textToDecrypt);
|
||||
return apimHelper.DecryptPoc(textToDecrypt, encryptedEphemeralKey);
|
||||
})
|
||||
.WithName("DecryptPoc")
|
||||
.WithSummary("Decrypt POC")
|
||||
.WithOpenApi();
|
||||
|
||||
app.Run();
|
||||
@ -0,0 +1,38 @@
|
||||
// Rename this file to appsettings.json and provide correct credentials and locations for the cryptographic files
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"UserProperties": {
|
||||
"uris": {
|
||||
"apimBaseUri": "https://api-ovpay-acc.translink.nl",
|
||||
"b2bApiUri": "/b2b-client-authentication/v1/token",
|
||||
"padp1201Uri": "/pad-management/v2/personal-data/{xtat}",
|
||||
"padp1202Uri": "/pad-management/v2/personal-data/{xtat}",
|
||||
"padp1204Uri": "/pad-management/v2/personal-data/{xtat}",
|
||||
"padp1205Uri": "/pad-management/v2/personal-data/{xtat}",
|
||||
"padp1206V2Uri": "/pad-management/v2/personal-data/{xtat}/generate-otp",
|
||||
"padp1207V2Uri": "/pad-management/v2/personal-data/{xtat}/validate-otp",
|
||||
"padp1206V3Uri": "/pad-management/v3/personal-data/generate-otp",
|
||||
"padp1207V3Uri": "/pad-management/v3/personal-data/validate-otp",
|
||||
"padp1210Uri": "/pad-management/v2/personal-data/encrypted-update-init",
|
||||
"padp1211Uri": "/pad-management/v2/personal-data/{xtat}/administrative-data"
|
||||
},
|
||||
"rsa": {
|
||||
"publicKeyFile": "\\Properties\\{public key in PEM format}.pem",
|
||||
"privateKeyFile": "\\Properties\\{private key in PEM format}.pem"
|
||||
},
|
||||
"credentials": {
|
||||
"clientCertFile": "\\Properties\\{APIM client certificate}.pfx",
|
||||
"clientCertPassword": "{pfxPassword}",
|
||||
"clientId": "HTM_Retailer",
|
||||
"clientSecret": "{clientSecret}",
|
||||
"b2bApiKey": "{b2bApiKey}",
|
||||
"padApiKey": "{padApiKey}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class AdministrativeData
|
||||
{
|
||||
public AdministrativeData(AdministrativeDataElement name, AdministrativeDataElement photo, AdministrativeDataElement birthdate)
|
||||
{
|
||||
this.name = name;
|
||||
this.photo = photo;
|
||||
this.birthdate = birthdate;
|
||||
}
|
||||
|
||||
public AdministrativeDataElement name { get; set; }
|
||||
public AdministrativeDataElement photo { get; set; }
|
||||
public AdministrativeDataElement birthdate { get; set; }
|
||||
|
||||
public class AdministrativeDataElement
|
||||
{
|
||||
public AdministrativeDataElement(bool inaccuracyFlag, string inaccuracyFlagReason, int inaccuracyFlagCounter, int changeCounter, int maxUpdatesVerificationCount, DateTime lastChangeDate, bool isValidated)
|
||||
{
|
||||
this.inaccuracyFlag = inaccuracyFlag;
|
||||
this.inaccuracyFlagReason = inaccuracyFlagReason;
|
||||
this.inaccuracyFlagCounter = inaccuracyFlagCounter;
|
||||
this.changeCounter = changeCounter;
|
||||
this.maxUpdatesVerificationCount = maxUpdatesVerificationCount;
|
||||
this.lastChangeDate = lastChangeDate;
|
||||
this.isValidated = isValidated;
|
||||
}
|
||||
|
||||
[JsonPropertyName("inaccuracyFlag")]
|
||||
public bool inaccuracyFlag { get; set; }
|
||||
[JsonPropertyName("inaccuracyFlagReason")]
|
||||
public string inaccuracyFlagReason { get; set; }
|
||||
[JsonPropertyName("inaccuracyFlagCounter")]
|
||||
public int inaccuracyFlagCounter { get; set; }
|
||||
[JsonPropertyName("changeCounter")]
|
||||
public int changeCounter { get; set; }
|
||||
[JsonPropertyName("maxUpdatesVerificationCount")]
|
||||
public int maxUpdatesVerificationCount { get; set; }
|
||||
[JsonPropertyName("lastChangeDate")]
|
||||
public DateTime lastChangeDate { get; set; }
|
||||
[JsonPropertyName("isValidated")]
|
||||
public bool isValidated { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class B2bAccessToken
|
||||
{
|
||||
public B2bAccessToken(string accessToken, int expiresIn, int refreshExpiresIn, string refreshToken, string tokenType, int notBeforePolicy, string scope, string beId)
|
||||
{
|
||||
this.accessToken = accessToken;
|
||||
this.expiresIn = expiresIn;
|
||||
this.refreshExpiresIn = refreshExpiresIn;
|
||||
this.refreshToken = refreshToken;
|
||||
this.tokenType = tokenType;
|
||||
this.notBeforePolicy = notBeforePolicy;
|
||||
this.scope = scope;
|
||||
this.beId = beId;
|
||||
}
|
||||
|
||||
[JsonPropertyName("access_token")]
|
||||
public string accessToken { get; set; }
|
||||
[JsonPropertyName("expires_in")]
|
||||
public int expiresIn { get; set; }
|
||||
[JsonPropertyName("refresh_expires_in")]
|
||||
public int refreshExpiresIn { get; set; }
|
||||
[JsonPropertyName("refresh_token")]
|
||||
public string refreshToken { get; set; }
|
||||
[JsonPropertyName("token_type")]
|
||||
public string tokenType { get; set; }
|
||||
[JsonPropertyName("not-before-policy")]
|
||||
public int notBeforePolicy { get; set; }
|
||||
[JsonPropertyName("scope")]
|
||||
public string scope { get; set; }
|
||||
[JsonPropertyName("BE_ID")]
|
||||
public string beId { get; set; }
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class CreatePersonalDataRequest
|
||||
{
|
||||
|
||||
[JsonPropertyName("metadata")]
|
||||
public Metadata metadata { get; set; } = new Metadata();
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public Data data { get; set; } = new Data();
|
||||
|
||||
public class Metadata
|
||||
{
|
||||
public string? email { get; set; }
|
||||
public string? ephemeralKeyAlias { get; set; }
|
||||
}
|
||||
|
||||
public class Data
|
||||
{
|
||||
public PersonalAccountData personalAccountData { get; set; } = new PersonalAccountData();
|
||||
}
|
||||
|
||||
public class PersonalAccountData
|
||||
{
|
||||
public string? name { get; set; }
|
||||
public string? birthdate { get; set; }
|
||||
public string? photo { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
|
||||
public class DecryptedPersonalData
|
||||
{
|
||||
public DecryptedPersonalData(DecryptedData decryptedData, PersonalData encryptedData)
|
||||
{
|
||||
this.decryptedData = decryptedData;
|
||||
this.encryptedData = encryptedData;
|
||||
}
|
||||
|
||||
public DecryptedData decryptedData { get; set; }
|
||||
public PersonalData encryptedData { get; set; }
|
||||
public class DecryptedData
|
||||
{
|
||||
[JsonPropertyName("decryptedName")]
|
||||
public string? decryptedName { get; set; }
|
||||
[JsonPropertyName("decryptedBirthdate")]
|
||||
public string? decryptedBirthdate { get; set; }
|
||||
[SwaggerSchema(Format = "byte", Description = "Base64 encoded photo")]
|
||||
public string? decryptedPhoto { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class DeletePersonalDataResponse
|
||||
{
|
||||
public DeletePersonalDataResponse(string[] deletedAttributes)
|
||||
{
|
||||
this.deletedAttributes = deletedAttributes;
|
||||
}
|
||||
|
||||
[JsonPropertyName("deletedAttributes")]
|
||||
public string[] deletedAttributes { get; set; }
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class EphemeralKey
|
||||
{
|
||||
public EphemeralKey(string ephemeralKeyAlias, string encryptedEphemeralKey)
|
||||
{
|
||||
this.ephemeralKeyAlias = ephemeralKeyAlias;
|
||||
this.encryptedEphemeralKey = encryptedEphemeralKey;
|
||||
}
|
||||
|
||||
[JsonPropertyName("ephemeralKeyAlias")]
|
||||
public string ephemeralKeyAlias { get; set; }
|
||||
|
||||
[JsonPropertyName("encryptedEphemeralKey")]
|
||||
public string encryptedEphemeralKey { get; set; }
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class ErrorResponse
|
||||
{
|
||||
[JsonConstructor]
|
||||
public ErrorResponse(Error[] errors, string exceptionClassName, string exceptionStackTrace)
|
||||
{
|
||||
this.errors = errors;
|
||||
this.exceptionClassName = exceptionClassName;
|
||||
this.exceptionStackTrace = exceptionStackTrace;
|
||||
}
|
||||
|
||||
public ErrorResponse(string errorMessage, int statusCode)
|
||||
{
|
||||
this.errors = new Error[] { new Error(statusCode.ToString(), new string[] { }, errorMessage) };
|
||||
this.exceptionClassName = null;
|
||||
this.exceptionStackTrace = null;
|
||||
}
|
||||
|
||||
public Error[] errors { get; set; }
|
||||
public string? exceptionClassName { get; set; }
|
||||
public string? exceptionStackTrace { get; set; }
|
||||
|
||||
public class Error
|
||||
{
|
||||
public Error(string code, string[] data, string message)
|
||||
{
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public string code { get; set; }
|
||||
public string[] data { get; set; }
|
||||
public string message { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class GenerateOtpRequestV3
|
||||
{
|
||||
[JsonPropertyName("source")]
|
||||
public string source { get; set; }
|
||||
|
||||
[JsonPropertyName("recipient")]
|
||||
public string recipient { get; set; }
|
||||
|
||||
[JsonPropertyName("channel")]
|
||||
public string channel { get; set; }
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class OtpResponse
|
||||
{
|
||||
public OtpResponse(string maskedEmailAddress)
|
||||
{
|
||||
this.maskedEmailAddress = maskedEmailAddress;
|
||||
}
|
||||
|
||||
[JsonPropertyName("maskedEmailAddress")]
|
||||
public string maskedEmailAddress { get; set; }
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class PersonalData
|
||||
{
|
||||
public PersonalData(Metadata metadata, Data data)
|
||||
{
|
||||
this.metadata = metadata;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Metadata metadata { get; set; }
|
||||
public Data data { get; set; }
|
||||
|
||||
public class Metadata
|
||||
{
|
||||
public Metadata(string encryptedEphemeralKey)
|
||||
{
|
||||
this.encryptedEphemeralKey = encryptedEphemeralKey;
|
||||
}
|
||||
|
||||
[JsonPropertyName("encryptedEphemeralKey")]
|
||||
public string encryptedEphemeralKey { get; set; }
|
||||
}
|
||||
|
||||
public class Data
|
||||
{
|
||||
public Data(string name, string birthdate, string photo)
|
||||
{
|
||||
this.name = name;
|
||||
this.birthdate = birthdate;
|
||||
this.photo = photo;
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string name { get; set; }
|
||||
[JsonPropertyName("birthdate")]
|
||||
public string birthdate { get; set; }
|
||||
[JsonPropertyName("photo")]
|
||||
public string photo { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Class |
|
||||
AttributeTargets.Struct |
|
||||
AttributeTargets.Parameter |
|
||||
AttributeTargets.Property |
|
||||
AttributeTargets.Enum,
|
||||
AllowMultiple = false)]
|
||||
public class SwaggerSchemaExampleAttribute : Attribute
|
||||
{
|
||||
public SwaggerSchemaExampleAttribute(string example)
|
||||
{
|
||||
Example = example;
|
||||
}
|
||||
|
||||
public string Example { get; set; }
|
||||
}
|
||||
|
||||
public class SwaggerSchemaExampleFilter : ISchemaFilter
|
||||
{
|
||||
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
|
||||
{
|
||||
if (context.MemberInfo != null)
|
||||
{
|
||||
var schemaAttribute = context.MemberInfo.GetCustomAttributes<SwaggerSchemaExampleAttribute>()
|
||||
.FirstOrDefault();
|
||||
if (schemaAttribute != null)
|
||||
ApplySchemaAttribute(schema, schemaAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplySchemaAttribute(OpenApiSchema schema, SwaggerSchemaExampleAttribute schemaAttribute)
|
||||
{
|
||||
if (schemaAttribute.Example != null)
|
||||
{
|
||||
schema.Example = new Microsoft.OpenApi.Any.OpenApiString(schemaAttribute.Example);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class UpdatePersonalDataRequest
|
||||
{
|
||||
|
||||
[JsonPropertyName("metadata")]
|
||||
public Metadata metadata { get; set; } = new Metadata();
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public Data data { get; set; } = new Data();
|
||||
|
||||
public class Metadata
|
||||
{
|
||||
public bool skipUpdateCounter { get; set; }
|
||||
public string? ephemeralKeyAlias { get; set; }
|
||||
}
|
||||
|
||||
public class Data
|
||||
{
|
||||
public PersonalAccountData personalAccountData { get; set; } = new PersonalAccountData();
|
||||
}
|
||||
|
||||
public class PersonalAccountData
|
||||
{
|
||||
public string? name { get; set; }
|
||||
public string? birthdate { get; set; }
|
||||
public string? photo { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class UserAccessToken
|
||||
{
|
||||
public UserAccessToken(string accessToken)
|
||||
{
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
[JsonPropertyName("accessToken")]
|
||||
public string accessToken { get; set; }
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
public class UserAuthInfo
|
||||
{
|
||||
public string? UserAccessToken { get; set; }
|
||||
public string? ephemeralKeyAlias { get; set; }
|
||||
public string? encryptedEphemeralKey { get; set; }
|
||||
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
public class UserProperties
|
||||
{
|
||||
public UserProperties(UrisSettings uris, RsaSettings rsa, CredentialsSettings credentials)
|
||||
{
|
||||
(Uris, Rsa, Credentials) = (uris, rsa, credentials);
|
||||
}
|
||||
|
||||
public UrisSettings Uris { get; set; }
|
||||
public RsaSettings Rsa { get; set; }
|
||||
public CredentialsSettings Credentials { get; set; }
|
||||
|
||||
public class UrisSettings
|
||||
{
|
||||
public UrisSettings(string apimBaseUri, string b2bApiUri, string padp1201Uri, string padp1202Uri, string padp1204Uri, string padp1205Uri, string padp1206V2Uri, string padp1207V2Uri, string padp1206V3Uri, string padp1207V3Uri, string padp1210Uri, string padp1211Uri)
|
||||
{
|
||||
(ApimBaseUri, B2bApiUri, Padp1201Uri, Padp1202Uri, Padp1204Uri, Padp1205Uri, Padp1206V2Uri, Padp1207V2Uri, Padp1206V3Uri, Padp1207V3Uri, Padp1210Uri, Padp1211Uri) = (apimBaseUri, b2bApiUri, padp1201Uri, padp1202Uri, padp1204Uri, padp1205Uri, padp1206V2Uri, padp1207V2Uri, padp1206V3Uri, padp1207V3Uri, padp1210Uri, padp1211Uri);
|
||||
}
|
||||
|
||||
public string ApimBaseUri { get; set; }
|
||||
public string B2bApiUri { get; set; }
|
||||
public string Padp1201Uri { get; set; }
|
||||
public string Padp1202Uri { get; set; }
|
||||
public string Padp1204Uri { get; set; }
|
||||
public string Padp1205Uri { get; set; }
|
||||
public string Padp1206V2Uri { get; set; }
|
||||
public string Padp1207V2Uri { get; set; }
|
||||
public string Padp1206V3Uri { get; set; }
|
||||
public string Padp1207V3Uri { get; set; }
|
||||
public string Padp1210Uri { get; set; }
|
||||
public string Padp1211Uri { get; set; }
|
||||
}
|
||||
|
||||
public class RsaSettings
|
||||
{
|
||||
public RsaSettings(string publicKeyFile, string privateKeyFile)
|
||||
{
|
||||
(PublicKeyFile, PrivateKeyFile) = (publicKeyFile, privateKeyFile);
|
||||
}
|
||||
|
||||
public string PublicKeyFile { get; set; }
|
||||
public string PrivateKeyFile { get; set; }
|
||||
}
|
||||
|
||||
public class CredentialsSettings
|
||||
{
|
||||
public CredentialsSettings(string clientCertFile, string clientCertPassword, string clientId, string clientSecret, string b2bApiKey, string padApiKey)
|
||||
{
|
||||
(ClientCertFile, ClientCertPassword, ClientId, ClientSecret, B2bApiKey, PadApiKey) = (clientCertFile, clientCertPassword, clientId, clientSecret, b2bApiKey, padApiKey);
|
||||
}
|
||||
|
||||
public string ClientCertFile { get; set; }
|
||||
public string ClientCertPassword { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
public string ClientSecret { get; set; }
|
||||
public string B2bApiKey { get; set; }
|
||||
public string PadApiKey { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class ValidateOtpRequestV3
|
||||
{
|
||||
[JsonPropertyName("otp")]
|
||||
public string otp { get; set; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string source { get; set; }
|
||||
|
||||
[JsonPropertyName("recipient")]
|
||||
public string recipient { get; set; }
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="temurin-21" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
@ -1,7 +1,9 @@
|
||||
# ABTProducts PUT request body generator
|
||||
Simple tool to quickly edit HTM products via ABTProducts REST API.
|
||||
|
||||
- Requires JRE 21
|
||||
- Requires JRE 17
|
||||
|
||||
## Generating a PUT output (that you need to supply to PUT API yourself):
|
||||
- Run via: `java -jar ABTProductsPUTGenerator.jar`
|
||||
- Specify custom input/output path via: `java -jar ABTProductsPUTGenerator.jar <inputPath> <outputPath>`
|
||||
- Takes a ABTProducts GET response body in JSON format (product details)
|
||||
@ -10,3 +12,14 @@ Simple tool to quickly edit HTM products via ABTProducts REST API.
|
||||
- `curl -X PUT -H 'Content-Type: application/json' {baseUrl}/abt/abtproducts/1.0/38 --data @output.json`
|
||||
- Default input path: /input.json
|
||||
- Default output path: /output.json (output is overwritten if it exists)
|
||||
|
||||
## Bulk clearing (set to null) of a certain product attribute for all productIds in a product-tree (SE product reponse)
|
||||
- Run via: `java -jar ABTProductsPUTGenerator.jar clearAttribute <inputPath> <attributeToClear> <environment> <wso2BearerToken>`
|
||||
- Takes a SE GET product tree response body or ABTProducts GET response body in JSON format
|
||||
- Also needs the attribute to clear and the WSO2 environment and valid WSO2 bearer token for that environment
|
||||
- Performs the following operations:
|
||||
- Finds all productId's in the given product(tree) and for each productId found:
|
||||
- GETs productdetails via ABTProducts API
|
||||
- Converts it to PUT request body using the functionality in the previous section
|
||||
- Replaces <attributeToClear> with `null`
|
||||
- Actually sends the modified PUT request body to ABTProducts PUT API
|
||||
|
||||
@ -58,8 +58,8 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>21</source>
|
||||
<target>21</target>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@ -3,8 +3,11 @@ package nl.htm.ovpay.abt;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -19,6 +22,15 @@ public class ABTProductsPUTGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ABTProductsPUTGenerator.class);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
LOGGER.info("Starting ABTProductsPUTGenerator with arguments {}", Arrays.stream(args).toList());
|
||||
if (args.length > 0 && args[0].equalsIgnoreCase("clearAttribute")) {
|
||||
clearAttribute(args);
|
||||
} else {
|
||||
generateOutput(args);
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateOutput(String[] args) throws Exception {
|
||||
if (args.length != 2) {
|
||||
LOGGER.info("To modify input/output path, use: java -jar ABTProductsPUTGenerator.jar <inputPath> <outputPath>");
|
||||
}
|
||||
@ -40,6 +52,49 @@ public class ABTProductsPUTGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearAttribute(String[] args) throws Exception {
|
||||
if (args.length != 5) {
|
||||
LOGGER.error("Incorrect input parameters!");
|
||||
LOGGER.error("To clear attribute, use: java -jar ABTProductsPUTGenerator.jar clearAttribute <inputPath> <attributeToClear> <environment> <wso2BearerToken>");
|
||||
return;
|
||||
}
|
||||
|
||||
var inputFile = args[1];
|
||||
var attributeToClear = args[2];
|
||||
var environment = args[3];
|
||||
var wso2BearerToken = args[4];
|
||||
|
||||
try (InputStream is = getInputStream(inputFile)) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode jsonNode = mapper.readTree(is);
|
||||
var productIds = jsonNode.findValues("productId").stream().filter(JsonNode::isValueNode).map(JsonNode::asText).toList();
|
||||
|
||||
LOGGER.info("Found productIds to process: {}", productIds);
|
||||
LOGGER.warn("Are you SURE you want to set attribute \"{}\" for all these productIds on environment {} to NULL?", attributeToClear, environment);
|
||||
LOGGER.warn("Type 'yes' to continue...");
|
||||
var input = new Scanner(System.in).nextLine();
|
||||
if (!input.equalsIgnoreCase("yes")) {
|
||||
LOGGER.info("Aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var productId : productIds) {
|
||||
LOGGER.info("Getting product details for product {}...", productId);
|
||||
var productJsonString = APIHelper.getProductDetails(environment, productId, wso2BearerToken);
|
||||
var productJsonNode = mapper.readTree(productJsonString);
|
||||
var putJsonNode = processJsonNode(productJsonNode);
|
||||
LOGGER.info("Clearing attribute \"{}\" from product with productId {}...", attributeToClear, productId);
|
||||
((ObjectNode)putJsonNode).putRawValue(attributeToClear, null);
|
||||
|
||||
LOGGER.info("PUT product details for product with productId {} with cleared attribute \"{}\"...", productId, attributeToClear);
|
||||
LOGGER.info("PUT product details with JSON body: {}", putJsonNode.toPrettyString());
|
||||
APIHelper.putProductDetails(environment, productId, putJsonNode.toString(), wso2BearerToken);
|
||||
}
|
||||
|
||||
LOGGER.info("DONE clearing attribute \"{}\" for productIds {}!", attributeToClear, productIds);
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream getInputStream(String filePath) throws IOException {
|
||||
var externalResource = new File(filePath);
|
||||
if (externalResource.exists()) {
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
package nl.htm.ovpay.abt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class APIHelper {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(APIHelper.class);
|
||||
private static final String PRODUCT_DETAILS_URI = "https://services.<ENV>.api.htm.nl/abt/abtproducts/1.0/products/<PRODUCTID>";
|
||||
|
||||
|
||||
public static String envToUriPart(String environment) {
|
||||
return switch (environment) {
|
||||
case "DEV" -> "dev";
|
||||
case "ACC" -> "acc";
|
||||
case "PRD" -> "";
|
||||
default -> throw new IllegalArgumentException("Invalid environment: " + environment);
|
||||
};
|
||||
}
|
||||
|
||||
public static String getProductDetails(String environment, String productId, String wso2BearerToken) throws Exception {
|
||||
var envUriPart = envToUriPart(environment);
|
||||
var getProductDetailsUri = PRODUCT_DETAILS_URI.replace("<ENV>", envUriPart).replace("<PRODUCTID>", productId);
|
||||
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init(null, DummyX509TrustManager.getDummyArray(), new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
|
||||
URL url = new URL(getProductDetailsUri);
|
||||
URLConnection con = url.openConnection();
|
||||
HttpURLConnection http = (HttpURLConnection)con;
|
||||
http.setRequestMethod("GET");
|
||||
http.setDoOutput(false);
|
||||
http.setRequestProperty("Authorization", "Bearer " + wso2BearerToken);
|
||||
http.connect();
|
||||
|
||||
try(InputStream is = http.getInputStream()) {
|
||||
return new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
public static void putProductDetails(String environment, String productId, String jsonBody, String wso2BearerToken) throws Exception {
|
||||
var envUriPart = envToUriPart(environment);
|
||||
var putProductDetailsUri = PRODUCT_DETAILS_URI.replace("<ENV>", envUriPart).replace("<PRODUCTID>", productId);
|
||||
|
||||
LOGGER.info("PUT product details to URI: {}", putProductDetailsUri);
|
||||
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init(null, DummyX509TrustManager.getDummyArray(), new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
|
||||
URL url = new URL(putProductDetailsUri);
|
||||
URLConnection con = url.openConnection();
|
||||
HttpURLConnection http = (HttpURLConnection)con;
|
||||
http.setRequestMethod("PUT");
|
||||
http.setDoOutput(true);
|
||||
http.setRequestProperty("Authorization", "Bearer " + wso2BearerToken);
|
||||
http.setRequestProperty("Content-Type", "application/json");
|
||||
|
||||
byte[] out = jsonBody.getBytes(StandardCharsets.UTF_8);
|
||||
int length = out.length;
|
||||
http.setFixedLengthStreamingMode(length);
|
||||
http.connect();
|
||||
|
||||
try(OutputStream os = http.getOutputStream()) {
|
||||
os.write(out);
|
||||
}
|
||||
|
||||
try(InputStream is = http.getInputStream()) {
|
||||
LOGGER.info("Got response from PUT API: {}", new String(is.readAllBytes(), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package nl.htm.ovpay.abt;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public final class DummyX509TrustManager implements X509TrustManager {
|
||||
|
||||
private static DummyX509TrustManager INSTANCE;
|
||||
|
||||
private DummyX509TrustManager() {
|
||||
// prevent instantiation
|
||||
}
|
||||
|
||||
public static DummyX509TrustManager getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new DummyX509TrustManager();
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static TrustManager[] getDummyArray() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new DummyX509TrustManager();
|
||||
}
|
||||
return new TrustManager[] { INSTANCE };
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
}
|
||||
@ -1,23 +1,33 @@
|
||||
{
|
||||
"productId": 251,
|
||||
"fikoArticleNumber": null,
|
||||
"productId": 663,
|
||||
"parentProductId": null,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"layerInfo": {
|
||||
"layerInfoId": 7,
|
||||
"choiceKey": "isRenewable",
|
||||
"choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn",
|
||||
"isCustomChoice": false
|
||||
},
|
||||
"fikoArticleNumber": null,
|
||||
"gboPackageTemplateId": "30001",
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "MaxTestPOST-21-okt-test-1 edited PUT",
|
||||
"productDescription": "21-okt-test-1 edited PUT - reis met 90% korting gedurende de eerste F&F pilot!",
|
||||
"validityPeriod": null,
|
||||
"productTranslations": null,
|
||||
"productName": "Test OVPAY-2306",
|
||||
"productDescription": "Test OVPAY-2306 (sellingPeriods in kindje verwijderen en later opnieuw weer kunnen toevoegen)",
|
||||
"validityPeriod": {
|
||||
"validityPeriodId": 782,
|
||||
"fromInclusive": "2025-12-31T23:00:00.000Z",
|
||||
"toInclusive": "2026-03-30T22:00:00.000Z"
|
||||
},
|
||||
"productTranslations": [],
|
||||
"allowedGboAgeProfiles": [],
|
||||
"productOwner": {
|
||||
"productOwnerId": 1,
|
||||
"name": "Corneel Verstoep",
|
||||
"organization": "HTM"
|
||||
"name": "Wie dit leest",
|
||||
"organization": "... is een aap."
|
||||
},
|
||||
"marketSegments": null,
|
||||
"customerSegments": null,
|
||||
"allowedGboAgeProfiles": null,
|
||||
"marketSegments": [],
|
||||
"customerSegments": [],
|
||||
"productCategory": {
|
||||
"productCategoryId": 9,
|
||||
"productCategoryId": 1,
|
||||
"isTravelProduct": true,
|
||||
"name": "Kortingsabonnement"
|
||||
},
|
||||
@ -25,32 +35,10 @@
|
||||
"requiredCustomerLevelId": 1,
|
||||
"name": "guest"
|
||||
},
|
||||
"requiredProducts": null,
|
||||
"incompatibleProducts": null,
|
||||
"mandatoryCustomerDataItems": [
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"customerDataItem": "emailAddress"
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 5,
|
||||
"customerDataItem": "address"
|
||||
}
|
||||
],
|
||||
"requiredGboPersonalAttributes": [
|
||||
{
|
||||
"requiredGboPersonalAttributeId": 1,
|
||||
"name": "NAME"
|
||||
},
|
||||
{
|
||||
"requiredGboPersonalAttributeId": 2,
|
||||
"name": "BIRTHDATE"
|
||||
},
|
||||
{
|
||||
"requiredGboPersonalAttributeId": 3,
|
||||
"name": "PHOTO"
|
||||
}
|
||||
],
|
||||
"requiredProducts": [],
|
||||
"incompatibleProducts": [],
|
||||
"mandatoryCustomerDataItems": [],
|
||||
"requiredGboPersonalAttributes": [],
|
||||
"tokenTypes": [
|
||||
{
|
||||
"tokenTypeId": 1,
|
||||
@ -61,72 +49,36 @@
|
||||
"paymentMomentId": 1,
|
||||
"name": "prepaid"
|
||||
},
|
||||
"serviceOptions": null,
|
||||
"validityDuration": "P7D",
|
||||
"maxStartInFutureDuration": "P6W",
|
||||
"isRenewable": false,
|
||||
"serviceOptions": [
|
||||
{
|
||||
"serviceOptionId": 4,
|
||||
"action": "cancel_notAllowed",
|
||||
"description": "Stopzetting is niet toegestaan (doorgaans in combinatie met refund_notAllowed)"
|
||||
},
|
||||
{
|
||||
"serviceOptionId": 10,
|
||||
"action": "refund_notAllowed",
|
||||
"description": "Terugbetaling niet toegestaan (doorgaans in combinatie met cancel_notAllowed)"
|
||||
}
|
||||
],
|
||||
"validityDuration": "P1W",
|
||||
"maxStartInFutureDuration": "P1W",
|
||||
"isRenewable": null,
|
||||
"sendInvoice": false,
|
||||
"imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg",
|
||||
"productPageUrl": "https://www.htm.nl/nog-onbekende-product-pagina",
|
||||
"termsUrl": "https://www.htm.nl/nog-onbekende-productvoorwaarden-pagina",
|
||||
"imageReference": null,
|
||||
"productPageUrl": null,
|
||||
"termsUrl": null,
|
||||
"isSellableAtHtm": true,
|
||||
"needsSolvencyCheckConsumer": false,
|
||||
"needsSolvencyCheckBusiness": false,
|
||||
"sellingPeriods": [
|
||||
{
|
||||
"sellingPeriodId": 240,
|
||||
"fromInclusive": "2024-09-06T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-29T23:59:59.000+00:00",
|
||||
"sellingPeriodId": 1382,
|
||||
"fromInclusive": "2025-12-31T23:00:00.000Z",
|
||||
"toInclusive": "2026-03-30T22:00:00.000Z",
|
||||
"salesTouchpoint": {
|
||||
"salesTouchpointId": 6,
|
||||
"name": "Service-engine",
|
||||
"isActive": true,
|
||||
"retailer": {
|
||||
"retailerId": 1000,
|
||||
"name": "HTM intern beheer",
|
||||
"street": "Koningin Julianaplein",
|
||||
"number": 10,
|
||||
"numberAddition": null,
|
||||
"postalCode": "2595 AA",
|
||||
"city": "Den Haag",
|
||||
"country": "Nederland",
|
||||
"emailAddress": "info@htm.nl",
|
||||
"phoneNumber": "070 374 9002",
|
||||
"taxId": null,
|
||||
"imageReference": "https://www.htm.nl/typo3conf/ext/htm_template/Resources/Public/img/logo.svg"
|
||||
}
|
||||
},
|
||||
"forbiddenPaymentMethods": null,
|
||||
"sellingPrices": [
|
||||
{
|
||||
"sellingPriceId": 318,
|
||||
"taxCode": "V21",
|
||||
"taxPercentage": 21.0000,
|
||||
"amountExclTax": 94,
|
||||
"amountInclTax": 100,
|
||||
"fromInclusive": "2024-09-06T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-18T23:59:59.000+00:00",
|
||||
"internalPrice": 92.0000
|
||||
},
|
||||
{
|
||||
"sellingPriceId": 319,
|
||||
"taxCode": "V21",
|
||||
"taxPercentage": 21.0000,
|
||||
"amountExclTax": 98,
|
||||
"amountInclTax": 102,
|
||||
"fromInclusive": "2024-12-19T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-29T23:59:59.000+00:00",
|
||||
"internalPrice": 0.0000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sellingPeriodId": 241,
|
||||
"fromInclusive": "2024-09-06T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-29T23:59:59.000+00:00",
|
||||
"salesTouchpoint": {
|
||||
"salesTouchpointId": 5,
|
||||
"name": "Servicewinkel (Team Incident Masters)",
|
||||
"salesTouchpointId": 3,
|
||||
"name": "Website",
|
||||
"isActive": true,
|
||||
"retailer": {
|
||||
"retailerId": 1001,
|
||||
@ -139,64 +91,196 @@
|
||||
"country": "Nederland",
|
||||
"emailAddress": "info@htm.nl",
|
||||
"phoneNumber": "070 374 9002",
|
||||
"taxId": null,
|
||||
"imageReference": "https://www.htm.nl/typo3conf/ext/htm_template/Resources/Public/img/logo.svg"
|
||||
"taxId": 572309345923,
|
||||
"imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg"
|
||||
}
|
||||
},
|
||||
"forbiddenPaymentMethods": [
|
||||
{
|
||||
"forbiddenPaymentMethodId": 2,
|
||||
"name": "creditcard",
|
||||
"issuer": "Visa"
|
||||
"forbiddenPaymentMethods": [],
|
||||
"sellingPrices": []
|
||||
}
|
||||
],
|
||||
"sellingPrices": [
|
||||
"purchasePrices": [],
|
||||
"productVariants": [
|
||||
{
|
||||
"sellingPriceId": 320,
|
||||
"taxCode": "V21",
|
||||
"taxPercentage": 21.0000,
|
||||
"amountExclTax": 94,
|
||||
"amountInclTax": 100,
|
||||
"fromInclusive": "2024-09-06T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-18T23:59:59.000+00:00",
|
||||
"internalPrice": 92.0000
|
||||
"productId": 664,
|
||||
"parentProductId": 663,
|
||||
"layerInfo": {
|
||||
"layerInfoId": null,
|
||||
"choiceKey": null,
|
||||
"choiceLabel": null,
|
||||
"isCustomChoice": false
|
||||
},
|
||||
"fikoArticleNumber": null,
|
||||
"gboPackageTemplateId": "30001",
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "Losse week - Test OVPAY-2306",
|
||||
"productDescription": "Test OVPAY-2306 (sellingPeriods in kindje verwijderen en later opnieuw weer kunnen toevoegen)",
|
||||
"validityPeriod": {
|
||||
"validityPeriodId": 783,
|
||||
"fromInclusive": "2025-12-31T23:00:00.000Z",
|
||||
"toInclusive": "2026-03-30T22:00:00.000Z"
|
||||
},
|
||||
"productTranslations": [],
|
||||
"allowedGboAgeProfiles": [],
|
||||
"productOwner": {
|
||||
"productOwnerId": 1,
|
||||
"name": "Wie dit leest",
|
||||
"organization": "... is een aap."
|
||||
},
|
||||
"marketSegments": [],
|
||||
"customerSegments": [],
|
||||
"productCategory": {
|
||||
"productCategoryId": 1,
|
||||
"isTravelProduct": true,
|
||||
"name": "Kortingsabonnement"
|
||||
},
|
||||
"requiredCustomerLevel": {
|
||||
"requiredCustomerLevelId": 1,
|
||||
"name": "guest"
|
||||
},
|
||||
"requiredProducts": [],
|
||||
"incompatibleProducts": [],
|
||||
"mandatoryCustomerDataItems": [],
|
||||
"requiredGboPersonalAttributes": [],
|
||||
"tokenTypes": [
|
||||
{
|
||||
"tokenTypeId": 1,
|
||||
"name": "EMV"
|
||||
}
|
||||
],
|
||||
"paymentMoment": {
|
||||
"paymentMomentId": 1,
|
||||
"name": "prepaid"
|
||||
},
|
||||
"serviceOptions": [
|
||||
{
|
||||
"serviceOptionId": 4,
|
||||
"action": "cancel_notAllowed",
|
||||
"description": "Stopzetting is niet toegestaan (doorgaans in combinatie met refund_notAllowed)"
|
||||
},
|
||||
{
|
||||
"sellingPriceId": 321,
|
||||
"taxCode": "V21",
|
||||
"taxPercentage": 21.0000,
|
||||
"amountExclTax": 98,
|
||||
"amountInclTax": 102,
|
||||
"fromInclusive": "2024-12-19T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-29T23:59:59.000+00:00",
|
||||
"internalPrice": 0.0000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"purchasePrices": [
|
||||
{
|
||||
"purchasePriceId": 184,
|
||||
"taxCode": "V21",
|
||||
"taxPercentage": 21.0000,
|
||||
"amountExclTax": 0,
|
||||
"amountInclTax": 0,
|
||||
"fromInclusive": "2024-09-01T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-31T23:59:59.000+00:00"
|
||||
}
|
||||
],
|
||||
"auditTrail": [
|
||||
{
|
||||
"auditTrailId": 228,
|
||||
"action": "update",
|
||||
"user": "api",
|
||||
"timestamp": "2024-10-21T09:00:30.410+00:00"
|
||||
},
|
||||
{
|
||||
"auditTrailId": 227,
|
||||
"action": "insert",
|
||||
"user": "api",
|
||||
"timestamp": "2024-10-21T08:58:39.237+00:00"
|
||||
"serviceOptionId": 10,
|
||||
"action": "refund_notAllowed",
|
||||
"description": "Terugbetaling niet toegestaan (doorgaans in combinatie met cancel_notAllowed)"
|
||||
}
|
||||
],
|
||||
"validityDuration": "P1W",
|
||||
"maxStartInFutureDuration": "P1W",
|
||||
"isRenewable": false,
|
||||
"sendInvoice": false,
|
||||
"imageReference": null,
|
||||
"productPageUrl": null,
|
||||
"termsUrl": null,
|
||||
"isSellableAtHtm": true,
|
||||
"needsSolvencyCheckConsumer": false,
|
||||
"needsSolvencyCheckBusiness": false,
|
||||
"sellingPeriods": [
|
||||
{
|
||||
"sellingPeriodId": 1384,
|
||||
"fromInclusive": "2025-12-31T23:00:00.000Z",
|
||||
"toInclusive": "2026-03-30T22:00:00.000Z",
|
||||
"salesTouchpoint": {
|
||||
"salesTouchpointId": 3,
|
||||
"name": "Website",
|
||||
"isActive": true,
|
||||
"retailer": {
|
||||
"retailerId": 1001,
|
||||
"name": "HTM externe touchpoints",
|
||||
"street": "Koningin Julianaplein",
|
||||
"number": 10,
|
||||
"numberAddition": null,
|
||||
"postalCode": "2595 AA",
|
||||
"city": "Den Haag",
|
||||
"country": "Nederland",
|
||||
"emailAddress": "info@htm.nl",
|
||||
"phoneNumber": "070 374 9002",
|
||||
"taxId": 572309345923,
|
||||
"imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg"
|
||||
}
|
||||
},
|
||||
"forbiddenPaymentMethods": [],
|
||||
"sellingPrices": []
|
||||
}
|
||||
],
|
||||
"purchasePrices": [],
|
||||
"productVariants": []
|
||||
},
|
||||
{
|
||||
"productId": 665,
|
||||
"parentProductId": 663,
|
||||
"layerInfo": {
|
||||
"layerInfoId": null,
|
||||
"choiceKey": null,
|
||||
"choiceLabel": null,
|
||||
"isCustomChoice": false
|
||||
},
|
||||
"fikoArticleNumber": null,
|
||||
"gboPackageTemplateId": "30001",
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "Doorlopend - Test OVPAY-2306",
|
||||
"productDescription": "Test OVPAY-2306 (sellingPeriods in kindje verwijderen en later opnieuw weer kunnen toevoegen)",
|
||||
"validityPeriod": {
|
||||
"validityPeriodId": 784,
|
||||
"fromInclusive": "2025-12-31T23:00:00.000Z",
|
||||
"toInclusive": "2026-03-30T22:00:00.000Z"
|
||||
},
|
||||
"productTranslations": [],
|
||||
"allowedGboAgeProfiles": [],
|
||||
"productOwner": {
|
||||
"productOwnerId": 1,
|
||||
"name": "Wie dit leest",
|
||||
"organization": "... is een aap."
|
||||
},
|
||||
"marketSegments": [],
|
||||
"customerSegments": [],
|
||||
"productCategory": {
|
||||
"productCategoryId": 1,
|
||||
"isTravelProduct": true,
|
||||
"name": "Kortingsabonnement"
|
||||
},
|
||||
"requiredCustomerLevel": {
|
||||
"requiredCustomerLevelId": 1,
|
||||
"name": "guest"
|
||||
},
|
||||
"requiredProducts": [],
|
||||
"incompatibleProducts": [],
|
||||
"mandatoryCustomerDataItems": [],
|
||||
"requiredGboPersonalAttributes": [],
|
||||
"tokenTypes": [
|
||||
{
|
||||
"tokenTypeId": 1,
|
||||
"name": "EMV"
|
||||
}
|
||||
],
|
||||
"paymentMoment": {
|
||||
"paymentMomentId": 1,
|
||||
"name": "prepaid"
|
||||
},
|
||||
"serviceOptions": [
|
||||
{
|
||||
"serviceOptionId": 4,
|
||||
"action": "cancel_notAllowed",
|
||||
"description": "Stopzetting is niet toegestaan (doorgaans in combinatie met refund_notAllowed)"
|
||||
},
|
||||
{
|
||||
"serviceOptionId": 10,
|
||||
"action": "refund_notAllowed",
|
||||
"description": "Terugbetaling niet toegestaan (doorgaans in combinatie met cancel_notAllowed)"
|
||||
}
|
||||
],
|
||||
"validityDuration": "P1W",
|
||||
"maxStartInFutureDuration": "P1W",
|
||||
"isRenewable": true,
|
||||
"sendInvoice": false,
|
||||
"imageReference": null,
|
||||
"productPageUrl": null,
|
||||
"termsUrl": null,
|
||||
"isSellableAtHtm": true,
|
||||
"needsSolvencyCheckConsumer": false,
|
||||
"needsSolvencyCheckBusiness": false,
|
||||
"sellingPeriods": [],
|
||||
"purchasePrices": [],
|
||||
"productVariants": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -28,10 +28,33 @@ public final class Helpers {
|
||||
return new JSONObject(string).get("alertId").toString();
|
||||
}
|
||||
|
||||
public static String getTripId(String string) throws IOException {
|
||||
return new JSONObject(string).get("tripId").toString();
|
||||
}
|
||||
|
||||
public static String getXbot(String string) throws IOException {
|
||||
return new JSONObject(string).get("xbot").toString();
|
||||
}
|
||||
|
||||
public static void getTripDetails(String tripId, String xbot, String gboBearerToken) throws Exception {
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init(null, DummyX509TrustManager.getDummyArray(), new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
|
||||
URL url = new URL("https://api.sbx.idbt.translink.nl/api/v3/id-media/tokens/xbot/" + xbot + "/trips/details/" + tripId);
|
||||
URLConnection con = url.openConnection();
|
||||
HttpURLConnection http = (HttpURLConnection)con;
|
||||
http.setRequestMethod("GET");
|
||||
http.setDoOutput(true);
|
||||
http.setRequestProperty("Authorization", "Bearer " + gboBearerToken);
|
||||
http.connect();
|
||||
|
||||
try(InputStream is = http.getInputStream()) {
|
||||
String response = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||
LOGGER.info("GBO API 8659 trip details response for xBOT " + xbot + " and tripId " + tripId + ": \n" + new JSONObject(response).toString(2));
|
||||
}
|
||||
}
|
||||
|
||||
public static void getAlertDetails(String alertId, String xBot, String gboBearerToken) throws Exception {
|
||||
SSLContext sc = SSLContext.getInstance("SSL");
|
||||
sc.init(null, DummyX509TrustManager.getDummyArray(), new java.security.SecureRandom());
|
||||
@ -48,7 +71,7 @@ public final class Helpers {
|
||||
|
||||
try(InputStream is = http.getInputStream()) {
|
||||
String response = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||
LOGGER.info("GBO API 8851 alert details response for xBOT " + xBot + ": \n" + new JSONObject(response).toString(2));
|
||||
LOGGER.info("GBO API 8851 alert details response for xBOT " + xBot + " and alertId " + alertId + ": \n" + new JSONObject(response).toString(2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,14 +16,28 @@ public class RabbitConnector {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RabbitConnector.class);
|
||||
|
||||
// TRIPS
|
||||
// SubscriptionId = 3e246de5-d3ad-468f-834b-1aaebf52244c
|
||||
// Use API 9853 to manually add xBOT to queue
|
||||
private static final String QUEUE_NAME = "BEID_3.TRIPS";
|
||||
private static final String USER_NAME = "BEID_3_TRIPS_HlTT";
|
||||
private static final String PASSWORD = "xJR4C8hIqhHQw0sn";
|
||||
|
||||
// ALERTS
|
||||
// SubscriptionId = 17c8100b-88a2-4cef-b40d-8dca4f93d311
|
||||
// Use API 9853 to manually add xBOT to queue
|
||||
// private static final String QUEUE_NAME = "BEID_3.ALERTS";
|
||||
// private static final String USER_NAME = "BEID_3_ALERTS_nZs3";
|
||||
// private static final String PASSWORD = "VyubhPnczKgTB2zJ";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.setVirtualHost("/");
|
||||
factory.setAutomaticRecoveryEnabled(true);
|
||||
factory.setPort(443);
|
||||
factory.setHost("not.sbx.idbt.translink.nl");
|
||||
factory.setUsername("BEID_3_ALERTS_nZs3");
|
||||
factory.setPassword("VyubhPnczKgTB2zJ");
|
||||
factory.setUsername(USER_NAME);
|
||||
factory.setPassword(PASSWORD);
|
||||
factory.useSslProtocol("TLSv1.2");
|
||||
factory.setExceptionHandler(new ForgivingExceptionHandler());
|
||||
Map<String, Object> configs = factory.getClientProperties();
|
||||
@ -33,7 +47,7 @@ public class RabbitConnector {
|
||||
Channel channel = connection.createChannel();
|
||||
DeliverCallback deliverCallback = initDeliverCallback(channel);
|
||||
|
||||
AMQP.Queue.DeclareOk queue = channel.queueDeclarePassive("BEID_3.ALERTS");
|
||||
AMQP.Queue.DeclareOk queue = channel.queueDeclarePassive(QUEUE_NAME);
|
||||
LOGGER.info(
|
||||
"Declared queue: " + queue.getQueue() + ", consumer count: " + queue.getConsumerCount() + ", message count: " +
|
||||
queue.getMessageCount());
|
||||
@ -52,17 +66,39 @@ public class RabbitConnector {
|
||||
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
|
||||
LOGGER.info("Successfully acknowledged message with delivery tag: " + delivery.getEnvelope().getDeliveryTag());
|
||||
|
||||
LOGGER.info("Getting alert details via GBO API 8851...");
|
||||
if (QUEUE_NAME.equals("BEID_3.TRIPS")) {
|
||||
getTripDetails(message);
|
||||
} else if (QUEUE_NAME.equals("BEID_3.ALERTS")) {
|
||||
getAlertDetails(message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void getAlertDetails(String message) {
|
||||
try {
|
||||
String alertId = Helpers.getAlertId(message);
|
||||
String xBot = Helpers.getXbot(message);
|
||||
String gboBearerToken = Helpers.getGboBearerToken();
|
||||
|
||||
LOGGER.info("Getting alert details for xBOT {} and alertId {} via GBO API 8851...", xBot, alertId);
|
||||
Helpers.getAlertDetails(alertId, xBot, gboBearerToken);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void getTripDetails(String message) {
|
||||
try {
|
||||
String tripId = Helpers.getTripId(message);
|
||||
String xBot = Helpers.getXbot(message);
|
||||
String gboBearerToken = Helpers.getGboBearerToken();
|
||||
|
||||
LOGGER.info("Getting trip details for xBOT {} and tripId {} via GBO API 8659...", xBot, tripId);
|
||||
Helpers.getTripDetails(tripId, xBot, gboBearerToken);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,10 +386,10 @@ paths:
|
||||
"refundAmount": 2489,
|
||||
"refundMethods": ["creditInvoice", "iDeal"],
|
||||
}
|
||||
Unsuccesful validation:
|
||||
summary: Unsuccesful validation
|
||||
Unsuccessful validation:
|
||||
summary: Unsuccessful validation
|
||||
description: |
|
||||
Unsuccesful validation. The response contains the error message.
|
||||
Unsuccessful validation. The response contains the error message.
|
||||
value:
|
||||
{
|
||||
"validationResult": false,
|
||||
@ -574,6 +574,267 @@ paths:
|
||||
},
|
||||
},
|
||||
}
|
||||
/contracts/{uuid}/changemoments:
|
||||
parameters:
|
||||
- in: header
|
||||
name: X-HTM-JWT-AUTH-HEADER
|
||||
schema:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
required: true
|
||||
description: The JWT of the logged in customer.
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 9e224750-3065-471d-af57-85b9cffa7c89
|
||||
required: true
|
||||
description: The id of the contract to process.
|
||||
get:
|
||||
summary: Get all change moments for a given contract.
|
||||
description: Get all change moments for a given contract.
|
||||
tags:
|
||||
- SE Contract Changes v2
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
All change moments of a contract:
|
||||
summary: All change moments of a contract
|
||||
description: |
|
||||
All change moments of a contract. The response contains the
|
||||
allowed change moments for the current contract term.
|
||||
value:
|
||||
{
|
||||
"changeMoment": "termBound",
|
||||
"termDuration": "P1M",
|
||||
"billingDay": 18,
|
||||
"changeFrom": "2024-08-10T00:00:00",
|
||||
"changeUntil": "2024-08-10T03:59:59",
|
||||
}
|
||||
/contracts/{uuid}/changevalidation:
|
||||
parameters:
|
||||
- in: header
|
||||
name: X-HTM-JWT-AUTH-HEADER
|
||||
schema:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
required: true
|
||||
description: The JWT of the logged in customer.
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 9e224750-3065-471d-af57-85b9cffa7c89
|
||||
required: true
|
||||
description: The id of the contract to process.
|
||||
post:
|
||||
summary: Validate a change for a given contract.
|
||||
description: Validate a change for a given contract.
|
||||
tags:
|
||||
- SE Contract Changes v2
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Validate a change to another product:
|
||||
summary: Validate a change to another product
|
||||
description: |
|
||||
Validate a change to another product. The response contains the allowed change moments for the current contract term.
|
||||
value: { "productId": 124, "startDate": "2025-10-08" }
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Successfully validated change:
|
||||
summary: Successfully validated change
|
||||
description: |
|
||||
Successfully validated a change. The response contains the allowed change moments for the current contract term.
|
||||
value:
|
||||
{
|
||||
"validationResult": true,
|
||||
"validationMessage": "",
|
||||
"contract":
|
||||
{
|
||||
"contractId": "15b43d9b-367a-4952-87f6-3e0fa902486f",
|
||||
"contractNumber": "D123456",
|
||||
"customerProfileId": 42,
|
||||
"orderId": "eb3d08f7-7feb-4f31-9f5b-daa634e51f48",
|
||||
"orderLineId": "52efbbfc-8c28-4016-9ece-dc3ef9a70bd8",
|
||||
"touchpointId": 2,
|
||||
"contractStatus":
|
||||
{ "contractStatusId": 2, "name": "active" },
|
||||
"productId": 1,
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"termDuration": "P0Y1M0D",
|
||||
"billingDay": 15,
|
||||
"highestInvoiceTerm": 1,
|
||||
"created": "2024-08-01 15:01:00.000",
|
||||
"ovPayTokenId": 1337,
|
||||
"contractVersions":
|
||||
[
|
||||
{
|
||||
"contractVersionId": 2,
|
||||
"termsAndConditions": "https://www.htm.nl",
|
||||
"productId": 124,
|
||||
"productName": "Regiovrij Regio Centrum",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 12,
|
||||
"start": "2025-10-08",
|
||||
},
|
||||
{
|
||||
"contractVersionId": 1,
|
||||
"termsAndConditions": "https://www.htm.nl",
|
||||
"productId": 123,
|
||||
"productName": "Regiovrij Regio Zuid",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 10,
|
||||
"start": "2025-01-08",
|
||||
"end": "2025-10-07",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
Unsuccessful validation:
|
||||
summary: Unsuccessful validation
|
||||
description: |
|
||||
Unsuccessful validation. The response contains the error message.
|
||||
value:
|
||||
{
|
||||
"validationResult": false,
|
||||
"validationMessage": "Contract status is not ACTIVE",
|
||||
"contract": null,
|
||||
}
|
||||
/contracts/{uuid}/change:
|
||||
parameters:
|
||||
- in: header
|
||||
name: X-HTM-JWT-AUTH-HEADER
|
||||
schema:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
required: true
|
||||
description: The JWT of the logged in customer.
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 9e224750-3065-471d-af57-85b9cffa7c89
|
||||
required: true
|
||||
description: The id of the contract to process.
|
||||
post:
|
||||
summary: Change a contract.
|
||||
description: Change a contract.
|
||||
tags:
|
||||
- SE Contract Changes v2
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Change to another product:
|
||||
summary: Change to another product
|
||||
description: |
|
||||
Change to another product. The response contains the details of the changed contract.
|
||||
value: { "productId": 124, "startDate": "2025-10-08" }
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Successfully changed contract:
|
||||
summary: Successfully changed contract
|
||||
description: |
|
||||
Successfully changed a contract. The response contains the details of the changed contract.
|
||||
value:
|
||||
{
|
||||
"contractId": "15b43d9b-367a-4952-87f6-3e0fa902486f",
|
||||
"contractNumber": "D123456",
|
||||
"customerProfileId": 42,
|
||||
"orderId": "eb3d08f7-7feb-4f31-9f5b-daa634e51f48",
|
||||
"orderLineId": "52efbbfc-8c28-4016-9ece-dc3ef9a70bd8",
|
||||
"touchpointId": 2,
|
||||
"contractStatus":
|
||||
{ "contractStatusId": 2, "name": "active" },
|
||||
"productId": 1,
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"termDuration": "P0Y1M0D",
|
||||
"billingDay": 15,
|
||||
"highestInvoiceTerm": 1,
|
||||
"created": "2024-08-01 15:01:00.000",
|
||||
"ovPayTokenId": 1337,
|
||||
"contractVersions":
|
||||
[
|
||||
{
|
||||
"contractVersionId": 2,
|
||||
"termsAndConditions": "https://www.htm.nl",
|
||||
"productId": 124,
|
||||
"productName": "Regiovrij Regio Centrum",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 12,
|
||||
"start": "2025-10-08",
|
||||
},
|
||||
{
|
||||
"contractVersionId": 1,
|
||||
"termsAndConditions": "https://www.htm.nl",
|
||||
"productId": 123,
|
||||
"productName": "Regiovrij Regio Zuid",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 10,
|
||||
"start": "2025-01-08",
|
||||
"end": "2025-10-07",
|
||||
},
|
||||
],
|
||||
}
|
||||
"400":
|
||||
description: Bad Request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Unsuccessful change due to invalid productId:
|
||||
summary: Unsuccessful change due to invalid productId
|
||||
description: |
|
||||
Unsuccessful change due to invalid productId. The response contains the error message.
|
||||
value:
|
||||
{
|
||||
"type": "https://htm.nl/api/v1/probs/validationerror",
|
||||
"title": "Your request is not valid.",
|
||||
"detail": "The chosen parameters for this contract change are not valid.",
|
||||
"instance": "urn:uuid:4017fabc-1b28-11e8-accf-0ed5f89f718b",
|
||||
"errors":
|
||||
[
|
||||
{
|
||||
"code": "CHANGE_DATE_IN_THE_PAST",
|
||||
"detail": "Chosen date of contract change is in the past. This is not alllowed.",
|
||||
"path": "$.startDate",
|
||||
"parameter": null,
|
||||
},
|
||||
],
|
||||
}
|
||||
/contractpayments:
|
||||
parameters:
|
||||
- in: header
|
||||
@ -597,9 +858,13 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
List all contract payments for a single debtor:
|
||||
summary: List all contract payments for a single debtor
|
||||
description: List all contract payments for single debtor with debtor number 'D123456'.
|
||||
Empty list:
|
||||
summary: Empty list
|
||||
description: List all contract payments for a debtor with no payments.
|
||||
value: { "contractPayments": [] }
|
||||
Successful direct debit:
|
||||
summary: Successful direct debit
|
||||
description: One payment for a debtor with a successful direct debit.
|
||||
value:
|
||||
{
|
||||
"contractPayments":
|
||||
@ -607,8 +872,133 @@ paths:
|
||||
{
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "26.62",
|
||||
"paymentMethod": "Twikey",
|
||||
"paymentMethod": "Automatische incasso",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
Direct debit reversal:
|
||||
summary: Direct debit reversal
|
||||
description: One payment for a debtor with a reversed direct debit.
|
||||
value:
|
||||
{
|
||||
"contractPayments":
|
||||
[
|
||||
{
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "-26.62",
|
||||
"paymentMethod": "Stornering",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
iDEAL payment:
|
||||
summary: iDEAL payment
|
||||
description: One payment for a debtor with an iDEAL payment.
|
||||
value:
|
||||
{
|
||||
"contractPayments":
|
||||
[
|
||||
{
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "26.62",
|
||||
"paymentMethod": "iDEAL",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
Bank transfer:
|
||||
summary: Bank transfer
|
||||
description: One payment for a debtor with a bank transfer.
|
||||
value:
|
||||
{
|
||||
"contractPayments":
|
||||
[
|
||||
{
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "26.62",
|
||||
"paymentMethod": "Overboeking",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
List of four payments for one invoice:
|
||||
summary: List of four payments for one invoice
|
||||
description: Four payments for a debtor for one invoice; a direct debit, a direct debit reversal, a bank transfer and an iDEAL payment.
|
||||
value:
|
||||
{
|
||||
"contractPayments":
|
||||
[
|
||||
{
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "26.62",
|
||||
"paymentMethod": "Automatische incasso",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
@ -626,22 +1016,67 @@ paths:
|
||||
},
|
||||
},
|
||||
{
|
||||
"paymentId": "151845851",
|
||||
"totalAmount": "45.21",
|
||||
"paymentMethod": "Twikey",
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "-26.62",
|
||||
"paymentMethod": "Stornering",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722266",
|
||||
"invoiceNumber": "F2024-0002",
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/ddb245d6df67999eca48c4a71b5661b93038e20a/i/dp5h1i5cuu94nopiolkdst3u17vkmzo",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/7b2f8c1a-3d9d-4c2d-960e-4471e8e28b6a",
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"paymentId": "151845777",
|
||||
"totalAmount": "10.00",
|
||||
"paymentMethod": "Overboeking",
|
||||
"paymentDate": "2024-09-13",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"paymentId": "151845778",
|
||||
"totalAmount": "16.62",
|
||||
"paymentMethod": "iDEAL",
|
||||
"paymentDate": "2024-09-14",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_contractdetails":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/5ca46c1a-cb9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
|
||||
4327
src/openapi/customers/SE-customers-v2.yaml
Normal file
4327
src/openapi/customers/SE-customers-v2.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -359,7 +359,6 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CustomersResponse"
|
||||
|
||||
/customers/tokens:
|
||||
get:
|
||||
tags:
|
||||
@ -491,6 +490,7 @@ paths:
|
||||
"ovPayTokenId": 1,
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType": { "tokenTypeId": 1, "name": "EMV" },
|
||||
"ovpasNumber": "",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -567,6 +567,7 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -649,6 +650,7 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -771,6 +773,7 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -868,6 +871,7 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -983,6 +987,7 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -1003,6 +1008,7 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV31236",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 3, "name": "Replaced (*)" },
|
||||
@ -1024,6 +1030,7 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV36897",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 4, "name": "On stock" },
|
||||
@ -1045,6 +1052,7 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV33489",
|
||||
"alias": "Mijn OV Pas",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 5, "name": "Suspended" },
|
||||
@ -1066,6 +1074,7 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV48965",
|
||||
"alias": "Mijn OV Pas",
|
||||
"tokenStatus":
|
||||
{
|
||||
@ -1111,6 +1120,7 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV13458",
|
||||
"alias": "My found token",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 7, "name": "Renewed Active" },
|
||||
@ -2210,7 +2220,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OvPayTokenProductInstancesResponse"
|
||||
$ref: "#/components/schemas/ProductInstancesResponse"
|
||||
examples:
|
||||
getEmptyProductInstances:
|
||||
summary: No product-instances found on token
|
||||
@ -2223,6 +2233,7 @@ paths:
|
||||
"productInstances":
|
||||
[
|
||||
{
|
||||
"productInstanceId": "26d41861-f77e-4666-9cde-2c5c66ace0a2",
|
||||
"productId": 1,
|
||||
"name": "HTM 90% Korting",
|
||||
"status": "Active",
|
||||
@ -2239,11 +2250,6 @@ paths:
|
||||
"contractId": "56B17EF-C436-9043-B76C-481797WEB464F",
|
||||
"_links":
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/tokens/1/productinstances/1",
|
||||
"method": "GET",
|
||||
},
|
||||
"get_order":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
@ -3398,6 +3404,377 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
/productinstances:
|
||||
parameters:
|
||||
- name: X-HTM-JWT-AUTH-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
required: false
|
||||
description: The JWT of a customer in case of touchpoint were customer logs in themselves
|
||||
- name: X-HTM-CUSTOMER-PROFILE-ID-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: feaaef83-a551-4283-8419-340b1ada3b55
|
||||
required: false
|
||||
description: The customerProfileId of a customer in the case of the SMP
|
||||
- name: X-HTM-ROLE-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: Customer
|
||||
required: false
|
||||
- name: deviceId
|
||||
in: query
|
||||
description: Id of the device you want to get the instantiated HTM products for.
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: externalDeviceId
|
||||
in: query
|
||||
description: Id of the device you want to get the instantiated HTM products for.
|
||||
schema:
|
||||
type: string
|
||||
- name: ovpayTokenId
|
||||
in: query
|
||||
description: Id of the ovpay token you want to get the instantiated HTM products for.
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
get:
|
||||
summary: Get a list of all HTM products for a specific customer, device or token, at least one should be filled in
|
||||
description: |-
|
||||
Get a list of all HTM products instantiated for a specific customer, device or token, at least one of the query params should be filled in.
|
||||
Only HTM products are returned.
|
||||
Where relevant, operations to be performed are returned as HATEOAS links per product-instance.
|
||||
tags:
|
||||
- ProductInstances
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProductInstancesResponse"
|
||||
examples:
|
||||
getEmptyProductInstances:
|
||||
summary: No product-instances found
|
||||
value:
|
||||
productInstances: {
|
||||
"ovPayProducts":[],
|
||||
"barcodeTickets": [],
|
||||
"vouchers":[]
|
||||
}
|
||||
getSingleBarcodeProductInstanceForDevice:
|
||||
summary: One BarcodeTicket product-instance
|
||||
value:
|
||||
{
|
||||
"productInstances":{
|
||||
"ovPayProducts":[],
|
||||
"barcodeTickets":[
|
||||
{
|
||||
"productInstanceId": "0f0981bf-6d60-4b06-bc55-de1ba325f366",
|
||||
"productId": 13,
|
||||
"name": "HTM dagkaart",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 5,
|
||||
"name": "Barcode",
|
||||
},
|
||||
"orderId": "501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"orderLineId": "38B17EF-36C4-4039-B92C-4817969B464E",
|
||||
"status": "Active",
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"issuedAt": "2020-03-21T00:00:00",
|
||||
"activatedAt": null,
|
||||
"blocked": false,
|
||||
"cancelledAt": null,
|
||||
"fraudDetected": false,
|
||||
"barcode": "barcodeBytes",
|
||||
"deviceId": "e2be51ae-2701-4803-a2d7-97d4b714482d",
|
||||
"_links":
|
||||
{
|
||||
"get_order":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"method": "GET",
|
||||
},
|
||||
"patch_productinstance":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/productinstances/0f0981bf-6d60-4b06-bc55-de1ba325f366",
|
||||
"method": "PATCH",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"vouchers":[]
|
||||
}
|
||||
}
|
||||
getSingleOvpayProductInstanceForSpecificOvPayToken:
|
||||
summary: One Ovpay product-instance
|
||||
value:
|
||||
{
|
||||
"productInstances":{
|
||||
"ovPayProducts":[ {
|
||||
"productInstanceId": "26d41861-f77e-4666-9cde-2c5c66ace0a2",
|
||||
"productId": 1,
|
||||
"name": "HTM 90% Korting",
|
||||
"status": "Active",
|
||||
"isRenewable": true,
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 1,
|
||||
"name": "Kortingsabonnement",
|
||||
},
|
||||
"fromInclusive": "2024-11-25T13:25:00+01:00",
|
||||
"untilInclusive": "2024-12-25T03:59:59+01:00",
|
||||
"orderId": "501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"orderLineId": "38B17EF-36C4-4039-B92C-4817969B464E",
|
||||
"contractId": "56B17EF-C436-9043-B76C-481797WEB464F",
|
||||
"ovPayTokenId": 42,
|
||||
"deviceId": null,
|
||||
"_links":
|
||||
{
|
||||
"get_order":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"method": "GET",
|
||||
},
|
||||
"get_contract":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/56B17EF-C436-9043-B76C-481797WEB464F",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"barcodeTickets":[],
|
||||
"vouchers":[]
|
||||
}
|
||||
}
|
||||
getMultipleProductInstancesForCustomer:
|
||||
summary: Multiple product-instances for a customer
|
||||
value:
|
||||
{
|
||||
"productInstances":{
|
||||
"ovPayProducts":[ {
|
||||
"productInstanceId": "26d41861-f77e-4666-9cde-2c5c66ace0a2",
|
||||
"productId": 1,
|
||||
"name": "HTM 90% Korting",
|
||||
"isRenewable": true,
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 1,
|
||||
"name": "Kortingsabonnement",
|
||||
},
|
||||
"fromInclusive": "2024-11-25T13:25:00+01:00",
|
||||
"untilInclusive": "2024-12-25T03:59:59+01:00",
|
||||
"orderId": "501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"orderLineId": "38B17EF-36C4-4039-B92C-4817969B464E",
|
||||
"contractId": "56B17EF-C436-9043-B76C-481797WEB464F",
|
||||
"ovPayTokenId": 42,
|
||||
"deviceId": null,
|
||||
"_links":
|
||||
{
|
||||
"get_order":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"method": "GET",
|
||||
},
|
||||
"get_contract":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/56B17EF-C436-9043-B76C-481797WEB464F",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"barcodeTickets":
|
||||
[
|
||||
{
|
||||
"productInstanceId": "0f0981bf-6d60-4b06-bc55-de1ba325f366",
|
||||
"productId": 13,
|
||||
"name": "HTM dagkaart",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 5,
|
||||
"name": "Barcode",
|
||||
},
|
||||
"orderId": "501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"orderLineId": "38B17EF-36C4-4039-B92C-4817969B464E",
|
||||
"status": "Active",
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"issuedAt": "2020-03-21T00:00:00",
|
||||
"activatedAt": null,
|
||||
"blocked": false,
|
||||
"cancelledAt": null,
|
||||
"fraudDetected": false,
|
||||
"barcode": "barcodeBytes",
|
||||
"deviceId": "e2be51ae-2701-4803-a2d7-97d4b714482d",
|
||||
"_links":
|
||||
{
|
||||
"get_order":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"method": "GET",
|
||||
},
|
||||
"patch_productinstance":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/productinstances/0f0981bf-6d60-4b06-bc55-de1ba325f366",
|
||||
"method": "PATCH",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"vouchers":[]
|
||||
}
|
||||
}
|
||||
getSingleVoucherProductInstanceForCustomer:
|
||||
summary: One voucher product-instance
|
||||
value:
|
||||
{
|
||||
"productInstances":{
|
||||
"ovPayProducts":[],
|
||||
"barcodeTickets":[],
|
||||
"vouchers":[
|
||||
{
|
||||
"productInstanceId": "07a55d42-ea42-4f5c-896a-b340ab084309",
|
||||
"productId": 81,
|
||||
"name": "HTM ooivaarspas voucher ",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"voucherCode": "HTM45253",
|
||||
"fromInclusive": "2026-01-01T00:00:00",
|
||||
"untillInclusive": "2026-12-31T23:59:99",
|
||||
"voucherStatus": {
|
||||
"voucherStatusId": 2,
|
||||
"name": "issued"
|
||||
},
|
||||
"mandatoryCustomerDataItems":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"customerDataItem": "padBirthDate",
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"customerDataItem": "emailAddress",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
/productinstances/{productInstanceId}:
|
||||
parameters:
|
||||
- name: X-HTM-JWT-AUTH-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
required: false
|
||||
description: The JWT of a customer in case of touchpoint were customer logs in themselves
|
||||
- name: X-HTM-CUSTOMER-PROFILE-ID-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: feaaef83-a551-4283-8419-340b1ada3b55
|
||||
required: false
|
||||
description: The customerProfileId of a customer in the case of the SMP
|
||||
- name: X-HTM-ROLE-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: Customer
|
||||
required: false
|
||||
- name: productInstanceId
|
||||
in: path
|
||||
required: true
|
||||
style: simple
|
||||
description: Id of the product instance you want to change
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 0f0981bf-6d60-4b06-bc55-de1ba325f366
|
||||
patch:
|
||||
summary: Update a productInstance
|
||||
description: |-
|
||||
Update the status of the give productInstance.
|
||||
tags:
|
||||
- ProductInstances
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Update a productInstance status to active:
|
||||
value:
|
||||
{
|
||||
"status": "Active"
|
||||
}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Update a productInstance status to active:
|
||||
summary: Update a productInstance status to active
|
||||
value:
|
||||
{
|
||||
"productInstances":
|
||||
[
|
||||
{
|
||||
"productInstanceId": "0f0981bf-6d60-4b06-bc55-de1ba325f366",
|
||||
"productId": 13,
|
||||
"name": "HTM dagkaart",
|
||||
"purchasedProductType": "TapConnect",
|
||||
"status": "Active",
|
||||
"isRenewable": false,
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 2,
|
||||
"name": "Afgekocht reisrecht",
|
||||
},
|
||||
"fromInclusive": "2024-11-25T13:25:00+01:00",
|
||||
"untilInclusive": null,
|
||||
"orderId": "501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"orderLineId": "38B17EF-36C4-4039-B92C-4817969B464E",
|
||||
"contractId": null,
|
||||
"content": {
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"issuedAt": "2020-03-21T00:00:00",
|
||||
"activatedAt": "2020-03-21T00:00:00",
|
||||
"blocked": false,
|
||||
"cancelledAt": null,
|
||||
"fraudDetected": false,
|
||||
"barcode": "barcodeBytes"
|
||||
},
|
||||
"_links":
|
||||
{
|
||||
"get_order":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E",
|
||||
"method": "GET",
|
||||
},
|
||||
"patch_productinstance":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/productinstances/0f0981bf-6d60-4b06-bc55-de1ba325f366",
|
||||
"method": "PATCH",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
components:
|
||||
schemas:
|
||||
unavailable:
|
||||
@ -3786,20 +4163,39 @@ components:
|
||||
method:
|
||||
type: string
|
||||
example: GET
|
||||
OvPayTokenProductInstancesResponse:
|
||||
ProductInstancesResponse:
|
||||
type: object
|
||||
required:
|
||||
- productInstances
|
||||
properties:
|
||||
productInstances:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- productInstanceId
|
||||
- productId
|
||||
- name
|
||||
- status
|
||||
- purchasedProductType
|
||||
- isRenewable
|
||||
- productCategory
|
||||
- _links
|
||||
properties:
|
||||
productInstanceId:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 0f0981bf-6d60-4b06-bc55-de1ba325f366
|
||||
productId:
|
||||
type: integer
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: HTM 90% Korting
|
||||
purchasedProductType:
|
||||
type: string
|
||||
description: The type of product instance (e.g. GBO, TapConnect, physical, etc.)
|
||||
example: GBO
|
||||
status:
|
||||
type: string
|
||||
enum: ["Active", "Ended", "Refunded"]
|
||||
@ -3840,6 +4236,10 @@ components:
|
||||
format: uuid
|
||||
example: 56B17EF-C436-9043-B76C-481797WEB464F
|
||||
description: Only present for subscriptions/contracts
|
||||
content:
|
||||
type: object
|
||||
description: Custom data for the product-instance, depending on the purchasedProductType
|
||||
example: null
|
||||
_links:
|
||||
type: object
|
||||
properties:
|
||||
@ -3854,21 +4254,31 @@ components:
|
||||
example: GET
|
||||
get_order:
|
||||
type: object
|
||||
description: Always present for any HTM product-instance
|
||||
properties:
|
||||
href:
|
||||
type: string
|
||||
description: Always present for any HTM product-instance
|
||||
example: https://api.integratielaag.nl/abt/touchpoint/1.0/orders/501B17EF-36C4-4039-B92C-6517969B464E
|
||||
method:
|
||||
type: string
|
||||
example: GET
|
||||
get_contract:
|
||||
type: object
|
||||
description: Only present for subscriptions/contracts
|
||||
properties:
|
||||
href:
|
||||
type: string
|
||||
description: Only present for subscriptions/contracts
|
||||
example: https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/56B17EF-C436-9043-B76C-481797WEB464F
|
||||
method:
|
||||
type: string
|
||||
example: GET
|
||||
patch_productinstance:
|
||||
type: object
|
||||
description: Only present for TapConnect product-instances that need to be activated
|
||||
properties:
|
||||
href:
|
||||
type: string
|
||||
example: https://api.integratielaag.nl/abt/touchpoint/1.0/customers/productinstances/0f0981bf-6d60-4b06-bc55-de1ba325f366
|
||||
method:
|
||||
type: string
|
||||
example: PATCH
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -224,6 +224,7 @@ paths:
|
||||
name: Inactive
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 1
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -347,6 +348,7 @@ paths:
|
||||
name: Inactive
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 2
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -505,6 +507,7 @@ paths:
|
||||
name: Inactive
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 1
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -642,6 +645,7 @@ paths:
|
||||
name: Active
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 5
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -2709,10 +2713,6 @@ components:
|
||||
example: 1
|
||||
postCustomerStatusResponse:
|
||||
type: object
|
||||
properties:
|
||||
customerPreferenceId:
|
||||
type: integer
|
||||
example: 1
|
||||
postCustomerPreferencesResponse:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
1581
src/openapi/customers/customers-trips.yaml
Normal file
1581
src/openapi/customers/customers-trips.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -417,38 +417,56 @@ paths:
|
||||
example:
|
||||
Entries:
|
||||
phoneTypes:
|
||||
- name: mobile
|
||||
- name: Mobiel
|
||||
id: 1
|
||||
- name: fixed line
|
||||
- name: Thuis
|
||||
id: 2
|
||||
- name: Ouders
|
||||
id: 3
|
||||
- name: Bewindvoerder
|
||||
id: 4
|
||||
- name: Home
|
||||
id: 5
|
||||
- name: Mobile
|
||||
id: 6
|
||||
- name: Work
|
||||
id: 7
|
||||
- name: Noodtelefoon
|
||||
id: 8
|
||||
addressTypes:
|
||||
- name: home
|
||||
- name: Shipping
|
||||
id: 1
|
||||
- name: office
|
||||
- name: Billing
|
||||
id: 2
|
||||
customerStatuses:
|
||||
- name: active
|
||||
- name: Inactive
|
||||
id: 1
|
||||
- name: blocked
|
||||
- name: Active
|
||||
id: 2
|
||||
- name: inactive
|
||||
- name: Blocked
|
||||
id: 3
|
||||
- name: new
|
||||
- name: Frozen
|
||||
id: 4
|
||||
- name: Cleared
|
||||
id: 5
|
||||
tokenTypes:
|
||||
- name: Debit card
|
||||
- name: EMV
|
||||
id: 1
|
||||
- name: Credit card
|
||||
id: 2
|
||||
- name: OVPas physical
|
||||
id: 3
|
||||
id: 2
|
||||
- name: OVPas digital
|
||||
id: 4
|
||||
id: 3
|
||||
directDebitMandateTypes:
|
||||
- name: Paper Contract
|
||||
id: 1
|
||||
- name: PIN transaction
|
||||
id: 2
|
||||
- name: SEPA eMandate
|
||||
id: 3
|
||||
- name: Digital signature
|
||||
id: 4
|
||||
- name: IDEAL transaction
|
||||
id: 5
|
||||
tokenStatuses:
|
||||
- name: Expired
|
||||
id: 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,468 +0,0 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Service Engine APIs for maileon
|
||||
description: >-
|
||||
Service Engine APIs for maileon. These are NOT the CRUD APIs to access raw data in the database.
|
||||
version: "1.0"
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/maileon/1.0
|
||||
tags:
|
||||
- name: Customers
|
||||
description: >-
|
||||
Service Engine API's for maileon to update the customer profile. Only field isEmailVerified.
|
||||
- name: Notification categories
|
||||
description: >-
|
||||
Service Engine APIs for all HTM Notifications metadata. To build content only.
|
||||
- name: Notification subscriptions
|
||||
description: >-
|
||||
Service Engine APIs for the HTM Notification subscriptions for a user. Contains the subscriptions on category level.
|
||||
paths:
|
||||
/customers:
|
||||
patch:
|
||||
tags:
|
||||
- Customers
|
||||
parameters:
|
||||
- name: customerProfileId
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: 1
|
||||
required: true
|
||||
description: The customerProfileId of a customer
|
||||
- name: emailAddress
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
format: email
|
||||
example: john.doe@mymailprovider.com
|
||||
required: true
|
||||
description: The emailadress of the customer
|
||||
summary: Update a customer profile
|
||||
description: Update a customer profile based on the customerProfileId and emailAddress
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
patchCustomer:
|
||||
value:
|
||||
{
|
||||
"person": {
|
||||
"isEmailVerified": True
|
||||
}
|
||||
}
|
||||
responses:
|
||||
"202":
|
||||
description: OK
|
||||
/notificationcategories:
|
||||
get:
|
||||
tags:
|
||||
- Notification categories
|
||||
summary: Get notification categories and optins for that category that a touchpoint can show.
|
||||
description: |
|
||||
Get notification categories that a touchpoint can show and optins ( eventTypes) and channels (eventType_channels) for the optin for that category
|
||||
parameters:
|
||||
- name: expand
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [none, eventType, eventTypeChannel]
|
||||
default: none
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
getNotifactionCategories?expand=evenTypeChannel:
|
||||
summary: Return all the notification categories with their nested attributes
|
||||
value:
|
||||
{
|
||||
"notificationCategories":[
|
||||
{
|
||||
"notificationCategoryId": 1,
|
||||
"name": "Nieuwsbrief",
|
||||
"eventTypes": [
|
||||
{
|
||||
"eventTypeId": 1,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 6,
|
||||
"name": "Maileon"
|
||||
},
|
||||
"name": "HTM nieuwsbrief",
|
||||
"subName": "",
|
||||
"prettyName": "HTM nieuwsbrief",
|
||||
"optinRequired": False,
|
||||
"eventTypeChannels":[
|
||||
{
|
||||
"eventTypeChannelId": "447a1116-6cd7-4645-8c3d-43237b6186cd",
|
||||
"channel":{
|
||||
"channelId": 2,
|
||||
"name": "email"
|
||||
},
|
||||
"isDefault": True,
|
||||
"isMandatory": False
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"notificationCategoryId": 2,
|
||||
"name": "Mijn Reizen",
|
||||
"eventTypes": [
|
||||
{
|
||||
"eventTypeId": 2,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, TRAVEL_SCHEME",
|
||||
"subName": "CI",
|
||||
"prettyName": "Check In",
|
||||
"optinRequired": False,
|
||||
"eventTypeChannels":[
|
||||
{
|
||||
"eventTypeChannelId": "ccc8c025-06b5-4928-a632-23e1c55cd173",
|
||||
"channel":{
|
||||
"channelId": 1,
|
||||
"name": "push"
|
||||
},
|
||||
"isDefault": True,
|
||||
"isMandatory": False
|
||||
},
|
||||
{
|
||||
"eventTypeChannelId": "da2deb4c-ce77-4b5f-aecc-ddebfd14349d",
|
||||
"channel":{
|
||||
"channelId": 2,
|
||||
"name": "email"
|
||||
},
|
||||
"isDefault": False,
|
||||
"isMandatory": False
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"eventTypeId": 3,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, PAD",
|
||||
"subName": null,
|
||||
"prettyName": "Profielgegevens op de pas",
|
||||
"optinRequired": False,
|
||||
"eventTypeChannels":[
|
||||
{
|
||||
"eventTypeChannelId": "8e7df8f1-7e50-482f-8301-d399e75fd432",
|
||||
"channel":{
|
||||
"channelId": 1,
|
||||
"name": "push"
|
||||
},
|
||||
"isDefault": True,
|
||||
"isMandatory": False
|
||||
},
|
||||
{
|
||||
"eventTypeChannelId": "72960a92-1855-469f-9cfd-5d72f57106f2",
|
||||
"channel":{
|
||||
"channelId": 2,
|
||||
"name": "email"
|
||||
},
|
||||
"isDefault": False,
|
||||
"isMandatory": False
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"notificationCategoryId": 3,
|
||||
"name": "Mijn Passen",
|
||||
"eventTypes": [
|
||||
{
|
||||
"eventTypeId": 4,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, CARD",
|
||||
"subName": null,
|
||||
"prettyName": "Mijn passen",
|
||||
"optinRequired": False,
|
||||
"eventTypeChannels":[
|
||||
{
|
||||
"eventTypeChannelId": "be07c7bb-714b-4637-acf5-a67025ad8e60",
|
||||
"channel":{
|
||||
"channelId": 1,
|
||||
"name": "push"
|
||||
},
|
||||
"isDefault": True,
|
||||
"isMandatory": False
|
||||
},
|
||||
{
|
||||
"eventTypeChannelId": "0c797b5a-ed34-494b-8c64-0a832830d392",
|
||||
"channel":{
|
||||
"channelId": 2,
|
||||
"name": "email"
|
||||
},
|
||||
"isDefault": False,
|
||||
"isMandatory": False
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"eventTypeId": 5,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, PAD",
|
||||
"subName": null,
|
||||
"prettyName": "Profielgegevens op de pas",
|
||||
"optinRequired": False,
|
||||
"eventTypeChannels":[
|
||||
{
|
||||
"eventTypeChannelId": "b910368f-c045-4e8e-b01d-bcbc78708bac",
|
||||
"channel":{
|
||||
"channelId": 1,
|
||||
"name": "push"
|
||||
},
|
||||
"isDefault": True,
|
||||
"isMandatory": False
|
||||
},
|
||||
{
|
||||
"eventTypeChannelId": "93e773da-ba3b-48da-9a0e-ee478eaa752f",
|
||||
"channel":{
|
||||
"channelId": 2,
|
||||
"name": "email"
|
||||
},
|
||||
"isDefault": False,
|
||||
"isMandatory": False
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
getNotifactionCategories?expand=eventType:
|
||||
summary: Return all the notification categories with nested eventTypes
|
||||
value:
|
||||
{
|
||||
"notificationCategories":[
|
||||
{
|
||||
"notificationCategoryId": 1,
|
||||
"name": "Nieuwsbrief",
|
||||
"eventTypes": [
|
||||
{
|
||||
"eventTypeId": 1,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 6,
|
||||
"name": "Maileon"
|
||||
},
|
||||
"name": "HTM nieuwsbrief",
|
||||
"subName": "",
|
||||
"prettyName": "HTM nieuwsbrief",
|
||||
"optinRequired": False
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"notificationCategoryId": 2,
|
||||
"name": "Mijn Reizen",
|
||||
"eventTypes": [
|
||||
{
|
||||
"eventTypeId": 2,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, TRAVEL_SCHEME",
|
||||
"subName": "CI",
|
||||
"prettyName": "Check In",
|
||||
"optinRequired": False
|
||||
},
|
||||
{
|
||||
"eventTypeId": 3,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, PAD",
|
||||
"subName": null,
|
||||
"prettyName": "Profielgegevens op de pas",
|
||||
"optinRequired": False
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"notificationCategoryId": 3,
|
||||
"name": "Mijn Passen",
|
||||
"eventTypes": [
|
||||
{
|
||||
"eventTypeId": 4,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, CARD",
|
||||
"subName": null,
|
||||
"prettyName": "Mijn passen",
|
||||
"optinRequired": False
|
||||
},
|
||||
{
|
||||
"eventTypeId": 5,
|
||||
"eventOrigin": {
|
||||
"eventOriginId": 1,
|
||||
"name": "GBO"
|
||||
},
|
||||
"name": "ALERTS, PAD",
|
||||
"subName": null,
|
||||
"prettyName": "Profielgegevens op de pas",
|
||||
"optinRequired": False
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
getNotifactionCategories?expand=none:
|
||||
summary: Return all the notification categories
|
||||
value:
|
||||
{
|
||||
"notificationCategories":[
|
||||
{
|
||||
"notificationCategoryId": 1,
|
||||
"name": "Nieuwsbrief"
|
||||
},
|
||||
{
|
||||
"notificationCategoryId": 2,
|
||||
"name": "Mijn Reizen"
|
||||
},
|
||||
{
|
||||
"notificationCategoryId": 3,
|
||||
"name": "Mijn Passen"
|
||||
}
|
||||
]
|
||||
}
|
||||
"404":
|
||||
description: No notification category found
|
||||
content:
|
||||
application/json:
|
||||
example:
|
||||
{
|
||||
"type": "https://api.integratielaag.nl/abt/touchpoint/2.0/notifications",
|
||||
"title": "Niet gevonden",
|
||||
"detail": "Notificatiecategorie niet gevonden",
|
||||
"instance": "555d00b5-bc3f-4591-949b-479e76d49ea7",
|
||||
"errors": [
|
||||
{
|
||||
"code": "404",
|
||||
"detail": null,
|
||||
"path": null,
|
||||
"parameter": null
|
||||
}
|
||||
],
|
||||
}
|
||||
/notificationsubscriptions:
|
||||
get:
|
||||
tags:
|
||||
- Notification subscriptions
|
||||
summary: Get all possible notificationSubscriptions for a customer (account or private).
|
||||
description: |
|
||||
Get all possible notificationSubscriptions for a customer (account or private), including if they have opted-in for it.
|
||||
parameters:
|
||||
- name: customerProfileId
|
||||
in: header
|
||||
schema:
|
||||
type: integer
|
||||
example: 12361
|
||||
required: true
|
||||
description: The customerProfileId of a customer
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
getNotifactionSubscriptionsAll:
|
||||
summary: Return all the notification subscriptions where for each category the client has actively opted in or out - All
|
||||
value:
|
||||
{
|
||||
"notificationSubscriptions":[
|
||||
{
|
||||
"notificationSubscriptionId": "64047471-e0c3-4abc-b4eb-83a12a6de903",
|
||||
"notificationCategoryId": 1,
|
||||
"isActive": true
|
||||
},
|
||||
{
|
||||
"notificationSubscriptionId": "571388cd-8903-40d5-89e6-9191cb8d656e",
|
||||
"notificationCategoryId": 2,
|
||||
"isActive": true
|
||||
},
|
||||
{
|
||||
"notificationSubscriptionId": "cf736ff2-2f8f-434e-a3c7-a14064b73c9b",
|
||||
"notificationCategoryId": 3,
|
||||
"isActive": false
|
||||
}
|
||||
]
|
||||
}
|
||||
getNotifactionSubscriptionsSome:
|
||||
summary: Return all the notification subscriptions where for each category the client has actively opted in or out - Some
|
||||
value:
|
||||
{
|
||||
"notificationSubscriptions": [
|
||||
{
|
||||
"notificationSubscriptionId": "64047471-e0c3-4abc-b4eb-83a12a6de903",
|
||||
"notificationCategoryId": 1,
|
||||
"isActive": true
|
||||
},
|
||||
{
|
||||
"notificationSubscriptionId": "cf736ff2-2f8f-434e-a3c7-a14064b73c9b",
|
||||
"notificationCategoryId": 3,
|
||||
"isActive": false
|
||||
}
|
||||
]
|
||||
}
|
||||
"403":
|
||||
description: Forbidden // Als geverifieerd profiel gevonden wordt, maar niet op een geverifieerde manier benaderd wordt
|
||||
content:
|
||||
application/json:
|
||||
example:
|
||||
{
|
||||
"type": "https://api.integratielaag.nl/abt/touchpoint/2.0/notifications",
|
||||
"title": "Verboden",
|
||||
"detail": "Niet toegestaan",
|
||||
"instance": "555d00b5-bc3f-4591-949b-479e76d49ea7",
|
||||
"errors": [
|
||||
{
|
||||
"code": "403",
|
||||
"detail": null,
|
||||
"path": null,
|
||||
"parameter": null
|
||||
}
|
||||
],
|
||||
}
|
||||
"404":
|
||||
description: No notification subscriptions found
|
||||
content:
|
||||
application/json:
|
||||
example:
|
||||
{
|
||||
"type": "https://api.integratielaag.nl/abt/touchpoint/2.0/notifications",
|
||||
"title": "Niet gevonden",
|
||||
"detail": "Notificaties niet gevonden",
|
||||
"instance": "555d00b5-bc3f-4591-949b-479e76d49ea7",
|
||||
"errors": [
|
||||
{
|
||||
"code": "404",
|
||||
"detail": null,
|
||||
"path": null,
|
||||
"parameter": null
|
||||
}
|
||||
],
|
||||
}
|
||||
components:
|
||||
schemas:
|
||||
unavailable:
|
||||
type: object
|
||||
@ -228,7 +228,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsPostRequestBody"
|
||||
$ref: "#/components/schemas/TransactionItemsBulkRequestBody"
|
||||
examples:
|
||||
Add single transaction item:
|
||||
summary: Add single transaction item
|
||||
@ -285,7 +285,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsPostResponseBody"
|
||||
$ref: "#/components/schemas/BulkResponseBody"
|
||||
examples:
|
||||
Array of transaction items accepted:
|
||||
summary: Array of transaction items accepted
|
||||
@ -381,7 +381,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsResponseStatusGetResponseBody"
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
examples:
|
||||
Batch successfully processed:
|
||||
summary: Batch successfully processed
|
||||
@ -2979,10 +2979,10 @@ paths:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
x-throttling-tier: Unlimited
|
||||
/transactionitems/reject:
|
||||
post:
|
||||
summary: Reject transaction items to source in bulk.
|
||||
description: Reject transaction items to source in bulk.
|
||||
/transactionitems/bulk:
|
||||
patch:
|
||||
summary: Patch transaction items in bulk.
|
||||
description: Patch transaction items in bulk.
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
requestBody:
|
||||
@ -2992,76 +2992,117 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsBulkRequestBody"
|
||||
examples:
|
||||
List of transaction item ids to reject:
|
||||
summary: List of transaction item ids to reject to source
|
||||
description: List of transaction item ids to reject to source.
|
||||
List of transactions items to reject:
|
||||
summary: List of transaction items to reject to source
|
||||
description: List of transaction items to reject to source in bulk.
|
||||
value:
|
||||
transactionItemIds:
|
||||
- afce35b2-1dff-4ace-98d0-4b9ac405c87d
|
||||
- b1c4f8e7-3f4e-4d2a-9c6e-2f5e6d7c8b9a
|
||||
- c2d5e6f7-4g5h-5i6j-0k1l-3m4n5o6p7q8r
|
||||
transactionItems:
|
||||
- transactionItemId: d8ee7035-fa3d-400e-9ad5-4fe8c4c73eb7
|
||||
status: returned to src
|
||||
aggregationReference: null
|
||||
accountingSystemReference: null
|
||||
- transactionItemId: 88910e83-4b1e-4fde-ab13-bd8bb60cbcd3
|
||||
status: returned to src
|
||||
aggregationReference: null
|
||||
accountingSystemReference: null
|
||||
List of transactions items to return:
|
||||
summary: List of transaction items to return to transaction database
|
||||
description: List of transaction items to return to transaction database in bulk.
|
||||
value:
|
||||
transactionItems:
|
||||
- transactionItemId: eacb9bdc-c6b5-4277-942b-cebb102944f5
|
||||
status: returned to trx-db
|
||||
aggregationReference: null
|
||||
accountingSystemReference: null
|
||||
- transactionItemId: 2f361bfb-9df0-4e0f-af7c-7b9be3e7bc61
|
||||
status: returned to trx-db
|
||||
aggregationReference: null
|
||||
accountingSystemReference: null
|
||||
responses:
|
||||
"202":
|
||||
description: Accepted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsPostResponseBody"
|
||||
$ref: "#/components/schemas/BulkResponseBody"
|
||||
examples:
|
||||
Array of transaction items accepted:
|
||||
summary: Array of transaction item ids accepted
|
||||
summary: Array of transaction items accepted
|
||||
description: |
|
||||
The array of transaction item ids was accepted successfully.
|
||||
The array of transaction items was accepted successfully.
|
||||
The transaction items will be processed asynchronously.
|
||||
In the response body the consumer will find information on how to retrieve the processing status.
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.0672237Z
|
||||
status: Running
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
callbackurl: https://api.integratielaag.nl/transactionitems/reject/responsestatus/runtime/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
callbackurl: https://api.integratielaag.nl/transactionitems/bulk/responsestatus/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
retryAfter: 10
|
||||
security:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
x-throttling-tier: Unlimited
|
||||
/transactionitems/responsestatus/reject/{clientTrackingId}:
|
||||
/transactionitems/bulk/responsestatus/{clientTrackingId}:
|
||||
get:
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
summary: Get the status of the transaction item bulk reject.
|
||||
description: Get the status of the asynchronous transaction item bulk reject.
|
||||
summary: Get the status of the transaction item bulk patch.
|
||||
description: Get the status of the asynchronous transaction item bulk patch.
|
||||
parameters:
|
||||
- in: path
|
||||
name: clientTrackingId
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: The clientTrackingId of the transaction item bulk reject.
|
||||
description: The clientTrackingId of the transaction item bulk patch.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsRejectResponseStatusGetResponseBody"
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
examples:
|
||||
Batch successfully processed:
|
||||
summary: Batch successfully processed
|
||||
description: |
|
||||
Body of a batch of transaction items that was successfully rejected.
|
||||
A number of transaction items were rejected.
|
||||
Body of a batch of transaction items that was successfully patched.
|
||||
A number of transaction items were patched.
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.067Z
|
||||
status: Finished
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
summary:
|
||||
rejected: 15
|
||||
created: 0
|
||||
updated: 15
|
||||
total: 15
|
||||
"202":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
examples:
|
||||
Batch is still being processed:
|
||||
summary: Batch is still being processed
|
||||
description: |
|
||||
Batch is still being processed
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.067Z
|
||||
status: Running
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
summary:
|
||||
created: 0
|
||||
updated: 0
|
||||
total: 0
|
||||
security:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
x-throttling-tier: Unlimited
|
||||
/transactionitems/return:
|
||||
post:
|
||||
summary: Return transaction items to trx db in bulk.
|
||||
description: Return transaction items to trx db in bulk.
|
||||
/processingfailures/bulk:
|
||||
patch:
|
||||
summary: Patch processing failures in bulk.
|
||||
description: Patch processing failures in bulk.
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
requestBody:
|
||||
@ -3069,70 +3110,96 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsBulkRequestBody"
|
||||
$ref: "#/components/schemas/ProcessingFailuresBulkRequestBody"
|
||||
examples:
|
||||
List of transaction item ids to reject:
|
||||
summary: List of transaction item ids to return to trx db
|
||||
description: List of transaction item ids to return to trx db.
|
||||
List of processing failures to resolve:
|
||||
summary: List of processing failures to resolve
|
||||
description: List of processing failures to resolve in bulk.
|
||||
value:
|
||||
transactionItemIds:
|
||||
- afce35b2-1dff-4ace-98d0-4b9ac405c87d
|
||||
- b1c4f8e7-3f4e-4d2a-9c6e-2f5e6d7c8b9a
|
||||
- c2d5e6f7-4g5h-5i6j-0k1l-3m4n5o6p7q8r
|
||||
processingFailures:
|
||||
- processingFailureId: d8ee7035-fa3d-400e-9ad5-4fe8c4c73eb7
|
||||
resolved: true
|
||||
change: Configuratie aangepast voor artikelnummer 1337.
|
||||
- processingFailureId: 88910e83-4b1e-4fde-ab13-bd8bb60cbcd3
|
||||
resolved: true
|
||||
change: Configuratie aangepast voor artikelnummer 1337.
|
||||
responses:
|
||||
"202":
|
||||
description: Accepted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsPostResponseBody"
|
||||
$ref: "#/components/schemas/BulkResponseBody"
|
||||
examples:
|
||||
Array of transaction items accepted:
|
||||
summary: Array of transaction item ids accepted
|
||||
Array of processing failures accepted:
|
||||
summary: Array of processing failures accepted
|
||||
description: |
|
||||
The array of transaction item ids was accepted successfully.
|
||||
The transaction items will be processed asynchronously.
|
||||
The array of processing failures was accepted successfully.
|
||||
The processing failures will be processed asynchronously.
|
||||
In the response body the consumer will find information on how to retrieve the processing status.
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.0672237Z
|
||||
status: Running
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
callbackurl: https://api.integratielaag.nl/transactionitems/return/responsestatus/runtime/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
callbackurl: https://api.integratielaag.nl/processingfailures/bulk/responsestatus/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
retryAfter: 10
|
||||
security:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
x-throttling-tier: Unlimited
|
||||
/transactionitems/responsestatus/return/{clientTrackingId}:
|
||||
/processingfailures/bulk/responsestatus/{clientTrackingId}:
|
||||
get:
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
summary: Get the status of the transaction item bulk return.
|
||||
description: Get the status of the asynchronous transaction item bulk return.
|
||||
summary: Get the status of the processing failures bulk patch.
|
||||
description: Get the status of the asynchronous processing failures bulk patch.
|
||||
parameters:
|
||||
- in: path
|
||||
name: clientTrackingId
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: The clientTrackingId of the transaction item bulk return.
|
||||
description: The clientTrackingId of the processing failures bulk patch.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsReturnResponseStatusGetResponseBody"
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
examples:
|
||||
Batch successfully processed:
|
||||
summary: Batch successfully processed
|
||||
description: |
|
||||
Body of a batch of transaction items that was successfully returned to trx db.
|
||||
A number of transaction items were returned to trx db.
|
||||
Body of a batch of processing failures that was successfully patched.
|
||||
A number of processing failures were patched.
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.067Z
|
||||
status: Finished
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
summary:
|
||||
returned: 15
|
||||
created: 0
|
||||
updated: 15
|
||||
total: 15
|
||||
"202":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
examples:
|
||||
Batch is still being processed:
|
||||
summary: Batch is still being processed
|
||||
description: |
|
||||
Batch is still being processed
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.067Z
|
||||
status: Running
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
summary:
|
||||
created: 0
|
||||
updated: 0
|
||||
total: 0
|
||||
security:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
@ -3249,7 +3316,7 @@ components:
|
||||
- occurredOn
|
||||
- type
|
||||
- status
|
||||
TransactionItemsPostRequestBody:
|
||||
TransactionItemsBulkRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
transactionItems:
|
||||
@ -3257,6 +3324,10 @@ components:
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
transactionItemId:
|
||||
type: string
|
||||
format: uuid
|
||||
example: afce35b2-1dff-4ace-98d0-4b9ac405c87d
|
||||
transactionType:
|
||||
type: string
|
||||
enum:
|
||||
@ -3316,7 +3387,7 @@ components:
|
||||
- amountTax
|
||||
- occurredOn
|
||||
- type
|
||||
TransactionItemsPostResponseBody:
|
||||
BulkResponseBody:
|
||||
type: object
|
||||
properties:
|
||||
startTime:
|
||||
@ -4902,7 +4973,7 @@ components:
|
||||
required:
|
||||
- concessionId
|
||||
- name
|
||||
TransactionItemsResponseStatusGetResponseBody:
|
||||
GetResponseStatus:
|
||||
type: object
|
||||
properties:
|
||||
summary:
|
||||
@ -4959,51 +5030,24 @@ components:
|
||||
transactionLineId:
|
||||
type: string
|
||||
example: fee907dd-e59d-44f5-a63b-bbdec38f79b7
|
||||
TransactionItemsBulkRequestBody:
|
||||
ProcessingFailuresBulkRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
transactionItemIds:
|
||||
processingFailures:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
processingFailureId::
|
||||
type: string
|
||||
format: uuid
|
||||
example: 1ad109d3-fd7d-4b6f-872b-220d492f385f
|
||||
example: d8ee7035-fa3d-400e-9ad5-4fe8c4c73eb7
|
||||
resolved:
|
||||
type: boolean
|
||||
example: true
|
||||
required:
|
||||
- transactionItemIds
|
||||
TransactionItemsRejectResponseStatusGetResponseBody:
|
||||
type: object
|
||||
properties:
|
||||
summary:
|
||||
type: object
|
||||
properties:
|
||||
rejected:
|
||||
type: integer
|
||||
example: 3
|
||||
total:
|
||||
type: integer
|
||||
example: 3
|
||||
required:
|
||||
- rejected
|
||||
- total
|
||||
required:
|
||||
- summary
|
||||
TransactionItemsReturnResponseStatusGetResponseBody:
|
||||
type: object
|
||||
properties:
|
||||
summary:
|
||||
type: object
|
||||
properties:
|
||||
returned:
|
||||
type: integer
|
||||
example: 3
|
||||
total:
|
||||
type: integer
|
||||
example: 3
|
||||
required:
|
||||
- returned
|
||||
- total
|
||||
required:
|
||||
- summary
|
||||
- transactionItemId
|
||||
- resolved
|
||||
rfc9457:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
110
src/openapi/onetimetokens/onetimetokens.yaml
Normal file
110
src/openapi/onetimetokens/onetimetokens.yaml
Normal file
@ -0,0 +1,110 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Integratielaag APIs for one time tokens for a HTM customer
|
||||
description: >-
|
||||
Integratielaag APIs for one time tokens for a HTM customer. So that the a customer can be redirected between touchpoints, and the source of the request can be validated. NOTE : this is only to validate the redirect and the source of the redirect, touchpoint needs to make another call to take over the entra session.
|
||||
version: "1.0"
|
||||
servers:
|
||||
- url: https://api.integratielaag.nl/v1/touchpoint
|
||||
tags:
|
||||
- name: OneTimeTokens
|
||||
description: >-
|
||||
Service Engine APIs for HTM Customers. These are NOT the CRUD APIs to access raw data in the database.
|
||||
To be used by touchpoints to get information about HTM customers.
|
||||
paths:
|
||||
/one-time-tokens:
|
||||
post:
|
||||
tags:
|
||||
- OneTimeTokens
|
||||
summary: Create a one time token, to be included in the redirect
|
||||
description: |
|
||||
Create a one time token, to be included in the redirect
|
||||
parameters:
|
||||
- name: Authorization
|
||||
in: header
|
||||
required: true
|
||||
style: simple
|
||||
explode: false
|
||||
schema:
|
||||
type: string
|
||||
example: Bearer {WSO2 Token}
|
||||
description: Fill in a valid WSO2 Token for the touchpoint
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/unavailable'
|
||||
example:
|
||||
{
|
||||
"nonce": "randomNonce123",
|
||||
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q..."
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/oneTimeTokenResponse"
|
||||
/one-time-tokens/validate:
|
||||
post:
|
||||
tags:
|
||||
- OneTimeTokens
|
||||
summary: Validate a received one time token
|
||||
description: Validate a received one time token through the redirect, validates the source and validity of the token
|
||||
parameters:
|
||||
- name: Authorization
|
||||
in: header
|
||||
required: true
|
||||
style: simple
|
||||
explode: false
|
||||
schema:
|
||||
type: string
|
||||
example: Bearer {WSO2 Token}
|
||||
description: Fill in a valid WSO2 Token for the touchpoint
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/unavailable'
|
||||
example:
|
||||
{
|
||||
"token": "handoff-xyz987"
|
||||
}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
logged in user:
|
||||
summary: Logged in user
|
||||
description: Logged in user
|
||||
value:
|
||||
{
|
||||
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q..."
|
||||
}
|
||||
user not logged in:
|
||||
summary: User not logged in
|
||||
description: User not logged in
|
||||
value:
|
||||
{}
|
||||
"400":
|
||||
description: Bad request
|
||||
"401":
|
||||
description: Not authorized
|
||||
components:
|
||||
schemas:
|
||||
unavailable:
|
||||
type: object
|
||||
oneTimeTokenResponse:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
example: "handoff-xyz987"
|
||||
expires_in:
|
||||
type: integer
|
||||
example: 120
|
||||
@ -1,180 +0,0 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: ABT Service Engine Order APIs
|
||||
version: "1.0"
|
||||
description: Order APIs available in the Service Engine for order validation and fulfillment.
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/touchpoint/2.0
|
||||
paths:
|
||||
/orders/validation/gboAgeProfile:
|
||||
get:
|
||||
tags:
|
||||
- ServiceEngine Order validation
|
||||
summary: Get GBO age profile that is valid for the given input
|
||||
description: |-
|
||||
Only one age profile can be valid at any one time, so only one profile is returned.
|
||||
parameters:
|
||||
- name: productStartDate
|
||||
in: query
|
||||
required: true
|
||||
description: Start date of product validity
|
||||
schema:
|
||||
type: string
|
||||
format: date
|
||||
example: 2025-03-20
|
||||
- name: birthDate
|
||||
in: query
|
||||
required: false
|
||||
description: Birthdate of the OVpay-token holder
|
||||
schema:
|
||||
type: string
|
||||
format: date
|
||||
example: 2000-01-01
|
||||
- name: ovPayTokenId
|
||||
in: query
|
||||
required: false
|
||||
description: ovPayTokenId of the customer's selected token
|
||||
schema:
|
||||
type: integer
|
||||
example: 1
|
||||
- name: customerTokenId
|
||||
in: query
|
||||
required: false
|
||||
description: customerTokenId of the customer's selected token
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "4a2d2c9c-1e5d-4d8a-9c0a-6c0a6c0a6c0a"
|
||||
- name: serviceReferenceId
|
||||
in: query
|
||||
required: false
|
||||
description: serviceReferenceId of the customer's selected token
|
||||
schema:
|
||||
type: string
|
||||
example: "NLOV1234567ABCDEFG"
|
||||
- name: amount
|
||||
in: query
|
||||
required: false
|
||||
description: amount belonging to the serviceReferenceId
|
||||
schema:
|
||||
type: integer
|
||||
example: 100
|
||||
- name: ovpasNumber
|
||||
in: query
|
||||
required: false
|
||||
description: OVpas number of the customer's selected token
|
||||
schema:
|
||||
type: string
|
||||
example: "63AW974"
|
||||
- name: verificationCode
|
||||
in: query
|
||||
required: false
|
||||
description: verification code belonging to the OVpas number
|
||||
schema:
|
||||
type: string
|
||||
example: 1A3C7D
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GboAgeProfileResponse"
|
||||
|
||||
"400":
|
||||
description: Bad request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457Response"
|
||||
examples:
|
||||
Missing parameter(s):
|
||||
summary: Missing parameter(s)
|
||||
value:
|
||||
{
|
||||
"type": "https://www.htm.nl/api/v1/400Error",
|
||||
"title": "Missing parameter(s)",
|
||||
"detail": "At least one of the following parameters must be present: birthDate, ovPayTokenId, customerTokenId, (serviceReferenceId and amount), (ovpasNumber and verificationCode)",
|
||||
"instance": "urn:uuid:13c8416f-7632-4c8b-8a16-2132197be60c",
|
||||
"apiErrorCode": "htm.api.err.400.2",
|
||||
}
|
||||
Invalid date format:
|
||||
summary: Invalid date format
|
||||
value:
|
||||
{
|
||||
"type": "https://www.htm.nl/api/v1/400Error",
|
||||
"title": "Invalid input",
|
||||
"detail": "The given birthDate is not a valid Date format",
|
||||
"instance": "urn:uuid:13c8416f-7632-4c8b-8a16-2132197be60c",
|
||||
"apiErrorCode": "htm.api.err.400.3",
|
||||
}
|
||||
"404":
|
||||
description: Not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457Response"
|
||||
examples:
|
||||
No birthdate present in PAD of OVpay token:
|
||||
summary: No birthdate present in PAD of OVpay token
|
||||
value:
|
||||
{
|
||||
"type": "https://www.htm.nl/api/v1/404Error",
|
||||
"title": "Missing birthdate in PAD",
|
||||
"detail": "There is no birthdate present in the PAD of the OVpay token, or there is no PAD present at all",
|
||||
"instance": "urn:uuid:13c8416f-7632-4c8b-8a16-2132197be60c",
|
||||
"apiErrorCode": "htm.api.err.404.1",
|
||||
}
|
||||
components:
|
||||
schemas:
|
||||
GboAgeProfileResponse:
|
||||
type: object
|
||||
required:
|
||||
- gboAgeProfileId
|
||||
- name
|
||||
- ageFromInclusive
|
||||
- ageToInclusive
|
||||
properties:
|
||||
gboAgeProfileId:
|
||||
type: integer
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: Kind (4 t/m 11 jaar)
|
||||
ageFromInclusive:
|
||||
type: integer
|
||||
example: 4
|
||||
ageToInclusive:
|
||||
type: integer
|
||||
example: 11
|
||||
rfc9457Response:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
format: url
|
||||
example: "https://www.htm.nl/api/v1/rfc9457Error"
|
||||
title:
|
||||
type: string
|
||||
description: "Short summary of the error."
|
||||
example: "The request is not valid."
|
||||
detail:
|
||||
type: string
|
||||
description: "More detailed descriptionof the error."
|
||||
example: "Some required parameters are missing."
|
||||
instance:
|
||||
type: string
|
||||
description: "Unique identifier to correlate this specific error with logging in other applications."
|
||||
example: "urn:uuid:13c8416f-7632-4c8b-8a16-2132197be60c"
|
||||
additionalProperty1:
|
||||
type: string
|
||||
description: "Example of an additional property value to be used for error reporting."
|
||||
example: "additionalValue1"
|
||||
additionalProperty2:
|
||||
type: array
|
||||
description: "Example of an additional property array to be used for error reporting."
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- "additionalValue2-1"
|
||||
- "additionalValue2-2"
|
||||
@ -5,6 +5,12 @@ info:
|
||||
description: CRUD APIs for ABT Orders database. These are NOT the functional APIs from Service Engine.
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/abtorder/1.0
|
||||
tags:
|
||||
- name: Order
|
||||
- name: Order Line
|
||||
- name: Payment
|
||||
- name: Customer
|
||||
- name: Order Voucher
|
||||
paths:
|
||||
/orders:
|
||||
get:
|
||||
@ -50,6 +56,14 @@ paths:
|
||||
example: 1
|
||||
required: false
|
||||
description: The id of the touch point where the order was initiated.
|
||||
- in: query
|
||||
name: deviceId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "7a28bd54-7ca9-499a-a722-d15ab858ab99"
|
||||
required: false
|
||||
description: The id of the device used to place the order.
|
||||
- in: query
|
||||
name: languageId
|
||||
schema:
|
||||
@ -98,6 +112,14 @@ paths:
|
||||
explode: false
|
||||
required: false
|
||||
description: Filter on most recent order status. 1 = concept, 2 = awaitingPayment, 3 = pendingPayment, 4 = paid, 5 = delivered, 6 = cancelled.
|
||||
- in: query
|
||||
name: issuedVoucherId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "b0a9f3c9-9b92-4f8c-b78d-6129be7218a6"
|
||||
required: false
|
||||
description: Filter on applied issuedVoucherId for the order.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@ -119,6 +141,7 @@ paths:
|
||||
"touchPointId": 1,
|
||||
"name": "Perplex"
|
||||
},
|
||||
"deviceId": "42e77532-d831-41da-b07a-7edb9bb7f004",
|
||||
"language":
|
||||
{
|
||||
"languageId": 1,
|
||||
@ -148,6 +171,30 @@ paths:
|
||||
"description": "Betaling in behandeling",
|
||||
},
|
||||
],
|
||||
"orderVouchers": [
|
||||
{
|
||||
"orderVoucherId": "399bd3b3-9721-4f09-a936-d64637de1621",
|
||||
"issuedVoucher":{
|
||||
"issuedVoucherId": "a0996218-bc5e-4826-9020-cda98a32838d",
|
||||
"voucherCode": "Voucher1234",
|
||||
"purchasedProductId": 31,
|
||||
"fromInclusive": "2025-03-22T08:55:00",
|
||||
"untillInclusive": "2026-03-22T08:55:00"
|
||||
},
|
||||
"orderLineId": null
|
||||
},
|
||||
{
|
||||
"orderVoucherId": "f6c7ac42-1811-4e4d-82af-53e18fe16110",
|
||||
"issuedVoucher":{
|
||||
"issuedVoucherId": "54668baf-4905-4e9a-af02-09c170f295ed",
|
||||
"voucherCode": "Voucher124",
|
||||
"purchasedProductId": 35,
|
||||
"fromInclusive": "2025-03-22T08:55:00",
|
||||
"untillInclusive": "2026-03-22T08:55:00"
|
||||
},
|
||||
"orderLineId": "7a7a9d1a-3fc8-4058-a28b-082860aaa311"
|
||||
}
|
||||
],
|
||||
"orderLines":
|
||||
[
|
||||
{
|
||||
@ -277,7 +324,7 @@ paths:
|
||||
{
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"addressType":
|
||||
{ "addressTypeId": 3, "name": "Billing" },
|
||||
{ "addressTypeId": 2, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -327,19 +374,22 @@ paths:
|
||||
"customerProfileId": 1337,
|
||||
"totalAmount": 121,
|
||||
"touchPointId": 1,
|
||||
"deviceId": "b8ca9fdf-0bb9-4e49-b48d-41e395563377",
|
||||
"languageId": 1,
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"order_OrderStatus":
|
||||
[
|
||||
{
|
||||
"orderStatusId": 4,
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"description": "Order succesvol betaald",
|
||||
},
|
||||
{
|
||||
"orderStatusId": 3,
|
||||
"orderStatusId": 1,
|
||||
"createdOn": "2024-03-22T08:55:00",
|
||||
"description": "Betaling in behandeling",
|
||||
"description": "Concept order",
|
||||
},
|
||||
],
|
||||
"orderVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "e81b2197-a6c2-45b6-9560-8ce8442e8604",
|
||||
"orderLineId": "97824d2e-5189-456d-b6da-4cca511a7685"
|
||||
},
|
||||
],
|
||||
"orderLines":
|
||||
@ -390,57 +440,6 @@ paths:
|
||||
],
|
||||
},
|
||||
],
|
||||
"payments":
|
||||
[
|
||||
{
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"amountDebit": 121,
|
||||
"paymentMethodId": 1,
|
||||
"touchPointId": 1,
|
||||
"isRefund": false,
|
||||
"htmPaymentReference": "HTM-1234",
|
||||
"pspPaymentReference": "Buckaroo-1234",
|
||||
"paymentStatuses":
|
||||
[
|
||||
{
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"statusCode": "190",
|
||||
"statusDescription": "Success",
|
||||
"statusSubCode": "S001",
|
||||
"statusSubDescription": "PaymentSuccessFul",
|
||||
},
|
||||
],
|
||||
"mandateInput":
|
||||
{
|
||||
"directDebitMandateTypeId": 1,
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"bic": "RABONL2U",
|
||||
"iban": "NL44RABO0123456789",
|
||||
"ascription": "J. de Vries",
|
||||
"place": "Den Haag",
|
||||
},
|
||||
},
|
||||
],
|
||||
"orderCustomer":
|
||||
{
|
||||
"birthname": "Jan",
|
||||
"surname": "Vries",
|
||||
"prefix": "de",
|
||||
"emailAddress": "jandevries@outlook.com",
|
||||
"dateOfBirth": "1970-01-01",
|
||||
"orderCustomerAddresses":
|
||||
[
|
||||
{
|
||||
"addressTypeId": 1,
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
"postalCode": "2595 AA",
|
||||
"city": "Den Haag",
|
||||
"country": "NL",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
@ -487,6 +486,7 @@ paths:
|
||||
"touchPointId": 1,
|
||||
"name": "Perplex"
|
||||
},
|
||||
"deviceId": null,
|
||||
"language":
|
||||
{
|
||||
"languageId": 1,
|
||||
@ -512,6 +512,7 @@ paths:
|
||||
"description": "Betaling in behandeling",
|
||||
},
|
||||
],
|
||||
"orderVouchers": null,
|
||||
"orderLines":
|
||||
[
|
||||
{
|
||||
@ -634,7 +635,7 @@ paths:
|
||||
{
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"addressType":
|
||||
{ "addressTypeId": 3, "name": "Billing" },
|
||||
{ "addressTypeId": 2, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -658,6 +659,7 @@ paths:
|
||||
example:
|
||||
{
|
||||
"customerProfileId": 1337,
|
||||
"deviceId": "fe68e624-b75f-48ca-a179-d5f86a8ab7d5",
|
||||
"totalAmount": 121,
|
||||
"languageId": 1,
|
||||
"lastUpdatedOn": "2024-03-22T09:00:00",
|
||||
@ -678,6 +680,7 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
|
||||
/orders/{orderId}/statuses:
|
||||
parameters:
|
||||
- in: path
|
||||
@ -715,6 +718,143 @@ paths:
|
||||
{
|
||||
"order_orderStatusId": "b9cf0096-4211-4be6-ac21-7bc34bc8e066",
|
||||
}
|
||||
/orders/{orderId}/ordervouchers:
|
||||
parameters:
|
||||
- in: path
|
||||
name: orderId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d1dd439b-6072-4b97-89c9-724268865b93
|
||||
required: true
|
||||
description: The id of the order to process.
|
||||
post:
|
||||
summary: Add an order voucher.
|
||||
description: Add an order voucher.
|
||||
tags:
|
||||
- Order Voucher
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"issuedVoucherId": "eec6af41-1a60-49f6-a92e-440054a92f13",
|
||||
"orderLineId": "7a9d6e15-7c5c-421d-9ea9-00b9bb6dbe67"
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"orderVoucherId": "b9cf0096-4211-4be6-ac21-7bc34bc8e066",
|
||||
}
|
||||
/ordervouchers:
|
||||
parameters:
|
||||
- in: query
|
||||
name: orderVoucherId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d1dd439b-6072-4b97-89c9-724268865b93
|
||||
required: false
|
||||
description: The id of the orderVoucher you are looking for.
|
||||
- in: query
|
||||
name: orderId
|
||||
schema:
|
||||
type: string
|
||||
example: 90c926b9-3178-4757-acca-34cff66b980c
|
||||
required: false
|
||||
description: The id of the order
|
||||
- in: query
|
||||
name: orderLineId
|
||||
schema:
|
||||
type: string
|
||||
example: 9e3363c8-e776-4675-b108-99b8c2e38eb6
|
||||
required: false
|
||||
description: The id of the orderLine
|
||||
get:
|
||||
summary: Find vouchers on the order
|
||||
description: Find vouchers on the order
|
||||
tags:
|
||||
- Order Voucher
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
[
|
||||
{
|
||||
"orderVoucherId": "19ef6882-8eda-43bf-b48e-9b4ff8745a50",
|
||||
"issuedVoucher":{
|
||||
"issuedVoucherId": "54668baf-4905-4e9a-af02-09c170f295ed",
|
||||
"voucherCode": "Voucher124",
|
||||
"purchasedProductId": 35,
|
||||
"fromInclusive": "2025-03-22T08:55:00",
|
||||
"untillInclusive": "2026-03-22T08:55:00"
|
||||
},
|
||||
"orderId": "f59e4769-53a0-4156-8991-6f9119ba629f",
|
||||
"orderLineId": "eeb86071-4f59-405d-b2be-7d7a77044bfa"
|
||||
}
|
||||
]
|
||||
/ordervouchers/{ordervoucherId}:
|
||||
parameters:
|
||||
- in: path
|
||||
name: ordervoucherId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d1dd439b-6072-4b97-89c9-724268865b93
|
||||
required: true
|
||||
description: The id of the order to process.
|
||||
patch:
|
||||
summary: Update an order voucher.
|
||||
description: Update an order voucher.
|
||||
tags:
|
||||
- Order Voucher
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"issuedVoucherId": "eec6af41-1a60-49f6-a92e-440054a92f13",
|
||||
"orderLineId": "7a9d6e15-7c5c-421d-9ea9-00b9bb6dbe67"
|
||||
}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"orderVoucherId": "b9cf0096-4211-4be6-ac21-7bc34bc8e066",
|
||||
}
|
||||
delete:
|
||||
summary: Delete an order voucher.
|
||||
description: Delete an order voucher.
|
||||
tags:
|
||||
- Order Voucher
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{}
|
||||
/orders/{orderId}/orderlines:
|
||||
parameters:
|
||||
- in: path
|
||||
@ -820,7 +960,7 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
examples:
|
||||
Minimum orderline requestBody:
|
||||
value:
|
||||
{
|
||||
@ -906,7 +1046,7 @@ paths:
|
||||
"orderCustomerAddresses":
|
||||
[
|
||||
{
|
||||
"addressTypeId": 3,
|
||||
"addressTypeId": 2,
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -2187,7 +2327,7 @@ paths:
|
||||
{
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"addressType":
|
||||
{ "addressTypeId": 3, "name": "Billing" },
|
||||
{ "addressTypeId": 2, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -2257,7 +2397,7 @@ paths:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"addressTypeId": 3,
|
||||
"addressTypeId": 2,
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -2307,7 +2447,7 @@ paths:
|
||||
type: integer
|
||||
explode: false
|
||||
required: false
|
||||
description: Filter on possible types of addresses. 1 = Shipping, 3 = Billing.
|
||||
description: Filter on possible types of addresses. 1 = Shipping, 2 = Billing.
|
||||
- in: query
|
||||
name: street
|
||||
schema:
|
||||
@ -2363,7 +2503,7 @@ paths:
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"orderCustomerId": "540d8b7a-d626-443f-8f99-c24398604d7a",
|
||||
"orderId": "73cca95a-81d1-468f-a8bf-99b36367001a",
|
||||
"addressType": { "addressTypeId": 3, "name": "Billing" },
|
||||
"addressType": { "addressTypeId": 2, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
234
src/openapi/products/SE-vouchers-TP.yaml
Normal file
234
src/openapi/products/SE-vouchers-TP.yaml
Normal file
@ -0,0 +1,234 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Service Engine APIs for HTM voucher for sales Touchpint
|
||||
description: Service Engine APIs for HTM vouchers. These are NOT the CRUD APIs to the data hub. These ARE the api's for sales touchpoints.
|
||||
version: "1.0"
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/abtvouchersTouchpoint/1.0
|
||||
paths:
|
||||
/issuedvouchers:
|
||||
get:
|
||||
summary: Get a list of issued vouchers that were issued for a specific touch point
|
||||
description:
|
||||
Retrieve all issued vouchers for a specific touch point. This means that only products that have active sellingPeriods for touch points within the same
|
||||
retailer as the calling touch point are returned.
|
||||
parameters:
|
||||
- name: touchpointId
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
This endpoint is meant for salesTouchpoints to check the existance and validity of the voucher a customer has supplied
|
||||
schema:
|
||||
type: integer
|
||||
example: 1001
|
||||
- name: issuedVoucherId
|
||||
in: query
|
||||
required: false
|
||||
description: The unique identifier of the issued voucher instance to retrieve.
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
- name: voucherCode
|
||||
in: query
|
||||
required: false
|
||||
description: The unique code of the issued voucher to retrieve.
|
||||
schema:
|
||||
type: string
|
||||
example: VOUCHER123
|
||||
tags:
|
||||
- Vouchers
|
||||
responses:
|
||||
"200":
|
||||
description: Successful retrieval of voucher instance
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Voucher for a product with required attributes:
|
||||
summary: Voucher for a single product with required attributes
|
||||
value:
|
||||
{
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "VOUCHER123",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "HTM-80001",
|
||||
"productDescription": "10 euro korting op Regiovrij maand.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts":
|
||||
[
|
||||
{
|
||||
"productId": 126,
|
||||
"productName": "HTM-30001",
|
||||
"productDescription": "Regiovrij maand.",
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/126",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/263",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
"mandatoryCustomerDataItems":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"customerDataItem": "padBirthDate"
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"customerDataItem": "emailAddress"
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
Voucher for a whole order:
|
||||
summary: Voucher for a whole order
|
||||
value:
|
||||
{
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "VOUCHER123",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "HTM-80002",
|
||||
"productDescription": "10 euro korting op je gehele winkelmand.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts": [],
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/263",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mandatoryCustomerDataItems": [],
|
||||
],
|
||||
}
|
||||
"403":
|
||||
description: Forbidden
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Access denied due to insufficient permissions:
|
||||
summary: Access denied due to insufficient permissions
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/forbidden",
|
||||
"title": "Access denied",
|
||||
"detail": "You do not have permission to access this resource.",
|
||||
"instance": "/issuedvouchers",
|
||||
}
|
||||
"404":
|
||||
description: Not found
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Voucher not found:
|
||||
summary: Voucher not found
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/not-found",
|
||||
"title": "Voucher not found",
|
||||
"detail": "The voucher with code VOUCHER123 does not exist.",
|
||||
"instance": "/issuedvouchers",
|
||||
}
|
||||
"500":
|
||||
description: Internal server error
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Unexpected server error:
|
||||
summary: Unexpected server error
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/internal-server-error",
|
||||
"title": "Internal Server Error",
|
||||
"detail": "An unexpected error occurred while processing your request.",
|
||||
"instance": "/issuedvouchers",
|
||||
}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerToken:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
unavailable:
|
||||
type: object
|
||||
rfc9457:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
format: url
|
||||
example: https://example.com/probs/out-of-credit
|
||||
title:
|
||||
type: string
|
||||
example: You do not have enough credit.
|
||||
detail:
|
||||
type: string
|
||||
example: Your current balance is 30, but that costs 50.
|
||||
instance:
|
||||
type: string
|
||||
example: /account/12345/msgs/abc
|
||||
balance:
|
||||
type: string
|
||||
example: 30
|
||||
accounts:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- /account/12345
|
||||
- /account/67890
|
||||
617
src/openapi/products/SE-vouchers-supplier.yaml
Normal file
617
src/openapi/products/SE-vouchers-supplier.yaml
Normal file
@ -0,0 +1,617 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Service Engine APIs for HTM voucher suppliers
|
||||
description: Service Engine APIs for HTM vouchers suppliers, this means all instances responsible for supplying vouchers. These are NOT the CRUD APIs to the data hub. These are ALSO NOT the api's for sales touchpoints.
|
||||
version: "1.0"
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/abtvouchers/1.0
|
||||
paths:
|
||||
/voucherdefinitions:
|
||||
get:
|
||||
tags:
|
||||
- Vouchers
|
||||
summary: Get a list of all voucher definitions that a touch point is allowed to issue
|
||||
description: |-
|
||||
Get a list of all voucher definitions that the calling touch point is allowed to issue.
|
||||
Essentially, this means that only products that have active sellingPeriods for touch points within the same
|
||||
retailer as the calling touch point are returned.
|
||||
parameters:
|
||||
- name: touchpointId
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
Filter the voucher definitions on a specific touch point id. This means that only voucher definitions with active selling periods for the specified touch point are returned.
|
||||
This query parameter is only intended for administrative purposes, since the touch point associated with the access token used in the request is used to determine which voucher definitions are returned. This query parameter can be used to retrieve voucher definitions for other touch points within the same retailer, for example to retrieve voucher definitions for a specific sales touch point that is different from the calling touch point.
|
||||
schema:
|
||||
type: integer
|
||||
example: 1001
|
||||
- name: productId
|
||||
in: query
|
||||
required: false
|
||||
description: Filter the voucher definitions on a specific product id.
|
||||
schema:
|
||||
type: integer
|
||||
example: 263
|
||||
- name: requiredProductId
|
||||
in: query
|
||||
required: false
|
||||
description: Filter the voucher definitions on a specific required product id. This means that only voucher definitions that have the specified product id in their requiredProducts list are returned.
|
||||
schema:
|
||||
type: integer
|
||||
example: 126
|
||||
- name: showOnlyActive
|
||||
in: query
|
||||
required: false
|
||||
description: Filter the voucher definitions on active selling periods. If true, only voucher definitions with at least one active selling period are returned. If false, all voucher definitions are returned regardless of their selling periods.
|
||||
schema:
|
||||
type: boolean
|
||||
example: true
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
No products / Empty list:
|
||||
summary: No products / Empty list
|
||||
description: No products
|
||||
value: { "voucherDefinitions": [] }
|
||||
List containing one voucher definition (called by touchpointId 1001):
|
||||
summary: List containing one voucher definition (called by touchpointId 10010011)
|
||||
description: TODO
|
||||
value:
|
||||
{
|
||||
"voucherDefinitions":
|
||||
[
|
||||
{
|
||||
"productId": 1002,
|
||||
"productName": "Korting Ooievaarspas",
|
||||
"productDescription": "Kortingsvoucher voor houders van een Ooievaarspas",
|
||||
"validityPeriod":
|
||||
{
|
||||
"validityPeriodId": 144,
|
||||
"fromInclusive": "2023-12-31T23:00:00.000+00:00",
|
||||
"toInclusive": "2028-11-25T04:00:00.000+00:00",
|
||||
},
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"requiredProducts":
|
||||
[
|
||||
{
|
||||
"productId": 126,
|
||||
"productName": "HTM-30001",
|
||||
"productDescription": "Reis met 20% korting op je betaalpas bij HTM.",
|
||||
},
|
||||
],
|
||||
"mandatoryCustomerDataItems":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"customerDataItem": "padBirthDate",
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"customerDataItem": "emailAddress",
|
||||
},
|
||||
],
|
||||
"imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg",
|
||||
"productPageUrl": "https://www.htm.nl/nog-onbekende-product-pagina",
|
||||
"sellingPeriods":
|
||||
[
|
||||
{
|
||||
"sellingPeriodId": 78,
|
||||
"fromInclusive": "2024-09-30T23:00:00.000+00:00",
|
||||
"toInclusive": "2028-11-17T23:00:00.000+00:00",
|
||||
"salesTouchpoint":
|
||||
{
|
||||
"salesTouchpointId": 1001,
|
||||
"name": "Gemeente Den Haag",
|
||||
"isActive": true,
|
||||
"retailer":
|
||||
{
|
||||
"retailerId": 1001,
|
||||
"name": "Gemeente Den Haag",
|
||||
"street": "Koningin Julianaplein",
|
||||
"number": "10",
|
||||
"numberAddition": null,
|
||||
"postalCode": "2595 AA",
|
||||
"city": "Den Haag",
|
||||
"country": "Nederland",
|
||||
"emailAddress": "info@denhaag.nl",
|
||||
"phoneNumber": "070 374 9002",
|
||||
"taxId": "572309345923",
|
||||
"imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg",
|
||||
},
|
||||
},
|
||||
"forbiddenPaymentMethods": [],
|
||||
"sellingPrices":
|
||||
[
|
||||
{
|
||||
"sellingPriceId": 78,
|
||||
"amountExclTax": null,
|
||||
"amountInclTax": -100,
|
||||
"fromInclusive": "2024-09-30T23:00:00.000+00:00",
|
||||
"toInclusive": "2028-11-17T23:00:00.000+00:00",
|
||||
"internalPrice": 0.0000,
|
||||
"taxCode": "V09",
|
||||
"taxPercentage": 9.0000,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
"403":
|
||||
description: Forbidden
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Access denied due to insufficient permissions:
|
||||
summary: Access denied due to insufficient permissions
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/forbidden",
|
||||
"title": "Access denied",
|
||||
"detail": "You do not have permission to access this resource.",
|
||||
"instance": "/voucherdefinitions",
|
||||
}
|
||||
"404":
|
||||
description: Not found
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Voucher not found:
|
||||
summary: Voucher not found
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/not-found",
|
||||
"title": "Voucher not found",
|
||||
"detail": "The voucher definition does not exist.",
|
||||
"instance": "/voucherdefinitions",
|
||||
}
|
||||
"500":
|
||||
description: Internal server error
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Unexpected server error:
|
||||
summary: Unexpected server error
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/internal-server-error",
|
||||
"title": "Internal Server Error",
|
||||
"detail": "An unexpected error occurred while processing your request.",
|
||||
"instance": "/voucherdefinitions",
|
||||
}
|
||||
/issuedvouchers:
|
||||
get:
|
||||
summary: Get a list of issued vouchers that were issued for a specific touch point
|
||||
description:
|
||||
Retrieve all issued vouchers for a specific touch point. This means that only products that have active sellingPeriods for touch points within the same
|
||||
retailer as the calling touch point are returned.
|
||||
parameters:
|
||||
- name: touchpointId
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
Filter the issued vouchers on a specific touch point id. This means that only issued vouchers for products with active selling periods for the specified touch point are returned.
|
||||
This query parameter is only intended for administrative purposes, since the touch point associated with the access token used in the request is used to determine which issued vouchers are returned. This query parameter can be used to retrieve issued vouchers for other touch points within the same retailer, for example to retrieve issued vouchers for a specific sales touch point that is different from the calling touch point.
|
||||
schema:
|
||||
type: integer
|
||||
example: 1001
|
||||
- name: issuedVoucherId
|
||||
in: query
|
||||
required: false
|
||||
description: The unique identifier of the issued voucher instance to retrieve.
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
- name: voucherCode
|
||||
in: query
|
||||
required: false
|
||||
description: The unique code of the issued voucher to retrieve.
|
||||
schema:
|
||||
type: string
|
||||
example: VOUCHER123
|
||||
- name: productId
|
||||
in: query
|
||||
required: false
|
||||
description: The unique identifier of the product for which to retrieve all issued vouchers.
|
||||
schema:
|
||||
type: integer
|
||||
example: 263
|
||||
- name: highestVoucherStatusId
|
||||
in: query
|
||||
required: false
|
||||
explode: false
|
||||
description: |-
|
||||
The highest voucher status id to filter the issued vouchers on.
|
||||
- 1 = new
|
||||
- 2 = issued
|
||||
- 3 = redeemed
|
||||
- 4 = revoked
|
||||
- 5 = expired
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
example: [1, 2]
|
||||
tags:
|
||||
- Vouchers
|
||||
responses:
|
||||
"200":
|
||||
description: Successful retrieval of voucher instance
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Voucher for a product with required attributes:
|
||||
summary: Voucher for a single product with required attributes
|
||||
value:
|
||||
{
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "VOUCHER123",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "HTM-80001",
|
||||
"productDescription": "10 euro korting op Regiovrij maand.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts":
|
||||
[
|
||||
{
|
||||
"productId": 126,
|
||||
"productName": "HTM-30001",
|
||||
"productDescription": "Regiovrij maand.",
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/126",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/263",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
"claims":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItem":
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"customerDataItem": "padBirthDate",
|
||||
},
|
||||
"value": "1980-06-31",
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItem":
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"customerDataItem": "emailAddress",
|
||||
},
|
||||
"value": "harry@griffindor.co.uk",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
Voucher for a whole order:
|
||||
summary: Voucher for a whole order
|
||||
value:
|
||||
{
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "VOUCHER123",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "HTM-80002",
|
||||
"productDescription": "10 euro korting op je gehele winkelmand.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts": [],
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/263",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"claims": [],
|
||||
],
|
||||
}
|
||||
"403":
|
||||
description: Forbidden
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Access denied due to insufficient permissions:
|
||||
summary: Access denied due to insufficient permissions
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/forbidden",
|
||||
"title": "Access denied",
|
||||
"detail": "You do not have permission to access this resource.",
|
||||
"instance": "/issuedvouchers",
|
||||
}
|
||||
"404":
|
||||
description: Not found
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Voucher not found:
|
||||
summary: Voucher not found
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/not-found",
|
||||
"title": "Voucher not found",
|
||||
"detail": "The voucher with code VOUCHER123 does not exist.",
|
||||
"instance": "/issuedvouchers",
|
||||
}
|
||||
"500":
|
||||
description: Internal server error
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Unexpected server error:
|
||||
summary: Unexpected server error
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/internal-server-error",
|
||||
"title": "Internal Server Error",
|
||||
"detail": "An unexpected error occurred while processing your request.",
|
||||
"instance": "/issuedvouchers",
|
||||
}
|
||||
post:
|
||||
summary: Issue a voucher for a specific product
|
||||
description: |
|
||||
Issue a voucher for a specific product. The voucher will be issued for the touch point that is associated with the access token used in the request.
|
||||
The product for which the voucher should be issued must have active selling periods for touch points within the same retailer as the calling touch point.
|
||||
tags:
|
||||
- Vouchers
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Issue a voucher with prefilled voucher code:
|
||||
summary: Issue a voucher with prefilled voucher code
|
||||
value:
|
||||
{
|
||||
"voucherCode": "VOUCHER123",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"productId": 263,
|
||||
"voucherClaims":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"value": "1970-01-01",
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"value": "stasjo@html.nl",
|
||||
},
|
||||
],
|
||||
}
|
||||
Issue a voucher without prefilled voucher code:
|
||||
summary: Issue a voucher without prefilled voucher code
|
||||
value:
|
||||
{
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"productId": 263,
|
||||
"voucherClaims":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"value": "1970-01-01",
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"value": "stasjo@html.nl",
|
||||
},
|
||||
],
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Successfully issued a voucher:
|
||||
summary: Successfully issued a voucher
|
||||
value:
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "HKV-A7J-128-PYT",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus": { "voucherStatusId": 1, "name": "New" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "HTM-80002",
|
||||
"productDescription": "10 euro korting op je gehele winkelmand.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts": [],
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/263",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
/issuedvouchers/{issuedVoucherId}:
|
||||
parameters:
|
||||
- name: issuedVoucherId
|
||||
in: path
|
||||
required: true
|
||||
description: The unique identifier of the issued voucher instance to update the status for.
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
patch:
|
||||
summary: Update the status of an issued voucher
|
||||
description: Update the status of an issued voucher. This can be used to mark a voucher as redeemed, revoked or expired.
|
||||
tags:
|
||||
- Vouchers
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Mark a voucher as expired:
|
||||
summary: Mark a voucher as expired
|
||||
value:
|
||||
{
|
||||
"voucherStatusId": 5,
|
||||
}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
Successfully updated the status of a voucher:
|
||||
summary: Successfully updated the status of a voucher
|
||||
value:
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "HKV-A7J-128-PYT",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus": { "voucherStatusId": 5, "name": "Expired" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "HTM-80002",
|
||||
"productDescription": "10 euro korting op je gehele winkelmand.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": false,
|
||||
"name": "Voucher",
|
||||
},
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts": [],
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/263",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerToken:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
unavailable:
|
||||
type: object
|
||||
rfc9457:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
format: url
|
||||
example: https://example.com/probs/out-of-credit
|
||||
title:
|
||||
type: string
|
||||
example: You do not have enough credit.
|
||||
detail:
|
||||
type: string
|
||||
example: Your current balance is 30, but that costs 50.
|
||||
instance:
|
||||
type: string
|
||||
example: /account/12345/msgs/abc
|
||||
balance:
|
||||
type: string
|
||||
example: 30
|
||||
accounts:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- /account/12345
|
||||
- /account/67890
|
||||
@ -80,7 +80,11 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
examples:
|
||||
Empty list:
|
||||
value: { "purchasedProducts": [], "href": null }
|
||||
List with multiple purchased products:
|
||||
value:
|
||||
{
|
||||
"purchasedProducts":
|
||||
[
|
||||
@ -94,7 +98,10 @@ paths:
|
||||
{
|
||||
"purchasedProductResourceId": "c7900130-0637-41d7-83fe-6fe283a0a1f1",
|
||||
"resourceName":
|
||||
{ "resourceNameId": 1, "name": "contracts" },
|
||||
{
|
||||
"resourceNameId": 1,
|
||||
"name": "contracts",
|
||||
},
|
||||
"resourceIdentifier": "408eefa9-b393-4bb3-8439-b2e51833abc7",
|
||||
},
|
||||
{
|
||||
@ -124,66 +131,118 @@ paths:
|
||||
"lastUpdatedBy": null,
|
||||
},
|
||||
],
|
||||
"purchasedTapconnectTickets": [],
|
||||
"issuedVouchers": [],
|
||||
},
|
||||
],
|
||||
"href": null,
|
||||
}
|
||||
post:
|
||||
tags:
|
||||
- Purchased Product
|
||||
summary: Create a new purchased product.
|
||||
description: Create a new purchased product.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"productId": 11,
|
||||
"purchasedProductId": "599f1296-ed56-4b90-a518-5c8e917a7dd6",
|
||||
"productId": 12,
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"purchasedProductResources":
|
||||
[
|
||||
{
|
||||
"purchasedProductResourceId": "c7900130-0637-41d7-83fe-6fe283a0a1f1",
|
||||
"resourceName":
|
||||
{
|
||||
"resourceNameId": 1,
|
||||
"name": "contracts",
|
||||
},
|
||||
"resourceIdentifier": "408eefa9-b393-4bb3-8439-b2e51833abc7",
|
||||
},
|
||||
{
|
||||
"resourceNameId": 2,
|
||||
"purchasedProductResourceId": "06dae996-cdfe-45f1-833a-720201c35114",
|
||||
"resourceName":
|
||||
{ "resourceNameId": 2, "name": "orders" },
|
||||
"resourceIdentifier": "f809a6e1-1c8d-4f8e-8a6e-0d0b1e1e1e1e",
|
||||
},
|
||||
],
|
||||
"purchasedGboProducts":
|
||||
"purchasedGboProducts": [],
|
||||
"purchasedTapconnectTickets":
|
||||
[
|
||||
{
|
||||
"salesTimestamp": "2024-10-04T12:34:56.000",
|
||||
"refundTimestamp": "2024-10-04T12:34:56.000",
|
||||
"fromInclusive": "2024-10-04T12:34:56.000",
|
||||
"untilInclusive": "2024-10-04T12:34:56.000",
|
||||
"packageTemplateId": "30003",
|
||||
"xBot": "f15efe6f-7353-4968-b134-60ba6fc2da8b",
|
||||
"xTat": "42efebf7-132e-4ee0-9cbb-4037a9a54ad8",
|
||||
"xSpit": "d67b2f72-918a-4e6c-957d-a39ed9c9e16b",
|
||||
"customerTokenId": "b6492322-c458-4857-9ac3-a109c1887b9f",
|
||||
"ovPayTokenId": 13,
|
||||
"purchasedTapconnectTicketId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"issuedAt": "2024-10-04T12:34:56.000",
|
||||
"activatedAt": "2024-10-04T12:34:56.000",
|
||||
"cancelledAt": null,
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"createdBy": "someuser",
|
||||
"lastUpdatedBy": null,
|
||||
"createdBy": "user",
|
||||
"lastUpdatedBy": "user",
|
||||
},
|
||||
],
|
||||
"issuedVouchers": [],
|
||||
},
|
||||
{
|
||||
"purchasedProductId": "2c97c451-3bd5-467b-8db0-fd3a04fe5bc6",
|
||||
"productId": 12,
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"purchasedProductResources":
|
||||
[
|
||||
{
|
||||
"purchasedProductResourceId": "c7900130-0637-41d7-83fe-6fe283a0a1f1",
|
||||
"resourceName":
|
||||
{
|
||||
"resourceNameId": 1,
|
||||
"name": "contracts",
|
||||
},
|
||||
"resourceIdentifier": "408eefa9-b393-4bb3-8439-b2e51833abc7",
|
||||
},
|
||||
{
|
||||
"purchasedProductResourceId": "06dae996-cdfe-45f1-833a-720201c35114",
|
||||
"resourceName":
|
||||
{ "resourceNameId": 2, "name": "orders" },
|
||||
"resourceIdentifier": "f809a6e1-1c8d-4f8e-8a6e-0d0b1e1e1e1e",
|
||||
},
|
||||
],
|
||||
"purchasedGboProducts": [],
|
||||
"purchasedTapconnectTickets": [],
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6",
|
||||
"voucherCode": "VOUCHER12345",
|
||||
"voucherStatusInstances":
|
||||
[
|
||||
{
|
||||
"voucherStatusInstanceId": "ac8c54d1-79f7-4167-8817-c66b9575d679",
|
||||
"voucherStatus":
|
||||
{
|
||||
"voucherStatusId": 1,
|
||||
"name": "New",
|
||||
},
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
},
|
||||
{
|
||||
"voucherStatusInstanceId": "b01412e6-70fb-4c05-9bef-e65bf2747ca1",
|
||||
"voucherStatus":
|
||||
{
|
||||
"voucherStatusId": 2,
|
||||
"name": "Issued",
|
||||
},
|
||||
"createdOn": "2024-10-04T12:37:14.000",
|
||||
},
|
||||
],
|
||||
"voucherClaims":
|
||||
[
|
||||
{
|
||||
"voucherClaimId": "b1c2d3e4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
|
||||
"mandatoryCustomerDataItem":
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"name": "PadBirthdate",
|
||||
},
|
||||
"value": "1990-01-01",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"href": null,
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{ "purchasedProductId": "a9b3dea5-fb8a-4b1e-9fe6-90cad31c0cfd" }
|
||||
/purchasedproducts/{purchasedProductId}:
|
||||
parameters:
|
||||
- in: path
|
||||
@ -206,7 +265,9 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
examples:
|
||||
Get Purchased GBO Product:
|
||||
value:
|
||||
{
|
||||
"purchasedProductId": "a9b3dea5-fb8a-4b1e-9fe6-90cad31c0cfd",
|
||||
"productId": 14,
|
||||
@ -244,6 +305,102 @@ paths:
|
||||
"lastUpdatedBy": null,
|
||||
},
|
||||
],
|
||||
"purchasedTapconnectTickets": [],
|
||||
"issuedVouchers": [],
|
||||
}
|
||||
Get Purchased Tapconnect Ticket:
|
||||
value:
|
||||
{
|
||||
"purchasedProductId": "a9b3dea5-fb8a-4b1e-9fe6-90cad31c0cfd",
|
||||
"productId": 14,
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"purchasedProductResources":
|
||||
[
|
||||
{
|
||||
"resourceName":
|
||||
{ "resourceNameId": 1, "name": "contracts" },
|
||||
"resourceIdentifier": "408eefa9-b393-4bb3-8439-b2e51833abc7",
|
||||
},
|
||||
{
|
||||
"resourceName":
|
||||
{ "resourceNameId": 2, "name": "orders" },
|
||||
"resourceIdentifier": "f809a6e1-1c8d-4f8e-8a6e-0d0b1e1e1e1e",
|
||||
},
|
||||
],
|
||||
"purchasedGboProducts": [],
|
||||
"purchasedTapconnectTickets":
|
||||
[
|
||||
{
|
||||
"purchasedTapconnectTicketId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"issuedAt": "2024-10-04T12:34:56.000",
|
||||
"activatedAt": "2024-10-04T12:34:56.000",
|
||||
"cancelledAt": null,
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"createdBy": "user",
|
||||
"lastUpdatedBy": "user",
|
||||
},
|
||||
],
|
||||
"issuedVouchers": [],
|
||||
}
|
||||
Get Issued Voucher:
|
||||
value:
|
||||
{
|
||||
"purchasedProductId": "a9b3dea5-fb8a-4b1e-9fe6-90cad31c0cfd",
|
||||
"productId": 14,
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"purchasedProductResources":
|
||||
[
|
||||
{
|
||||
"resourceName":
|
||||
{ "resourceNameId": 1, "name": "contracts" },
|
||||
"resourceIdentifier": "408eefa9-b393-4bb3-8439-b2e51833abc7",
|
||||
},
|
||||
{
|
||||
"resourceName":
|
||||
{ "resourceNameId": 2, "name": "orders" },
|
||||
"resourceIdentifier": "f809a6e1-1c8d-4f8e-8a6e-0d0b1e1e1e1e",
|
||||
},
|
||||
],
|
||||
"purchasedGboProducts": [],
|
||||
"purchasedTapconnectTickets": [],
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "e1f2g3h4-i5j6-k7l8-m9n0-o1p2q3r4s5t6",
|
||||
"voucherCode": "VOUCHER12345",
|
||||
"voucherStatusInstances":
|
||||
[
|
||||
{
|
||||
"voucherStatusInstanceId": "ac8c54d1-79f7-4167-8817-c66b9575d679",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
},
|
||||
{
|
||||
"voucherStatusInstanceId": "b01412e6-70fb-4c05-9bef-e65bf2747ca1",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 2, "name": "Issued" },
|
||||
"createdOn": "2024-10-04T12:37:14.000",
|
||||
},
|
||||
],
|
||||
"voucherClaims":
|
||||
[
|
||||
{
|
||||
"voucherClaimId": "b1c2d3e4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
|
||||
"mandatoryCustomerDataItem":
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"name": "PadBirthdate",
|
||||
},
|
||||
"value": "1990-01-01",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
patch:
|
||||
tags:
|
||||
@ -598,6 +755,420 @@ paths:
|
||||
{
|
||||
"purchasedGboProductId": "a9b3dea5-fb8a-4b1e-9fe6-90cad31c0cfd",
|
||||
}
|
||||
/purchasedproducts/{purchasedProductId}/purchasedTapconnectTicket:
|
||||
parameters:
|
||||
- in: path
|
||||
name: purchasedProductId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 058a1af7-897f-45d5-b691-9cc9161e387f
|
||||
required: true
|
||||
description: The id of the purchased product to process.
|
||||
post:
|
||||
tags:
|
||||
- Purchased Tapconnect Ticket
|
||||
summary: Add a purchased Tapconnect ticket.
|
||||
description: Add a purchased Tapconnect ticket.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"issuedAt": "2024-10-04T12:34:56.000",
|
||||
"activatedAt": "2024-10-04T12:34:56.000",
|
||||
"cancelledAt": null,
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"createdBy": "user",
|
||||
"lastUpdatedBy": "user",
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"purchasedTapconnectTicketId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
}
|
||||
/purchasedtapconnecttickets:
|
||||
get:
|
||||
tags:
|
||||
- Purchased Tapconnect Ticket
|
||||
summary: Find purchased Tapconnect tickets.
|
||||
description: Find purchased Tapconnect tickets.
|
||||
parameters:
|
||||
- in: query
|
||||
name: purchasedTapconnectTicketId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
description: The id of the purchased Tapconnect ticket.
|
||||
- in: query
|
||||
name: purchasedProductId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 058a1af7-897f-45d5-b691-9cc9161e387f
|
||||
description: The id of the purchased product.
|
||||
- in: query
|
||||
name: issuedBefore
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The Tapconnect ticket should be issued before this timestamp.
|
||||
- in: query
|
||||
name: issuedAfter
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The Tapconnect ticket should be issued after this timestamp.
|
||||
- in: query
|
||||
name: activatedBefore
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The Tapconnect ticket should be activated before this timestamp.
|
||||
- in: query
|
||||
name: activatedAfter
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The Tapconnect ticket should be activated after this timestamp.
|
||||
- in: query
|
||||
name: cancelledBefore
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The Tapconnect ticket should be cancelled before this timestamp.
|
||||
- in: query
|
||||
name: cancelledAfter
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The Tapconnect ticket should be cancelled after this timestamp.
|
||||
- in: query
|
||||
name: ticketReference
|
||||
schema:
|
||||
type: string
|
||||
example: KJj43nejhbTxhr897287
|
||||
description: The reference of the Tapconnect ticket.
|
||||
- in: query
|
||||
name: createdBefore
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The purchased Tapconnect ticket should be created before this timestamp.
|
||||
- in: query
|
||||
name: createdAfter
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The purchased Tapconnect ticket should be created after this timestamp.
|
||||
- in: query
|
||||
name: lastUpdatedBefore
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The purchased Tapconnect ticket should be updated before this timestamp.
|
||||
- in: query
|
||||
name: lastUpdatedAfter
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2024-10-04T12:34:56.000
|
||||
description: The purchased Tapconnect ticket should be updated after this timestamp.
|
||||
- in: query
|
||||
name: createdBy
|
||||
schema:
|
||||
type: string
|
||||
example: user
|
||||
description: The user that created the purchased Tapconnect ticket.
|
||||
- in: query
|
||||
name: lastUpdatedBy
|
||||
schema:
|
||||
type: string
|
||||
example: user
|
||||
description: The user that last updated the purchased Tapconnect ticket.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"purchasedTapconnectTickets":
|
||||
[
|
||||
{
|
||||
"purchasedTapconnectTicketId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"purchasedProductId": "058a1af7-897f-45d5-b691-9cc9161e387f",
|
||||
"issuedAt": "2024-10-04T12:34:56.000",
|
||||
"activatedAt": "2024-10-04T12:34:56.000",
|
||||
"cancelledAt": null,
|
||||
"ticketReference": "KJj43nejhbTxhr897287",
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-04T12:34:56.000",
|
||||
"createdBy": "user",
|
||||
"lastUpdatedBy": "user",
|
||||
},
|
||||
],
|
||||
}
|
||||
/purchasedtapconnecttickets/{purchasedTapconnectTicketId}:
|
||||
parameters:
|
||||
- in: path
|
||||
name: purchasedTapconnectTicketId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
required: true
|
||||
description: The id of the purchased Tapconnect ticket to process.
|
||||
patch:
|
||||
tags:
|
||||
- Purchased Tapconnect Ticket
|
||||
summary: Update a purchased Tapconnect ticket.
|
||||
description: Update a purchased Tapconnect ticket.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"activatedAt": "2024-10-05T12:34:56.000",
|
||||
"cancelledAt": "2024-10-06T12:34:56.000",
|
||||
"lastUpdatedOn": "2024-10-05T12:34:56.000",
|
||||
}
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"purchasedTapconnectTicketId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
}
|
||||
/purchasedproducts/{purchasedProductId}/issuedvouchers:
|
||||
parameters:
|
||||
- in: path
|
||||
name: purchasedProductId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 058a1af7-897f-45d5-b691-9cc9161e387f
|
||||
required: true
|
||||
description: The id of the purchased product to process.
|
||||
post:
|
||||
tags:
|
||||
- Issued Voucher
|
||||
summary: Add an issued voucher.
|
||||
description: Add an issued voucher.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"voucherCode": "VOUCHER123",
|
||||
"voucherStatusInstances":
|
||||
[
|
||||
{
|
||||
"voucherStatusId": 1,
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
},
|
||||
],
|
||||
"voucherClaims":
|
||||
[
|
||||
{ "mandatoryCustomerDataItemId": 8, "value": "1999-12-31" },
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"value": "vlad.harkonnen@househarkonnen.net",
|
||||
},
|
||||
],
|
||||
"fromInclusive": "2024-10-04T12:34:56.000",
|
||||
"untilInclusive": "2025-10-04T12:34:56.000",
|
||||
}
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{ "issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90" }
|
||||
/issuedvouchers:
|
||||
get:
|
||||
tags:
|
||||
- Issued Voucher
|
||||
summary: Find issued vouchers.
|
||||
description: Find issued vouchers.
|
||||
parameters:
|
||||
- in: query
|
||||
name: issuedVoucherId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
description: The id of the issued voucher.
|
||||
- in: query
|
||||
name: purchasedProductId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 058a1af7-897f-45d5-b691-9cc9161e387f
|
||||
description: The id of the purchased product.
|
||||
- in: query
|
||||
name: voucherCode
|
||||
schema:
|
||||
type: string
|
||||
example: VOUCHER123
|
||||
description: The code of the voucher.
|
||||
- in: query
|
||||
name: voucherStatusId
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
explode: false
|
||||
required: false
|
||||
description: The moest recent status id of the voucher.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"issuedVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"purchasedProductId": "058a1af7-897f-45d5-b691-9cc9161e387f",
|
||||
"voucherCode": "VOUCHER123",
|
||||
"voucherStatusInstances":
|
||||
[
|
||||
{
|
||||
"voucherStatusInstanceId": "ac8c54d1-79f7-4167-8817-c66b9575d679",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
"createdOn": "2024-10-04T12:34:56.000",
|
||||
},
|
||||
{
|
||||
"voucherStatusInstanceId": "b01412e6-70fb-4c05-9bef-e65bf2747ca1",
|
||||
"voucherStatus":
|
||||
{ "voucherStatusId": 2, "name": "Issued" },
|
||||
"createdOn": "2024-10-04T12:37:14.000",
|
||||
},
|
||||
],
|
||||
"voucherClaims":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItem":
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"customerDataItem": "padBirthDate",
|
||||
},
|
||||
"value": "1999-12-31",
|
||||
},
|
||||
{
|
||||
"mandatoryCustomerDataItem":
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 4,
|
||||
"customerDataItem": "emailAddress",
|
||||
},
|
||||
"value": "vlad.harkonnen@househarkonnen.net",
|
||||
},
|
||||
],
|
||||
"fromInclusive": "2024-10-04T12:34:56.000",
|
||||
"untilInclusive": "2025-10-04T12:34:56.000",
|
||||
},
|
||||
],
|
||||
}
|
||||
/issuedvouchers/{issuedVoucherId}/voucherstatusinstances:
|
||||
parameters:
|
||||
- in: path
|
||||
name: issuedVoucherId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90
|
||||
required: true
|
||||
description: The id of the issued voucher to process.
|
||||
post:
|
||||
tags:
|
||||
- Issued Voucher
|
||||
summary: Update the status of an issued voucher.
|
||||
description: Update the status of an issued voucher.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{ "voucherStatusId": 2, "createdOn": "2024-10-04T12:34:56.000" }
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"voucherStatusInstanceId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
}
|
||||
/voucherstatuses:
|
||||
get:
|
||||
tags:
|
||||
- References
|
||||
summary: Get voucher statuses.
|
||||
description: Get voucher statuses.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"voucherStatuses":
|
||||
[
|
||||
{ "voucherStatusId": 1, "name": "New" },
|
||||
{ "voucherStatusId": 2, "name": "Issued" },
|
||||
{ "voucherStatusId": 3, "name": "Redeemed" },
|
||||
{ "voucherStatusId": 4, "name": "Revoked" },
|
||||
{ "voucherStatusId": 5, "name": "Expired" },
|
||||
],
|
||||
}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerToken:
|
||||
@ -607,6 +1178,56 @@ components:
|
||||
schemas:
|
||||
unavailable:
|
||||
type: object
|
||||
BulkResponseBody:
|
||||
type: object
|
||||
properties:
|
||||
startTime:
|
||||
type: string
|
||||
format: date-time
|
||||
example: 2025-02-14T05:32:47.0672237Z
|
||||
status:
|
||||
type: string
|
||||
example: Running
|
||||
clientTrackingId:
|
||||
type: string
|
||||
example: 08584620957189579629541919368CU00
|
||||
callbackurl:
|
||||
type: string
|
||||
format: uri
|
||||
example: https://services.api.htm.nl/purchasedproducts/responsestatus/runtime/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
retryAfter:
|
||||
type: integer
|
||||
example: 10
|
||||
summary:
|
||||
$ref: "#/components/schemas/summaryBody"
|
||||
required:
|
||||
- startTime
|
||||
- status
|
||||
- clientTrackingId
|
||||
- callbackurl
|
||||
- retryAfter
|
||||
- summary
|
||||
summaryBody:
|
||||
type: object
|
||||
properties:
|
||||
summary:
|
||||
type: object
|
||||
properties:
|
||||
created:
|
||||
type: integer
|
||||
example: 15
|
||||
updated:
|
||||
type: integer
|
||||
example: 2
|
||||
total:
|
||||
type: integer
|
||||
example: 17
|
||||
required:
|
||||
- created
|
||||
- total
|
||||
- updated
|
||||
required:
|
||||
- summary
|
||||
rfc9457:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
477
src/openapi/tapconnect/tapconnect.yaml
Normal file
477
src/openapi/tapconnect/tapconnect.yaml
Normal file
@ -0,0 +1,477 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: TapConnect
|
||||
description: >-
|
||||
Welcome to the TapConnect Issuing API documentation. These pages describe the endpoints available within TapConnect. Please note that for historical reasons, Date/times are always in the "Europe/Amsterdam" timezone. The endpoints in this document are grouped as follows:
|
||||
|
||||
- **Export endpoints**: Export related endpoints return information about events related to tickets that have been issued. This can be used for Business Intelligence purposes or for financial record keeping.
|
||||
- **Product endpoints**: Product related endpoints return information about products that are available to you as a sales partner and the details of each of these products.
|
||||
- **Ticket endpoints**: Ticket related endpoints allow you to manage tickets throughout their lifecycle. This includes ticket creation, retrieving ticket information, or retrieving the barcode for a ticket.
|
||||
- **Journey endpoints**: Used to calculate the price of a journey and to issue a ticket for that journey using the external fare calculation engine.
|
||||
|
||||
For more information on TapConnect please visit [https://tapconnect.io](https://tapconnect.io) or [https://documentation.tapconnect.io](https://documentation.tapconnect.io).
|
||||
version: '1.0'
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/tapconnect/1.0
|
||||
tags:
|
||||
- name: Export
|
||||
description: >-
|
||||
Export data that can be used to generate reports about issued tickets
|
||||
and related information
|
||||
paths:
|
||||
/v5/ticket-events-export:
|
||||
get:
|
||||
summary: Elastic Search ticket events export
|
||||
description: "Exports ticket events data from Elastic Search.\n\nBoth parameters\
|
||||
\ are a string, and they have to represent a date. Consider the list of valid\
|
||||
\ formats below:\n1. 2021 - searches for all events in a year\n2. 2021-02\
|
||||
\ - searches for all events in a month\n3. 2021-02-02 - searches for all events\
|
||||
\ in a day\n4. 2021-02-02T12 - searches for all events in a specific hour\n\
|
||||
5. 2021-02-02T12:00 - searches for all events in a specific minute\n6. 2021-02-02T12:00:00\
|
||||
\ - searches for all events in a specific second\n\nIf an error occur, the\
|
||||
\ last element returned will be a message with \"An error occurred on Elasticsearch\"\
|
||||
\ and it \nmeans that not all the results are returned.\n_Keep in mind that\
|
||||
\ the above timestamps would also be accepted as Zulu: 2021-02-02T11:00:00Z\
|
||||
\ (winter time)_\n"
|
||||
parameters:
|
||||
- explode: true
|
||||
in: query
|
||||
name: start
|
||||
required: true
|
||||
description: The date to be considered as the interval starting date
|
||||
schema:
|
||||
example: 2021-02-01T00:00:00
|
||||
type: string
|
||||
style: form
|
||||
- explode: true
|
||||
in: query
|
||||
name: end
|
||||
required: true
|
||||
description: The date to be considered as the interval ending date
|
||||
schema:
|
||||
example: 2021-02-02T00:00:00
|
||||
type: string
|
||||
style: form
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/v5_ticket_events_export_response'
|
||||
description: Returns a JSON chunked array of ticket events exported from elastic search.
|
||||
"400":
|
||||
description: |
|
||||
The request could not be validated. The request body or parameters contain incomplete or incorrect parameters. The body of the response will contain information about the problem.
|
||||
"401":
|
||||
description: |
|
||||
Unauthorized call, you are not authorized to call this endpoint with the api key provided in the Authorization header. Please verify that your api key is correct and/or if you are authorized to call this endpoint.
|
||||
"403":
|
||||
description: |
|
||||
Unauthorized call, you are not authorized to call this endpoint with the api key provided in the Authorization header. Please verify that your api key is correct and/or if you are authorized to call this endpoint.
|
||||
"404":
|
||||
description: |
|
||||
The requested URL does not exist, or the requested object was not found.
|
||||
"406":
|
||||
description: |
|
||||
The request was not accepted by the server. The body of the response will contain information about the problem.
|
||||
tags:
|
||||
- Export
|
||||
components:
|
||||
schemas:
|
||||
v5_ticket_events_export_response:
|
||||
type: array
|
||||
items:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/ActivateTicketEvent'
|
||||
- $ref: '#/components/schemas/CreateBarcodeEvent'
|
||||
- $ref: '#/components/schemas/CreateTicketEvent'
|
||||
- $ref: '#/components/schemas/TapEvent'
|
||||
- $ref: '#/components/schemas/InspectTicketEvent'
|
||||
- $ref: '#/components/schemas/NotifyEvent'
|
||||
ActivateTicketEvent:
|
||||
properties:
|
||||
eventId:
|
||||
example: 1
|
||||
type: number
|
||||
eventType:
|
||||
example: ACTIVATE_TICKET
|
||||
type: string
|
||||
occurredAt:
|
||||
example: 2021-06-07T08:42:00.791992000Z
|
||||
type: string
|
||||
receivedAt:
|
||||
example: 2021-06-07T08:42:00.791992000Z
|
||||
type: string
|
||||
timeToDie:
|
||||
example: 2445836980
|
||||
type: number
|
||||
operators:
|
||||
items:
|
||||
example: HTM
|
||||
type: string
|
||||
type: array
|
||||
createdBy:
|
||||
example: HTM
|
||||
type: string
|
||||
definedBy:
|
||||
example: HTM
|
||||
type: string
|
||||
ticketId:
|
||||
example: hkbu3415fbidswd803nfdg7
|
||||
type: string
|
||||
validityStart:
|
||||
example: 2021-06-06T22:00:00.000000000Z
|
||||
type: string
|
||||
validityEnd:
|
||||
example: 2021-06-07T23:40:00.000000000Z
|
||||
type: string
|
||||
validityType:
|
||||
example: FIXED
|
||||
type: string
|
||||
CreateBarcodeEvent:
|
||||
properties:
|
||||
eventId:
|
||||
example: 2
|
||||
type: number
|
||||
eventType:
|
||||
example: CREATE_BARCODE
|
||||
type: string
|
||||
occurredAt:
|
||||
example: 2021-06-07T08:42:01.629279000Z
|
||||
type: string
|
||||
receivedAt:
|
||||
example: 2021-06-07T08:42:01.629279000Z
|
||||
type: string
|
||||
timeToDie:
|
||||
example: 2445836980
|
||||
type: number
|
||||
operators:
|
||||
items:
|
||||
example: HTM
|
||||
type: string
|
||||
type: array
|
||||
createdBy:
|
||||
example: HTM
|
||||
type: string
|
||||
definedBy:
|
||||
example: HTM
|
||||
type: string
|
||||
ticketId:
|
||||
example: 2huCpR99LHjGfiq8ZJoF
|
||||
type: string
|
||||
barcodeSignatureKeyId:
|
||||
example: TCT07
|
||||
type: string
|
||||
barcodeValidityStart:
|
||||
example: 2021-06-06T22:00:00.000000000Z
|
||||
type: string
|
||||
barcodeValidityEnd:
|
||||
example: 2021-06-07T23:40:00.000000000Z
|
||||
type: string
|
||||
CreateTicketEvent:
|
||||
properties:
|
||||
eventId:
|
||||
example: 0
|
||||
type: number
|
||||
eventType:
|
||||
example: CREATE_TICKET
|
||||
type: string
|
||||
occurredAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
receivedAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
reportedAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
timeToDie:
|
||||
example: 2445836980
|
||||
type: number
|
||||
operators:
|
||||
items:
|
||||
example: HTM
|
||||
type: string
|
||||
type: array
|
||||
createdBy:
|
||||
example: HTM
|
||||
type: string
|
||||
definedBy:
|
||||
example: HTM
|
||||
type: string
|
||||
ticketId:
|
||||
example: 344BEuHcFkEChOPm06sY
|
||||
type: string
|
||||
serviceId:
|
||||
example: HTM-0987-7477-0993
|
||||
type: string
|
||||
productName:
|
||||
example: HTM Kinder Dagkaart
|
||||
type: string
|
||||
productCode:
|
||||
example: "303"
|
||||
type: string
|
||||
productValidityPeriodUnit:
|
||||
example: "DAYS"
|
||||
type: string
|
||||
productValidityPeriod:
|
||||
example: 1
|
||||
type: number
|
||||
lifespanStart:
|
||||
example: 2021-06-07
|
||||
type: string
|
||||
lifespanEnd:
|
||||
example: 2021-06-08
|
||||
type: string
|
||||
language:
|
||||
example: NL
|
||||
type: string
|
||||
salesChannelId:
|
||||
example: "9999"
|
||||
type: string
|
||||
salesChannelName:
|
||||
example: HTM App
|
||||
type: string
|
||||
startStation:
|
||||
example: Haarlem
|
||||
type: string
|
||||
endStation:
|
||||
example: Leiden Centraal
|
||||
type: string
|
||||
barcodeType:
|
||||
example: UIC
|
||||
type: string
|
||||
validityType:
|
||||
example: FIXED
|
||||
type: string
|
||||
refundable:
|
||||
example: true
|
||||
type: boolean
|
||||
priceInCents:
|
||||
example: 150,
|
||||
type: number
|
||||
numberOfAdults:
|
||||
example: 1
|
||||
type: number
|
||||
numberOfChildren:
|
||||
example: 0
|
||||
type: number
|
||||
roundToBusinessDay:
|
||||
example: true
|
||||
type: boolean
|
||||
modalities:
|
||||
example: ["BUS", "TRAM"]
|
||||
type: array
|
||||
items:
|
||||
example: BUS
|
||||
type: string
|
||||
TapEvent:
|
||||
properties:
|
||||
eventId:
|
||||
example: 5
|
||||
type: number
|
||||
eventType:
|
||||
example: TAP
|
||||
type: string
|
||||
occurredAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
receivedAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
timeToDie:
|
||||
example: 2445836980
|
||||
type: number
|
||||
validationAction:
|
||||
example: CHECK_OUT
|
||||
type: string
|
||||
validationResult:
|
||||
example: Approved
|
||||
type: string
|
||||
tapId:
|
||||
example: a9aea0ae-52de-42cd-a2f1-93b80d9af389
|
||||
type: string
|
||||
operators:
|
||||
items:
|
||||
example: HTM
|
||||
type: string
|
||||
type: array
|
||||
createdBy:
|
||||
example: HTM
|
||||
type: string
|
||||
definedBy:
|
||||
example: HTM
|
||||
type: string
|
||||
ticketId:
|
||||
example: hkbu3415fbidswd803nfdg7
|
||||
type: string
|
||||
modality:
|
||||
example: BUS
|
||||
type: string
|
||||
line:
|
||||
example: "25"
|
||||
type: string
|
||||
trip:
|
||||
example: "240"
|
||||
type: string
|
||||
vehicle:
|
||||
example: "1512"
|
||||
type: string
|
||||
deviceId:
|
||||
example: "13513A"
|
||||
type: string
|
||||
deviceType:
|
||||
example: VBS
|
||||
type: string
|
||||
lastStopId:
|
||||
example: "3409"
|
||||
type: string
|
||||
lastStopName:
|
||||
example: Gramsbergenlaan
|
||||
type: string
|
||||
nextStopId:
|
||||
example: "3409"
|
||||
type: string
|
||||
nextStopName:
|
||||
example: Gramsbergenlaan
|
||||
type: string
|
||||
location:
|
||||
type: object
|
||||
properties:
|
||||
lat:
|
||||
example: 52.00089453333333
|
||||
type: number
|
||||
lon:
|
||||
example: 4.004570666666667
|
||||
type: number
|
||||
InspectTicketEvent:
|
||||
properties:
|
||||
eventId:
|
||||
example: 3
|
||||
type: number
|
||||
eventType:
|
||||
example: INSPECT_TICKET
|
||||
type: string
|
||||
occurredAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
receivedAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
timeToDie:
|
||||
example: 2445836980
|
||||
type: number
|
||||
operators:
|
||||
items:
|
||||
example: HTM
|
||||
type: string
|
||||
type: array
|
||||
createdBy:
|
||||
example: HTM
|
||||
type: string
|
||||
definedBy:
|
||||
example: HTM
|
||||
type: string
|
||||
ticketId:
|
||||
example: uv1hzvrRd7Xd1Fs9vTxi
|
||||
type: string
|
||||
modality:
|
||||
example: BUS
|
||||
type: string
|
||||
deviceId:
|
||||
example: 6959bd00eaec8e68
|
||||
type: string
|
||||
deviceType:
|
||||
example: IBS
|
||||
type: string
|
||||
validationResult:
|
||||
example: Approved
|
||||
type: string
|
||||
NotifyEvent:
|
||||
properties:
|
||||
eventId:
|
||||
example: 1185
|
||||
type: number
|
||||
eventType:
|
||||
example: NOTIFY
|
||||
type: string
|
||||
occurredAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
receivedAt:
|
||||
example: 2021-06-07T08:42:00.790992000Z
|
||||
type: string
|
||||
timeToDie:
|
||||
example: 2445836980
|
||||
type: number
|
||||
tapId:
|
||||
example: a9aea0ae-52de-42cd-a2f1-93b80d9af389
|
||||
type: string
|
||||
sequence:
|
||||
example: 2
|
||||
type: number
|
||||
tapResponseTimeMillis:
|
||||
example: 402
|
||||
type: number
|
||||
validationAction:
|
||||
example: CHECK_OUT
|
||||
type: string
|
||||
validationMethod:
|
||||
example: ONLINE
|
||||
type: string
|
||||
validationResult:
|
||||
example: Approved
|
||||
type: string
|
||||
operators:
|
||||
items:
|
||||
example: HTM
|
||||
type: string
|
||||
type: array
|
||||
createdBy:
|
||||
example: HTM
|
||||
type: string
|
||||
definedBy:
|
||||
example: HTM
|
||||
type: string
|
||||
modality:
|
||||
example: TRAM
|
||||
type: string
|
||||
line:
|
||||
example: "3"
|
||||
type: string
|
||||
trip:
|
||||
example: "692"
|
||||
type: string
|
||||
vehicle:
|
||||
example: "4058"
|
||||
type: string
|
||||
deviceId:
|
||||
example: "13A886"
|
||||
type: string
|
||||
deviceType:
|
||||
example: VBS
|
||||
type: string
|
||||
lastStopId:
|
||||
example: "2005"
|
||||
type: string
|
||||
lastStopName:
|
||||
example: Fahrenheitstraat
|
||||
type: string
|
||||
nextStopId:
|
||||
example: "2011"
|
||||
type: string
|
||||
nextStopName:
|
||||
example: Valkenbosplein
|
||||
type: string
|
||||
ticketId:
|
||||
example: hkbu3415fbidswd803nfdg7
|
||||
type: string
|
||||
location:
|
||||
type: object
|
||||
properties:
|
||||
lat:
|
||||
example: 52.001300283333336
|
||||
type: number
|
||||
lon:
|
||||
example: 4.004586633333333
|
||||
type: number
|
||||
Loading…
Reference in New Issue
Block a user