diff --git a/src/CheckoutSdk/Accounts/Company.cs b/src/CheckoutSdk/Accounts/Company.cs index 11fcbc7d..40078b3d 100644 --- a/src/CheckoutSdk/Accounts/Company.cs +++ b/src/CheckoutSdk/Accounts/Company.cs @@ -1,4 +1,6 @@ -using Checkout.Common; +using Checkout.Accounts.Regional; +using Checkout.Common; +using Newtonsoft.Json; using System.Collections.Generic; namespace Checkout.Accounts diff --git a/src/CheckoutSdk/Accounts/IAccountsClient.cs b/src/CheckoutSdk/Accounts/IAccountsClient.cs index 136899ba..e2058814 100644 --- a/src/CheckoutSdk/Accounts/IAccountsClient.cs +++ b/src/CheckoutSdk/Accounts/IAccountsClient.cs @@ -1,5 +1,6 @@ using Checkout.Accounts.Payout.Request; using Checkout.Accounts.Payout.Response; +using Checkout.Accounts.Regional.US; using Checkout.Common; using System; using System.Threading; diff --git a/src/CheckoutSdk/Accounts/OnboardEntityDetailsResponse.cs b/src/CheckoutSdk/Accounts/OnboardEntityDetailsResponse.cs index 2dc544fb..1347abfd 100644 --- a/src/CheckoutSdk/Accounts/OnboardEntityDetailsResponse.cs +++ b/src/CheckoutSdk/Accounts/OnboardEntityDetailsResponse.cs @@ -1,4 +1,6 @@ -using Checkout.Common; +using Checkout.Accounts.Regional; +using Checkout.Common; +using Newtonsoft.Json; using System.Collections.Generic; namespace Checkout.Accounts @@ -18,7 +20,7 @@ public class OnboardEntityDetailsResponse : Resource public ContactDetails ContactDetails { get; set; } public Profile Profile { get; set; } - + public Company Company { get; set; } public Individual Individual { get; set; } diff --git a/src/CheckoutSdk/Accounts/Regional/CompanyTypeConverter.cs b/src/CheckoutSdk/Accounts/Regional/CompanyTypeConverter.cs new file mode 100644 index 00000000..a941f3d1 --- /dev/null +++ b/src/CheckoutSdk/Accounts/Regional/CompanyTypeConverter.cs @@ -0,0 +1,65 @@ +using Checkout.Accounts.Regional.US; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Reflection; + +namespace Checkout.Accounts.Regional +{ + public class CompanyTypeConverter : JsonConverter + { + public override bool CanWrite => false; + + public override bool CanConvert(Type objectType) + { + return typeof(OnboardEntityDetailsResponse).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); + } + + public override void WriteJson( + JsonWriter writer, + object value, + Newtonsoft.Json.JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + Newtonsoft.Json.JsonSerializer serializer) + { + + if (reader.TokenType == JsonToken.Null) + return null; + + var jObject = JToken.Load(reader); + if (jObject.Type == JTokenType.Object) + { + var businessTypeToken = jObject["company"]?["business_type"]; + if (businessTypeToken != null && businessTypeToken.Type == JTokenType.String ) + { + var enumString = businessTypeToken.Value(); + + var businessType = CheckoutUtils.GetEnumFromStringMemberValue(enumString); + if (businessType != null) + { + var target = new OnboardEntityDetailsResponse(); + serializer.Populate(jObject.CreateReader(), target); + return target; + } + + var usBusinessType = CheckoutUtils.GetEnumFromStringMemberValue(enumString); + if (usBusinessType != null) + { + var target = new OnboardEntityDetailsUSCompanyResponse(); + serializer.Populate(jObject.CreateReader(), target); + return target; + } + } + } + + throw new JsonSerializationException($"Unexpected token or value when parsing enum. Token: {reader.TokenType}, Value: {jObject}"); + } + } +} \ No newline at end of file diff --git a/src/CheckoutSdk/Accounts/Regional/US/OnboardEntityDetailsUSCompanyResponse.cs b/src/CheckoutSdk/Accounts/Regional/US/OnboardEntityDetailsUSCompanyResponse.cs new file mode 100644 index 00000000..05bc7c8f --- /dev/null +++ b/src/CheckoutSdk/Accounts/Regional/US/OnboardEntityDetailsUSCompanyResponse.cs @@ -0,0 +1,7 @@ +namespace Checkout.Accounts.Regional.US +{ + public class OnboardEntityDetailsUSCompanyResponse : OnboardEntityDetailsResponse + { + public new USCompany Company { get; set; } + } +} \ No newline at end of file diff --git a/src/CheckoutSdk/Accounts/Regional/US/USCompany.cs b/src/CheckoutSdk/Accounts/Regional/US/USCompany.cs index 2c9f9136..df05bad2 100644 --- a/src/CheckoutSdk/Accounts/Regional/US/USCompany.cs +++ b/src/CheckoutSdk/Accounts/Regional/US/USCompany.cs @@ -1,4 +1,6 @@ -namespace Checkout.Accounts.Regional.US +using Newtonsoft.Json; + +namespace Checkout.Accounts.Regional.US { public class USCompany : Company { diff --git a/src/CheckoutSdk/JsonSerializer.cs b/src/CheckoutSdk/JsonSerializer.cs index 693f419f..a730b0fc 100644 --- a/src/CheckoutSdk/JsonSerializer.cs +++ b/src/CheckoutSdk/JsonSerializer.cs @@ -1,4 +1,5 @@ using Checkout.Accounts.Payout.Response.Util; +using Checkout.Accounts.Regional; using Checkout.Instruments.Create.Util; using Checkout.Instruments.Get.Util; using Checkout.Instruments.Update.Util; @@ -50,6 +51,7 @@ private static JsonSerializerSettings CreateSerializerSettings(Action + { + new Representative + { + FirstName = "John", + LastName = "Doe", + Address = GetAddress(), + Identification = new Identification { NationalIdNumber = "AB123456C", } + } + } + } + }; + + var entityResponse = await api.AccountsClient().CreateEntity(entityRequest); + + var entityDetailsResponse = await api.AccountsClient().GetEntity(entityResponse.Id); + + var file = await UploadFile(); + + var instrumentRequest = new PaymentInstrumentRequest + { + Label = "Barclays", + Type = InstrumentType.BankAccount, + Currency = Currency.GBP, + Country = CountryCode.GB, + DefaultDestination = false, + Document = new InstrumentDocument { Type = "bank_statement", FileId = file.Id }, + InstrumentDetails = new InstrumentDetailsFasterPayments + { + AccountNumber = "12334454", BankCode = "050389" + } + }; + + var instrumentResponse = await api.AccountsClient().CreatePaymentInstrument(entityResponse.Id, instrumentRequest); + instrumentResponse.ShouldNotBeNull(); + instrumentResponse.Id.ShouldNotBeNull(); + + entityDetailsResponse.ShouldNotBeNull(); + + var instrumentDetails = await api.AccountsClient().RetrievePaymentInstrumentDetails(entityResponse.Id, instrumentResponse.Id); + instrumentDetails.ShouldNotBeNull(); + instrumentDetails.Id.ShouldNotBeNull(); + instrumentDetails.Status.ShouldNotBeNull(); + instrumentDetails.Label.ShouldNotBeNull(); + instrumentDetails.Type.ShouldNotBeNull(); + instrumentDetails.Currency.ShouldNotBeNull(); + instrumentDetails.Country.ShouldNotBeNull(); + instrumentDetails.Document.ShouldNotBeNull(); + + var queryResponse = await api.AccountsClient().QueryPaymentInstruments(entityResponse.Id); + queryResponse.ShouldNotBeNull(); + queryResponse.Data.ShouldNotBeNull(); + } + + + private static string RandomString(int length) { diff --git a/test/CheckoutSdkTest/CheckoutSdkTest.csproj b/test/CheckoutSdkTest/CheckoutSdkTest.csproj index b6bcb6f1..02f3052a 100644 --- a/test/CheckoutSdkTest/CheckoutSdkTest.csproj +++ b/test/CheckoutSdkTest/CheckoutSdkTest.csproj @@ -85,6 +85,17 @@ PreserveNewest + + + PreserveNewest + + + + PreserveNewest + + + PreserveNewest + diff --git a/test/CheckoutSdkTest/JsonSerializerTest.cs b/test/CheckoutSdkTest/JsonSerializerTest.cs index 4bc2b616..71e0a7c0 100644 --- a/test/CheckoutSdkTest/JsonSerializerTest.cs +++ b/test/CheckoutSdkTest/JsonSerializerTest.cs @@ -1,3 +1,5 @@ +using Checkout.Accounts; +using Checkout.Accounts.Regional.US; using Checkout.Financial; using Checkout.Issuing.Cards; using Checkout.Issuing.Cards.Requests.Create; @@ -126,6 +128,28 @@ public void ShouldSerializeDateTimeFormatsFromJson() financialActionsQueryResponse.ShouldNotBeNull(); financialActionsQueryResponse.Data[0].ProcessedOn.ShouldNotBeNull(); } + + [Fact] + public void ShouldSerializeOnBoardSubEntityCompanyFromJson() + { + var fileContent = GetJsonFileContent("./Resources/OnBoardSubEntityCompanyResponse.json"); + OnboardEntityDetailsResponse onboardEntityDetailsResponse = + (OnboardEntityDetailsResponse)new JsonSerializer().Deserialize(fileContent, + typeof(OnboardEntityDetailsResponse)); + onboardEntityDetailsResponse.ShouldNotBeNull(); + onboardEntityDetailsResponse.Company.BusinessType.ShouldBeOfType(); + } + + [Fact] + public void ShouldSerializeOnBoardSubEntityUSCompanyFromJson() + { + var fileContent = GetJsonFileContent("./Resources/OnBoardSubEntityUSCompanyResponse.json"); + OnboardEntityDetailsUSCompanyResponse onboardEntityDetailsResponse = + (OnboardEntityDetailsUSCompanyResponse)new JsonSerializer().Deserialize(fileContent, + typeof(OnboardEntityDetailsUSCompanyResponse)); + onboardEntityDetailsResponse.ShouldNotBeNull(); + onboardEntityDetailsResponse.Company.BusinessType.ShouldBeOfType(); + } [Fact] public void ShouldDeserializeDateTimeFormatsFromStrings() diff --git a/test/CheckoutSdkTest/Resources/OnBoardSubEntityCompanyResponse.json b/test/CheckoutSdkTest/Resources/OnBoardSubEntityCompanyResponse.json new file mode 100644 index 00000000..8b7aff6d --- /dev/null +++ b/test/CheckoutSdkTest/Resources/OnBoardSubEntityCompanyResponse.json @@ -0,0 +1,69 @@ +{ + "id": "ent_saf19jffasdf", + "contact_details": { + "phone": { + "number": "2345678910" + }, + "email_addresses": { + "primary": "admin@superhero1234.com" + } + }, + "profile": { + "urls": [ + "https://www.superheroexample.com" + ], + "mccs": [ + "5311" + ], + "default_holding_currency": "GBP", + "holding_currencies": [ + "GBP" + ] + }, + "company": { + "business_registration_number": "12345678", + "business_type": "public_limited_company", + "legal_name": "Acme Corporation Inc.", + "trading_name": "Acme Corporation", + "principal_address": { + "address_line1": "Flat 456", + "city": "London", + "zip": "SW1A 1AA", + "country": "GB" + }, + "registered_address": { + "address_line1": "Flat 456", + "city": "London", + "zip": "SW1A 1AA", + "country": "GB" + }, + "representatives": [ + { + "id": "rep_1d1j98j1h991dlkjdajsjd", + "first_name": "John", + "last_name": "Smith", + "address": { + "address_line1": "Flat 456", + "city": "London", + "zip": "SW1A 1AA", + "country": "GB" + }, + "identification": { + "national_id_number": "AB123456C", + "document": { + "type": "driving_license", + "front": "file_wxglze3wwywujg4nna5fb7ldli", + "back": "file_adglze3wwywujg4nna5fb7l1sg" + } + }, + "phone": { + "number": "2345678910" + }, + "roles": [ + "authorised_signatory", + "ubo" + ] + } + ] + } +} \ No newline at end of file diff --git a/test/CheckoutSdkTest/Resources/OnBoardSubEntityUSCompanyResponse.json b/test/CheckoutSdkTest/Resources/OnBoardSubEntityUSCompanyResponse.json new file mode 100644 index 00000000..6380a039 --- /dev/null +++ b/test/CheckoutSdkTest/Resources/OnBoardSubEntityUSCompanyResponse.json @@ -0,0 +1,96 @@ +{ + "id": "ent_saf19jffasdf", + "contact_details": { + "phone": { + "number": "2345678910" + }, + "email_addresses": { + "primary": "admin@superhero1234.com" + } + }, + "profile": { + "urls": [ + "https://www.superheroexample.com" + ], + "mccs": [ + "5311" + ], + "default_holding_currency": "USD", + "holding_currencies": [ + "GBP", + "USD" + ] + }, + "company": { + "business_registration_number": "123456789", + "business_type": "private_corporation", + "legal_name": "Acme Corporation Inc.", + "trading_name": "Acme Corporation", + "principal_address": { + "address_line1": "Fulton Street", + "city": "Houston", + "state": "TX", + "zip": "12345", + "country": "US" + }, + "registered_address": { + "address_line1": "Fulton Street", + "city": "Houston", + "state": "TX", + "zip": "12345", + "country": "US" + }, + "representatives": [ + { + "id": "rep_1d1j98j1h991dlkjdajsjd", + "first_name": "John", + "last_name": "Smith", + "address": { + "address_line1": "Fulton Street", + "city": "Houston", + "state": "TX", + "zip": "12345", + "country": "US" + }, + "identification": { + "national_id_number": "123456789" + }, + "phone": { + "number": "2345678910" + }, + "date_of_birth": { + "day": 5, + "month": 6, + "year": 1995 + }, + "roles": [ + "ubo", + "authorised_signatory" + ], + "documents": { + "identity_verification": { + "type": "driving_license", + "front": "file_wxglze3wwywujg4nna5fb7ldli", + "back": "file_adglze3wwywujg4nna5fb7l1sg" + } + } + } + ], + "financial_details": { + "annual_processing_volume": 120000, + "average_transaction_value": 10000, + "highest_transaction_value": 2500, + "currency": "USD" + } + }, + "documents": { + "company_verification": { + "type": "incorporation_document", + "front": "file_aaz5pemp6326zbuvevp6qroqu4" + }, + "tax_verification": { + "type": "ein_letter", + "front": "file_aaz5pemp6326zbuvevp6qroqu4" + } + } +} \ No newline at end of file