1+ //-----------------------------------------------------------------------------
2+ // Filename: WebhookUpdate.cs
3+ //
4+ // Description: Model for updating a merchant webhook.
5+ //
6+ // Author(s):
7+ // Donal O'Connor ([email protected] ) 8+ //
9+ // History:
10+ // 19 09 2025 Donal O'Connor Created, Harcourt St, Dublin, Ireland.
11+ //
12+ // License:
13+ // MIT.
14+ //-----------------------------------------------------------------------------
15+
16+ using NoFrixion . MoneyMoov . Attributes ;
17+ using NoFrixion . MoneyMoov . Enums ;
18+ using System . ComponentModel . DataAnnotations ;
19+
20+ namespace NoFrixion . MoneyMoov . Models ;
21+
22+ public class WebhookUpdate : IValidatableObject
23+ {
24+ public const int SECRET_MAX_LENGTH = 32 ;
25+
26+ public Guid ID { get ; set ; }
27+
28+ [ Required ]
29+ public Guid MerchantID { get ; set ; }
30+
31+ [ Obsolete ( "This field has been deprecated. Please use ResourceTypes instead." ) ]
32+ public WebhookResourceTypesEnum Type
33+ {
34+ get =>
35+ ResourceTypes . Any ( ) ? ResourceTypes . ToFlagEnum ( ) : WebhookResourceTypesEnum . None ;
36+
37+ init
38+ {
39+ if ( value == WebhookResourceTypesEnum . None )
40+ {
41+ ResourceTypes . Clear ( ) ;
42+ }
43+ else
44+ {
45+ ResourceTypes = value . ToList ( ) ;
46+ }
47+ }
48+ }
49+
50+ /// <summary>
51+ /// The resource types that the webhook should be generated for.
52+ /// </summary>
53+ public List < WebhookResourceTypesEnum > ResourceTypes { get ; set ; } = new List < WebhookResourceTypesEnum > ( ) ;
54+
55+ /// <summary>
56+ /// The destination URL for the webhook.
57+ /// Required for webhook notifications.
58+ /// </summary>
59+ public string ? DestinationUrl { get ; set ; }
60+
61+ public bool Retry { get ; set ; } = true ;
62+
63+ /// <summary>
64+ /// The secret key required to authenticate webhook notifications.
65+ /// Required for webhook notifications.
66+ /// </summary>
67+ public string ? Secret { get ; set ; }
68+
69+ public bool IsActive { get ; set ; } = true ;
70+
71+ /// <summary>
72+ /// The recipient email address(es) for notifications. Multiple addresses can be separated by a comma, semicolon, or space.
73+ /// Reruired for email notifications.
74+ /// </summary>
75+ [ EmailAddressMultiple ( ErrorMessage = "One or more of the email addresses are invalid. Addresses can be separated by a comma, semi-colon or space." ) ]
76+ public string ? EmailAddress { get ; set ; }
77+
78+ /// <summary>
79+ /// The email address to which notifications about failed webhook deliveries will be sent.
80+ /// </summary>
81+ [ EmailAddressMultiple ( ErrorMessage = "One or more of the email addresses are invalid. Addresses can be separated by a comma, semi-colon or space." ) ]
82+ public string ? FailedNotificationEmailAddress { get ; set ; }
83+
84+ /// <summary>
85+ /// Determines the delivery method for the notification. The default is Webhook.
86+ /// </summary>
87+ /// <remarks>
88+ /// This property dictates which other fields are required:
89+ /// <list type="bullet">
90+ /// <item>
91+ /// <term><b>Email</b></term>
92+ /// <description>Sends a notification to a specified email inbox. Requires the <c>EmailAddress</c> property to be set.</description>
93+ /// </item>
94+ /// <item>
95+ /// <term><b>Webhook</b></term>
96+ /// <description>Sends a notification via an HTTP POST request to a specified endpoint. Requires the <c>DestinationUrl</c> and <c>Secret</c> properties to be set.</description>
97+ /// </item>
98+ /// </list>
99+ /// </remarks>
100+ [ Required ]
101+ public NotificationMethodTypesEnum NotificationMethod { get ; set ; } = NotificationMethodTypesEnum . Webhook ;
102+
103+ public IEnumerable < ValidationResult > Validate ( ValidationContext validationContext )
104+ {
105+ if ( Secret ? . Length > SECRET_MAX_LENGTH )
106+ {
107+ yield return new ValidationResult ( $ "The Secret string was too long. The Secret maximum length is { SECRET_MAX_LENGTH } characters.") ;
108+ }
109+
110+ if ( ResourceTypes == null || ResourceTypes . Count ( ) == 0 )
111+ {
112+ yield return new ValidationResult ( "Cannot create a webhook with an empty resource type list. Please specify at least one resource type." ) ;
113+ }
114+
115+ if ( ResourceTypes ? . Contains ( WebhookResourceTypesEnum . None ) == true )
116+ {
117+ yield return new ValidationResult ( "Cannot create a webhook with a resource type of none." ) ;
118+ }
119+
120+ if ( NotificationMethod is NotificationMethodTypesEnum . None )
121+ {
122+ yield return new ValidationResult ( "Cannot create a webhook with a notification method type of none." ) ;
123+ }
124+
125+ if ( NotificationMethod is NotificationMethodTypesEnum . Email
126+ && string . IsNullOrWhiteSpace ( EmailAddress ) )
127+ {
128+ yield return new ValidationResult ( "Email address is required for email notification method." ) ;
129+ }
130+
131+ if ( NotificationMethod is NotificationMethodTypesEnum . Webhook && string . IsNullOrWhiteSpace ( DestinationUrl ) )
132+ {
133+ yield return new ValidationResult ( "Destination URL is required for webhook notification method." ) ;
134+ }
135+ }
136+
137+ public Dictionary < string , string > ToDictionary ( )
138+ {
139+ var dict = new Dictionary < string , string >
140+ {
141+ { nameof ( ID ) , ID . ToString ( ) } ,
142+ { nameof ( MerchantID ) , MerchantID . ToString ( ) } ,
143+ { nameof ( DestinationUrl ) , DestinationUrl ?? string . Empty } ,
144+ { nameof ( Retry ) , Retry . ToString ( ) } ,
145+ { nameof ( Secret ) , Secret ?? string . Empty } ,
146+ { nameof ( IsActive ) , IsActive . ToString ( ) } ,
147+ { nameof ( EmailAddress ) , EmailAddress ?? string . Empty } ,
148+ { nameof ( FailedNotificationEmailAddress ) , FailedNotificationEmailAddress ?? string . Empty } ,
149+ { nameof ( NotificationMethod ) , NotificationMethod . ToString ( ) }
150+ } ;
151+
152+ if ( ResourceTypes ? . Count ( ) > 0 )
153+ {
154+ int resourceTypeNumber = 0 ;
155+ foreach ( var resourceType in ResourceTypes )
156+ {
157+ dict . Add ( $ "{ nameof ( ResourceTypes ) } [{ resourceTypeNumber } ]", resourceType . ToString ( ) ) ;
158+ resourceTypeNumber ++ ;
159+ }
160+ }
161+
162+ return dict ;
163+ }
164+ }
0 commit comments