From 93e44db0c52abaf2a2f13cc1c1a44f75eb6f85e7 Mon Sep 17 00:00:00 2001 From: paojed97 Date: Wed, 5 Nov 2025 16:09:22 +0100 Subject: [PATCH] refactor: refactored customer, wallet and payout requests and responses --- Embedly.Examples/Examples/CustomerExamples.cs | 4 +- .../CustomerWorkflowIntegrationTests.cs | 13 +-- .../Integration/TestIntegration.cs | 16 ++-- .../Services/CustomerServiceTests.cs | 48 +++++----- .../Services/PayoutServiceTests.cs | 44 ++++----- .../Services/WalletServiceTests.cs | 4 +- Embedly.SDK.Tests/Testing/ServiceTestBase.cs | 3 +- .../Customers/AddressVerificationRequest.cs | 18 ---- .../Customers/BvnKycUpgradeRequest.cs | 21 +++++ .../Customers/UpdateCustomerContactRequest.cs | 21 +++-- .../Customers/UpdateCustomerNameRequest.cs | 43 +++++++++ .../Models/Responses/Customers/Customer.cs | 94 ++++++++++++------- .../CustomerVerificationProperties.cs | 58 +++++------- Embedly.SDK/Models/Responses/Payout/Bank.cs | 12 --- .../Responses/Payout/NameEnquiryResponse.cs | 48 +++++----- .../Payout/PayoutTransactionStatus.cs | 39 ++++++++ .../Models/Responses/Wallets/Wallet.cs | 6 +- .../Services/Customers/CustomerService.cs | 14 +-- .../Services/Customers/ICustomerService.cs | 6 +- Embedly.SDK/Services/Payout/IPayoutService.cs | 4 +- Embedly.SDK/Services/Payout/PayoutService.cs | 8 +- 21 files changed, 303 insertions(+), 221 deletions(-) create mode 100644 Embedly.SDK/Models/Responses/Payout/PayoutTransactionStatus.cs diff --git a/Embedly.Examples/Examples/CustomerExamples.cs b/Embedly.Examples/Examples/CustomerExamples.cs index a9eed04..1ab5f05 100644 --- a/Embedly.Examples/Examples/CustomerExamples.cs +++ b/Embedly.Examples/Examples/CustomerExamples.cs @@ -78,7 +78,7 @@ public async Task> GetCustomerAsync(string customerId) logger.LogInformation("Customer retrieved: {CustomerName}. Correlation: {CorrelationId}", $"{response.Data.FirstName} {response.Data.LastName}", correlationId); - return $"Customer: {response.Data.FirstName} {response.Data.LastName} ({response.Data.Email})"; + return $"Customer: {response.Data.FirstName} {response.Data.LastName} ({response.Data.EmailAddress})"; }, "GetCustomer"); } @@ -100,7 +100,7 @@ public async Task>> ListCustomersAsync(int page = 1, int pag throw new InvalidOperationException($"Customer listing failed: {customers.Error?.Message}"); var customerList = customers.Data - .Select(c => $"{c.FirstName} {c.LastName} - {c.Email}") + .Select(c => $"{c.FirstName} {c.LastName} - {c.EmailAddress}") .ToList(); logger.LogInformation("Retrieved {Count} customers. Correlation: {CorrelationId}", diff --git a/Embedly.SDK.Tests/Integration/CustomerWorkflowIntegrationTests.cs b/Embedly.SDK.Tests/Integration/CustomerWorkflowIntegrationTests.cs index 499f6b8..3f67e3e 100644 --- a/Embedly.SDK.Tests/Integration/CustomerWorkflowIntegrationTests.cs +++ b/Embedly.SDK.Tests/Integration/CustomerWorkflowIntegrationTests.cs @@ -63,7 +63,7 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() getResponse.Data!.Id.Should().Be(customerId); getResponse.Data.FirstName.Should().Be(createRequest.FirstName); getResponse.Data.LastName.Should().Be(createRequest.LastName); - getResponse.Data.Email.Should().Be(createRequest.EmailAddress); + getResponse.Data.EmailAddress.Should().Be(createRequest.EmailAddress); LogSuccess("Customer retrieved successfully with matching data"); @@ -82,7 +82,7 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() if (updateResponse.Success) { - updateResponse.Data.Should().NotBeNull(); + updateResponse.Data.Should().BeTrue(); LogSuccess("Customer name updated successfully"); } else @@ -94,8 +94,8 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() LogStep("Updating customer contact information"); var updateContactRequest = new UpdateCustomerContactRequest { - Email = CreateTestEmail("updated"), - PhoneNumber = CreateTestPhoneNumber() + EmailAddress = CreateTestEmail("updated"), + MobileNumber = CreateTestPhoneNumber() }; LogApiCall("Update Customer Contact", updateContactRequest); @@ -104,7 +104,7 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() if (contactResponse.Success) { - contactResponse.Data.Should().NotBeNull(); + contactResponse.Data.Should().BeTrue(); LogSuccess("Customer contact updated successfully"); } else @@ -166,7 +166,8 @@ public async Task CustomerKycUpgradeWorkflow_ShouldHandleDifferentVerificationMe var bvnUpgradeRequest = new BvnKycUpgradeRequest { CustomerId = customerId, - Bvn = "12345678909" // Test BVN + Bvn = "12345678909", // Test BVN + Verify = 1 // No. of Verification Attempts }; LogApiCall("BVN KYC Upgrade", bvnUpgradeRequest); diff --git a/Embedly.SDK.Tests/Integration/TestIntegration.cs b/Embedly.SDK.Tests/Integration/TestIntegration.cs index 94afe84..b682730 100644 --- a/Embedly.SDK.Tests/Integration/TestIntegration.cs +++ b/Embedly.SDK.Tests/Integration/TestIntegration.cs @@ -63,7 +63,7 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() getResponse.Data!.Id.Should().Be(customerId); getResponse.Data.FirstName.Should().Be(createRequest.FirstName); getResponse.Data.LastName.Should().Be(createRequest.LastName); - getResponse.Data.Email.Should().Be(createRequest.EmailAddress); + getResponse.Data.EmailAddress.Should().Be(createRequest.EmailAddress); LogSuccess("Customer retrieved successfully with matching data"); @@ -82,7 +82,7 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() if (updateResponse.Success) { - updateResponse.Data.Should().NotBeNull(); + updateResponse.Data.Should().BeTrue(); LogSuccess("Customer name updated successfully"); } else @@ -94,8 +94,8 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() LogStep("Updating customer contact information"); var updateContactRequest = new UpdateCustomerContactRequest { - Email = CreateTestEmail("updated"), - PhoneNumber = CreateTestPhoneNumber() + EmailAddress = CreateTestEmail("updated"), + MobileNumber = CreateTestPhoneNumber() }; LogApiCall("Update Customer Contact", updateContactRequest); @@ -104,7 +104,7 @@ public async Task CompleteCustomerLifecycleWorkflow_ShouldSucceedWithAllSteps() if (contactResponse.Success) { - contactResponse.Data.Should().NotBeNull(); + contactResponse.Data.Should().BeTrue(); LogSuccess("Customer contact updated successfully"); } else @@ -189,7 +189,8 @@ public async Task CustomerKycUpgradeWorkflow_ShouldHandleDifferentVerificationMe var bvnUpgradeRequest = new BvnKycUpgradeRequest { CustomerId = customerId, - Bvn = "12345678901" // Test BVN + Bvn = "12345678901", // Test BVN + Verify = 1 // No. of Verification Attempts }; LogApiCall("BVN KYC Upgrade", bvnUpgradeRequest); @@ -212,8 +213,7 @@ public async Task CustomerKycUpgradeWorkflow_ShouldHandleDifferentVerificationMe { CustomerId = customerId, HouseAddress = "123 Integration Test Street", - PostalCode = "12345", - Country = "NG", + MeterNumber = "67492874901" }; LogApiCall("Address Verification", addressRequest); diff --git a/Embedly.SDK.Tests/Services/CustomerServiceTests.cs b/Embedly.SDK.Tests/Services/CustomerServiceTests.cs index 1af969b..6b09c21 100644 --- a/Embedly.SDK.Tests/Services/CustomerServiceTests.cs +++ b/Embedly.SDK.Tests/Services/CustomerServiceTests.cs @@ -52,7 +52,7 @@ public async Task CreateAsync_WithValidRequest_ReturnsSuccessfulResponse() result.Data!.Id.Should().Be(expectedCustomer.Id); result.Data.FirstName.Should().Be(request.FirstName); result.Data.LastName.Should().Be(request.LastName); - result.Data.Email.Should().Be(request.EmailAddress); + result.Data.EmailAddress.Should().Be(request.EmailAddress); result.Data.MobileNumber.Should().Be(request.MobileNumber); VerifyHttpClientPostCall("api/v1/customers/add", request); @@ -232,13 +232,10 @@ public async Task UpdateNameAsync_WithValidParameters_ReturnsUpdatedCustomer() var customerId = CreateTestGuid().ToString(); const string firstName = "Updated"; const string lastName = "Name"; - var expectedCustomer = CreateTestCustomer(customerId); - expectedCustomer.FirstName = firstName; - expectedCustomer.LastName = lastName; - var apiResponse = CreateSuccessfulApiResponse(expectedCustomer); + var apiResponse = CreateSuccessfulApiResponse(true); MockHttpClient - .Setup(x => x.PatchAsync( + .Setup(x => x.PatchAsync( It.Is(url => url.Contains($"api/v1/customers/customer/{customerId}/updatename")), It.IsAny(), It.IsAny())) @@ -250,12 +247,10 @@ public async Task UpdateNameAsync_WithValidParameters_ReturnsUpdatedCustomer() // Assert result.Should().NotBeNull(); result.Success.Should().BeTrue(); - result.Data.Should().NotBeNull(); - result.Data!.FirstName.Should().Be(firstName); - result.Data.LastName.Should().Be(lastName); + result.Data.Should().BeTrue(); MockHttpClient.Verify( - x => x.PatchAsync( + x => x.PatchAsync( It.Is(url => url.Contains($"api/v1/customers/customer/{customerId}/updatename")), It.Is(r => r.CustomerId == customerId && @@ -275,11 +270,10 @@ public async Task UpdateNameAsync_WithRequestObject_CallsCorrectEndpoint() FirstName = "NewFirst", LastName = "NewLast" }; - var expectedCustomer = CreateTestCustomer(request.CustomerId); - var apiResponse = CreateSuccessfulApiResponse(expectedCustomer); + var apiResponse = CreateSuccessfulApiResponse(true); MockHttpClient - .Setup(x => x.PatchAsync( + .Setup(x => x.PatchAsync( It.IsAny(), It.IsAny(), It.IsAny())) @@ -292,7 +286,7 @@ public async Task UpdateNameAsync_WithRequestObject_CallsCorrectEndpoint() result.Should().NotBeNull(); result.Success.Should().BeTrue(); - VerifyHttpClientPatchCall( + VerifyHttpClientPatchCall( $"api/v1/customers/customer/{request.CustomerId}/updatename", request); } @@ -303,14 +297,13 @@ public async Task UpdateContactAsync_WithValidRequest_ReturnsUpdatedCustomer() var customerId = CreateTestGuid().ToString(); var request = new UpdateCustomerContactRequest { - Email = "updated@test.com", - PhoneNumber = "+2348012345678" + EmailAddress = "updated@test.com", + MobileNumber = "+2348012345678" }; - var expectedCustomer = CreateTestCustomer(customerId); - var apiResponse = CreateSuccessfulApiResponse(expectedCustomer); + var apiResponse = CreateSuccessfulApiResponse(true); MockHttpClient - .Setup(x => x.PatchAsync( + .Setup(x => x.PatchAsync( It.Is(url => url.Contains($"api/v1/customers/customer/{customerId}/updatecontact")), request, It.IsAny())) @@ -323,7 +316,7 @@ public async Task UpdateContactAsync_WithValidRequest_ReturnsUpdatedCustomer() result.Should().NotBeNull(); result.Success.Should().BeTrue(); - VerifyHttpClientPatchCall( + VerifyHttpClientPatchCall( $"api/v1/customers/customer/{customerId}/updatecontact", request); } @@ -439,7 +432,8 @@ public async Task UpgradeKycWithBvnAsync_WithValidRequest_ReturnsBvnKycResult() var request = new BvnKycUpgradeRequest { CustomerId = CreateTestGuid().ToString(), - Bvn = "12345678901" + Bvn = "12345678901", + Verify = 1 // No. of verification attempts }; var expectedResult = new BvnKycUpgradeResponse @@ -566,8 +560,8 @@ public async Task GetVerificationPropertiesAsync_WithValidId_ReturnsProperties() var expectedProperties = new CustomerVerificationProperties { CustomerId = customerId, - KycLevel = "TIER_1", - CompletedVerifications = new List { "NIN", "BVN", "EMAIL", "PHONE" } + CustomerTierId = 1, + HasNin = true }; var apiResponse = CreateSuccessfulApiResponse(expectedProperties); @@ -585,7 +579,7 @@ public async Task GetVerificationPropertiesAsync_WithValidId_ReturnsProperties() result.Success.Should().BeTrue(); result.Data.Should().NotBeNull(); result.Data!.CustomerId.Should().Be(customerId); - result.Data.KycLevel.Should().Be("TIER_1"); + result.Data.CustomerTierId.Should().Be(1); VerifyHttpClientGetCall( $"api/v1/customers/customer-verification-properties/{customerId}"); @@ -692,7 +686,7 @@ public void UpdateNameAsync_WithNullRequestObject_ThrowsArgumentNullException() public void UpdateContactAsync_WithNullCustomerId_ThrowsArgumentException() { // Arrange - var request = new UpdateCustomerContactRequest { Email = "test@test.com" }; + var request = new UpdateCustomerContactRequest { EmailAddress = "test@test.com" }; // Act & Assert var exception = @@ -733,10 +727,10 @@ private Customer CreateTestCustomer(string? customerId = null) Id = customerId ?? CreateTestGuid().ToString(), FirstName = "John", LastName = "Doe", - Email = CreateTestEmail("john.doe"), + EmailAddress = CreateTestEmail("john.doe"), MobileNumber = CreateTestPhoneNumber("1234"), DateOfBirth = DateTime.UtcNow.AddYears(-25), - CreatedAt = DateTimeOffset.UtcNow, + DateCreated = DateTimeOffset.UtcNow, CustomerTierId = 0, Status = CustomerStatus.Active }; diff --git a/Embedly.SDK.Tests/Services/PayoutServiceTests.cs b/Embedly.SDK.Tests/Services/PayoutServiceTests.cs index be8c452..d20e157 100644 --- a/Embedly.SDK.Tests/Services/PayoutServiceTests.cs +++ b/Embedly.SDK.Tests/Services/PayoutServiceTests.cs @@ -103,7 +103,9 @@ public async Task NameEnquiryAsync_WithValidRequest_ReturnsAccountName() result.Should().NotBeNull(); result.Success.Should().BeTrue(); result.Data.Should().NotBeNull(); - result.Data!.Data.AccountName.Should().NotBeNullOrEmpty(); + result.Data!.AccountName.Should().NotBeNullOrEmpty(); + result.Data!.AccountNumber.Should().NotBeNullOrEmpty(); + result.Data!.DestinationInstitutionCode.Should().NotBeNullOrEmpty(); } [Test] @@ -118,11 +120,11 @@ public async Task InterBankTransferAsync_WithValidRequest_ReturnsTransactionDeta { // Arrange var request = CreateValidBankTransferRequest(); - var expectedTransaction = CreateTestPayoutTransaction(); - var apiResponse = CreateSuccessfulApiResponse(expectedTransaction); + var expectedReference = CreateTestStringId(prefix: "EMB"); + var apiResponse = CreateSuccessfulApiResponse(expectedReference); MockHttpClient - .Setup(x => x.PostAsync( + .Setup(x => x.PostAsync( It.IsAny(), request, It.IsAny())) @@ -133,10 +135,8 @@ public async Task InterBankTransferAsync_WithValidRequest_ReturnsTransactionDeta // Assert result.Should().NotBeNull(); - result.Success.Should().BeTrue(); + result.Succeeded.Should().BeTrue(); result.Data.Should().NotBeNull(); - result.Data!.Id.Should().Be(expectedTransaction.Id); - result.Data.Amount.Should().Be(expectedTransaction.Amount); } [Test] @@ -150,12 +150,19 @@ public void InterBankTransferAsync_WithNullRequest_ThrowsArgumentNullException() public async Task GetTransactionStatusAsync_WithValidReference_ReturnsTransactionStatus() { // Arrange - var transactionReference = "TXN-123456789"; - var expectedTransaction = CreateTestPayoutTransaction(); - var apiResponse = CreateSuccessfulApiResponse(expectedTransaction); + var transactionReference = CreateTestStringId(prefix: "EMB"); + var expectedTransactionStatus = new PayoutTransactionStatus + { + PaymentReference = CreateTestLongId().ToString(), + ProviderReference = CreateTestLongId().ToString(), + SessionId = CreateTestLongId().ToString(), + Status = "success", + TransactionReference = transactionReference + }; + var apiResponse = CreateSuccessfulApiResponse(expectedTransactionStatus); MockHttpClient - .Setup(x => x.GetAsync( + .Setup(x => x.GetAsync( It.IsAny(), It.IsAny())) .ReturnsAsync(apiResponse); @@ -167,7 +174,7 @@ public async Task GetTransactionStatusAsync_WithValidReference_ReturnsTransactio result.Should().NotBeNull(); result.Success.Should().BeTrue(); result.Data.Should().NotBeNull(); - result.Data!.Reference.Should().Be(expectedTransaction.Reference); + result.Data!.TransactionReference.Should().Be(expectedTransactionStatus.TransactionReference); } [Test] @@ -386,8 +393,6 @@ private Bank CreateTestBank(string code, string name) { BankCode = code, BankName = name, - IsActive = true, - Type = "Commercial" }; } @@ -404,13 +409,10 @@ private NameEnquiryResponse CreateTestNameEnquiryResponse() { return new NameEnquiryResponse { - Status = "success", - Data = new BankAccountVerificationData - { - DestinationBankCode = "000010", - AccountNumber = "1111111111", - AccountName = "CHECKING ACCOUNT" - } + DestinationInstitutionCode = "000010", + AccountName = "CHECKING ACCOUNT", + AccountNumber = "1111111111", + SessionId = CreateTestLongId().ToString() }; } diff --git a/Embedly.SDK.Tests/Services/WalletServiceTests.cs b/Embedly.SDK.Tests/Services/WalletServiceTests.cs index 21a294a..38ab646 100644 --- a/Embedly.SDK.Tests/Services/WalletServiceTests.cs +++ b/Embedly.SDK.Tests/Services/WalletServiceTests.cs @@ -394,8 +394,8 @@ private Wallet CreateTestWallet() CustomerId = CreateTestGuid(), Name = "Test Wallet", CurrencyId = Guid.Parse("fd5e474d-bb42-4db1-ab74-e8d2a01047e9"), - LedgerBalance = 50000.00, - AvailableBalance = 45000.00, + LedgerBalance = 50000m, + AvailableBalance = 45000m, IsDefault = true, VirtualAccount = CreateTestVirtualAccount(), WalletGroupId = CreateTestGuid(), diff --git a/Embedly.SDK.Tests/Testing/ServiceTestBase.cs b/Embedly.SDK.Tests/Testing/ServiceTestBase.cs index 9c11331..6b3a437 100644 --- a/Embedly.SDK.Tests/Testing/ServiceTestBase.cs +++ b/Embedly.SDK.Tests/Testing/ServiceTestBase.cs @@ -68,11 +68,11 @@ protected static void AssertThrowsArgumentExceptionForNullOrEmptyStringOptional success message. /// A successful API response. protected static ApiResponse CreateSuccessfulApiResponse(T data, string? message = null) - where T : class { return new ApiResponse { Success = true, + Succeeded = true, Data = data, Message = message ?? "Operation completed successfully", RequestId = "test-request-id", @@ -155,7 +155,6 @@ protected void VerifyHttpClientPatchCall( TRequest request, Times? times = null) where TRequest : class - where TResponse : class { MockHttpClient.Verify( x => x.PatchAsync( diff --git a/Embedly.SDK/Models/Requests/Customers/AddressVerificationRequest.cs b/Embedly.SDK/Models/Requests/Customers/AddressVerificationRequest.cs index 0cbf9a9..f960947 100644 --- a/Embedly.SDK/Models/Requests/Customers/AddressVerificationRequest.cs +++ b/Embedly.SDK/Models/Requests/Customers/AddressVerificationRequest.cs @@ -28,22 +28,4 @@ public sealed class AddressVerificationRequest [Required(ErrorMessage = "The house address is required")] [JsonPropertyName("houseAddress")] public string HouseAddress { get; set; } = string.Empty; - - /// - /// Gets or sets the postal code. - /// - [JsonPropertyName("postalCode")] - public string? PostalCode { get; set; } - - /// - /// Gets or sets the country code. - /// - [JsonPropertyName("country")] - public string Country { get; set; } = "NG"; - - /// - /// Gets or sets the verification document or evidence. - /// - [JsonPropertyName("verificationDocument")] - public string? VerificationDocument { get; set; } } \ No newline at end of file diff --git a/Embedly.SDK/Models/Requests/Customers/BvnKycUpgradeRequest.cs b/Embedly.SDK/Models/Requests/Customers/BvnKycUpgradeRequest.cs index 899298a..f507b51 100644 --- a/Embedly.SDK/Models/Requests/Customers/BvnKycUpgradeRequest.cs +++ b/Embedly.SDK/Models/Requests/Customers/BvnKycUpgradeRequest.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; @@ -23,4 +24,24 @@ public sealed class BvnKycUpgradeRequest [RegularExpression(@"^\d{11}$", ErrorMessage = "BVN must be 11 digits")] [JsonPropertyName("bvn")] public string Bvn { get; set; } = string.Empty; + + /// + /// The number verification attempts to be made. + /// + [JsonPropertyName("verify")] + public int? Verify { get; set; } + + /// + /// Adds query parameters to the request endpoint. + /// + /// A simple query parameters dictionary. + public Dictionary ToQueryParameters() + { + var parameters = new Dictionary + { + ["verify"] = Verify + }; + + return parameters; + } } \ No newline at end of file diff --git a/Embedly.SDK/Models/Requests/Customers/UpdateCustomerContactRequest.cs b/Embedly.SDK/Models/Requests/Customers/UpdateCustomerContactRequest.cs index 450f339..932dede 100644 --- a/Embedly.SDK/Models/Requests/Customers/UpdateCustomerContactRequest.cs +++ b/Embedly.SDK/Models/Requests/Customers/UpdateCustomerContactRequest.cs @@ -1,3 +1,4 @@ +using System; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; @@ -9,22 +10,22 @@ namespace Embedly.SDK.Models.Requests.Customers; public sealed record UpdateCustomerContactRequest { /// - /// Gets or sets the customer's email address. + /// Gets or sets the unique identifier of the organization associated with the customer. /// - [EmailAddress(ErrorMessage = "Invalid email format")] - [JsonPropertyName("email")] - public string? Email { get; init; } + [JsonPropertyName("organizationId")] + public Guid OrganizationId { get; set; } /// - /// Gets or sets the customer's phone number. + /// Gets or sets the customer's mobile phone number. /// [Phone(ErrorMessage = "Invalid phone number format")] - [JsonPropertyName("phoneNumber")] - public string? PhoneNumber { get; init; } + [JsonPropertyName("mobileNumber")] + public string MobileNumber { get; set; } = string.Empty; /// - /// Gets or sets the customer's address. + /// Gets or sets the customer's email address. /// - [JsonPropertyName("address")] - public string? Address { get; init; } + [EmailAddress(ErrorMessage = "Invalid email format")] + [JsonPropertyName("emailAddress")] + public string EmailAddress { get; set; } = string.Empty; } \ No newline at end of file diff --git a/Embedly.SDK/Models/Requests/Customers/UpdateCustomerNameRequest.cs b/Embedly.SDK/Models/Requests/Customers/UpdateCustomerNameRequest.cs index ab44f7f..4c5038e 100644 --- a/Embedly.SDK/Models/Requests/Customers/UpdateCustomerNameRequest.cs +++ b/Embedly.SDK/Models/Requests/Customers/UpdateCustomerNameRequest.cs @@ -1,3 +1,4 @@ +using System; using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; @@ -14,6 +15,12 @@ public sealed class UpdateCustomerNameRequest [JsonIgnore] public string CustomerId { get; set; } = string.Empty; + /// + /// Gets or sets the unique identifier of the organization associated with the customer. + /// + [JsonPropertyName("organizationId")] + public Guid OrganizationId { get; set; } + /// /// Gets or sets the customer's new first name. /// @@ -29,4 +36,40 @@ public sealed class UpdateCustomerNameRequest [StringLength(50, ErrorMessage = "Last name cannot exceed 50 characters")] [JsonPropertyName("lastName")] public string LastName { get; set; } = string.Empty; + + /// + /// Gets or sets the customer's middle name. + /// + [JsonPropertyName("middleName")] + public string MiddleName { get; set; } = string.Empty; + + /// + /// Gets or sets the customer's date of birth, if available. + /// + [JsonPropertyName("dob")] + public DateTime? DateOfBirth { get; set; } + + /// + /// Gets or sets the city where the customer resides. + /// + [JsonPropertyName("city")] + public string City { get; set; } = string.Empty; + + /// + /// Gets or sets the customer's residential address. + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; + + /// + /// Gets or sets the customer's occupation. + /// + [JsonPropertyName("occupation")] + public string Occupation { get; set; } = string.Empty; + + /// + /// Gets or sets the customer's gender. + /// + [JsonPropertyName("gender")] + public string Gender { get; set; } = string.Empty; } \ No newline at end of file diff --git a/Embedly.SDK/Models/Responses/Customers/Customer.cs b/Embedly.SDK/Models/Responses/Customers/Customer.cs index 61eaec4..a408216 100644 --- a/Embedly.SDK/Models/Responses/Customers/Customer.cs +++ b/Embedly.SDK/Models/Responses/Customers/Customer.cs @@ -5,81 +5,117 @@ namespace Embedly.SDK.Models.Responses.Customers; /// -/// Represents a customer in the Embedly system. +/// Represents a customer within an organization. /// public sealed class Customer { /// - /// Gets or sets the unique customer identifier. + /// Gets or sets the unique identifier of the customer. /// [JsonPropertyName("id")] public string Id { get; set; } = string.Empty; /// - /// Gets or sets the customer's first name. + /// Gets or sets the unique identifier of the organization associated with the customer. + /// + [JsonPropertyName("organizationId")] + public Guid OrganizationId { get; set; } + + /// + /// Gets or sets the first name of the customer. /// [JsonPropertyName("firstName")] public string FirstName { get; set; } = string.Empty; /// - /// Gets or sets the customer's last name. + /// Gets or sets the last name of the customer. /// [JsonPropertyName("lastName")] public string LastName { get; set; } = string.Empty; /// - /// Gets or sets the customer's full name. + /// Gets or sets the middle name of the customer. /// [JsonPropertyName("middleName")] - public string? MiddleName { get; set; } + public string MiddleName { get; set; } = string.Empty; + + /// + /// ets or sets the date of birth of the customer, if available. + /// + [JsonPropertyName("dob")] + public DateTime? DateOfBirth { get; set; } + + /// + /// Gets or sets the unique identifier for the customer type. + /// + [JsonPropertyName("customerTypeId")] + public Guid CustomerTypeId { get; set; } /// - /// Gets or sets the customer tier ID. + /// Gets or sets the tier level of the customer. /// [JsonPropertyName("customerTierId")] public int CustomerTierId { get; set; } /// - /// Gets or sets the customer's email address. + /// Gets or sets an alternate or display name for the customer, if any. /// - [JsonPropertyName("emailAddress")] - public string Email { get; set; } = string.Empty; + [JsonPropertyName("alias")] + public string? Alias { get; set; } + + /// + /// Gets or sets the unique identifier of the customer’s country. + /// + [JsonPropertyName("countryId")] + public Guid CountryId { get; set; } + + /// + /// Gets or sets the city where the customer resides. + /// + [JsonPropertyName("city")] + public string City { get; set; } = string.Empty; + + /// + /// Gets or sets the residential or business address of the customer. + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; /// - /// Gets or sets the customer's phone number. + /// Gets or sets the customer's mobile phone number. /// [JsonPropertyName("mobileNumber")] public string MobileNumber { get; set; } = string.Empty; /// - /// Gets or sets the customer's date of birth. + /// Gets or sets the email address of the customer. /// - [JsonPropertyName("dob")] - public DateTime? DateOfBirth { get; set; } + [JsonPropertyName("emailAddress")] + public string EmailAddress { get; set; } = string.Empty; /// - /// Gets or sets the customer's verification status. + /// Gets or sets the date when the customer record was created, if available. /// - [JsonPropertyName("verificationStatus")] - public CustomerVerificationStatus VerificationStatus { get; set; } + [JsonPropertyName("dateCreated")] + public DateTimeOffset? DateCreated { get; set; } /// - /// Gets or sets the customer type. + /// Gets or sets a value indicating whether the corporate customer has been verified. /// - [JsonPropertyName("customerType")] - public CustomerType? CustomerType { get; set; } + [JsonPropertyName("isCorporateVerified")] + public string IsCorporateVerified { get; set; } = string.Empty; /// - /// Gets or sets the customer's address. + /// Gets or sets the customer's verification status. /// - [JsonPropertyName("address")] - public string? Address { get; set; } + [JsonPropertyName("verificationStatus")] + public CustomerVerificationStatus VerificationStatus { get; set; } /// - /// Gets or sets the customer's city. + /// Gets or sets the customer type. /// - [JsonPropertyName("city")] - public string? City { get; set; } + [JsonPropertyName("customerType")] + public CustomerType? CustomerType { get; set; } /// /// Gets or sets the customer status. @@ -87,12 +123,6 @@ public sealed class Customer [JsonPropertyName("status")] public CustomerStatus Status { get; set; } - /// - /// Gets or sets the date when the customer was created. - /// - [JsonPropertyName("dateCreated")] - public DateTimeOffset? CreatedAt { get; set; } - /// /// Gets or sets the date when the customer was last updated. /// diff --git a/Embedly.SDK/Models/Responses/Customers/CustomerVerificationProperties.cs b/Embedly.SDK/Models/Responses/Customers/CustomerVerificationProperties.cs index 7949d4a..e217a8d 100644 --- a/Embedly.SDK/Models/Responses/Customers/CustomerVerificationProperties.cs +++ b/Embedly.SDK/Models/Responses/Customers/CustomerVerificationProperties.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using System.Text.Json.Serialization; namespace Embedly.SDK.Models.Responses.Customers; @@ -10,70 +8,58 @@ namespace Embedly.SDK.Models.Responses.Customers; public sealed class CustomerVerificationProperties { /// - /// Gets or sets the customer identifier. + /// Gets or sets the unique identifier of the customer. /// [JsonPropertyName("customerId")] public string CustomerId { get; set; } = string.Empty; /// - /// Gets or sets the current KYC level. + /// Gets or sets a value indicating whether the customer has a registered BVN (Bank Verification Number). /// - [JsonPropertyName("kycLevel")] - public string KycLevel { get; set; } = string.Empty; + [JsonPropertyName("hasBvn")] + public bool HasBvn { get; set; } /// - /// Gets or sets the verification status. - /// - [JsonPropertyName("verificationStatus")] - public CustomerVerificationStatus VerificationStatus { get; set; } - - /// - /// Gets or sets whether identity verification is completed. + /// Gets or sets a value indicating whether the customer has a registered NIN (National Identification Number). /// - [JsonPropertyName("identityVerified")] - public bool IdentityVerified { get; set; } + [JsonPropertyName("hasNin")] + public bool HasNin { get; set; } /// - /// Gets or sets whether address verification is completed. + /// Gets or sets a value indicating whether the customer's address has been verified. /// - [JsonPropertyName("addressVerified")] - public bool AddressVerified { get; set; } + [JsonPropertyName("hasAddressVerification")] + public bool HasAddressVerification { get; set; } /// - /// Gets or sets whether phone number is verified. + /// Gets or sets the customer's verification tier level. /// - [JsonPropertyName("phoneVerified")] - public bool PhoneVerified { get; set; } + [JsonPropertyName("customerTierId")] + public int CustomerTierId { get; set; } /// - /// Gets or sets whether email is verified. + /// Gets or sets the customer's BVN value, if available. /// - [JsonPropertyName("emailVerified")] - public bool EmailVerified { get; set; } + [JsonPropertyName("bvnValue")] + public string BvnValue { get; set; } = string.Empty; /// - /// Gets or sets the verification methods completed. + /// Gets or sets the customer's NIN value, if available. /// - [JsonPropertyName("completedVerifications")] - public List CompletedVerifications { get; set; } = new(); + [JsonPropertyName("ninValue")] + public string NinValue { get; set; } = string.Empty; /// - /// Gets or sets the pending verification requirements. + /// Gets or sets the verification status. /// - [JsonPropertyName("pendingVerifications")] - public List PendingVerifications { get; set; } = new(); + [JsonPropertyName("verificationStatus")] + public CustomerVerificationStatus VerificationStatus { get; set; } /// /// Gets or sets the maximum transaction limits for this KYC level. /// [JsonPropertyName("transactionLimits")] public TransactionLimits? TransactionLimits { get; set; } - - /// - /// Gets or sets the date when verification was last updated. - /// - [JsonPropertyName("lastVerificationUpdate")] - public DateTime? LastVerificationUpdate { get; set; } } /// diff --git a/Embedly.SDK/Models/Responses/Payout/Bank.cs b/Embedly.SDK/Models/Responses/Payout/Bank.cs index f571eb1..0be2192 100644 --- a/Embedly.SDK/Models/Responses/Payout/Bank.cs +++ b/Embedly.SDK/Models/Responses/Payout/Bank.cs @@ -18,16 +18,4 @@ public sealed class Bank /// [JsonPropertyName("bankName")] public string BankName { get; set; } = string.Empty; - - /// - /// Gets or sets whether the bank is active. - /// - [JsonPropertyName("isActive")] - public bool IsActive { get; set; } - - /// - /// Gets or sets the bank type. - /// - [JsonPropertyName("type")] - public string? Type { get; set; } } \ No newline at end of file diff --git a/Embedly.SDK/Models/Responses/Payout/NameEnquiryResponse.cs b/Embedly.SDK/Models/Responses/Payout/NameEnquiryResponse.cs index d42010f..df73cc8 100644 --- a/Embedly.SDK/Models/Responses/Payout/NameEnquiryResponse.cs +++ b/Embedly.SDK/Models/Responses/Payout/NameEnquiryResponse.cs @@ -8,50 +8,44 @@ namespace Embedly.SDK.Models.Responses.Payout; public sealed class NameEnquiryResponse { /// - /// Gets or sets the overall status of the verification response. + /// Gets or sets the unique session identifier for the transaction. /// - [JsonPropertyName("status")] - public string Status { get; set; } = string.Empty; + [JsonPropertyName("sessionID")] + public string SessionId { get; set; } = string.Empty; /// - /// Gets or sets the detailed bank account verification data. + /// Gets or sets the destination institution code associated with the transaction. /// - [JsonPropertyName("data")] - public BankAccountVerificationData Data { get; set; } = new(); + [JsonPropertyName("destinationInstitutionCode")] + public string DestinationInstitutionCode { get; set; } = string.Empty; /// - /// Gets or sets the response code returned from the verification service. + /// Gets or sets the channel code used for the transaction. /// - [JsonPropertyName("code")] - public string? Code { get; set; } + [JsonPropertyName("channelCode")] + public int ChannelCode { get; set; } /// - /// Gets or sets the message returned from the verification service. + /// Gets or sets the customer's account number. /// - [JsonPropertyName("message")] - public string? Message { get; set; } -} + [JsonPropertyName("accountNumber")] + public string AccountNumber { get; set; } = string.Empty; -/// -/// Represents the detailed data for the bank account verification response. -/// -public class BankAccountVerificationData -{ /// - /// Gets or sets the destination bank code associated with the account. + /// Gets or sets the customer's account name. /// - [JsonPropertyName("destinationBankCode")] - public string DestinationBankCode { get; set; } = string.Empty; + [JsonPropertyName("accountName")] + public string AccountName { get; set; } = string.Empty; /// - /// Gets or sets the verified bank account number. + /// Gets or sets the customer's KYC (Know Your Customer) level. /// - [JsonPropertyName("accountNumber")] - public string AccountNumber { get; set; } = string.Empty; + [JsonPropertyName("kycLevel")] + public string KycLevel { get; set; } = string.Empty; /// - /// Gets or sets the verified name associated with the bank account. + /// Gets or sets the response code indicating the outcome of the verification. /// - [JsonPropertyName("accountName")] - public string AccountName { get; set; } = string.Empty; + [JsonPropertyName("responseCode")] + public string ResponseCode { get; set; } = string.Empty; } \ No newline at end of file diff --git a/Embedly.SDK/Models/Responses/Payout/PayoutTransactionStatus.cs b/Embedly.SDK/Models/Responses/Payout/PayoutTransactionStatus.cs new file mode 100644 index 0000000..d4c5743 --- /dev/null +++ b/Embedly.SDK/Models/Responses/Payout/PayoutTransactionStatus.cs @@ -0,0 +1,39 @@ +using System.Text.Json.Serialization; + +namespace Embedly.SDK.Models.Responses.Payout; + +/// +/// Represents the response details for a payout transaction. +/// +public sealed class PayoutTransactionStatus +{ + /// + /// Gets or sets the overall status of the transaction. + /// + [JsonPropertyName("status")] + public string Status { get; set; } = string.Empty; + + /// + /// Gets or sets the unique reference assigned to the transaction. + /// + [JsonPropertyName("transactionReference")] + public string TransactionReference { get; set; } = string.Empty; + + /// + /// Gets or sets the unique reference provided by the payment provider. + /// + [JsonPropertyName("providerReference")] + public string ProviderReference { get; set; } = string.Empty; + + /// + /// Gets or sets the reference associated with the payment. + /// + [JsonPropertyName("paymentReference")] + public string PaymentReference { get; set; } = string.Empty; + + /// + /// Gets or sets the session identifier for the transaction process. + /// + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} diff --git a/Embedly.SDK/Models/Responses/Wallets/Wallet.cs b/Embedly.SDK/Models/Responses/Wallets/Wallet.cs index 85c64fa..913b2fb 100644 --- a/Embedly.SDK/Models/Responses/Wallets/Wallet.cs +++ b/Embedly.SDK/Models/Responses/Wallets/Wallet.cs @@ -30,13 +30,13 @@ public sealed class Wallet /// Gets or sets the available balance. /// [JsonPropertyName("availableBalance")] - public double AvailableBalance { get; set; } + public decimal AvailableBalance { get; set; } /// /// Gets or sets the ledger balance. /// [JsonPropertyName("ledgerBalance")] - public double LedgerBalance { get; set; } + public decimal LedgerBalance { get; set; } /// /// Gets or sets the wallet restriction ID. @@ -78,7 +78,7 @@ public sealed class Wallet /// Gets or sets the overdraft limit. /// [JsonPropertyName("overdraft")] - public double? Overdraft { get; set; } + public decimal? Overdraft { get; set; } /// /// Gets or sets the virtual account information. diff --git a/Embedly.SDK/Services/Customers/CustomerService.cs b/Embedly.SDK/Services/Customers/CustomerService.cs index 2c0e979..12c746c 100644 --- a/Embedly.SDK/Services/Customers/CustomerService.cs +++ b/Embedly.SDK/Services/Customers/CustomerService.cs @@ -78,7 +78,7 @@ public async Task>> GetAllAsync(GetCustomersRe } /// - public async Task> UpdateNameAsync(string customerId, string firstName, string lastName, + public async Task> UpdateNameAsync(string customerId, string firstName, string lastName, CancellationToken cancellationToken = default) { Guard.ThrowIfNullOrWhiteSpace(customerId, nameof(customerId)); @@ -96,14 +96,14 @@ public async Task> UpdateNameAsync(string customerId, stri } /// - public async Task> UpdateNameAsync(UpdateCustomerNameRequest request, + public async Task> UpdateNameAsync(UpdateCustomerNameRequest request, CancellationToken cancellationToken = default) { Guard.ThrowIfNull(request, nameof(request)); Guard.ThrowIfNullOrWhiteSpace(request.CustomerId, nameof(request.CustomerId)); var url = BuildUrl(ServiceUrls.Base, $"api/v1/customers/customer/{request.CustomerId}/updatename"); - return await HttpClient.PatchAsync(url, request, cancellationToken); + return await HttpClient.PatchAsync(url, request, cancellationToken); } /// @@ -135,7 +135,9 @@ public async Task> UpgradeKycWithBvnAsync(Bvn Guard.ThrowIfNull(request, nameof(request)); var url = BuildUrl(ServiceUrls.Base, $"api/v1/customers/kyc/premium-kyc"); - return await HttpClient.PostAsync(url, request, cancellationToken); + var queryParams = request.ToQueryParameters(); + + return await HttpClient.PostAsync(url, request, queryParams, cancellationToken); } /// @@ -202,13 +204,13 @@ public async Task> UpdateCustomerTypeAsync(string customer } /// - public async Task> UpdateContactAsync(string customerId, UpdateCustomerContactRequest request, + public async Task> UpdateContactAsync(string customerId, UpdateCustomerContactRequest request, CancellationToken cancellationToken = default) { Guard.ThrowIfNullOrWhiteSpace(customerId, nameof(customerId)); Guard.ThrowIfNull(request, nameof(request)); var url = BuildUrl(ServiceUrls.Base, $"api/v1/customers/customer/{customerId}/updatecontact"); - return await HttpClient.PatchAsync(url, request, cancellationToken); + return await HttpClient.PatchAsync(url, request, cancellationToken); } } \ No newline at end of file diff --git a/Embedly.SDK/Services/Customers/ICustomerService.cs b/Embedly.SDK/Services/Customers/ICustomerService.cs index 82ffb26..8211b99 100644 --- a/Embedly.SDK/Services/Customers/ICustomerService.cs +++ b/Embedly.SDK/Services/Customers/ICustomerService.cs @@ -56,7 +56,7 @@ Task>> GetAllAsync(GetCustomersRequest request /// The new last name. /// The cancellation token. /// The API response containing the updated customer. - Task> UpdateNameAsync(string customerId, string firstName, string lastName, + Task> UpdateNameAsync(string customerId, string firstName, string lastName, CancellationToken cancellationToken = default); /// @@ -65,7 +65,7 @@ Task> UpdateNameAsync(string customerId, string firstName, /// The update request. /// The cancellation token. /// The API response containing the updated customer. - Task> UpdateNameAsync(UpdateCustomerNameRequest request, + Task> UpdateNameAsync(UpdateCustomerNameRequest request, CancellationToken cancellationToken = default); /// @@ -135,6 +135,6 @@ Task> UpdateCustomerTypeAsync(string customerId, string cu /// The contact update request. /// The cancellation token. /// The API response containing the updated customer. - Task> UpdateContactAsync(string customerId, UpdateCustomerContactRequest request, + Task> UpdateContactAsync(string customerId, UpdateCustomerContactRequest request, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/Embedly.SDK/Services/Payout/IPayoutService.cs b/Embedly.SDK/Services/Payout/IPayoutService.cs index 6f7dd53..4c2c942 100644 --- a/Embedly.SDK/Services/Payout/IPayoutService.cs +++ b/Embedly.SDK/Services/Payout/IPayoutService.cs @@ -38,7 +38,7 @@ Task> NameEnquiryAsync(NameEnquiryRequest reque /// The bank transfer request. /// Cancellation token. /// The transfer transaction details. - Task> InterBankTransferAsync(BankTransferRequest request, + Task> InterBankTransferAsync(BankTransferRequest request, CancellationToken cancellationToken = default); /// @@ -47,7 +47,7 @@ Task> InterBankTransferAsync(BankTransferRequest /// The transaction reference. /// Cancellation token. /// The transaction status details. - Task> GetTransactionStatusAsync(string transactionReference, + Task> GetTransactionStatusAsync(string transactionReference, CancellationToken cancellationToken = default); /// diff --git a/Embedly.SDK/Services/Payout/PayoutService.cs b/Embedly.SDK/Services/Payout/PayoutService.cs index 9bf42ad..e2c3fce 100644 --- a/Embedly.SDK/Services/Payout/PayoutService.cs +++ b/Embedly.SDK/Services/Payout/PayoutService.cs @@ -47,23 +47,23 @@ public async Task> NameEnquiryAsync(NameEnquiry } /// - public async Task> InterBankTransferAsync(BankTransferRequest request, + public async Task> InterBankTransferAsync(BankTransferRequest request, CancellationToken cancellationToken = default) { Guard.ThrowIfNull(request, nameof(request)); var url = BuildUrl(ServiceUrls.Payout, "api/Payout/inter-bank-transfer"); - return await HttpClient.PostAsync(url, request, cancellationToken); + return await HttpClient.PostAsync(url, request, cancellationToken); } /// - public async Task> GetTransactionStatusAsync(string transactionReference, + public async Task> GetTransactionStatusAsync(string transactionReference, CancellationToken cancellationToken = default) { Guard.ThrowIfNullOrWhiteSpace(transactionReference, nameof(transactionReference)); var url = BuildUrl(ServiceUrls.Payout, $"api/Payout/status/{transactionReference}"); - return await HttpClient.GetAsync(url, cancellationToken); + return await HttpClient.GetAsync(url, cancellationToken); } ///