Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e87a21d5f8 |
@ -1,614 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1,124 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
<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>
|
||||
@ -1,250 +0,0 @@
|
||||
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();
|
||||
@ -1,38 +0,0 @@
|
||||
// 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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class DeletePersonalDataResponse
|
||||
{
|
||||
public DeletePersonalDataResponse(string[] deletedAttributes)
|
||||
{
|
||||
this.deletedAttributes = deletedAttributes;
|
||||
}
|
||||
|
||||
[JsonPropertyName("deletedAttributes")]
|
||||
public string[] deletedAttributes { get; set; }
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class OtpResponse
|
||||
{
|
||||
public OtpResponse(string maskedEmailAddress)
|
||||
{
|
||||
this.maskedEmailAddress = maskedEmailAddress;
|
||||
}
|
||||
|
||||
[JsonPropertyName("maskedEmailAddress")]
|
||||
public string maskedEmailAddress { get; set; }
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class UserAccessToken
|
||||
{
|
||||
public UserAccessToken(string accessToken)
|
||||
{
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
[JsonPropertyName("accessToken")]
|
||||
public string accessToken { get; set; }
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
public class UserAuthInfo
|
||||
{
|
||||
public string? UserAccessToken { get; set; }
|
||||
public string? ephemeralKeyAlias { get; set; }
|
||||
public string? encryptedEphemeralKey { get; set; }
|
||||
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="temurin-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
@ -1,9 +1,7 @@
|
||||
# ABTProducts PUT request body generator
|
||||
Simple tool to quickly edit HTM products via ABTProducts REST API.
|
||||
|
||||
- Requires JRE 17
|
||||
|
||||
## Generating a PUT output (that you need to supply to PUT API yourself):
|
||||
- Requires JRE 21
|
||||
- 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)
|
||||
@ -12,14 +10,3 @@ 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>17</source>
|
||||
<target>17</target>
|
||||
<source>21</source>
|
||||
<target>21</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@ -3,11 +3,8 @@ 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;
|
||||
@ -22,15 +19,6 @@ 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>");
|
||||
}
|
||||
@ -52,49 +40,6 @@ 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()) {
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
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,33 +1,23 @@
|
||||
{
|
||||
"productId": 663,
|
||||
"parentProductId": null,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 7,
|
||||
"choiceKey": "isRenewable",
|
||||
"choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn",
|
||||
"isCustomChoice": false
|
||||
},
|
||||
"productId": 251,
|
||||
"fikoArticleNumber": null,
|
||||
"gboPackageTemplateId": "30001",
|
||||
"parentProductId": null,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"tapConnectProductCode": 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": [],
|
||||
"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,
|
||||
"productOwner": {
|
||||
"productOwnerId": 1,
|
||||
"name": "Wie dit leest",
|
||||
"organization": "... is een aap."
|
||||
"name": "Corneel Verstoep",
|
||||
"organization": "HTM"
|
||||
},
|
||||
"marketSegments": [],
|
||||
"customerSegments": [],
|
||||
"marketSegments": null,
|
||||
"customerSegments": null,
|
||||
"allowedGboAgeProfiles": null,
|
||||
"productCategory": {
|
||||
"productCategoryId": 1,
|
||||
"productCategoryId": 9,
|
||||
"isTravelProduct": true,
|
||||
"name": "Kortingsabonnement"
|
||||
},
|
||||
@ -35,10 +25,32 @@
|
||||
"requiredCustomerLevelId": 1,
|
||||
"name": "guest"
|
||||
},
|
||||
"requiredProducts": [],
|
||||
"incompatibleProducts": [],
|
||||
"mandatoryCustomerDataItems": [],
|
||||
"requiredGboPersonalAttributes": [],
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"tokenTypes": [
|
||||
{
|
||||
"tokenTypeId": 1,
|
||||
@ -49,36 +61,72 @@
|
||||
"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": null,
|
||||
"serviceOptions": null,
|
||||
"validityDuration": "P7D",
|
||||
"maxStartInFutureDuration": "P6W",
|
||||
"isRenewable": false,
|
||||
"sendInvoice": false,
|
||||
"imageReference": null,
|
||||
"productPageUrl": null,
|
||||
"termsUrl": null,
|
||||
"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",
|
||||
"isSellableAtHtm": true,
|
||||
"needsSolvencyCheckConsumer": false,
|
||||
"needsSolvencyCheckBusiness": false,
|
||||
"sellingPeriods": [
|
||||
{
|
||||
"sellingPeriodId": 1382,
|
||||
"fromInclusive": "2025-12-31T23:00:00.000Z",
|
||||
"toInclusive": "2026-03-30T22:00:00.000Z",
|
||||
"sellingPeriodId": 240,
|
||||
"fromInclusive": "2024-09-06T00:00:00.000+00:00",
|
||||
"toInclusive": "2024-12-29T23:59:59.000+00:00",
|
||||
"salesTouchpoint": {
|
||||
"salesTouchpointId": 3,
|
||||
"name": "Website",
|
||||
"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)",
|
||||
"isActive": true,
|
||||
"retailer": {
|
||||
"retailerId": 1001,
|
||||
@ -91,196 +139,64 @@
|
||||
"country": "Nederland",
|
||||
"emailAddress": "info@htm.nl",
|
||||
"phoneNumber": "070 374 9002",
|
||||
"taxId": 572309345923,
|
||||
"imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg"
|
||||
"taxId": null,
|
||||
"imageReference": "https://www.htm.nl/typo3conf/ext/htm_template/Resources/Public/img/logo.svg"
|
||||
}
|
||||
},
|
||||
"forbiddenPaymentMethods": [],
|
||||
"sellingPrices": []
|
||||
"forbiddenPaymentMethods": [
|
||||
{
|
||||
"forbiddenPaymentMethodId": 2,
|
||||
"name": "creditcard",
|
||||
"issuer": "Visa"
|
||||
}
|
||||
],
|
||||
"sellingPrices": [
|
||||
{
|
||||
"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
|
||||
},
|
||||
{
|
||||
"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": [],
|
||||
"productVariants": [
|
||||
"purchasePrices": [
|
||||
{
|
||||
"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)"
|
||||
},
|
||||
{
|
||||
"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": []
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"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": []
|
||||
"auditTrailId": 227,
|
||||
"action": "insert",
|
||||
"user": "api",
|
||||
"timestamp": "2024-10-21T08:58:39.237+00:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -28,33 +28,10 @@ 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());
|
||||
@ -71,7 +48,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 + " and alertId " + alertId + ": \n" + new JSONObject(response).toString(2));
|
||||
LOGGER.info("GBO API 8851 alert details response for xBOT " + xBot + ": \n" + new JSONObject(response).toString(2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,28 +16,14 @@ 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(USER_NAME);
|
||||
factory.setPassword(PASSWORD);
|
||||
factory.setUsername("BEID_3_ALERTS_nZs3");
|
||||
factory.setPassword("VyubhPnczKgTB2zJ");
|
||||
factory.useSslProtocol("TLSv1.2");
|
||||
factory.setExceptionHandler(new ForgivingExceptionHandler());
|
||||
Map<String, Object> configs = factory.getClientProperties();
|
||||
@ -47,7 +33,7 @@ public class RabbitConnector {
|
||||
Channel channel = connection.createChannel();
|
||||
DeliverCallback deliverCallback = initDeliverCallback(channel);
|
||||
|
||||
AMQP.Queue.DeclareOk queue = channel.queueDeclarePassive(QUEUE_NAME);
|
||||
AMQP.Queue.DeclareOk queue = channel.queueDeclarePassive("BEID_3.ALERTS");
|
||||
LOGGER.info(
|
||||
"Declared queue: " + queue.getQueue() + ", consumer count: " + queue.getConsumerCount() + ", message count: " +
|
||||
queue.getMessageCount());
|
||||
@ -66,39 +52,17 @@ public class RabbitConnector {
|
||||
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
|
||||
LOGGER.info("Successfully acknowledged message with delivery tag: " + delivery.getEnvelope().getDeliveryTag());
|
||||
|
||||
if (QUEUE_NAME.equals("BEID_3.TRIPS")) {
|
||||
getTripDetails(message);
|
||||
} else if (QUEUE_NAME.equals("BEID_3.ALERTS")) {
|
||||
getAlertDetails(message);
|
||||
LOGGER.info("Getting alert details via GBO API 8851...");
|
||||
try {
|
||||
String alertId = Helpers.getAlertId(message);
|
||||
String xBot = Helpers.getXbot(message);
|
||||
String gboBearerToken = Helpers.getGboBearerToken();
|
||||
|
||||
Helpers.getAlertDetails(alertId, xBot, gboBearerToken);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,10 +17,10 @@ paths:
|
||||
description: >
|
||||
Create a claim by sending a JSON as specified in the schema. By
|
||||
specifying the chipcardnumber under 'chipkaart',
|
||||
a claim for OV chipcard will be sent to the OVC API. If no
|
||||
chipcardnumber is specified under 'chipkaart', a claim for EMV/OV-pas is sent
|
||||
to Mendix, where it can be handled according to the fields present
|
||||
(serviceRefId + totaalbedrag or ovPasNumber + verificationCode)
|
||||
|
||||
a claim for OV chipcard will be send to the OVC API. If no
|
||||
chipcardnumber is specified under 'chipkaart', a claim for EMV is send
|
||||
to mendix.
|
||||
parameters: []
|
||||
requestBody:
|
||||
content:
|
||||
@ -47,6 +47,8 @@ paths:
|
||||
toelichting: string
|
||||
lijn: '1'
|
||||
vervoertype: '1'
|
||||
serviceRefId: '1'
|
||||
Totaalbedrag: 0
|
||||
EMV:
|
||||
value:
|
||||
aankomsthalte: '1'
|
||||
@ -65,28 +67,8 @@ paths:
|
||||
toelichting: string
|
||||
lijn: '1'
|
||||
vervoertype: '1'
|
||||
serviceRefId: 'NLOV1234567ABCDEFG'
|
||||
totaalbedrag: 3.14
|
||||
OV-pas:
|
||||
value:
|
||||
aankomsthalte: '1'
|
||||
instapdatum: '2024-03-06T15:20:44.549Z'
|
||||
instaptijd: '2024-03-06T15:20:44.549Z'
|
||||
ingecheckt: true
|
||||
uitgecheckt: true
|
||||
afgeschrevenbedrag: 0
|
||||
vertrekhalte: string
|
||||
korting: true
|
||||
iban: '1234123412341234'
|
||||
naam: string
|
||||
emailadres: user@example.com
|
||||
uitstaptijd: '2024-03-06T15:20:44.549Z'
|
||||
verwachtbedrag: 0
|
||||
toelichting: string
|
||||
lijn: '1'
|
||||
vervoertype: '1'
|
||||
ovPasNumber: '63AW974'
|
||||
verificationCode: '2FQ8'
|
||||
serviceRefId: '1'
|
||||
Totaalbedrag: 0
|
||||
responses:
|
||||
'200':
|
||||
description: ok
|
||||
@ -121,19 +103,18 @@ paths:
|
||||
examples:
|
||||
EMV:
|
||||
value:
|
||||
emailAddress: 'stasjo@htm.nl'
|
||||
emailAddress: 'j.beek@htm.nl'
|
||||
orderNumber: 'ORD1000046'
|
||||
serviceReferenceId: 'NLOVA5BCD124H3Z21X'
|
||||
amount: 2305
|
||||
iban: 'NL98INGB0003856625'
|
||||
orderDate: '2025-01-13'
|
||||
productName: 'HTM 20% korting'
|
||||
OV-pas:
|
||||
OVpas:
|
||||
value:
|
||||
emailAddress: 'stasjo@htm.nl'
|
||||
emailAddress: 'j.beek@htm.nl'
|
||||
orderNumber: 'ORD1000046'
|
||||
ovpasNumber: '63AW974'
|
||||
verificationCode: '2FQ8'
|
||||
iban: 'NL98INGB0003856625'
|
||||
orderDate: '2025-01-13'
|
||||
productName: 'HTM 20% korting'
|
||||
@ -200,7 +181,7 @@ components:
|
||||
iban:
|
||||
type: string
|
||||
description: String of length between 15 en 32 characters
|
||||
example: NL98INGB0003856625
|
||||
example: '1234123412341234'
|
||||
naam:
|
||||
type: string
|
||||
emailadres:
|
||||
@ -220,16 +201,9 @@ components:
|
||||
type: string
|
||||
serviceRefId:
|
||||
type: string
|
||||
example: NLOV1234567ABCDEFG
|
||||
totaalbedrag:
|
||||
Totaalbedrag:
|
||||
type: number
|
||||
format: float
|
||||
ovPasNumber:
|
||||
type: string
|
||||
example: 63AW974
|
||||
verificationCode:
|
||||
type: string
|
||||
example: 2FQ8
|
||||
refundsEntity:
|
||||
required:
|
||||
- emailAddress
|
||||
@ -239,7 +213,7 @@ components:
|
||||
emailAddress:
|
||||
type: string
|
||||
format: email
|
||||
example: stasjo@htm.nl
|
||||
example: j.beek@htm.nl
|
||||
orderNumber:
|
||||
type: string
|
||||
example: ORD1000046
|
||||
@ -252,9 +226,6 @@ components:
|
||||
ovpasNumber:
|
||||
type: string
|
||||
example: 63AW974
|
||||
verificationCode:
|
||||
type: string
|
||||
example: 2FQ8
|
||||
iban:
|
||||
type: string
|
||||
example: NL00RABO000001337
|
||||
|
||||
@ -45,36 +45,12 @@ paths:
|
||||
"contractStatus":
|
||||
{ "contractStatusId": 2, "name": "active" },
|
||||
"productId": 1,
|
||||
"productName": "HTM Maand 20% korting doorlopend",
|
||||
"termDuration": "P1M",
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"termDuration": "P0Y1M0D",
|
||||
"billingDay": 15,
|
||||
"highestInvoiceTerm": 1,
|
||||
"created": "2024-08-01T15:01:00.000Z",
|
||||
"created": "2024-08-01 15:01:00.000",
|
||||
"ovPayTokenId": 1337,
|
||||
"contractVersions": [
|
||||
{
|
||||
"contractVersionId": 1,
|
||||
"termsAndConditions": "https://www.htm.nl/reisproducten/productvoorwaarden/htm-maandkorting/",
|
||||
"productId": 1,
|
||||
"productName": "HTM Maand 20% korting doorlopend",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9,
|
||||
"termAmountInclTax": 400,
|
||||
"start": "2024-08-01T15:01:00.000Z",
|
||||
"end": "2025-01-01T03:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"contractVersionId": 2,
|
||||
"termsAndConditions": "https://www.htm.nl/reisproducten/productvoorwaarden/htm-maandkorting/",
|
||||
"productId": 1,
|
||||
"productName": "HTM Maand 20% korting doorlopend",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9,
|
||||
"termAmountInclTax": 500,
|
||||
"start": "2025-01-01T03:00:00.000Z",
|
||||
"end": null
|
||||
}
|
||||
],
|
||||
"_links":
|
||||
{
|
||||
"get_token":
|
||||
@ -92,38 +68,14 @@ paths:
|
||||
"orderLineId": "42f68042-908f-41f4-9d9b-4cab843ff0e8",
|
||||
"touchpointId": 2,
|
||||
"contractStatus":
|
||||
{ "contractStatusId": 6, "name": "pending cancellation" },
|
||||
{ "contractStatusId": 1, "name": "new" },
|
||||
"productId": 1,
|
||||
"productName": "HTM 20% Korting doorlopend",
|
||||
"termDuration": "P1M",
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"termDuration": "P0Y1M0D",
|
||||
"billingDay": 15,
|
||||
"highestInvoiceTerm": 1,
|
||||
"created": "2024-08-01T15:01:00.000Z",
|
||||
"created": "2024-08-01 15:01:00.000",
|
||||
"ovPayTokenId": 1338,
|
||||
"contractVersions": [
|
||||
{
|
||||
"contractVersionId": 1,
|
||||
"termsAndConditions": "https://www.htm.nl/reisproducten/productvoorwaarden/htm-maandkorting/",
|
||||
"productId": 1,
|
||||
"productName": "HTM 20% Korting doorlopend",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9,
|
||||
"termAmountInclTax": 400,
|
||||
"start": "2024-08-01T15:01:00.000Z",
|
||||
"end": "2025-01-01T03:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"contractVersionId": 2,
|
||||
"termsAndConditions": "https://www.htm.nl/reisproducten/productvoorwaarden/htm-maandkorting/",
|
||||
"productId": 1,
|
||||
"productName": "HTM 20% Korting doorlopend",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9,
|
||||
"termAmountInclTax": 500,
|
||||
"start": "2025-01-01T03:00:00.000Z",
|
||||
"end": "2025-02-01T03:00:00.000Z"
|
||||
}
|
||||
],
|
||||
"_links":
|
||||
{
|
||||
"get_token":
|
||||
@ -202,8 +154,8 @@ paths:
|
||||
"contractStatus":
|
||||
{ "contractStatusId": 2, "name": "active" },
|
||||
"productId": 1,
|
||||
"productName": "HTM 20% Korting doorlopend",
|
||||
"termDuration": "P1M",
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"termDuration": "P0Y1M0D",
|
||||
"billingDay": 15,
|
||||
"highestInvoiceTerm": 1,
|
||||
"ovPayTokenId": 1337,
|
||||
@ -213,22 +165,22 @@ paths:
|
||||
"contractVersionId": 1,
|
||||
"termsAndConditions": "https://www.htm.nl/reisproducten/productvoorwaarden/htm-maandkorting/",
|
||||
"productId": 1,
|
||||
"productName": "HTM 20% Korting doorlopend",
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 400,
|
||||
"start": "2024-08-01T15:01:00.000Z",
|
||||
"end": "2025-01-01T03:00:00.000Z",
|
||||
"start": "2024-07-04 15:01:00.000",
|
||||
"end": "2024-12-31 15:01:00.000",
|
||||
},
|
||||
{
|
||||
"contractVersionId": 2,
|
||||
"termsAndConditions": "https://www.htm.nl/reisproducten/productvoorwaarden/htm-maandkorting/",
|
||||
"productId": 1,
|
||||
"productName": "HTM 20% Korting doorlopend",
|
||||
"productName": "HTM Maand 20% korting",
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 400,
|
||||
"start": "2025-01-01T03:00:00.000Z",
|
||||
"start": "2025-01-01 15:01:00.000",
|
||||
},
|
||||
],
|
||||
"contractActions":
|
||||
@ -238,7 +190,7 @@ paths:
|
||||
"actionType":
|
||||
{ "actionTypeId": 1, "name": "create" },
|
||||
"user": "subid123456",
|
||||
"timestamp": "2024-07-02T15:01:00.000Z",
|
||||
"timestamp": "2024-07-02 15:01:00.000",
|
||||
"details": "Contract created",
|
||||
"correlationId": "976e7a4c-bf24-43d2-b444-55817556e7ee",
|
||||
},
|
||||
@ -247,7 +199,7 @@ paths:
|
||||
"actionType":
|
||||
{ "actionTypeId": 2, "name": "change" },
|
||||
"user": "subid123456",
|
||||
"timestamp": "2024-07-03T15:01:00.000Z",
|
||||
"timestamp": "2024-07-03 15:01:00.000",
|
||||
"details": "Contract changed",
|
||||
"correlationId": "e2462347-6749-4841-b42a-cf8de19ec727",
|
||||
},
|
||||
@ -259,8 +211,8 @@ paths:
|
||||
"externalReference": "F2024-0001",
|
||||
"term": 1,
|
||||
"invoiceDate": "2024-07-02",
|
||||
"created": "2024-07-02T15:01:00.000Z",
|
||||
"updated": "2024-07-02T15:01:00.000Z",
|
||||
"created": "2024-07-02 15:01:00.000",
|
||||
"updated": "2024-07-02 15:01:00.000",
|
||||
"state": "invoice_created",
|
||||
"data": "{json}",
|
||||
"isCredit": false,
|
||||
@ -318,8 +270,8 @@ paths:
|
||||
"externalReference": "F2024-0001",
|
||||
"term": 1,
|
||||
"invoiceDate": "2024-07-02",
|
||||
"created": "2024-07-02T15:01:34.000Z",
|
||||
"updated": "2024-07-04T00:04:56.000Z",
|
||||
"created": "2024-07-02 15:01:34.000",
|
||||
"updated": "2024-07-04 00:04:56.000",
|
||||
"state": "invoice_created",
|
||||
"public_link": "http://mijnfactuurinzien.nl/F2024-0001",
|
||||
"isCredit": false,
|
||||
@ -330,8 +282,8 @@ paths:
|
||||
"externalReference": "F2024-0002",
|
||||
"term": 2,
|
||||
"invoiceDate": "2024-08-02",
|
||||
"created": "2024-08-02T15:01:34.000Z",
|
||||
"updated": "2024-08-04T00:04:56.000Z",
|
||||
"created": "2024-08-02 15:01:34.000",
|
||||
"updated": "2024-08-04 00:04:56.000",
|
||||
"state": "invoice_created",
|
||||
"public_link": "http://mijnfactuurinzien.nl/F2024-0002",
|
||||
"isCredit": false,
|
||||
@ -376,8 +328,8 @@ paths:
|
||||
"cancellationMoment": "termBound",
|
||||
"termDuration": "P1M",
|
||||
"billingDay": 18,
|
||||
"cancellationFrom": "2024-08-10T00:00:00Z",
|
||||
"cancellationUntil": "2026-08-10T00:00:00Z",
|
||||
"cancellationFrom": "2024-08-10T00:00:00",
|
||||
"cancellationUntil": "2026-08-10T00:00:00",
|
||||
}
|
||||
/contracts/{contractId}/cancellationvalidation:
|
||||
parameters:
|
||||
@ -430,14 +382,14 @@ paths:
|
||||
{
|
||||
"validationResult": true,
|
||||
"validationMessage": "",
|
||||
"end": "2024-08-10T03:59:59Z",
|
||||
"end": "2024-08-10T03:59:59",
|
||||
"refundAmount": 2489,
|
||||
"refundMethods": ["creditInvoice", "iDeal"],
|
||||
}
|
||||
Unsuccessful validation:
|
||||
summary: Unsuccessful validation
|
||||
Unsuccesful validation:
|
||||
summary: Unsuccesful validation
|
||||
description: |
|
||||
Unsuccessful validation. The response contains the error message.
|
||||
Unsuccesful validation. The response contains the error message.
|
||||
value:
|
||||
{
|
||||
"validationResult": false,
|
||||
@ -499,7 +451,7 @@ paths:
|
||||
the refund amount and refund method.
|
||||
value:
|
||||
{
|
||||
"end": "2024-08-10T03:59:59Z",
|
||||
"end": "2024-08-10T03:59:59",
|
||||
"refundAmount": 2489,
|
||||
"refundMethod": "creditInvoice",
|
||||
}
|
||||
@ -564,8 +516,8 @@ paths:
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 400,
|
||||
"start": "2024-07-04T15:01:00.000Z",
|
||||
"end": "2024-12-31T15:01:00.000Z",
|
||||
"start": "2024-07-04 15:01:00.000",
|
||||
"end": "2024-12-31 15:01:00.000",
|
||||
},
|
||||
{
|
||||
"contractVersionId": 2,
|
||||
@ -575,8 +527,7 @@ paths:
|
||||
"taxCode": "V9",
|
||||
"taxPercentage": 9.0,
|
||||
"termAmountInclTax": 400,
|
||||
"start": "2025-01-01T15:01:00.000Z",
|
||||
"end": null
|
||||
"start": "2025-01-01 15:01:00.000",
|
||||
},
|
||||
],
|
||||
"contractActions":
|
||||
@ -586,7 +537,7 @@ paths:
|
||||
"actionType":
|
||||
{ "actionTypeId": 1, "name": "create" },
|
||||
"user": "subid123456",
|
||||
"timestamp": "2024-07-02T15:01:00.000Z",
|
||||
"timestamp": "2024-07-02 15:01:00.000",
|
||||
"details": "Contract created",
|
||||
"correlationId": "976e7a4c-bf24-43d2-b444-55817556e7ee",
|
||||
},
|
||||
@ -595,7 +546,7 @@ paths:
|
||||
"actionType":
|
||||
{ "actionTypeId": 2, "name": "change" },
|
||||
"user": "subid123456",
|
||||
"timestamp": "2024-07-03T15:01:00.000Z",
|
||||
"timestamp": "2024-07-03 15:01:00.000",
|
||||
"details": "Contract changed",
|
||||
"correlationId": "e2462347-6749-4841-b42a-cf8de19ec727",
|
||||
},
|
||||
@ -607,8 +558,8 @@ paths:
|
||||
"externalReference": "F2024-0001",
|
||||
"term": 1,
|
||||
"invoiceDate": "2024-07-02",
|
||||
"created": "2024-07-02T15:01:00.000Z",
|
||||
"updated": "2024-07-02T15:01:00.000Z",
|
||||
"created": "2024-07-02 15:01:00.000",
|
||||
"updated": "2024-07-02 15:01:00.000",
|
||||
"state": "invoice_created",
|
||||
"data": "{json}",
|
||||
"isCredit": false,
|
||||
@ -623,267 +574,6 @@ 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-01T15:01:00.000Z",
|
||||
"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-01T15:01:00.000Z",
|
||||
"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
|
||||
@ -907,13 +597,9 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
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.
|
||||
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'.
|
||||
value:
|
||||
{
|
||||
"contractPayments":
|
||||
@ -921,9 +607,8 @@ paths:
|
||||
{
|
||||
"paymentId": "151845776",
|
||||
"totalAmount": "26.62",
|
||||
"paymentMethod": "Automatische incasso",
|
||||
"paymentMethod": "Twikey",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
@ -940,192 +625,23 @@ paths:
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
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",
|
||||
"paymentId": "151845851",
|
||||
"totalAmount": "45.21",
|
||||
"paymentMethod": "Twikey",
|
||||
"paymentDate": "2024-09-12",
|
||||
"iban": "NL25INGB******1337",
|
||||
"invoice":
|
||||
{
|
||||
"invoiceId": "147722263",
|
||||
"invoiceNumber": "F2024-0001",
|
||||
"invoiceId": "147722266",
|
||||
"invoiceNumber": "F2024-0002",
|
||||
"description": "HTM Maandkorting 20%",
|
||||
"publicLink": "https://factuurinzien.nl/d/b0aac3f42f325f5dd6abc172f723caab5956524d/i/ddb245d6df67999eca48c4a71b5661b93038e20a",
|
||||
"publicLink": "https://factuurinzien.nl/d/ddb245d6df67999eca48c4a71b5661b93038e20a/i/dp5h1i5cuu94nopiolkdst3u17vkmzo",
|
||||
},
|
||||
"_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",
|
||||
"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": "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",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/customers/contracts/7b2f8c1a-3d9d-4c2d-960e-4471e8e28b6a",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -358,7 +358,8 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CustomersResponse"
|
||||
$ref: "#/components/schemas/CustomersResponse"
|
||||
|
||||
/customers/tokens:
|
||||
get:
|
||||
tags:
|
||||
@ -490,7 +491,6 @@ paths:
|
||||
"ovPayTokenId": 1,
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType": { "tokenTypeId": 1, "name": "EMV" },
|
||||
"ovpasNumber": "",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -567,7 +567,6 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -650,7 +649,6 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -773,7 +771,6 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -871,7 +868,6 @@ paths:
|
||||
"xTat": "32089cc8-d187-47ff-a3a9-5c2558def811",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -987,7 +983,6 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV34567",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 2, "name": "Active" },
|
||||
@ -1008,7 +1003,6 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV31236",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 3, "name": "Replaced (*)" },
|
||||
@ -1030,7 +1024,6 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV36897",
|
||||
"alias": "MyToken",
|
||||
"tokenStatus":
|
||||
{ "tokenStatusId": 4, "name": "On stock" },
|
||||
@ -1052,7 +1045,6 @@ 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" },
|
||||
@ -1074,7 +1066,6 @@ paths:
|
||||
"xTat": "e7fa3392-646b-40e2-95a6-c417dc0b0969",
|
||||
"tokenType":
|
||||
{ "tokenTypeId": 2, "name": "OV-pas physical" },
|
||||
"ovpasNumber": "OV48965",
|
||||
"alias": "Mijn OV Pas",
|
||||
"tokenStatus":
|
||||
{
|
||||
@ -1120,7 +1111,6 @@ 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" },
|
||||
@ -1960,7 +1950,7 @@ paths:
|
||||
type: integer
|
||||
example: 1
|
||||
required: true
|
||||
summary: "**INTERNAL USE ONLY** Replace an OVpay token with another (+ transfer products) - V2"
|
||||
summary: Replace an OVpay token with another (+ transfer products) - V2 (for Integratielaag)
|
||||
description: |
|
||||
Transfer products from one OVpay token to another, and replace the tokens in the database.
|
||||
This endpoint is for usage by integratielaag only. Touch points should use
|
||||
@ -2249,6 +2239,11 @@ 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",
|
||||
@ -3793,23 +3788,11 @@ components:
|
||||
example: GET
|
||||
OvPayTokenProductInstancesResponse:
|
||||
type: object
|
||||
required:
|
||||
- productInstances
|
||||
properties:
|
||||
productInstances:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- productId
|
||||
- name
|
||||
- status
|
||||
- isRenewable
|
||||
- productCategory
|
||||
- fromInclusive
|
||||
- orderId
|
||||
- orderLineId
|
||||
- _links
|
||||
properties:
|
||||
productId:
|
||||
type: integer
|
||||
@ -3871,20 +3854,20 @@ 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,341 +0,0 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Service Engine APIs for TAT security
|
||||
description: >-
|
||||
Service Engine APIs for TAT security. These are NOT the raw GBO APIs to access TAT security at GBO directly.
|
||||
To be used by touch points to get secure a TAT.
|
||||
version: "2.0"
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/touchpoint/2.0
|
||||
tags:
|
||||
- name: TAT Security
|
||||
paths:
|
||||
/tokens/securetoken:
|
||||
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: integer
|
||||
example: 323
|
||||
required: false
|
||||
description: The id of the customer Profile
|
||||
- name: X-HTM-ROLE-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: Customer
|
||||
required: false
|
||||
description: The role of the HTM employee in the case of the SMP
|
||||
post:
|
||||
tags:
|
||||
- TAT Security
|
||||
summary: Request additional OV-pas security for a token either in profile or anonymous.
|
||||
description: Request additional OV-pas security for a token either in profile or anonymous
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SecureTokenRequest"
|
||||
examples:
|
||||
With customer account:
|
||||
value:
|
||||
ovPayTokenId: 42
|
||||
emailAddress: stasjo@htm.nl
|
||||
Without customer account:
|
||||
value:
|
||||
xtat: 62914b49-2c7f-437f-b4b0-2ad61a9f902d
|
||||
emailAddress: stasjo@htm.nl
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EmailNotPreApprovedResponse"
|
||||
example:
|
||||
uid: 7594f3ee-cd3d-40a3-8e82-73b90d16c481
|
||||
recipient: xxxxxx.user@gmail.com
|
||||
key: 123456789123456789123456789abcde
|
||||
description: OTP Sent
|
||||
"400":
|
||||
description: Bad Request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
examples:
|
||||
Missing Parameters:
|
||||
value:
|
||||
status: 400
|
||||
title: Missing Mandatory Parameter
|
||||
detail: Required parameter {0} is missing.
|
||||
Invalid Parameters:
|
||||
value:
|
||||
status: 400
|
||||
title: Invalid Parameter
|
||||
detail: Required parameter {0} is invalid.
|
||||
"401":
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
examples:
|
||||
Unauthorized:
|
||||
value:
|
||||
status: 401
|
||||
title: Unauthorized
|
||||
detail: Invalid Access Token
|
||||
"404":
|
||||
description: Not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
examples:
|
||||
TAT not found:
|
||||
value:
|
||||
status: 404
|
||||
title: Not Found
|
||||
detail: TAT Account Not Found
|
||||
"409":
|
||||
description: Conflict
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
examples:
|
||||
TAT Already Secured:
|
||||
value:
|
||||
status: 409
|
||||
title: Conflict
|
||||
detail: TAT Already Secured
|
||||
"500":
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
example:
|
||||
error: An unknown error has occurred
|
||||
/tokens/verifyotp:
|
||||
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: integer
|
||||
example: 323
|
||||
required: false
|
||||
description: The id of the customer Profile
|
||||
- name: X-HTM-ROLE-HEADER
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
example: Customer
|
||||
required: false
|
||||
description: The role of the HTM employee in the case of the SMP
|
||||
post:
|
||||
tags:
|
||||
- TAT Security
|
||||
summary: Submit an OTP for a triggered OTP flow.
|
||||
description: |
|
||||
Submit an OTP for a triggered OTP flow. This can either be result of an AGO activation, or
|
||||
result of an AGO authorization flow. Since the backoffice behaves slightly different depending
|
||||
on which use case is executed, the calling TP needs to provide an `action` in the request body.
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/VerifyOtpRequest"
|
||||
examples:
|
||||
OTP verification for TAT security activation for token in customer account:
|
||||
value:
|
||||
ovPayTokenId: 42
|
||||
otp: 123456
|
||||
action: secure
|
||||
OTP verification for TAT security authorization for anonymous token:
|
||||
value:
|
||||
xtat: 0f0defe8-828c-48e5-97e5-26d1d0179ef0
|
||||
otp: 123456
|
||||
action: authorize
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/VerifyOtpResponse'
|
||||
examples:
|
||||
Tat Secured:
|
||||
value:
|
||||
status: Success
|
||||
description: TAT Secured
|
||||
Tat Unsecured:
|
||||
value:
|
||||
status: Success
|
||||
description: TAT Unsecured
|
||||
Tat Authorized:
|
||||
value:
|
||||
status: Success
|
||||
description: TAT Authorized
|
||||
"400":
|
||||
description: Bad request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
examples:
|
||||
Missing Parameters:
|
||||
value:
|
||||
status: 400
|
||||
title: Missing Mandatory Parameter
|
||||
detail: Required parameter {0} is missing.
|
||||
Invalid Parameters:
|
||||
value:
|
||||
status: 400
|
||||
title: Invalid Parameter
|
||||
detail: Required parameter {0} is invalid.
|
||||
"401":
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
examples:
|
||||
Unauthorized:
|
||||
value:
|
||||
status: 401
|
||||
title: Unauthorized
|
||||
detail: Invalid Access Token
|
||||
"500":
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
example:
|
||||
error: An unknown error has occurred
|
||||
components:
|
||||
schemas:
|
||||
unavailable:
|
||||
type: object
|
||||
GenerateTatOutput:
|
||||
type: object
|
||||
properties:
|
||||
uid:
|
||||
type: string
|
||||
description: >-
|
||||
An uid IS A unique identifier THAT is associated with the
|
||||
user.
|
||||
recipient:
|
||||
type: string
|
||||
description: >-
|
||||
A recipient IS A unique identifier THAT is associated with the
|
||||
TAT owner.
|
||||
key:
|
||||
type: string
|
||||
description: >-
|
||||
A key IS a 32 character string THAT uniquely identifies the
|
||||
OTP session.
|
||||
EmailNotPreApprovedResponse:
|
||||
type: object
|
||||
description: >-
|
||||
EmailNotPreApprovedResponse IS AN object THAT represents the response of
|
||||
email pre-approval check.
|
||||
properties:
|
||||
uid:
|
||||
type: string
|
||||
description: A uid IS A unique identifier THAT is associated with the user.
|
||||
example: 7594f3ee-cd3d-40a3-8e82-73b90d16c481
|
||||
recipient:
|
||||
type: string
|
||||
description: >-
|
||||
A recipient IS A unique identifier THAT is associated with the TAT
|
||||
owner.
|
||||
example: xxxxxx.user@gmail.com
|
||||
key:
|
||||
type: string
|
||||
description: >-
|
||||
A key IS a 32 character string THAT uniquely identifies the OTP
|
||||
session.
|
||||
example: 123456789123456789123456789abcde
|
||||
description:
|
||||
type: string
|
||||
description: >-
|
||||
A description IS A string THAT describes the reason why the email is
|
||||
not pre-approved.
|
||||
example: OTP Sent
|
||||
SecureTokenRequest:
|
||||
type: object
|
||||
properties:
|
||||
ovPayTokenId:
|
||||
type: integer
|
||||
example: 42
|
||||
xtat:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 6134db53-9ae5-41d1-a343-36656b60b510
|
||||
emailAddress:
|
||||
type: string
|
||||
format: email
|
||||
example: stasjo@htm.nl
|
||||
required:
|
||||
- ovPayTokenId
|
||||
VerifyOtpRequest:
|
||||
type: object
|
||||
properties:
|
||||
ovPayTokenId:
|
||||
type: integer
|
||||
example: 42
|
||||
xtat:
|
||||
type: string
|
||||
format: uuid
|
||||
example: f3474452-e1d4-428c-b366-e5ad5965eb8c
|
||||
otp:
|
||||
type: string
|
||||
example: 123456
|
||||
action:
|
||||
type: string
|
||||
example: secure
|
||||
required:
|
||||
- otp
|
||||
- action
|
||||
VerifyOtpResponse:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: Success
|
||||
description:
|
||||
type: string
|
||||
example: TAT Secured
|
||||
ErrorResponse:
|
||||
description: Default response when an invalid request has been sent
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: integer
|
||||
description: >-
|
||||
A status IS An integer that represents the HTTP status code of the
|
||||
response.
|
||||
example: 400
|
||||
title:
|
||||
type: string
|
||||
description: A title IS A string that provides a brief summary of the error.
|
||||
detail:
|
||||
type: string
|
||||
description: A detail IS A string that provides more details about the error.
|
||||
@ -224,7 +224,6 @@ paths:
|
||||
name: Inactive
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 1
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -243,7 +242,7 @@ paths:
|
||||
suffix: PhD
|
||||
dateOfBirth: "2002-10-29"
|
||||
emailAddresses: TEST@HTM.NL
|
||||
isEmailVerified: false
|
||||
isEmailVerified: True
|
||||
addresses:
|
||||
- addressId: 1
|
||||
street: mystreet
|
||||
@ -332,6 +331,14 @@ paths:
|
||||
user: user
|
||||
timestamp: "2023-10-20T17:05:52.000+02:00"
|
||||
correlationId: 01c6d8b4-1cd3-4f9b-85ea-c9adca53ce95
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?customerProfileId=1",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
- customerProfileId: 12
|
||||
customerNumber: 1000002
|
||||
debtorNumber: DB100121
|
||||
@ -339,14 +346,13 @@ paths:
|
||||
debtorStatusId: 1
|
||||
name: Inactive
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 2
|
||||
customerPreference:
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
ietfCode: nl-NL
|
||||
iso639Code: nl
|
||||
customerStatusInstances:
|
||||
customerStatusInstances:
|
||||
- customerStatus:
|
||||
name: Active
|
||||
customerStatusId: 2
|
||||
@ -369,7 +375,7 @@ paths:
|
||||
suffix: PhD
|
||||
dateOfBirth: "2002-10-29"
|
||||
emailAddresses: TEST@HTM.NL
|
||||
isEmailVerified: false
|
||||
isEmailVerified: False
|
||||
address:
|
||||
- addressId: 1
|
||||
street: mystreet
|
||||
@ -459,7 +465,32 @@ paths:
|
||||
user: user
|
||||
timestamp: "2023-10-20T17:05:52.000+02:00"
|
||||
correlationId: 01c6d8b4-1cd3-4f9b-85ea-c9adca53ce95
|
||||
href: "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?offset=20&limit=20"
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?customerProfileId=12",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?offset=20",
|
||||
"method": "GET",
|
||||
},
|
||||
"prev":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers",
|
||||
"method": "GET",
|
||||
},
|
||||
"next":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?offset=40",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
getCustomerActive:
|
||||
summary: getCustomerActive
|
||||
description: >-
|
||||
@ -473,8 +504,7 @@ paths:
|
||||
debtorStatusId: 1
|
||||
name: Inactive
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 1
|
||||
customerPreference:
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -493,7 +523,7 @@ paths:
|
||||
suffix: PhD
|
||||
dateOfBirth: "2002-10-29"
|
||||
emailAddresses: TEST@HTM.NL
|
||||
isEmailVerified: false
|
||||
isEmailVerified: False
|
||||
addresses:
|
||||
- addressId: 1
|
||||
street: mystreet
|
||||
@ -582,7 +612,22 @@ paths:
|
||||
user: user
|
||||
timestamp: "2023-10-20T17:05:52.000+02:00"
|
||||
correlationId: 01c6d8b4-1cd3-4f9b-85ea-c9adca53ce95
|
||||
href: https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?offset=20&limit=20
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?customerProfileId=1",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
getCustomerBlocked:
|
||||
summary: getCustomerBlocked
|
||||
description: >-
|
||||
@ -596,8 +641,7 @@ paths:
|
||||
debtorStatusId: 2
|
||||
name: Active
|
||||
vasCustomerNumber: CST005
|
||||
customerPreference:
|
||||
customerPreferenceId: 5
|
||||
customerPreference:
|
||||
language:
|
||||
languageId: 1
|
||||
name: Dutch
|
||||
@ -621,7 +665,7 @@ paths:
|
||||
suffix: PhD
|
||||
dateOfBirth: "2002-10-29"
|
||||
emailAddresses: TEST@HTM.NL
|
||||
isEmailVerified: false
|
||||
isEmailVerified: True
|
||||
addresses:
|
||||
- addressId: 1
|
||||
street: mystreet
|
||||
@ -710,7 +754,22 @@ paths:
|
||||
user: user
|
||||
timestamp: "2023-10-20T17:05:52.000+02:00"
|
||||
correlationId: 01c6d8b4-1cd3-4f9b-85ea-c9adca53ce95
|
||||
href: https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?offset=20&limit=20
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers?customerProfileId=1",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
_links:
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/customers",
|
||||
"method": "GET",
|
||||
},
|
||||
}
|
||||
400:
|
||||
description: Bad Request
|
||||
content:
|
||||
@ -772,7 +831,7 @@ paths:
|
||||
suffix: jr
|
||||
dateOfBirth: "1970-01-01"
|
||||
emailAddress: j.jansen@hatseflats.nl
|
||||
isEmailVerified: false
|
||||
isEmailVerified: False
|
||||
addresses:
|
||||
- street: Laan van Meerdervoort
|
||||
houseNumber: 5
|
||||
@ -871,7 +930,7 @@ paths:
|
||||
suffix: "jr",
|
||||
dateOfBirth: "1970-01-01",
|
||||
emailAddress: "TEST@TEST1.NL",
|
||||
isEmailVerified: false
|
||||
isEmailVerified: False
|
||||
}
|
||||
updateCompleteEntity:
|
||||
value:
|
||||
@ -883,7 +942,7 @@ paths:
|
||||
suffix: "jr",
|
||||
dateOfBirth: "1970-01-01",
|
||||
emailAddress: "TEST@TEST1.NL",
|
||||
isEmailVerified: false
|
||||
isEmailVerified: True
|
||||
}
|
||||
required: true
|
||||
responses:
|
||||
@ -1240,6 +1299,7 @@ paths:
|
||||
name: externalDeviceId
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: c5545584-04af-4c60-a955-d6a70baab848
|
||||
required: false
|
||||
description: The external id of the device.
|
||||
@ -1375,7 +1435,13 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/patchDeviceResponse"
|
||||
$ref: "#/components/schemas/getDevices"
|
||||
examples:
|
||||
updateDeviceResponse:
|
||||
value:
|
||||
deviceId: "5bedce29-af0c-4f3c-b182-2caa8a1f9377"
|
||||
externalDeviceId: "7122a988-a00a-417d-a5b4-da2d91354976"
|
||||
alias: "iPhone zakelijk"
|
||||
|
||||
security:
|
||||
- default: []
|
||||
@ -1538,7 +1604,24 @@ paths:
|
||||
"replacedByTokenId": 12,
|
||||
},
|
||||
],
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/ovPayTokens?offset=20&limit=20"
|
||||
"_links":
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/ovPayTokens?offset=20",
|
||||
"method": "GET",
|
||||
},
|
||||
"prev":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/ovPayTokens",
|
||||
"method": "GET",
|
||||
},
|
||||
"next":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/ovPayTokens?offset=40",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
}
|
||||
/customers/{customerProfileId}/ovpaytokens:
|
||||
post:
|
||||
@ -1857,10 +1940,9 @@ paths:
|
||||
"created": "2024-10-20T17:05:52.000",
|
||||
},
|
||||
],
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/billingInformations?offset=20&limit=20"
|
||||
}
|
||||
getBillingInformationSingleSpecificCustomer:
|
||||
summary: Get single billing information entity for a specific customers
|
||||
summary: Get singel billing information entity for a specific customers
|
||||
description: >-
|
||||
Found one billing information matching the search parameters
|
||||
value:
|
||||
@ -2050,7 +2132,59 @@ paths:
|
||||
"updateTimestamp": "2024-03-22T08:55:00",
|
||||
},
|
||||
],
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/directdebitmandates?offset=20&limit=20"
|
||||
"_links":
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/directdebitmandates",
|
||||
"method": "GET",
|
||||
},
|
||||
"next":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/directdebitmandates?offset=20",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
}
|
||||
getDirectDebitMandateWithNextPageandPreviousPage:
|
||||
value:
|
||||
{
|
||||
"directDebitMandates":
|
||||
[
|
||||
{
|
||||
"directDebitMandateId": 71,
|
||||
"customerProfileId": 12,
|
||||
"billingInformationId": 51,
|
||||
"directDebitMandateType":
|
||||
{
|
||||
"directDebitMandateTypeId": 1,
|
||||
"name": "import",
|
||||
"description": "import",
|
||||
},
|
||||
"created": "2024-03-22T08:55:00",
|
||||
"mandateReference": "CORE01",
|
||||
"mandateState": "SIGNED",
|
||||
"updateTimestamp": "2024-03-22T08:55:00",
|
||||
},
|
||||
],
|
||||
"_links":
|
||||
{
|
||||
"self":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/directdebitmandates?offset=20",
|
||||
"method": "GET",
|
||||
},
|
||||
"prev":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/directdebitmandates",
|
||||
"method": "GET",
|
||||
},
|
||||
"next":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/abtcustomers/2.0/directdebitmandates?offset=40",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
}
|
||||
/billingInformation/{billingInformationId}/directdebitmandates:
|
||||
post:
|
||||
@ -2342,6 +2476,7 @@ components:
|
||||
format: uuid
|
||||
externalDeviceId:
|
||||
type: string
|
||||
format: uuid
|
||||
alias:
|
||||
type: string
|
||||
required:
|
||||
@ -2460,6 +2595,7 @@ components:
|
||||
properties:
|
||||
externalDeviceId:
|
||||
type: string
|
||||
format: uuid
|
||||
alias:
|
||||
type: string
|
||||
defaultCustomerProfileResponse:
|
||||
@ -2573,6 +2709,10 @@ components:
|
||||
example: 1
|
||||
postCustomerStatusResponse:
|
||||
type: object
|
||||
properties:
|
||||
customerPreferenceId:
|
||||
type: integer
|
||||
example: 1
|
||||
postCustomerPreferencesResponse:
|
||||
type: object
|
||||
properties:
|
||||
@ -2706,7 +2846,7 @@ components:
|
||||
emailAddress:
|
||||
type: string
|
||||
isEmailVerified:
|
||||
type: boolean
|
||||
type: string
|
||||
postOvPayTokenResponse:
|
||||
type: object
|
||||
properties:
|
||||
@ -2720,14 +2860,6 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/getDeviceEntity"
|
||||
patchDeviceResponse:
|
||||
type: object
|
||||
properties:
|
||||
deviceId:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "b2c8a8c6-3d1c-4b6b-8f8d-3a6a1b6a1b6a"
|
||||
|
||||
getDeviceEntity:
|
||||
type: object
|
||||
properties:
|
||||
@ -2738,6 +2870,7 @@ components:
|
||||
type: integer
|
||||
externalDeviceId:
|
||||
type: string
|
||||
format: uuid
|
||||
alias:
|
||||
type: string
|
||||
required:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -417,56 +417,38 @@ paths:
|
||||
example:
|
||||
Entries:
|
||||
phoneTypes:
|
||||
- name: Mobiel
|
||||
- name: mobile
|
||||
id: 1
|
||||
- name: Thuis
|
||||
- name: fixed line
|
||||
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: Shipping
|
||||
- name: home
|
||||
id: 1
|
||||
- name: Billing
|
||||
- name: office
|
||||
id: 2
|
||||
customerStatuses:
|
||||
- name: Inactive
|
||||
- name: active
|
||||
id: 1
|
||||
- name: Active
|
||||
- name: blocked
|
||||
id: 2
|
||||
- name: Blocked
|
||||
- name: inactive
|
||||
id: 3
|
||||
- name: Frozen
|
||||
- name: new
|
||||
id: 4
|
||||
- name: Cleared
|
||||
id: 5
|
||||
tokenTypes:
|
||||
- name: EMV
|
||||
- name: Debit card
|
||||
id: 1
|
||||
- name: OVPas physical
|
||||
- name: Credit card
|
||||
id: 2
|
||||
- name: OVPas digital
|
||||
- name: OVPas physical
|
||||
id: 3
|
||||
- name: OVPas digital
|
||||
id: 4
|
||||
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
468
src/openapi/customers/se-maileon.yaml
Normal file
468
src/openapi/customers/se-maileon.yaml
Normal file
@ -0,0 +1,468 @@
|
||||
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/TransactionItemsBulkRequestBody"
|
||||
$ref: "#/components/schemas/TransactionItemsPostRequestBody"
|
||||
examples:
|
||||
Add single transaction item:
|
||||
summary: Add single transaction item
|
||||
@ -285,7 +285,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BulkResponseBody"
|
||||
$ref: "#/components/schemas/TransactionItemsPostResponseBody"
|
||||
examples:
|
||||
Array of transaction items accepted:
|
||||
summary: Array of transaction items accepted
|
||||
@ -381,7 +381,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
$ref: "#/components/schemas/TransactionItemsResponseStatusGetResponseBody"
|
||||
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/bulk:
|
||||
patch:
|
||||
summary: Patch transaction items in bulk.
|
||||
description: Patch transaction items in bulk.
|
||||
/transactionitems/reject:
|
||||
post:
|
||||
summary: Reject transaction items to source in bulk.
|
||||
description: Reject transaction items to source in bulk.
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
requestBody:
|
||||
@ -2992,117 +2992,76 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TransactionItemsBulkRequestBody"
|
||||
examples:
|
||||
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.
|
||||
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.
|
||||
value:
|
||||
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
|
||||
transactionItemIds:
|
||||
- afce35b2-1dff-4ace-98d0-4b9ac405c87d
|
||||
- b1c4f8e7-3f4e-4d2a-9c6e-2f5e6d7c8b9a
|
||||
- c2d5e6f7-4g5h-5i6j-0k1l-3m4n5o6p7q8r
|
||||
responses:
|
||||
"202":
|
||||
description: Accepted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BulkResponseBody"
|
||||
$ref: "#/components/schemas/TransactionItemsPostResponseBody"
|
||||
examples:
|
||||
Array of transaction items accepted:
|
||||
summary: Array of transaction items accepted
|
||||
summary: Array of transaction item ids accepted
|
||||
description: |
|
||||
The array of transaction items was accepted successfully.
|
||||
The array of transaction item ids 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/bulk/responsestatus/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
callbackurl: https://api.integratielaag.nl/transactionitems/reject/responsestatus/runtime/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
retryAfter: 10
|
||||
security:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
x-throttling-tier: Unlimited
|
||||
/transactionitems/bulk/responsestatus/{clientTrackingId}:
|
||||
/transactionitems/responsestatus/reject/{clientTrackingId}:
|
||||
get:
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
summary: Get the status of the transaction item bulk patch.
|
||||
description: Get the status of the asynchronous transaction item bulk patch.
|
||||
summary: Get the status of the transaction item bulk reject.
|
||||
description: Get the status of the asynchronous transaction item bulk reject.
|
||||
parameters:
|
||||
- in: path
|
||||
name: clientTrackingId
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: The clientTrackingId of the transaction item bulk patch.
|
||||
description: The clientTrackingId of the transaction item bulk reject.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
$ref: "#/components/schemas/TransactionItemsRejectResponseStatusGetResponseBody"
|
||||
examples:
|
||||
Batch successfully processed:
|
||||
summary: Batch successfully processed
|
||||
description: |
|
||||
Body of a batch of transaction items that was successfully patched.
|
||||
A number of transaction items were patched.
|
||||
Body of a batch of transaction items that was successfully rejected.
|
||||
A number of transaction items were rejected.
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.067Z
|
||||
status: Finished
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
summary:
|
||||
created: 0
|
||||
updated: 15
|
||||
rejected: 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
|
||||
/processingfailures/bulk:
|
||||
patch:
|
||||
summary: Patch processing failures in bulk.
|
||||
description: Patch processing failures in bulk.
|
||||
/transactionitems/return:
|
||||
post:
|
||||
summary: Return transaction items to trx db in bulk.
|
||||
description: Return transaction items to trx db in bulk.
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
requestBody:
|
||||
@ -3110,96 +3069,70 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProcessingFailuresBulkRequestBody"
|
||||
$ref: "#/components/schemas/TransactionItemsBulkRequestBody"
|
||||
examples:
|
||||
List of processing failures to resolve:
|
||||
summary: List of processing failures to resolve
|
||||
description: List of processing failures to resolve in bulk.
|
||||
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.
|
||||
value:
|
||||
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.
|
||||
transactionItemIds:
|
||||
- afce35b2-1dff-4ace-98d0-4b9ac405c87d
|
||||
- b1c4f8e7-3f4e-4d2a-9c6e-2f5e6d7c8b9a
|
||||
- c2d5e6f7-4g5h-5i6j-0k1l-3m4n5o6p7q8r
|
||||
responses:
|
||||
"202":
|
||||
description: Accepted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BulkResponseBody"
|
||||
$ref: "#/components/schemas/TransactionItemsPostResponseBody"
|
||||
examples:
|
||||
Array of processing failures accepted:
|
||||
summary: Array of processing failures accepted
|
||||
Array of transaction items accepted:
|
||||
summary: Array of transaction item ids accepted
|
||||
description: |
|
||||
The array of processing failures was accepted successfully.
|
||||
The processing failures will be processed asynchronously.
|
||||
The array of transaction item ids 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/processingfailures/bulk/responsestatus/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
callbackurl: https://api.integratielaag.nl/transactionitems/return/responsestatus/runtime/webhooks/workflow/scaleUnits/prod-00/workflows/6fd466916c
|
||||
retryAfter: 10
|
||||
security:
|
||||
- default: []
|
||||
x-auth-type: Application & Application User
|
||||
x-throttling-tier: Unlimited
|
||||
/processingfailures/bulk/responsestatus/{clientTrackingId}:
|
||||
/transactionitems/responsestatus/return/{clientTrackingId}:
|
||||
get:
|
||||
tags:
|
||||
- Bulk processing v2.2
|
||||
summary: Get the status of the processing failures bulk patch.
|
||||
description: Get the status of the asynchronous processing failures bulk patch.
|
||||
summary: Get the status of the transaction item bulk return.
|
||||
description: Get the status of the asynchronous transaction item bulk return.
|
||||
parameters:
|
||||
- in: path
|
||||
name: clientTrackingId
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: The clientTrackingId of the processing failures bulk patch.
|
||||
description: The clientTrackingId of the transaction item bulk return.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GetResponseStatus"
|
||||
$ref: "#/components/schemas/TransactionItemsReturnResponseStatusGetResponseBody"
|
||||
examples:
|
||||
Batch successfully processed:
|
||||
summary: Batch successfully processed
|
||||
description: |
|
||||
Body of a batch of processing failures that was successfully patched.
|
||||
A number of processing failures were patched.
|
||||
Body of a batch of transaction items that was successfully returned to trx db.
|
||||
A number of transaction items were returned to trx db.
|
||||
value:
|
||||
startTime: 2025-02-14T05:32:47.067Z
|
||||
status: Finished
|
||||
clientTrackingId: 08584620957189579629541919368CU00
|
||||
summary:
|
||||
created: 0
|
||||
updated: 15
|
||||
returned: 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
|
||||
@ -3316,7 +3249,7 @@ components:
|
||||
- occurredOn
|
||||
- type
|
||||
- status
|
||||
TransactionItemsBulkRequestBody:
|
||||
TransactionItemsPostRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
transactionItems:
|
||||
@ -3324,10 +3257,6 @@ components:
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
transactionItemId:
|
||||
type: string
|
||||
format: uuid
|
||||
example: afce35b2-1dff-4ace-98d0-4b9ac405c87d
|
||||
transactionType:
|
||||
type: string
|
||||
enum:
|
||||
@ -3387,7 +3316,7 @@ components:
|
||||
- amountTax
|
||||
- occurredOn
|
||||
- type
|
||||
BulkResponseBody:
|
||||
TransactionItemsPostResponseBody:
|
||||
type: object
|
||||
properties:
|
||||
startTime:
|
||||
@ -4973,7 +4902,7 @@ components:
|
||||
required:
|
||||
- concessionId
|
||||
- name
|
||||
GetResponseStatus:
|
||||
TransactionItemsResponseStatusGetResponseBody:
|
||||
type: object
|
||||
properties:
|
||||
summary:
|
||||
@ -5030,24 +4959,51 @@ components:
|
||||
transactionLineId:
|
||||
type: string
|
||||
example: fee907dd-e59d-44f5-a63b-bbdec38f79b7
|
||||
ProcessingFailuresBulkRequestBody:
|
||||
TransactionItemsBulkRequestBody:
|
||||
type: object
|
||||
properties:
|
||||
processingFailures:
|
||||
transactionItemIds:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
processingFailureId::
|
||||
type: string
|
||||
format: uuid
|
||||
example: d8ee7035-fa3d-400e-9ad5-4fe8c4c73eb7
|
||||
resolved:
|
||||
type: boolean
|
||||
example: true
|
||||
required:
|
||||
- transactionItemId
|
||||
- resolved
|
||||
type: string
|
||||
format: uuid
|
||||
example: 1ad109d3-fd7d-4b6f-872b-220d492f385f
|
||||
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
|
||||
rfc9457:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
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
|
||||
180
src/openapi/orders/SE-orders-gboAgeProfile.yaml
Normal file
180
src/openapi/orders/SE-orders-gboAgeProfile.yaml
Normal file
@ -0,0 +1,180 @@
|
||||
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,12 +5,6 @@ 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:
|
||||
@ -56,13 +50,6 @@ paths:
|
||||
example: 1
|
||||
required: false
|
||||
description: The id of the touch point where the order was initiated.
|
||||
- in: query
|
||||
name: externalDeviceId
|
||||
schema:
|
||||
type: string
|
||||
example: "7a28bd54-7ca9-499a-a722-d15ab858ab99"
|
||||
required: false
|
||||
description: The external id of the device used to place the order.
|
||||
- in: query
|
||||
name: languageId
|
||||
schema:
|
||||
@ -132,7 +119,6 @@ paths:
|
||||
"touchPointId": 1,
|
||||
"name": "Perplex"
|
||||
},
|
||||
"externalDeviceId": "42e77532-d831-41da-b07a-7edb9bb7f004",
|
||||
"language":
|
||||
{
|
||||
"languageId": 1,
|
||||
@ -162,30 +148,6 @@ 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":
|
||||
[
|
||||
{
|
||||
@ -315,7 +277,7 @@ paths:
|
||||
{
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"addressType":
|
||||
{ "addressTypeId": 2, "name": "Billing" },
|
||||
{ "addressTypeId": 3, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -365,24 +327,21 @@ paths:
|
||||
"customerProfileId": 1337,
|
||||
"totalAmount": 121,
|
||||
"touchPointId": 1,
|
||||
"externalDeviceId": "b8ca9fdf-0bb9-4e49-b48d-41e395563377",
|
||||
"languageId": 1,
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"order_OrderStatus":
|
||||
[
|
||||
{
|
||||
"orderStatusId": 1,
|
||||
"orderStatusId": 4,
|
||||
"createdOn": "2024-03-22T09:00:00",
|
||||
"description": "Order succesvol betaald",
|
||||
},
|
||||
{
|
||||
"orderStatusId": 3,
|
||||
"createdOn": "2024-03-22T08:55:00",
|
||||
"description": "Concept order",
|
||||
"description": "Betaling in behandeling",
|
||||
},
|
||||
],
|
||||
"orderVouchers":
|
||||
[
|
||||
{
|
||||
"issuedVoucherId": "e81b2197-a6c2-45b6-9560-8ce8442e8604",
|
||||
"orderLineId": "97824d2e-5189-456d-b6da-4cca511a7685"
|
||||
},
|
||||
],
|
||||
"orderLines":
|
||||
[
|
||||
{
|
||||
@ -431,6 +390,57 @@ 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":
|
||||
@ -477,7 +487,6 @@ paths:
|
||||
"touchPointId": 1,
|
||||
"name": "Perplex"
|
||||
},
|
||||
"externalDeviceId": null,
|
||||
"language":
|
||||
{
|
||||
"languageId": 1,
|
||||
@ -503,7 +512,6 @@ paths:
|
||||
"description": "Betaling in behandeling",
|
||||
},
|
||||
],
|
||||
"orderVouchers": null,
|
||||
"orderLines":
|
||||
[
|
||||
{
|
||||
@ -626,7 +634,7 @@ paths:
|
||||
{
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"addressType":
|
||||
{ "addressTypeId": 2, "name": "Billing" },
|
||||
{ "addressTypeId": 3, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -650,7 +658,6 @@ paths:
|
||||
example:
|
||||
{
|
||||
"customerProfileId": 1337,
|
||||
"externalDeviceId": "fe68e624-b75f-48ca-a179-d5f86a8ab7d5",
|
||||
"totalAmount": 121,
|
||||
"languageId": 1,
|
||||
"lastUpdatedOn": "2024-03-22T09:00:00",
|
||||
@ -671,7 +678,6 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
|
||||
/orders/{orderId}/statuses:
|
||||
parameters:
|
||||
- in: path
|
||||
@ -709,143 +715,6 @@ 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
|
||||
@ -951,7 +820,7 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
examples:
|
||||
example:
|
||||
Minimum orderline requestBody:
|
||||
value:
|
||||
{
|
||||
@ -1037,7 +906,7 @@ paths:
|
||||
"orderCustomerAddresses":
|
||||
[
|
||||
{
|
||||
"addressTypeId": 2,
|
||||
"addressTypeId": 3,
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -2318,7 +2187,7 @@ paths:
|
||||
{
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"addressType":
|
||||
{ "addressTypeId": 2, "name": "Billing" },
|
||||
{ "addressTypeId": 3, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -2388,7 +2257,7 @@ paths:
|
||||
$ref: "#/components/schemas/unavailable"
|
||||
example:
|
||||
{
|
||||
"addressTypeId": 2,
|
||||
"addressTypeId": 3,
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
@ -2438,7 +2307,7 @@ paths:
|
||||
type: integer
|
||||
explode: false
|
||||
required: false
|
||||
description: Filter on possible types of addresses. 1 = Shipping, 2 = Billing.
|
||||
description: Filter on possible types of addresses. 1 = Shipping, 3 = Billing.
|
||||
- in: query
|
||||
name: street
|
||||
schema:
|
||||
@ -2494,7 +2363,7 @@ paths:
|
||||
"orderCustomerAddressId": "aa50047c-58ac-4f15-9448-ee000dfc6893",
|
||||
"orderCustomerId": "540d8b7a-d626-443f-8f99-c24398604d7a",
|
||||
"orderId": "73cca95a-81d1-468f-a8bf-99b36367001a",
|
||||
"addressType": { "addressTypeId": 2, "name": "Billing" },
|
||||
"addressType": { "addressTypeId": 3, "name": "Billing" },
|
||||
"street": "Kon. Julianaplein",
|
||||
"houseNumber": 10,
|
||||
"houseNumberSuffix": "a",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -313,7 +313,6 @@ paths:
|
||||
{
|
||||
"productId": 24,
|
||||
"parentProductId": null,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "30901",
|
||||
@ -430,7 +429,6 @@ paths:
|
||||
{
|
||||
"productId": 126,
|
||||
"parentProductId": null,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 1,
|
||||
"choiceKey": "isRenewable",
|
||||
@ -539,7 +537,6 @@ paths:
|
||||
{
|
||||
"productId": 119,
|
||||
"parentProductId": 126,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "30001",
|
||||
@ -655,7 +652,6 @@ paths:
|
||||
{
|
||||
"productId": 120,
|
||||
"parentProductId": 126,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "30001",
|
||||
@ -783,7 +779,6 @@ paths:
|
||||
{
|
||||
"productId": 49,
|
||||
"parentProductId": null,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 2,
|
||||
"choiceKey": "regio",
|
||||
@ -931,7 +926,6 @@ paths:
|
||||
{
|
||||
"productId": 109,
|
||||
"parentProductId": 49,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 3,
|
||||
"choiceKey": "allowedGboAgeProfiles",
|
||||
@ -1082,7 +1076,6 @@ paths:
|
||||
{
|
||||
"productId": 114,
|
||||
"parentProductId": 109,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 1,
|
||||
"choiceKey": "isRenewable",
|
||||
@ -1233,7 +1226,6 @@ paths:
|
||||
{
|
||||
"productId": 115,
|
||||
"parentProductId": 109,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 1,
|
||||
"choiceKey": "isRenewable",
|
||||
@ -1385,7 +1377,6 @@ paths:
|
||||
{
|
||||
"productId": 116,
|
||||
"parentProductId": 115,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "33615",
|
||||
@ -1535,7 +1526,6 @@ paths:
|
||||
{
|
||||
"productId": 117,
|
||||
"parentProductId": 115,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "33615",
|
||||
@ -1689,7 +1679,6 @@ paths:
|
||||
{
|
||||
"productId": 112,
|
||||
"parentProductId": 49,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 3,
|
||||
"choiceKey": "allowedGboAgeProfiles",
|
||||
@ -2161,10 +2150,6 @@ components:
|
||||
parentProductId:
|
||||
type: integer
|
||||
example: 1
|
||||
needsVoucher:
|
||||
type: boolean
|
||||
description: Indicates if the product needs a voucher (with this productId as requiredProductId) to be bought - if false, this is optional, but still allowed
|
||||
example: false
|
||||
layerInfo:
|
||||
$ref: '#/components/schemas/LayerInfoResponse'
|
||||
fikoArticleNumber:
|
||||
|
||||
@ -313,7 +313,6 @@ paths:
|
||||
{
|
||||
"productId": 24,
|
||||
"parentProductId": null,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "30901",
|
||||
@ -430,7 +429,6 @@ paths:
|
||||
{
|
||||
"productId": 126,
|
||||
"parentProductId": null,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 1,
|
||||
"choiceKey": "isRenewable",
|
||||
@ -539,7 +537,6 @@ paths:
|
||||
{
|
||||
"productId": 119,
|
||||
"parentProductId": 126,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "30001",
|
||||
@ -655,7 +652,6 @@ paths:
|
||||
{
|
||||
"productId": 120,
|
||||
"parentProductId": 126,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "30001",
|
||||
@ -783,7 +779,6 @@ paths:
|
||||
{
|
||||
"productId": 49,
|
||||
"parentProductId": null,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 2,
|
||||
"choiceKey": "regio",
|
||||
@ -931,7 +926,6 @@ paths:
|
||||
{
|
||||
"productId": 109,
|
||||
"parentProductId": 49,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 3,
|
||||
"choiceKey": "allowedGboAgeProfiles",
|
||||
@ -1082,7 +1076,6 @@ paths:
|
||||
{
|
||||
"productId": 114,
|
||||
"parentProductId": 109,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 1,
|
||||
"choiceKey": "isRenewable",
|
||||
@ -1233,7 +1226,6 @@ paths:
|
||||
{
|
||||
"productId": 115,
|
||||
"parentProductId": 109,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 1,
|
||||
"choiceKey": "isRenewable",
|
||||
@ -1385,7 +1377,6 @@ paths:
|
||||
{
|
||||
"productId": 116,
|
||||
"parentProductId": 115,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "33615",
|
||||
@ -1535,7 +1526,6 @@ paths:
|
||||
{
|
||||
"productId": 117,
|
||||
"parentProductId": 115,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": null,
|
||||
"fikoArticleNumber": "1234",
|
||||
"gboPackageTemplateId": "33615",
|
||||
@ -1689,7 +1679,6 @@ paths:
|
||||
{
|
||||
"productId": 112,
|
||||
"parentProductId": 49,
|
||||
"needsVoucher": false,
|
||||
"layerInfo": {
|
||||
"layerInfoId": 3,
|
||||
"choiceKey": "allowedGboAgeProfiles",
|
||||
@ -2161,10 +2150,6 @@ components:
|
||||
parentProductId:
|
||||
type: integer
|
||||
example: 1
|
||||
needsVoucher:
|
||||
type: boolean
|
||||
description: Indicates if the product needs a voucher (with this productId as requiredProductId) to be bought - if false, this is optional, but still allowed
|
||||
example: false
|
||||
layerInfo:
|
||||
$ref: '#/components/schemas/LayerInfoResponse'
|
||||
fikoArticleNumber:
|
||||
|
||||
@ -1,400 +0,0 @@
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: Service Engine APIs for HTM voucher for sales Touchpoint
|
||||
description: Service Engine APIs for HTM vouchers. These are NOT the CRUD APIs to the data hub. These ARE the APIs for sales touchpoints.
|
||||
version: "1.0"
|
||||
servers:
|
||||
- url: https://services.acc.api.htm.nl/abt/abtvouchersTouchpoint/1.0
|
||||
paths:
|
||||
/issuedvouchers/{voucherCode}:
|
||||
get:
|
||||
summary: Get details of a voucher, that was issued for a specific touchpoint
|
||||
description:
|
||||
Get details of an issued voucher for a specific touchpoint. This means that only products that the calling touchpoint is allowed to see or sell
|
||||
(i.e. has active sellingPeriods for touchPointId of the calling touchpoint) are returned.
|
||||
parameters:
|
||||
- name: voucherCode
|
||||
in: path
|
||||
required: true
|
||||
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/salesTouchpointIssuedVoucherResponse"
|
||||
examples:
|
||||
Voucher that grants a voucher-only product for free:
|
||||
summary: Voucher that grants a voucher-only product for free
|
||||
description: |-
|
||||
Voucher that grants a product (that can only be acquired via a voucher) for free.
|
||||
In this case, the voucher has an amountInclTax of 0. If the requiredProduct has a
|
||||
non-zero sellingPrice (amountInclTax), the difference between sellingPrice and
|
||||
voucher amountInclTax represents the granted discount. If the requiredProduct has
|
||||
a sellingPrice of 0, no "discount" is shown; just the voucher's amountInclTax.
|
||||
value:
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "HTM-A7J-128-PYT",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus": { "voucherStatusId": 2, "name": "issued" },
|
||||
"product":
|
||||
{
|
||||
"productId": 263,
|
||||
"productName": "Voucher Ooievaarspas-product AOW",
|
||||
"productDescription": "Voucher voor AOW-ers in Den Haag met een Ooievaarspas, die ingewisseld kan worden voor het product \"Ooievaarspas voor AOW-ers in Den Haag\"",
|
||||
"amountInclTax": 0,
|
||||
"requiredProducts":
|
||||
[
|
||||
{
|
||||
"productId": 982,
|
||||
"productName": "Ooievaarspas voor AOW-ers in Den Haag",
|
||||
"productDescription": "Vrij reizen bij HTM voor Haagse AOW-gerechtigden met een Ooievaarspas.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 2,
|
||||
"isTravelProduct": true,
|
||||
"name": "Afgekocht reisrecht",
|
||||
},
|
||||
"amountInclTax": 0,
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/982",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
"mandatoryCustomerDataItems":
|
||||
[
|
||||
{
|
||||
"mandatoryCustomerDataItemId": 8,
|
||||
"customerDataItem": "padBirthDate"
|
||||
}
|
||||
]
|
||||
}
|
||||
Voucher that grants a hybrid product for a reduced price:
|
||||
summary: Voucher that grants a hybrid product for a reduced price
|
||||
description: |-
|
||||
Voucher that grants a hybrid product (that can be acquired via voucher or via ordinary order flow)
|
||||
for a reduced price. In this case, the voucher has an amountInclTax > 0, which dictates the (modified)
|
||||
total amount that needs to be paid for said product. If the requiredProduct has a
|
||||
non-zero sellingPrice (amountInclTax), the difference between sellingPrice and
|
||||
voucher amountInclTax represents the granted discount. If the requiredProduct has
|
||||
a sellingPrice of 0, no "discount" is shown; just the voucher's amountInclTax./
|
||||
Specifically, in this example, the product "HTM 20% Korting" can be purchased for 1 euro instead of 5 euro.
|
||||
value:
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "HTM-A7J-128-PYT",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus": { "voucherStatusId": 2, "name": "issued" },
|
||||
"product":
|
||||
{
|
||||
"productId": 264,
|
||||
"productName": "Kortingsvoucher HTM 20% Korting ",
|
||||
"productDescription": "Voucher waarmee het product \"HTM 20% Korting\" voor een lagere prijs kan worden aangeschaft.",
|
||||
"amountInclTax": 100,
|
||||
"requiredProducts":
|
||||
[
|
||||
{
|
||||
"productId": 984,
|
||||
"productName": "HTM 20% Korting",
|
||||
"productDescription": "Reis met 20% korting op je betaalpas bij HTM.",
|
||||
"productCategory":
|
||||
{
|
||||
"productCategoryId": 1,
|
||||
"isTravelProduct": true,
|
||||
"name": "Kortingsabonnement",
|
||||
},
|
||||
"amountInclTax": 500,
|
||||
"_links":
|
||||
{
|
||||
"get_details":
|
||||
{
|
||||
"href": "https://api.integratielaag.nl/abt/touchpoint/1.0/products/984",
|
||||
"method": "GET",
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
"mandatoryCustomerDataItems": []
|
||||
}
|
||||
Voucher that grants a discount for a whole order:
|
||||
summary: Voucher that grants a discount for a whole order
|
||||
description: |-
|
||||
Voucher that grants a discount for a whole order. In this case, no requiredProduct is specified, and
|
||||
the voucher has an amountInclTax < 0. The (negative) amountInclTax dictates the value of the voucher,
|
||||
that is subtracted from the total order value as a discount (with a minimum order total of 0).
|
||||
value:
|
||||
{
|
||||
"issuedVoucherId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
||||
"voucherCode": "HTM-A7J-128-PYT",
|
||||
"fromInclusive": "2024-10-04T00:00:00.000",
|
||||
"untilInclusive": "2024-11-04T00:00:00.000",
|
||||
"voucherStatus": { "voucherStatusId": 2, "name": "issued" },
|
||||
"product":
|
||||
{
|
||||
"productId": 265,
|
||||
"productName": "Voucher 10 euro korting",
|
||||
"productDescription": "Voucher die 10 euro korting geeft op je gehele winkelmand.",
|
||||
"amountInclTax": -1000,
|
||||
"requiredProducts": []
|
||||
},
|
||||
"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",
|
||||
}
|
||||
"400":
|
||||
description: Bad request
|
||||
content:
|
||||
application/problem+json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/rfc9457"
|
||||
examples:
|
||||
Invalid voucher code:
|
||||
summary: Invalid voucher code
|
||||
value:
|
||||
{
|
||||
"type": "https://example.com/probs/bad-request",
|
||||
"title": "Invalid voucher code",
|
||||
"detail": "No valid voucher found for code VOUCHER123.",
|
||||
"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:
|
||||
salesTouchpointIssuedVoucherResponse:
|
||||
type: object
|
||||
required:
|
||||
- issuedVoucherId
|
||||
- voucherCode
|
||||
- fromInclusive
|
||||
- untilInclusive
|
||||
- voucherStatus
|
||||
- product
|
||||
- mandatoryCustomerDataItems
|
||||
properties:
|
||||
issuedVoucherId:
|
||||
type: string
|
||||
description: The unique (technical) identifier of the issued voucher instance.
|
||||
example: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90"
|
||||
voucherCode:
|
||||
type: string
|
||||
description: The voucher code that is shared with the customer and uniquely identifies this voucher.
|
||||
example: "HTM-A7J-128-PYT"
|
||||
fromInclusive:
|
||||
type: string
|
||||
format: date-time-offset
|
||||
description: |-
|
||||
The date and time the voucher becomes valid for redemption. This has nothing to do with
|
||||
the allowed start date of a requiredProduct (for this, the existing order flow logic is applied).
|
||||
example: "2024-10-04T00:00:00.000+02:00"
|
||||
untilInclusive:
|
||||
type: string
|
||||
format: date-time-offset
|
||||
description: |-
|
||||
The date and time the voucher becomes invalid for redemption. This has nothing to do with
|
||||
the maximum allowed start date of a requiredProduct (for this, the existing order flow logic is applied).
|
||||
example: "2024-11-04T00:00:00.000+01:00"
|
||||
voucherStatus:
|
||||
type: object
|
||||
required:
|
||||
- voucherStatusId
|
||||
- name
|
||||
description: |-
|
||||
The current status of the voucher. Can be any of the following:
|
||||
- 1 = new
|
||||
- 2 = issued
|
||||
- 3 = redeemed
|
||||
- 4 = revoked
|
||||
- 5 = expired
|
||||
- 6 = pendingRedemption
|
||||
properties:
|
||||
voucherStatusId:
|
||||
type: integer
|
||||
example: 2
|
||||
name:
|
||||
type: string
|
||||
example: "issued"
|
||||
product:
|
||||
type: object
|
||||
description: The "product" referencing the voucher definition that this voucher instance is based on
|
||||
required:
|
||||
- productId
|
||||
- productName
|
||||
- productDescription
|
||||
- amountInclTax
|
||||
properties:
|
||||
productId:
|
||||
type: integer
|
||||
example: 263
|
||||
productName:
|
||||
type: string
|
||||
example: Voucher Ooievaarspas-product AOW
|
||||
productDescription:
|
||||
type: string
|
||||
example: |-
|
||||
Voucher voor AOW-ers in Den Haag met een Ooievaarspas, die ingewisseld kan worden
|
||||
voor het product "Ooievaarspas voor AOW-ers in Den Haag".
|
||||
amountInclTax:
|
||||
type: integer
|
||||
description: |-
|
||||
When combined with a requiredProduct, the (positive or zero) amountInclTax dictates
|
||||
the (modified) total amount that needs to be paid for said product. When the requiredProduct
|
||||
has a sellingPrice > 0, the difference between sellingPrice and voucher amountInclTax
|
||||
represents the granted discount.
|
||||
When not combined with a required product, the (negative) amountInclTax dictates
|
||||
the value of the voucher, that is subtracted from the total order value as a discount
|
||||
(with a minimum order total of 0).
|
||||
example: 0
|
||||
requiredProducts:
|
||||
type: array
|
||||
description: |-
|
||||
Currently, only one requiredProduct is supported and thus, this array can contain at
|
||||
most one element.
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- productId
|
||||
properties:
|
||||
productId:
|
||||
type: integer
|
||||
example: 892
|
||||
productName:
|
||||
type: string
|
||||
example: "Ooievaarspas voor AOW-ers in Den Haag"
|
||||
productDescription:
|
||||
type: string
|
||||
example: "Vrij reizen bij HTM voor Haagse AOW-gerechtigden met een Ooievaarspas."
|
||||
productCategory:
|
||||
type: object
|
||||
required:
|
||||
- productCategoryId
|
||||
- isTravelProduct
|
||||
- name
|
||||
properties:
|
||||
productCategoryId:
|
||||
type: integer
|
||||
example: 2
|
||||
isTravelProduct:
|
||||
type: boolean
|
||||
example: true
|
||||
name:
|
||||
type: string
|
||||
example: "Afgekocht reisrecht"
|
||||
amountInclTax:
|
||||
type: integer
|
||||
description: |-
|
||||
Selling price of the product in cents (including tax, if applicable) that is
|
||||
currently active for the calling touchpoint. When 0, the product is free of charge.
|
||||
example: 0
|
||||
imageReference:
|
||||
type: string
|
||||
description: Can be a URL or a base64 encoded image
|
||||
example: https://www.htm.nl/nog-onbekende-productafbeelding
|
||||
_links:
|
||||
type: object
|
||||
properties:
|
||||
get_details:
|
||||
type: object
|
||||
description: Link to get more details for the product that this voucher instance applies to
|
||||
properties:
|
||||
href:
|
||||
type: string
|
||||
example: https://api.integratielaag.nl/abt/touchpoint/1.0/products/982
|
||||
method:
|
||||
type: string
|
||||
example: GET
|
||||
mandatoryCustomerDataItems:
|
||||
type: array
|
||||
description: |-
|
||||
List of mandatory customer data items that are required to redeem this voucher.\
|
||||
The values provided for these data items may be checked against allowed values as provided by the voucher issuer.
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- mandatoryCustomerDataItemId
|
||||
- customerDataItem
|
||||
properties:
|
||||
mandatoryCustomerDataItemId:
|
||||
type: integer
|
||||
example: 8
|
||||
customerDataItem:
|
||||
type: string
|
||||
example: padBirthdate
|
||||
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
@ -1553,9 +1553,6 @@ components:
|
||||
- productCategoryId: 8
|
||||
name: Saldo
|
||||
isTravelProduct: true
|
||||
- productCategoryId: 9
|
||||
name: Voucher
|
||||
isTravelProduct: false
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/productCategoryGetEntity'
|
||||
@ -1814,7 +1811,7 @@ components:
|
||||
- mandatoryCustomerDataItemId: 5
|
||||
customerDataItem: address
|
||||
- mandatoryCustomerDataItemId: 6
|
||||
customerDataItem: voucher
|
||||
customerDataItem: phone
|
||||
- mandatoryCustomerDataItemId: 7
|
||||
customerDataItem: ovPayToken
|
||||
- mandatoryCustomerDataItemId: 8
|
||||
@ -1823,8 +1820,6 @@ components:
|
||||
customerDataItem: shippingAddress
|
||||
- mandatoryCustomerDataItemId: 10
|
||||
customerDataItem: billingAddress
|
||||
- mandatoryCustomerDataItemId: 11
|
||||
customerDataItem: startDate
|
||||
items:
|
||||
$ref: '#/components/schemas/mandatoryCustomerDataItemGetEntity'
|
||||
type: array
|
||||
|
||||
@ -46,13 +46,6 @@ paths:
|
||||
when false, return only non-archived products (isArchived = false).
|
||||
schema:
|
||||
type: boolean
|
||||
- name: onlyVouchers
|
||||
in: query
|
||||
required: false
|
||||
description: |-
|
||||
When omitted, defaults to false (i.e. return all normal products that are NOT voucher definitions); when true, return only voucher definitions
|
||||
schema:
|
||||
type: boolean
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
@ -394,7 +387,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"productName": "HTM pilot 90% korting",
|
||||
"productDescription": "Reis met 90% korting gedurende de eerste F&F pilot!",
|
||||
@ -482,7 +474,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"productName": "HTM pilot 90% korting",
|
||||
"productDescription": "Reis met 90% korting gedurende de eerste F&F pilot!",
|
||||
@ -569,7 +560,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"productName": "HTM pilot 90% korting",
|
||||
"productDescription": "Reis met 90% korting gedurende de eerste F&F pilot!",
|
||||
@ -690,7 +680,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "33610",
|
||||
"productName": "HTM Regio Vrij DH73",
|
||||
"productDescription": "Voor een vast bedrag onbeperkt reizen met EBS, HTM en RET in het gekozen gebied in de regio Rotterdam Den Haag.",
|
||||
@ -877,7 +866,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "HTM pilot 90% korting",
|
||||
@ -1040,7 +1028,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "30901",
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "HTM pilot 90% korting",
|
||||
@ -1283,7 +1270,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": "33610",
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "HTM Regio Vrij DH73",
|
||||
@ -1489,7 +1475,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": null,
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "IBAN wijzigen functioneel product",
|
||||
@ -1687,7 +1672,6 @@ paths:
|
||||
"fikoArticleNumber": "1234",
|
||||
"isValid": true,
|
||||
"isArchived": false,
|
||||
"needsVoucher": false,
|
||||
"gboPackageTemplateId": null,
|
||||
"tapConnectProductCode": null,
|
||||
"productName": "OV-pas saldo (1 eurocent)",
|
||||
@ -2791,10 +2775,6 @@ components:
|
||||
type: boolean
|
||||
description: Indicates if the product is archived - if true, the Service Engine will prevent touchpoints from seeing this product
|
||||
example: false
|
||||
needsVoucher:
|
||||
type: boolean
|
||||
description: Indicates if the product needs a voucher (with this productId as requiredProductId) to be bought - if false, this is optional, but still allowed
|
||||
example: false
|
||||
gboPackageTemplateId:
|
||||
type: string
|
||||
example: '30901'
|
||||
@ -3152,10 +3132,6 @@ components:
|
||||
type: boolean
|
||||
description: Indicates if the product is archived - if true, the Service Engine will prevent touchpoints from seeing this product
|
||||
example: false
|
||||
needsVoucher:
|
||||
type: boolean
|
||||
description: Indicates if the product needs a voucher (with this productId as requiredProductId) to be bought - if false, this is optional, but still allowed
|
||||
example: false
|
||||
gboPackageTemplateId:
|
||||
type: string
|
||||
description: >-
|
||||
@ -3527,10 +3503,6 @@ components:
|
||||
type: boolean
|
||||
description: Indicates if the product is archived - if true, the Service Engine will prevent touchpoints from seeing this product
|
||||
example: false
|
||||
needsVoucher:
|
||||
type: boolean
|
||||
description: Indicates if the product needs a voucher (with this productId as requiredProductId) to be bought - if false, this is optional, but still allowed
|
||||
example: false
|
||||
gboPackageTemplateId:
|
||||
type: string
|
||||
description: >-
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,477 +0,0 @@
|
||||
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