diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 00000000..828793bb
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 00000000..1fe41e41
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,34 @@
+
+
+
+
+
+ true
+ true
+ Tingle Software Limited
+
+
+
+
+
+ true
+
+
+ true
+
+
+ true
+ snupkg
+
+ MIT
+
+
+
+ $(GITVERSION_NUGETVERSION)
+
+
+
+
+
+
+
diff --git a/src/Falu/Core/BasicListOptions.cs b/src/Falu/Core/BasicListOptions.cs
index 84e971ae..37498f8d 100644
--- a/src/Falu/Core/BasicListOptions.cs
+++ b/src/Falu/Core/BasicListOptions.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.Serialization;
namespace Falu.Core
{
@@ -58,19 +57,7 @@ internal virtual IDictionary PopulateQueryValues(IDictionary d.ToString("o");
internal static string ConvertInt32(int i) => i.ToString();
internal static string ConvertInt64(long i) => i.ToString();
- internal static string ConvertEnum(T e) where T : Enum
- {
- // Give priority to EnumMemberAttribute
- var memInfo = typeof(T).GetMember(e.ToString());
- var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false)
- .OfType()
- .FirstOrDefault();
-
- return attr?.Value ?? e.ToString().ToLowerInvariant();
- }
- internal static string ConvertEnumList(IList list) where T : Enum
- {
- return string.Join(",", list.Select(l => ConvertEnum(l)));
- }
+ internal static string ConvertEnum(T e) where T : Enum => e.GetEnumMemberAttrValueOrDefault();
+ internal static string ConvertEnumList(IList list) where T : Enum => string.Join(",", list.Select(l => ConvertEnum(l)));
}
}
diff --git a/src/Falu/Core/IHasTags.cs b/src/Falu/Core/IHasTags.cs
index 3f1a501a..5a2c8b4b 100644
--- a/src/Falu/Core/IHasTags.cs
+++ b/src/Falu/Core/IHasTags.cs
@@ -10,6 +10,7 @@ public interface IHasTags
///
/// Set of values that you can attach to an object. This can be useful for searching.
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/Evaluations/EvaluationPatchModel.cs b/src/Falu/Evaluations/EvaluationPatchModel.cs
index b7bb4bdc..47036ff1 100644
--- a/src/Falu/Evaluations/EvaluationPatchModel.cs
+++ b/src/Falu/Evaluations/EvaluationPatchModel.cs
@@ -15,6 +15,7 @@ public class EvaluationPatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/Evaluations/EvaluationsService.cs b/src/Falu/Evaluations/EvaluationsService.cs
index 86462aa4..29053910 100644
--- a/src/Falu/Evaluations/EvaluationsService.cs
+++ b/src/Falu/Evaluations/EvaluationsService.cs
@@ -84,36 +84,54 @@ public virtual async Task> CreateAsync(EvaluationCr
CancellationToken cancellationToken = default)
{
if (evaluation is null) throw new ArgumentNullException(nameof(evaluation));
+ if (evaluation.Scope is null) throw new InvalidOperationException($"{nameof(evaluation.Scope)} cannot be null.");
+ if (evaluation.Provider is null) throw new InvalidOperationException($"{nameof(evaluation.Provider)} cannot be null.");
+ if (string.IsNullOrWhiteSpace(evaluation.Name))
+ {
+ throw new InvalidOperationException($"{nameof(evaluation.Name)} cannot be null or whitespace.");
+ }
var content = new MultipartFormDataContent
{
// populate fields of the model as key value pairs
- { new StringContent(evaluation.Currency), nameof(evaluation.Currency) },
- { new StringContent(evaluation.Scope.ToString()), nameof(evaluation.Scope) },
- { new StringContent(evaluation.Provider.ToString()), nameof(evaluation.Provider) },
- { new StringContent(evaluation.Name), nameof(evaluation.Name) },
- { new StringContent(evaluation.Phone), nameof(evaluation.Phone) },
- { new StringContent(evaluation.Password), nameof(evaluation.Password) },
+ { new StringContent(evaluation.Currency), "currency" },
+ { new StringContent(evaluation.Scope?.GetEnumMemberAttrValueOrDefault()), "scope" },
+ { new StringContent(evaluation.Provider?.GetEnumMemberAttrValueOrDefault()), "provider" },
+ { new StringContent(evaluation.Name), "name" },
// populate the file stream
- { new StreamContent(evaluation.Content), "File", evaluation.FileName },
+ { new StreamContent(evaluation.Content), "file", evaluation.FileName },
};
+ // Add phone if provided
+ if (!string.IsNullOrWhiteSpace(evaluation.Phone))
+ {
+ content.Add(new StringContent(evaluation.Phone), "phone");
+ }
+
+ // Add password if provided
+ if (!string.IsNullOrWhiteSpace(evaluation.Password))
+ {
+ content.Add(new StringContent(evaluation.Password), "password");
+ }
+
// Add description if provided
if (!string.IsNullOrWhiteSpace(evaluation.Description))
{
- content.Add(new StringContent(evaluation.Description), nameof(evaluation.Description));
+ content.Add(new StringContent(evaluation.Description), "description");
}
// Add tags if provided
+#pragma warning disable CS0618 // Type or member is obsolete
var tags = evaluation.Tags;
if (tags != null)
{
for (var i = 0; i < tags.Count; i++)
{
- content.Add(new StringContent(tags[i]), $"{nameof(evaluation.Tags)}[{i}]");
+ content.Add(new StringContent(tags[i]), $"tags[{i}]");
}
}
+#pragma warning restore CS0618 // Type or member is obsolete
// Add metadata if provided
var metadata = evaluation.Metadata?.ToList();
@@ -121,8 +139,8 @@ public virtual async Task> CreateAsync(EvaluationCr
{
for (var i = 0; i < metadata.Count; i++)
{
- content.Add(new StringContent(metadata[i].Key), $"{nameof(evaluation.Metadata)}[{i}].Key");
- content.Add(new StringContent(metadata[i].Value), $"{nameof(evaluation.Metadata)}[{i}].Value");
+ content.Add(new StringContent(metadata[i].Key), $"metadata[{i}].Key");
+ content.Add(new StringContent(metadata[i].Value), $"metadata[{i}].Value");
}
}
diff --git a/src/Falu/Events/WebhookEvent.cs b/src/Falu/Events/WebhookEvent.cs
index 766b39ad..5e30009e 100644
--- a/src/Falu/Events/WebhookEvent.cs
+++ b/src/Falu/Events/WebhookEvent.cs
@@ -16,7 +16,7 @@ public class WebhookEvent : IHasId, IHasCreated, IHasMetadata, IHasWork
public DateTimeOffset Created { get; set; }
///
- /// Type of event (e.g. payment.updated, balance.updated, etc.).
+ /// Type of event (e.g. payment.updated, payment_balances.updated, etc.).
/// Possible values are available in .
///
public string? Type { get; set; }
diff --git a/src/Falu/Events/WebhookEventData.cs b/src/Falu/Events/WebhookEventData.cs
index d9451432..18b41db0 100644
--- a/src/Falu/Events/WebhookEventData.cs
+++ b/src/Falu/Events/WebhookEventData.cs
@@ -7,7 +7,7 @@ public class WebhookEventData
{
///
/// Object containing the API resource relevant to the event.
- /// For example, a balance.updated event will have a full balance object.
+ /// For example, a payment_balances.updated event will have a full balance object.
///
public TObject? Object { get; set; }
diff --git a/src/Falu/Extensions/EnumExtensions.cs b/src/Falu/Extensions/EnumExtensions.cs
new file mode 100644
index 00000000..47ff406e
--- /dev/null
+++ b/src/Falu/Extensions/EnumExtensions.cs
@@ -0,0 +1,18 @@
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace System.Collections.Generic
+{
+ internal static class EnumExtensions
+ {
+ public static string GetEnumMemberAttrValueOrDefault(this T enumVal) where T : Enum
+ {
+ var memInfo = typeof(T).GetMember(enumVal.ToString());
+ var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false)
+ .OfType()
+ .FirstOrDefault();
+
+ return attr?.Value ?? enumVal.ToString().ToLowerInvariant();
+ }
+ }
+}
diff --git a/src/Falu/Falu.csproj b/src/Falu/Falu.csproj
index e6451b3e..63e194b6 100644
--- a/src/Falu/Falu.csproj
+++ b/src/Falu/Falu.csproj
@@ -2,12 +2,7 @@
netstandard2.1
- true
- true
-
The official client library for Falu. (https://falu.io)
- Tingle Software Limited
- Tingle Software Limited
@@ -19,26 +14,4 @@
-
-
- true
-
-
- true
-
-
- true
- snupkg
-
- MIT
-
-
-
- $(GITVERSION_NUGETVERSION)
-
-
-
-
-
-
diff --git a/src/Falu/MessageStreams/MessageStreamPatchModel.cs b/src/Falu/MessageStreams/MessageStreamPatchModel.cs
index 02c1acaf..4b90b22f 100644
--- a/src/Falu/MessageStreams/MessageStreamPatchModel.cs
+++ b/src/Falu/MessageStreams/MessageStreamPatchModel.cs
@@ -20,6 +20,7 @@ public class MessageStreamPatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/MessageStrings.cs b/src/Falu/MessageStrings.cs
new file mode 100644
index 00000000..fce183f8
--- /dev/null
+++ b/src/Falu/MessageStrings.cs
@@ -0,0 +1,7 @@
+namespace Falu
+{
+ internal class MessageStrings
+ {
+ public const string TagsDeprecated = "Tags have been deprecated and scheduled to be removed in a future API update. Migrate to using Metadata.";
+ }
+}
diff --git a/src/Falu/MessageTemplates/MessageTemplatePatchModel.cs b/src/Falu/MessageTemplates/MessageTemplatePatchModel.cs
index 1588b6ad..4b51fcd1 100644
--- a/src/Falu/MessageTemplates/MessageTemplatePatchModel.cs
+++ b/src/Falu/MessageTemplates/MessageTemplatePatchModel.cs
@@ -28,6 +28,7 @@ public class MessageTemplatePatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/Messages/MessagePatchModel.cs b/src/Falu/Messages/MessagePatchModel.cs
index 620e9ded..958429b9 100644
--- a/src/Falu/Messages/MessagePatchModel.cs
+++ b/src/Falu/Messages/MessagePatchModel.cs
@@ -12,6 +12,7 @@ public class MessagePatchModel : IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/PaymentAuthorizations/PaymentAuthorization.cs b/src/Falu/PaymentAuthorizations/PaymentAuthorization.cs
index defab835..095f504b 100644
--- a/src/Falu/PaymentAuthorizations/PaymentAuthorization.cs
+++ b/src/Falu/PaymentAuthorizations/PaymentAuthorization.cs
@@ -48,6 +48,11 @@ public class PaymentAuthorization : PaymentAuthorizationPatchModel, IHasId, IHas
///
public PaymentMpesaDetails? Mpesa { get; set; }
+ ///
+ /// Identifier of the payment created after the authorization is approved and closed.
+ ///
+ public string? PaymentId { get; set; }
+
///
public string? WorkspaceId { get; set; }
diff --git a/src/Falu/PaymentAuthorizations/PaymentAuthorizationPatchModel.cs b/src/Falu/PaymentAuthorizations/PaymentAuthorizationPatchModel.cs
index b7d9f158..e51b2bf9 100644
--- a/src/Falu/PaymentAuthorizations/PaymentAuthorizationPatchModel.cs
+++ b/src/Falu/PaymentAuthorizations/PaymentAuthorizationPatchModel.cs
@@ -12,6 +12,7 @@ public class PaymentAuthorizationPatchModel : IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/PaymentReversals/PaymentReversalFailureReason.cs b/src/Falu/PaymentReversals/PaymentReversalFailureReason.cs
index 7cb3ea83..a0011ffe 100644
--- a/src/Falu/PaymentReversals/PaymentReversalFailureReason.cs
+++ b/src/Falu/PaymentReversals/PaymentReversalFailureReason.cs
@@ -18,6 +18,10 @@ public enum PaymentReversalFailureReason
[EnumMember(Value = "authentication_error")]
AuthenticationError,
+ ///
+ [EnumMember(Value = "amount_out_of_bound")]
+ AmountOutOfBound,
+
///
Timeout,
diff --git a/src/Falu/PaymentReversals/PaymentReversalPatchModel.cs b/src/Falu/PaymentReversals/PaymentReversalPatchModel.cs
index 75196761..b502c5ba 100644
--- a/src/Falu/PaymentReversals/PaymentReversalPatchModel.cs
+++ b/src/Falu/PaymentReversals/PaymentReversalPatchModel.cs
@@ -15,6 +15,7 @@ public class PaymentReversalPatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/Payments/Payment.cs b/src/Falu/Payments/Payment.cs
index 7d378d16..0ff326f0 100644
--- a/src/Falu/Payments/Payment.cs
+++ b/src/Falu/Payments/Payment.cs
@@ -35,6 +35,11 @@ public class Payment : PaymentPatchModel, IHasId, IHasCurrency, IHasCreated, IHa
///
public DateTimeOffset? Succeeded { get; set; }
+ ///
+ /// Identifier of the authorization, if the payment passed through a flow requiring authorization.
+ ///
+ public string? AuthorizationId { get; set; }
+
///
/// The type of the Payment.
/// An additional property is populated on the Payment with a name matching this value.
diff --git a/src/Falu/Payments/PaymentFailureReason.cs b/src/Falu/Payments/PaymentFailureReason.cs
index d2596021..03cb3b40 100644
--- a/src/Falu/Payments/PaymentFailureReason.cs
+++ b/src/Falu/Payments/PaymentFailureReason.cs
@@ -18,6 +18,10 @@ public enum PaymentFailureReason
[EnumMember(Value = "authentication_error")]
AuthenticationError,
+ ///
+ [EnumMember(Value = "amount_out_of_bound")]
+ AmountOutOfBound,
+
///
Timeout,
diff --git a/src/Falu/Payments/PaymentPatchModel.cs b/src/Falu/Payments/PaymentPatchModel.cs
index bb69b688..34363cab 100644
--- a/src/Falu/Payments/PaymentPatchModel.cs
+++ b/src/Falu/Payments/PaymentPatchModel.cs
@@ -15,6 +15,7 @@ public class PaymentPatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/TransferReversals/TransferReversalFailureReason.cs b/src/Falu/TransferReversals/TransferReversalFailureReason.cs
index 9ac75ebb..6194826d 100644
--- a/src/Falu/TransferReversals/TransferReversalFailureReason.cs
+++ b/src/Falu/TransferReversals/TransferReversalFailureReason.cs
@@ -18,6 +18,10 @@ public enum TransferReversalFailureReason
[EnumMember(Value = "authentication_error")]
AuthenticationError,
+ ///
+ [EnumMember(Value = "amount_out_of_bound")]
+ AmountOutOfBound,
+
///
Timeout,
diff --git a/src/Falu/TransferReversals/TransferReversalPatchModel.cs b/src/Falu/TransferReversals/TransferReversalPatchModel.cs
index 643fb063..5aad3412 100644
--- a/src/Falu/TransferReversals/TransferReversalPatchModel.cs
+++ b/src/Falu/TransferReversals/TransferReversalPatchModel.cs
@@ -15,6 +15,7 @@ public class TransferReversalPatchModel : IHasDescription, IHasMetadata, IHasTag
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/Transfers/TransferFailureReason.cs b/src/Falu/Transfers/TransferFailureReason.cs
index f3e548e9..7bd0dc3f 100644
--- a/src/Falu/Transfers/TransferFailureReason.cs
+++ b/src/Falu/Transfers/TransferFailureReason.cs
@@ -18,6 +18,10 @@ public enum TransferFailureReason
[EnumMember(Value = "authentication_error")]
AuthenticationError,
+ ///
+ [EnumMember(Value = "amount_out_of_bound")]
+ AmountOutOfBound,
+
///
Timeout,
diff --git a/src/Falu/Transfers/TransferPatchModel.cs b/src/Falu/Transfers/TransferPatchModel.cs
index db0ee20d..a768e6ba 100644
--- a/src/Falu/Transfers/TransferPatchModel.cs
+++ b/src/Falu/Transfers/TransferPatchModel.cs
@@ -15,6 +15,7 @@ public class TransferPatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}
diff --git a/src/Falu/Webhooks/EventTypes.cs b/src/Falu/Webhooks/EventTypes.cs
index 979e8a77..2d373cb4 100644
--- a/src/Falu/Webhooks/EventTypes.cs
+++ b/src/Falu/Webhooks/EventTypes.cs
@@ -25,9 +25,9 @@ public static class EventTypes
#region Payments
///
- /// Occurs whenever the balance has been updated.
+ /// Occurs whenever a payment balances are updated.
///
- public const string BalanceUpdated = "balance.updated";
+ public const string PaymentBalancesUpdated = "payment_balances.updated";
///
/// Occurs whenever a payment is updated.
diff --git a/src/Falu/Webhooks/WebhookEndpointPatchModel.cs b/src/Falu/Webhooks/WebhookEndpointPatchModel.cs
index 5a51b562..e493f6a5 100644
--- a/src/Falu/Webhooks/WebhookEndpointPatchModel.cs
+++ b/src/Falu/Webhooks/WebhookEndpointPatchModel.cs
@@ -36,6 +36,7 @@ public class WebhookEndpointPatchModel : IHasDescription, IHasMetadata, IHasTags
public Dictionary? Metadata { get; set; }
///
+ [System.Obsolete(MessageStrings.TagsDeprecated)]
public List? Tags { get; set; }
}
}