first
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Csob.Services;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// AISP – account information. All endpoints require the ČSOB credential headers
|
||||
/// (eIDAS certificate, access token, API key, TPP name). See the Swagger description for details.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("accounts")]
|
||||
[Produces("application/json")]
|
||||
[Tags("AISP – Accounts")]
|
||||
public sealed class AccountsController : ControllerBase
|
||||
{
|
||||
private readonly AccountsService _service;
|
||||
|
||||
public AccountsController(AccountsService service) => _service = service;
|
||||
|
||||
/// <summary>List the PSU's payment accounts (paged).</summary>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> List(
|
||||
[FromQuery] int? page, [FromQuery] int? size, [FromQuery] string? sort, [FromQuery] string? order, CancellationToken ct)
|
||||
=> Ok(await _service.ListAsync(page, size, sort, order, ct));
|
||||
|
||||
/// <summary>Get the balance(s) of an account.</summary>
|
||||
[HttpGet("{id}/balance")]
|
||||
public async Task<IActionResult> Balance(string id, [FromQuery] string? currency, CancellationToken ct)
|
||||
=> Ok(await _service.BalanceAsync(id, currency, ct));
|
||||
|
||||
/// <summary>List booked transactions of an account (paged, optional date range).</summary>
|
||||
[HttpGet("{id}/transactions")]
|
||||
public async Task<IActionResult> Transactions(
|
||||
string id,
|
||||
[FromQuery] int? page, [FromQuery] int? size, [FromQuery] string? sort, [FromQuery] string? order,
|
||||
[FromQuery] string? dateFrom, [FromQuery] string? dateTo, CancellationToken ct)
|
||||
=> Ok(await _service.TransactionsAsync(id, new TransactionQuery
|
||||
{
|
||||
Page = page, Size = size, Sort = sort, Order = order, DateFrom = dateFrom, DateTo = dateTo,
|
||||
}, ct));
|
||||
|
||||
/// <summary>List awaiting (pending) transactions of an account.</summary>
|
||||
[HttpGet("{id}/transactions/awaiting")]
|
||||
public async Task<IActionResult> Awaiting(string id, [FromQuery] int? page, [FromQuery] int? size, CancellationToken ct)
|
||||
=> Ok(await _service.AwaitingTransactionsAsync(id, page, size, ct));
|
||||
|
||||
/// <summary>List the account's existing standing orders.</summary>
|
||||
[HttpGet("{id}/standing-orders")]
|
||||
public async Task<IActionResult> StandingOrders(string id, [FromQuery] int? page, [FromQuery] int? size, CancellationToken ct)
|
||||
=> Ok(await _service.StandingOrdersAsync(id, page, size, ct));
|
||||
|
||||
/// <summary>Get a standing-order detail for the account.</summary>
|
||||
[HttpGet("{id}/standing-orders/{standingOrderId}")]
|
||||
public async Task<IActionResult> StandingOrderDetail(string id, string standingOrderId, CancellationToken ct)
|
||||
=> Ok(await _service.StandingOrderDetailAsync(id, standingOrderId, ct));
|
||||
|
||||
/// <summary>List the account's direct-debit mandates.</summary>
|
||||
[HttpGet("{id}/direct-debits")]
|
||||
public async Task<IActionResult> DirectDebits(string id, [FromQuery] int? page, [FromQuery] int? size, CancellationToken ct)
|
||||
=> Ok(await _service.DirectDebitsAsync(id, page, size, ct));
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Csob.Services;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Common – PSU consent lifecycle. Requires the ČSOB credential headers. The consent body is
|
||||
/// forwarded to ČSOB as raw JSON (COBS consent shape).
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("consents")]
|
||||
[Produces("application/json")]
|
||||
[Tags("Consents")]
|
||||
public sealed class ConsentsController : ControllerBase
|
||||
{
|
||||
private readonly ConsentsService _service;
|
||||
|
||||
public ConsentsController(ConsentsService service) => _service = service;
|
||||
|
||||
/// <summary>Create a consent.</summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromBody] JsonNode request, CancellationToken ct)
|
||||
=> Ok(await _service.CreateAsync(request, ct));
|
||||
|
||||
/// <summary>Get a consent detail.</summary>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> Detail(string id, CancellationToken ct)
|
||||
=> Ok(await _service.DetailAsync(id, ct));
|
||||
|
||||
/// <summary>Revoke a consent.</summary>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> Delete(string id, CancellationToken ct)
|
||||
=> Ok(await _service.DeleteAsync(id, ct));
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Csob.Services;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// PISP – direct-debit mandate initiation and its authorization (sign) flow. Requires the ČSOB
|
||||
/// credential headers. The mandate body is forwarded to ČSOB as raw JSON (COBS direct-debit shape).
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("direct-debits")]
|
||||
[Produces("application/json")]
|
||||
[Tags("PISP – Direct debits")]
|
||||
public sealed class DirectDebitsController : ControllerBase
|
||||
{
|
||||
private readonly DirectDebitsService _service;
|
||||
|
||||
public DirectDebitsController(DirectDebitsService service) => _service = service;
|
||||
|
||||
/// <summary>Initiate a direct-debit mandate.</summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Initiate([FromBody] JsonNode request, CancellationToken ct)
|
||||
=> Ok(await _service.InitiateAsync(request, ct));
|
||||
|
||||
/// <summary>Get the direct-debit mandate detail.</summary>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> Detail(string id, CancellationToken ct)
|
||||
=> Ok(await _service.DetailAsync(id, ct));
|
||||
|
||||
/// <summary>Get the direct-debit instruction status.</summary>
|
||||
[HttpGet("{id}/status")]
|
||||
public async Task<IActionResult> Status(string id, CancellationToken ct)
|
||||
=> Ok(await _service.StatusAsync(id, ct));
|
||||
|
||||
/// <summary>Revoke a direct-debit mandate.</summary>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> Cancel(string id, CancellationToken ct)
|
||||
=> Ok(await _service.CancelAsync(id, ct));
|
||||
|
||||
/// <summary>Start the authorization (SCA) of a direct-debit mandate. Returns the PSU redirect details.</summary>
|
||||
[HttpPost("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> StartSign(string id, string signId, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] JsonNode? body, CancellationToken ct)
|
||||
=> Ok(await _service.StartSignAsync(id, signId, body, ct));
|
||||
|
||||
/// <summary>Get the current state of an authorization (sign) transaction.</summary>
|
||||
[HttpGet("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> SignStatus(string id, string signId, CancellationToken ct)
|
||||
=> Ok(await _service.SignStatusAsync(id, signId, ct));
|
||||
|
||||
/// <summary>Finalize an authorization (sign) transaction.</summary>
|
||||
[HttpPut("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> FinalizeSign(string id, string signId, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] JsonNode? body, CancellationToken ct)
|
||||
=> Ok(await _service.FinalizeSignAsync(id, signId, body, ct));
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Csob.Configuration;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>Service metadata endpoints. These do not require ČSOB credentials.</summary>
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Tags("Meta")]
|
||||
public sealed class MetaController : ControllerBase
|
||||
{
|
||||
private readonly CsobSettings _settings;
|
||||
|
||||
public MetaController(CsobSettings settings) => _settings = settings;
|
||||
|
||||
/// <summary>Liveness probe.</summary>
|
||||
[HttpGet("/health")]
|
||||
public IActionResult Health() => Ok(new { status = "ok" });
|
||||
|
||||
/// <summary>Service name, version and the configured upstream endpoints (no secrets).</summary>
|
||||
[HttpGet("/version")]
|
||||
public IActionResult Version() => Ok(new
|
||||
{
|
||||
app = _settings.AppName,
|
||||
version = _settings.AppVersion,
|
||||
language = "dotnet",
|
||||
api = "ČSOB PSD2 (Czech Open Banking Standard / COBS)",
|
||||
root_path = _settings.RootPath,
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Reports the non-secret configuration. This service is stateless and multi-tenant: it holds
|
||||
/// no credentials, so there is nothing per-client to report — every secret is supplied per
|
||||
/// request via headers.
|
||||
/// </summary>
|
||||
[HttpGet("/status")]
|
||||
public IActionResult Status() => Ok(new
|
||||
{
|
||||
stateless = true,
|
||||
api_base_url = _settings.ApiBaseUrl,
|
||||
oauth_authorize_url = _settings.OAuthAuthorizeUrl,
|
||||
oauth_token_url = _settings.OAuthTokenUrl,
|
||||
request_timeout_seconds = _settings.RequestTimeoutSeconds,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Csob.Models;
|
||||
using Csob.Services;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// OAuth2 Authorization Code helper for the ČSOB PSD2 PSU consent flow. Build the authorization URL,
|
||||
/// redirect the PSU to it, then exchange the returned code for tokens. The token/refresh calls run
|
||||
/// over mutual TLS, so they require the <c>X-CSOB-Certificate</c> header; client id/secret are also
|
||||
/// supplied per request (this service is multi-tenant).
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("oauth")]
|
||||
[Produces("application/json")]
|
||||
[Tags("OAuth2")]
|
||||
public sealed class OAuthController : ControllerBase
|
||||
{
|
||||
private readonly OAuthService _service;
|
||||
|
||||
public OAuthController(OAuthService service) => _service = service;
|
||||
|
||||
/// <summary>Build the ČSOB authorization URL to which the PSU must be redirected.</summary>
|
||||
[HttpGet("authorization-url")]
|
||||
public IActionResult AuthorizationUrl(
|
||||
[FromQuery] string redirectUri, [FromQuery] string? scope, [FromQuery] string? state)
|
||||
=> Ok(_service.BuildAuthorizationUrl(redirectUri, scope, state));
|
||||
|
||||
/// <summary>Exchange an authorization code for an access/refresh token (mutual TLS).</summary>
|
||||
[HttpPost("token")]
|
||||
public async Task<ActionResult<JsonNode>> Token([FromBody] TokenExchangeRequest request, CancellationToken ct)
|
||||
=> Ok(await _service.ExchangeCodeAsync(request, ct));
|
||||
|
||||
/// <summary>Refresh an access token using a refresh token (mutual TLS).</summary>
|
||||
[HttpPost("refresh")]
|
||||
public async Task<ActionResult<JsonNode>> Refresh([FromBody] TokenRefreshRequest request, CancellationToken ct)
|
||||
=> Ok(await _service.RefreshAsync(request, ct));
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Csob.Models;
|
||||
using Csob.Services;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// PISP – single payment initiation and its authorization (sign) flow. Requires the ČSOB credential
|
||||
/// headers. After <c>POST /payments</c> the response carries <c>signInfo.signId</c>; use it with the
|
||||
/// sign endpoints to drive Strong Customer Authentication (SCA).
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("payments")]
|
||||
[Produces("application/json")]
|
||||
[Tags("PISP – Payments")]
|
||||
public sealed class PaymentsController : ControllerBase
|
||||
{
|
||||
private readonly PaymentsService _service;
|
||||
|
||||
public PaymentsController(PaymentsService service) => _service = service;
|
||||
|
||||
/// <summary>Initiate a domestic (DMCT) or SEPA (ESCT) payment.</summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Initiate([FromBody] PaymentInitiationRequest request, CancellationToken ct)
|
||||
=> Ok(await _service.InitiateAsync(request, ct));
|
||||
|
||||
/// <summary>Get the full payment detail.</summary>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> Detail(string id, CancellationToken ct)
|
||||
=> Ok(await _service.DetailAsync(id, ct));
|
||||
|
||||
/// <summary>Get the payment instruction status.</summary>
|
||||
[HttpGet("{id}/status")]
|
||||
public async Task<IActionResult> Status(string id, CancellationToken ct)
|
||||
=> Ok(await _service.StatusAsync(id, ct));
|
||||
|
||||
/// <summary>Cancel a not-yet-authorized payment.</summary>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> Cancel(string id, CancellationToken ct)
|
||||
=> Ok(await _service.CancelAsync(id, ct));
|
||||
|
||||
/// <summary>Start the authorization (SCA) of a payment. Returns the PSU redirect details.</summary>
|
||||
[HttpPost("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> StartSign(string id, string signId, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] JsonNode? body, CancellationToken ct)
|
||||
=> Ok(await _service.StartSignAsync(id, signId, body, ct));
|
||||
|
||||
/// <summary>Get the current state of an authorization (sign) transaction.</summary>
|
||||
[HttpGet("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> SignStatus(string id, string signId, CancellationToken ct)
|
||||
=> Ok(await _service.SignStatusAsync(id, signId, ct));
|
||||
|
||||
/// <summary>Finalize an authorization (sign) transaction.</summary>
|
||||
[HttpPut("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> FinalizeSign(string id, string signId, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] JsonNode? body, CancellationToken ct)
|
||||
=> Ok(await _service.FinalizeSignAsync(id, signId, body, ct));
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Csob.Models;
|
||||
using Csob.Services;
|
||||
|
||||
namespace Csob.Controllers;
|
||||
|
||||
/// <summary>PISP – standing-order initiation and its authorization (sign) flow. Requires the ČSOB credential headers.</summary>
|
||||
[ApiController]
|
||||
[Route("standing-orders")]
|
||||
[Produces("application/json")]
|
||||
[Tags("PISP – Standing orders")]
|
||||
public sealed class StandingOrdersController : ControllerBase
|
||||
{
|
||||
private readonly StandingOrdersService _service;
|
||||
|
||||
public StandingOrdersController(StandingOrdersService service) => _service = service;
|
||||
|
||||
/// <summary>Initiate a standing order.</summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Initiate([FromBody] StandingOrderInitiationRequest request, CancellationToken ct)
|
||||
=> Ok(await _service.InitiateAsync(request, ct));
|
||||
|
||||
/// <summary>Get the standing-order detail.</summary>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> Detail(string id, CancellationToken ct)
|
||||
=> Ok(await _service.DetailAsync(id, ct));
|
||||
|
||||
/// <summary>Get the standing-order instruction status.</summary>
|
||||
[HttpGet("{id}/status")]
|
||||
public async Task<IActionResult> Status(string id, CancellationToken ct)
|
||||
=> Ok(await _service.StatusAsync(id, ct));
|
||||
|
||||
/// <summary>Cancel a standing order.</summary>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> Cancel(string id, CancellationToken ct)
|
||||
=> Ok(await _service.CancelAsync(id, ct));
|
||||
|
||||
/// <summary>Start the authorization (SCA) of a standing order. Returns the PSU redirect details.</summary>
|
||||
[HttpPost("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> StartSign(string id, string signId, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] JsonNode? body, CancellationToken ct)
|
||||
=> Ok(await _service.StartSignAsync(id, signId, body, ct));
|
||||
|
||||
/// <summary>Get the current state of an authorization (sign) transaction.</summary>
|
||||
[HttpGet("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> SignStatus(string id, string signId, CancellationToken ct)
|
||||
=> Ok(await _service.SignStatusAsync(id, signId, ct));
|
||||
|
||||
/// <summary>Finalize an authorization (sign) transaction.</summary>
|
||||
[HttpPut("{id}/sign/{signId}")]
|
||||
public async Task<IActionResult> FinalizeSign(string id, string signId, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] JsonNode? body, CancellationToken ct)
|
||||
=> Ok(await _service.FinalizeSignAsync(id, signId, body, ct));
|
||||
}
|
||||
Reference in New Issue
Block a user