diff --git a/VERAG_REST_SERVER/App_Start/BasicAuthenticationAttribute.vb b/VERAG_REST_SERVER/App_Start/BasicAuthenticationAttribute.vb index cd1c25a..0ec12e4 100644 --- a/VERAG_REST_SERVER/App_Start/BasicAuthenticationAttribute.vb +++ b/VERAG_REST_SERVER/App_Start/BasicAuthenticationAttribute.vb @@ -8,7 +8,6 @@ Imports VERAG_PROG_ALLGEMEIN - Public Class BasicAuthenticationAttribute Inherits AuthorizationFilterAttribute diff --git a/VERAG_REST_SERVER/App_Start/SwaggerConfig.vb b/VERAG_REST_SERVER/App_Start/SwaggerConfig.vb index 10253b2..8c69d9f 100644 --- a/VERAG_REST_SERVER/App_Start/SwaggerConfig.vb +++ b/VERAG_REST_SERVER/App_Start/SwaggerConfig.vb @@ -1,12 +1,11 @@ -Imports System.IO -Imports System.Net.Http -Imports System.Reflection -Imports System.Web.Http +Imports System.Web.Http Imports System.Web.Http.Description Imports System.Web.Routing Imports Microsoft.Extensions.Options Imports Swashbuckle.Application Imports NSwag.AspNet.Owin +Imports System.IO +Imports System.Reflection @@ -87,12 +86,13 @@ Public Class SwaggerConfig Public Shared Sub Register(ByVal config As HttpConfiguration) - RouteTable.Routes.MapOwinPath("swagger", Function(app) As Owin.IAppBuilder + RouteTable.Routes.MapOwinPath("swagger", Sub(app) app.UseSwaggerUi(GetType(WebApiApplication).Assembly, Function(settings) As SwaggerUiSettings(Of NSwag.Generation.WebApi.WebApiOpenApiDocumentGeneratorSettings) settings.MiddlewareBasePath = "/swagger" + settings.GeneratorSettings.OperationProcessors.Add(New WiseWebhookExampleProcessor()) settings.GeneratorSettings.DefaultUrlTemplate = "api/{controller}/{id}" settings.DocumentTitle = descr settings.DocExpansion = "list" @@ -102,8 +102,7 @@ Public Class SwaggerConfig - Return app - End Function) + End Sub) End Sub diff --git a/VERAG_REST_SERVER/App_Start/WiseWebhookExampleProcessor.vb b/VERAG_REST_SERVER/App_Start/WiseWebhookExampleProcessor.vb new file mode 100644 index 0000000..cd8da84 --- /dev/null +++ b/VERAG_REST_SERVER/App_Start/WiseWebhookExampleProcessor.vb @@ -0,0 +1,31 @@ +Imports NSwag.Generation.Processors +Imports NSwag.Generation.Processors.Contexts +Imports NJsonSchema + +Public Class WiseWebhookExampleProcessor + Implements IOperationProcessor + + Public Function Process(context As OperationProcessorContext) As Boolean Implements IOperationProcessor.Process + If context.ControllerType.Name = "WiseController" AndAlso context.MethodInfo.Name = "Webhook" Then + Dim operation = context.OperationDescription.Operation + If operation.RequestBody IsNot Nothing AndAlso operation.RequestBody.Content.ContainsKey("application/json") Then + Dim content = operation.RequestBody.Content("application/json") + content.Example = New With { + .event_type = "balance.credit", + .data = New With { + .id = 123456789, + .balance_id = 99887766, + .amount = New With { + .value = 1500.00, + .currency = "EUR" + }, + .occurred_at = "2025-12-06T10:15:30Z", + .description = "Incoming transfer", + .sender_name = "ACME GmbH" + } + } + End If + End If + Return True + End Function +End Class diff --git a/VERAG_REST_SERVER/Controllers/Wise/WiseController.vb b/VERAG_REST_SERVER/Controllers/Wise/WiseController.vb new file mode 100644 index 0000000..afb01ee --- /dev/null +++ b/VERAG_REST_SERVER/Controllers/Wise/WiseController.vb @@ -0,0 +1,100 @@ +Imports System.Net +Imports System.IO +Imports System.Web.Http +Imports System.Web.Http.Description +Imports System.Diagnostics +Imports Newtonsoft.Json +Imports VERAG_PROG_ALLGEMEIN +Imports VERAG_REST_SERVER + +Namespace ApiController.Controllers + + Public Class WiseController + Inherits System.Web.Http.ApiController + + + + + + Public Function Webhook( payload As WiseWebhookRequest) As IHttpActionResult + Dim json As String = "" + Try + If payload IsNot Nothing Then + json = JsonConvert.SerializeObject(payload) + Else + If Request IsNot Nothing AndAlso Request.Content IsNot Nothing Then + json = Request.Content.ReadAsStringAsync().Result + End If + End If + Catch + End Try + + Dim saveResult = SaveWiseWebhook(json, payload) + If payload Is Nothing Then + ' Invalid JSON or empty body, but Wise expects 200 OK + Return Ok() + End If + + Try + If payload.EventType = "balance.credit" AndAlso payload.Data IsNot Nothing Then + Dim amountVal As Decimal = 0 + Dim currency As String = "" + + If payload.Data.Amount IsNot Nothing Then + amountVal = payload.Data.Amount.Value + currency = payload.Data.Amount.Currency + End If + + Dim balanceId = payload.Data.BalanceId + Dim senderName = payload.Data.SenderName + + ' Log the details + Trace.WriteLine(String.Format("Wise Webhook: Event={0}, Amount={1} {2}, BalanceId={3}, Sender={4}", + payload.EventType, amountVal, currency, balanceId, senderName)) + End If + Catch ex As Exception + ' Log exception but return 200 OK as per requirements + Trace.WriteLine("Wise Webhook Error: " & ex.Message) + End Try + + Return Ok() + End Function + + Private Shared fileLock As New Object() + + Private Function SaveWiseWebhook(json As String, payload As WiseWebhookRequest) As String + Try + Dim tmpPath As String = "" + If Environment.GetFolderPath(Environment.SpecialFolder.Personal) = "" Then + tmpPath = "G:\temp\Verag\DatenTMP\WISE\" + Else + tmpPath = Path.GetTempPath() & "\VERAG\DatenTMP\" + End If + tmpPath = tmpPath.Replace("\\", "\") + If Not My.Computer.FileSystem.DirectoryExists(tmpPath) Then + My.Computer.FileSystem.CreateDirectory(tmpPath) + End If + + Dim evt = If(payload IsNot Nothing AndAlso payload.EventType IsNot Nothing, payload.EventType, "unknown") + Dim bal = If(payload IsNot Nothing AndAlso payload.Data IsNot Nothing, payload.Data.BalanceId.ToString(), "unknown") + Dim name = VERAG_PROG_ALLGEMEIN.cDATENSERVER.replaceInvalidCahr($"WISE_{evt}_{bal}_{Now:ddMMyy_HHmmss}") + Dim extension = ".txt" + Dim destPath = tmpPath & name + + SyncLock fileLock + While File.Exists(destPath & extension) + destPath = tmpPath & name & "_" & Now.ToString("yyyyMMddHHmmssfff") + End While + End SyncLock + + Dim contentToWrite = If(String.IsNullOrEmpty(json), "", json) + File.WriteAllText(destPath & extension, contentToWrite, System.Text.Encoding.UTF8) + + Return "OK" + Catch ex As Exception + VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR(ex.Message, ex.StackTrace & vbNewLine, System.Reflection.MethodInfo.GetCurrentMethod.Name) + Return "ERR" + End Try + End Function + End Class +End Namespace diff --git a/VERAG_REST_SERVER/Models/WiseWebhookModels.vb b/VERAG_REST_SERVER/Models/WiseWebhookModels.vb new file mode 100644 index 0000000..8f1fd54 --- /dev/null +++ b/VERAG_REST_SERVER/Models/WiseWebhookModels.vb @@ -0,0 +1,37 @@ +Imports Newtonsoft.Json + +Public Class WiseWebhookRequest + + Public Property EventType As String + + + Public Property Data As WiseWebhookData +End Class + +Public Class WiseWebhookData + + Public Property Id As Long + + + Public Property BalanceId As Long + + + Public Property Amount As WiseWebhookAmount + + + Public Property OccurredAt As DateTime + + + Public Property Description As String + + + Public Property SenderName As String +End Class + +Public Class WiseWebhookAmount + + Public Property Value As Decimal + + + Public Property Currency As String +End Class diff --git a/VERAG_REST_SERVER/VERAG_REST_SERVER.vbproj b/VERAG_REST_SERVER/VERAG_REST_SERVER.vbproj index e3800df..1f6ba59 100644 --- a/VERAG_REST_SERVER/VERAG_REST_SERVER.vbproj +++ b/VERAG_REST_SERVER/VERAG_REST_SERVER.vbproj @@ -377,8 +377,10 @@ + + @@ -390,6 +392,7 @@ Global.asax + diff --git a/VERAG_REST_SERVER/Web.config b/VERAG_REST_SERVER/Web.config index 066d493..742f94e 100644 --- a/VERAG_REST_SERVER/Web.config +++ b/VERAG_REST_SERVER/Web.config @@ -1,4 +1,4 @@ - +