From d366091625b11b7d872abaeb12fa7a793fe56f03 Mon Sep 17 00:00:00 2001 From: vineethKExalture <91251412+vineethKExalture@users.noreply.github.com> Date: Fri, 18 Nov 2022 19:07:26 +0530 Subject: [PATCH] [MSUE-43] [MSUE-123] - Verification API Endpoints Integration + Merchant API (#22) * Verification API Endpoints Integration * Webhook Validation Implementation * Merchants API Integration --- Sift/Core/Client.cs | 34 ++++ Sift/Core/WebhookValidator.cs | 61 ++++++ Sift/Request/GetMerchantsRequest.cs | 83 ++++++++ Sift/Request/MerchantRequest.cs | 163 ++++++++++++++++ Sift/Request/VerificationRequest.cs | 161 ++++++++++++++++ Sift/Response/GetMerchantsResponse.cs | 177 +++++++++++++++++ Sift/Response/MerchantResponse.cs | 114 +++++++++++ Sift/Response/VerificationResponse.cs | 43 +++++ Sift/Sift.csproj | 5 +- Test/Test.cs | 263 ++++++++++++++++++++++++++ 10 files changed, 1100 insertions(+), 4 deletions(-) create mode 100644 Sift/Core/WebhookValidator.cs create mode 100644 Sift/Request/GetMerchantsRequest.cs create mode 100644 Sift/Request/MerchantRequest.cs create mode 100644 Sift/Request/VerificationRequest.cs create mode 100644 Sift/Response/GetMerchantsResponse.cs create mode 100644 Sift/Response/MerchantResponse.cs create mode 100644 Sift/Response/VerificationResponse.cs diff --git a/Sift/Core/Client.cs b/Sift/Core/Client.cs index 450e9cb..f642944 100644 --- a/Sift/Core/Client.cs +++ b/Sift/Core/Client.cs @@ -73,6 +73,40 @@ public async Task SendAsync(WorkflowStatusRequest workfl { return await SendAsync(workflowStatusRequest); } + public async Task SendAsync(VerificationCheckRequest verificationCheckRequest) + { + return await SendAsync(verificationCheckRequest); + } + + public async Task SendAsync(VerificationSendRequest verificationSendRequest) + { + return await SendAsync(verificationSendRequest); + } + + public async Task SendAsync(VerificationReSendRequest verificationReSendRequest) + { + return await SendAsync(verificationReSendRequest); + } + + public async Task SendAsync(GetMerchantsRequest getMerchantRequest) + { + return await SendAsync(getMerchantRequest); + } + + public async Task SendAsync(CreateMerchantRequest createMerchantRequest) + { + return await SendAsync(createMerchantRequest); + } + + public async Task SendAsync(UpdateMerchantRequest updateMerchantRequest) + { + return await SendAsync(updateMerchantRequest); + } + + public async Task SendAsync(GetMerchantDetailsRequest getMerchantRequest) + { + return await SendAsync(getMerchantRequest); + } async Task SendAsync(SiftRequest siftRequest) where T : SiftResponse { diff --git a/Sift/Core/WebhookValidator.cs b/Sift/Core/WebhookValidator.cs new file mode 100644 index 0000000..697a122 --- /dev/null +++ b/Sift/Core/WebhookValidator.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; + +namespace Sift.Core +{ + public class WebhookValidator + { + private const string Sha1Prefix = "sha1="; + + public bool IsValidWebhook(string payload, string secretKey, string signatureWithPrefix) + { + if (string.IsNullOrWhiteSpace(payload)) + { + throw new ArgumentNullException(nameof(payload)); + } + if (string.IsNullOrWhiteSpace(secretKey)) + { + throw new ArgumentNullException(nameof(secretKey)); + } + if (string.IsNullOrWhiteSpace(signatureWithPrefix)) + { + throw new ArgumentNullException(nameof(signatureWithPrefix)); + } + + if (signatureWithPrefix.StartsWith(Sha1Prefix, StringComparison.OrdinalIgnoreCase)) + { + var signature = signatureWithPrefix.Substring(Sha1Prefix.Length); + var secret = Encoding.ASCII.GetBytes(secretKey); + var payloadBytes = Encoding.ASCII.GetBytes(payload); + + using (var hmSha1 = new HMACSHA1(secret)) + { + var hash = hmSha1.ComputeHash(payloadBytes); + + var hashString = ToHexString(hash); + + if (hashString.Equals(signature)) + { + return true; + } + } + } + + return false; + } + + + public static string ToHexString(byte[] bytes) + { + var builder = new StringBuilder(bytes.Length * 2); + foreach (byte b in bytes) + { + builder.AppendFormat("{0:x2}", b); + } + + return builder.ToString(); + } + } +} diff --git a/Sift/Request/GetMerchantsRequest.cs b/Sift/Request/GetMerchantsRequest.cs new file mode 100644 index 0000000..13bc3e4 --- /dev/null +++ b/Sift/Request/GetMerchantsRequest.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; + +namespace Sift +{ + public class GetMerchantsRequest : SiftRequest + { + static readonly String GetMerchantsUrl = @"https://api.sift.com/v3/accounts/{0}/psp_management/merchants"; + + public string AccountId { get; set; } + public string BatchToken { get; set; } + public int? BatchSize { get; set; } + + + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Get, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + return request; + } + } + + protected override Uri Url + { + get + { + var url = new Uri(String.Format(GetMerchantsUrl, + Uri.EscapeDataString(AccountId))); + + + if (!String.IsNullOrEmpty(BatchToken)) + { + url = url.AddQuery("batch_token", BatchToken); + } + + if (BatchSize.HasValue) + { + url = url.AddQuery("limit", BatchSize.Value.ToString()); + } + + + return url; + } + } + + } + + public class GetMerchantDetailsRequest : SiftRequest + { + static readonly String GetMerchantsUrl = @"https://api.sift.com/v3/accounts/{0}/psp_management/merchants/{1}"; + + public string AccountId { get; set; } + public string MerchantId { get; set; } + + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Get, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + return request; + } + } + + protected override Uri Url + { + get + { + var url = new Uri(String.Format(GetMerchantsUrl, + Uri.EscapeDataString(AccountId), + Uri.EscapeDataString(MerchantId))); + return url; + } + } + + } + +} diff --git a/Sift/Request/MerchantRequest.cs b/Sift/Request/MerchantRequest.cs new file mode 100644 index 0000000..07e256a --- /dev/null +++ b/Sift/Request/MerchantRequest.cs @@ -0,0 +1,163 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; + +namespace Sift +{ + public class CreateMerchantRequest : SiftRequest + { + static readonly String CreateMerchantUrl = @"https://api.sift.com/v3/accounts/{0}/psp_management/merchants"; + + [JsonIgnore] + public string AccountId { get; set; } + + [JsonIgnore] + public override string ApiKey { get; set; } + + [JsonProperty("id", NullValueHandling = NullValueHandling.Ignore)] + public string Id { get; set; } + + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; set; } + + [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] + public string Description { get; set; } + + [JsonProperty("address")] + public MerchantAddress Address { get; set; } + + [JsonProperty("category", NullValueHandling = NullValueHandling.Ignore)] + public string Category { get; set; } + + [JsonProperty("service_level", NullValueHandling = NullValueHandling.Ignore)] + public string ServiceLevel { get; set; } + + [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] + public string Status { get; set; } + + [JsonProperty("risk_profile")] + public MerchantRiskProfile RiskProfile { get; set; } + + [JsonIgnore] + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Post, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + request.Content = new StringContent(JsonConvert.SerializeObject(this), Encoding.UTF8, "application/json"); + return request; + } + } + + [JsonIgnore] + protected override Uri Url + { + get + { + return new Uri(String.Format(CreateMerchantUrl, + Uri.EscapeDataString(AccountId))); + } + } + } + + public class UpdateMerchantRequest : SiftRequest + { + static readonly String UpdateMerchantUrl = @"https://api.sift.com/v3/accounts/{0}/psp_management/merchants/{1}"; + + [JsonIgnore] + public string AccountId { get; set; } + + [JsonIgnore] + public string MerchantId { get; set; } + + [JsonIgnore] + public override string ApiKey { get; set; } + + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; set; } + + [JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)] + public string Description { get; set; } + + [JsonProperty("address")] + public MerchantAddress Address { get; set; } + + [JsonProperty("category", NullValueHandling = NullValueHandling.Ignore)] + public string Category { get; set; } + + [JsonProperty("service_level", NullValueHandling = NullValueHandling.Ignore)] + public string ServiceLevel { get; set; } + + [JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)] + public string Status { get; set; } + + [JsonProperty("risk_profile")] + public MerchantRiskProfile RiskProfile { get; set; } + + [JsonIgnore] + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Put, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + request.Content = new StringContent(JsonConvert.SerializeObject(this), Encoding.UTF8, "application/json"); + return request; + } + } + + [JsonIgnore] + protected override Uri Url + { + get + { + return new Uri(String.Format(UpdateMerchantUrl, + Uri.EscapeDataString(AccountId), + Uri.EscapeDataString(MerchantId))); + } + } + } + + public class MerchantAddress + { + [JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)] + public string Name { get; set; } + + [JsonProperty("address_1", NullValueHandling = NullValueHandling.Ignore)] + public string Address1 { get; set; } + + [JsonProperty("address_2", NullValueHandling = NullValueHandling.Ignore)] + public string Address2 { get; set; } + + [JsonProperty("city", NullValueHandling = NullValueHandling.Ignore)] + public string City { get; set; } + + [JsonProperty("region", NullValueHandling = NullValueHandling.Ignore)] + public string Region { get; set; } + + [JsonProperty("country", NullValueHandling = NullValueHandling.Ignore)] + public string Country { get; set; } + + [JsonProperty("zipcode", NullValueHandling = NullValueHandling.Ignore)] + public string ZipCode { get; set; } + + [JsonProperty("phone", NullValueHandling = NullValueHandling.Ignore)] + public string Phone { get; set; } + } + + public class MerchantRiskProfile + { + [JsonProperty("level", NullValueHandling = NullValueHandling.Ignore)] + public string Level { get; set; } + + [JsonProperty("score", NullValueHandling = NullValueHandling.Ignore)] + public int Score { get; set; } + } +} \ No newline at end of file diff --git a/Sift/Request/VerificationRequest.cs b/Sift/Request/VerificationRequest.cs new file mode 100644 index 0000000..f27e29c --- /dev/null +++ b/Sift/Request/VerificationRequest.cs @@ -0,0 +1,161 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; + +namespace Sift +{ + public class VerificationCheckRequest : SiftRequest + { + static readonly String VerificationCheckUrl = @"https://api.sift.com/v1.1/verification/check"; + + [JsonIgnore] + public override string ApiKey { get; set; } + + [JsonProperty("$user_id", NullValueHandling = NullValueHandling.Ignore)] + public string UserId { get; set; } + + [JsonProperty("$code", NullValueHandling = NullValueHandling.Ignore)] + public int Code { get; set; } + + [JsonProperty("$verified_event", NullValueHandling = NullValueHandling.Ignore)] + public string VerifiedEvent { get; set; } + + [JsonProperty("$verified_entity_id", NullValueHandling = NullValueHandling.Ignore)] + public string VerifiedEntityId { get; set; } + + [JsonIgnore] + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Post, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + request.Content = new StringContent(JsonConvert.SerializeObject(this), Encoding.UTF8, "application/json"); + return request; + } + } + + [JsonIgnore] + protected override Uri Url + { + get + { + return new Uri(VerificationCheckUrl); + } + } + } + + public class VerificationSendRequest : SiftRequest + { + static readonly String VerificationSendUrl = @"https://api.sift.com/v1.1/verification/send"; + + [JsonIgnore] + public override string ApiKey { get; set; } + + [JsonProperty("$user_id", NullValueHandling = NullValueHandling.Ignore)] + public string UserId { get; set; } + + + [JsonProperty("$send_to", NullValueHandling = NullValueHandling.Ignore)] + public string SendTo { get; set; } + + [JsonProperty("$verification_type", NullValueHandling = NullValueHandling.Ignore)] + public string VerificationType { get; set; } + + [JsonProperty("$brand_name", NullValueHandling = NullValueHandling.Ignore)] + public string BrandName { get; set; } + + [JsonProperty("$language", NullValueHandling = NullValueHandling.Ignore)] + public string Language { get; set; } + + [JsonProperty("$event")] + public VerificationSendEvent Event { get; set; } + + [JsonIgnore] + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Post, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + request.Content = new StringContent(JsonConvert.SerializeObject(this), Encoding.UTF8, "application/json"); + return request; + } + } + + [JsonIgnore] + protected override Uri Url + { + get + { + return new Uri(VerificationSendUrl); + } + } + } + + public class VerificationReSendRequest : SiftRequest + { + static readonly String VerificationReSendUrl = @"https://api.sift.com/v1.1/verification/resend"; + + [JsonIgnore] + public override string ApiKey { get; set; } + + [JsonProperty("$user_id", NullValueHandling = NullValueHandling.Ignore)] + public string UserId { get; set; } + + [JsonProperty("$verified_event", NullValueHandling = NullValueHandling.Ignore)] + public string VerifiedEvent { get; set; } + + [JsonProperty("$verified_entity_id", NullValueHandling = NullValueHandling.Ignore)] + public string VerifiedEntityId { get; set; } + + [JsonIgnore] + public override HttpRequestMessage Request + { + get + { + var request = new HttpRequestMessage(HttpMethod.Post, Url); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey))); + request.Content = new StringContent(JsonConvert.SerializeObject(this), Encoding.UTF8, "application/json"); + return request; + } + } + + [JsonIgnore] + protected override Uri Url + { + get + { + return new Uri(VerificationReSendUrl); + } + } + } + + + public class VerificationSendEvent + { + [JsonProperty("$session_id", NullValueHandling = NullValueHandling.Ignore)] + public string SessionId { get; set; } + + [JsonProperty("$verified_event", NullValueHandling = NullValueHandling.Ignore)] + public string VerifiedEvent { get; set; } + + [JsonProperty("$reason", NullValueHandling = NullValueHandling.Ignore)] + public string Reason { get; set; } + + [JsonProperty("$ip", NullValueHandling = NullValueHandling.Ignore)] + public string IP { get; set; } + + [JsonProperty("$browser")] + public VerificationSendBrowser Browser { get; set; } + } + + public class VerificationSendBrowser + { + [JsonProperty("$user_agent", NullValueHandling = NullValueHandling.Ignore)] + public string UserAgent { get; set; } + } +} diff --git a/Sift/Response/GetMerchantsResponse.cs b/Sift/Response/GetMerchantsResponse.cs new file mode 100644 index 0000000..2d9abd7 --- /dev/null +++ b/Sift/Response/GetMerchantsResponse.cs @@ -0,0 +1,177 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + + +namespace Sift +{ + public class GetMerchantsResponse : SiftResponse + { + [JsonProperty("data")] + public List Merchants { get; set; } + + public class MerchantJson + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("created_at")] + public long CreatedAt { get; set; } + + [JsonProperty("created_by")] + public long CreatedBy { get; set; } + + [JsonProperty("last_updated_at")] + public long UpdatedAt { get; set; } + + [JsonProperty("last_updated_by")] + public string UpdatedBy { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("address")] + public MerchantAddressJson Address { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("service_level")] + public string ServiceLevel { get; set; } + + [JsonProperty("status")] + public bool Status { get; set; } + + [JsonProperty("risk_profile")] + public MerchantRiskProfile RiskProfile { get; set; } + + [JsonProperty("has_more")] + public bool HasMore { get; set; } + + [JsonProperty("next_ref")] + public string NextRef { get; set; } + + } + + public class MerchantAddressJson + { + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("address_1")] + public string Address1 { get; set; } + + [JsonProperty("address_2")] + public string Address2 { get; set; } + + [JsonProperty("city")] + public string City { get; set; } + + [JsonProperty("region")] + public string Region { get; set; } + + [JsonProperty("country")] + public string Country { get; set; } + + [JsonProperty("zipcode")] + public string ZipCode { get; set; } + + [JsonProperty("phone")] + public string Phone { get; set; } + } + + public class MerchantRiskProfile + { + [JsonProperty("level")] + public string Level { get; set; } + + [JsonProperty("score")] + public int Score { get; set; } + } + } + + public class GetMerchantDetailsResponse : SiftResponse + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("created_at")] + public long CreatedAt { get; set; } + + [JsonProperty("created_by")] + public long CreatedBy { get; set; } + + [JsonProperty("last_updated_at")] + public long UpdatedAt { get; set; } + + [JsonProperty("last_updated_by")] + public string UpdatedBy { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("address")] + public MerchantAddressJson Address { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("service_level")] + public string ServiceLevel { get; set; } + + [JsonProperty("status")] + public bool Status { get; set; } + + [JsonProperty("risk_profile")] + public MerchantRiskProfile RiskProfile { get; set; } + + [JsonProperty("has_more")] + public bool HasMore { get; set; } + + [JsonProperty("next_ref")] + public string NextRef { get; set; } + + public class MerchantAddressJson + { + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("address_1")] + public string Address1 { get; set; } + + [JsonProperty("address_2")] + public string Address2 { get; set; } + + [JsonProperty("city")] + public string City { get; set; } + + [JsonProperty("region")] + public string Region { get; set; } + + [JsonProperty("country")] + public string Country { get; set; } + + [JsonProperty("zipcode")] + public string ZipCode { get; set; } + + [JsonProperty("phone")] + public string Phone { get; set; } + } + + public class MerchantRiskProfile + { + [JsonProperty("level")] + public string Level { get; set; } + + [JsonProperty("score")] + public int Score { get; set; } + } + } +} diff --git a/Sift/Response/MerchantResponse.cs b/Sift/Response/MerchantResponse.cs new file mode 100644 index 0000000..9e1d7d1 --- /dev/null +++ b/Sift/Response/MerchantResponse.cs @@ -0,0 +1,114 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sift +{ + public class CreateMerchantResponse : SiftResponse + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("created_at")] + public long CreatedAt { get; set; } + + [JsonProperty("created_by")] + public long CreatedBy { get; set; } + + [JsonProperty("last_updated_at")] + public long UpdatedAt { get; set; } + + [JsonProperty("last_updated_by")] + public string UpdatedBy { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("address")] + public MerchantAddressJson Address { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("service_level")] + public string ServiceLevel { get; set; } + + [JsonProperty("status")] + public bool Status { get; set; } + + [JsonProperty("risk_profile")] + public MerchantRiskProfile RiskProfile { get; set; } + } + + public class UpdateMerchantResponse : SiftResponse + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("created_at")] + public long CreatedAt { get; set; } + + [JsonProperty("created_by")] + public long CreatedBy { get; set; } + + [JsonProperty("last_updated_at")] + public long UpdatedAt { get; set; } + + [JsonProperty("last_updated_by")] + public string UpdatedBy { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("address")] + public MerchantAddressJson Address { get; set; } + + [JsonProperty("category")] + public string Category { get; set; } + + [JsonProperty("service_level")] + public string ServiceLevel { get; set; } + + [JsonProperty("status")] + public bool Status { get; set; } + + [JsonProperty("risk_profile")] + public MerchantRiskProfile RiskProfile { get; set; } + } + + public class MerchantAddressJson + { + [JsonProperty("name")] + public string Name { get; set; } + + [JsonProperty("address_1")] + public string Address1 { get; set; } + + [JsonProperty("address_2")] + public string Address2 { get; set; } + + [JsonProperty("city")] + public string City { get; set; } + + [JsonProperty("region")] + public string Region { get; set; } + + [JsonProperty("country")] + public string Country { get; set; } + + [JsonProperty("zipcode")] + public string ZipCode { get; set; } + + [JsonProperty("phone")] + public string Phone { get; set; } + } + + +} diff --git a/Sift/Response/VerificationResponse.cs b/Sift/Response/VerificationResponse.cs new file mode 100644 index 0000000..0942359 --- /dev/null +++ b/Sift/Response/VerificationResponse.cs @@ -0,0 +1,43 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sift +{ + public class VerificationCheckResponse : SiftResponse + { + [JsonProperty("$status")] + public string Status { get; set; } + + [JsonProperty("$error_message")] + public string ErrorMessage { get; set; } + + [JsonProperty("$checked_at")] + public string CheckedAt { get; set; } + } + public class VerificationSendResponse : SiftResponse + { + [JsonProperty("$status")] + public string Status { get; set; } + + [JsonProperty("$error_message")] + public string ErrorMessage { get; set; } + + [JsonProperty("$sent_at")] + public string SentAt { get; set; } + } + + public class VerificationReSendResponse : SiftResponse + { + [JsonProperty("$status")] + public string Status { get; set; } + + [JsonProperty("$error_message")] + public string ErrorMessage { get; set; } + + [JsonProperty("$sent_at")] + public string SentAt { get; set; } + } + +} diff --git a/Sift/Sift.csproj b/Sift/Sift.csproj index f60a61f..22bb13c 100644 --- a/Sift/Sift.csproj +++ b/Sift/Sift.csproj @@ -4,7 +4,7 @@ Sift, Gary Lee Sift Sift - 0.9.2 + 0.9.3 beta Beta release netstandard2.0 @@ -20,10 +20,7 @@ - - - diff --git a/Test/Test.cs b/Test/Test.cs index 465029b..1dd2ce5 100644 --- a/Test/Test.cs +++ b/Test/Test.cs @@ -4,6 +4,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; +using System.Security.Cryptography; +using System.IO; +using Sift.Core; +using System.Linq; namespace Test { @@ -553,6 +557,265 @@ public void TestCreateOrderEventWithWirePaymentMethod() Uri.UnescapeDataString(eventRequest.Request.RequestUri.ToString())); } + [Fact] + public void TestVerificationCheckRequest() + { + var verificationCheckRequest = new VerificationCheckRequest + { + ApiKey = "35d603c1513f2567:", + Code = 655543, + UserId = "vineethk@exalture.com" + + }; + + verificationCheckRequest.ApiKey = "35d603c1513f2567"; + + Assert.Equal(Convert.ToBase64String(Encoding.Default.GetBytes("35d603c1513f2567")), + verificationCheckRequest.Request.Headers.Authorization.Parameter); + + Assert.Equal("https://api.sift.com/v1.1/verification/check", + verificationCheckRequest.Request.RequestUri.ToString()); + } + + [Fact] + public void TestVerificationSendRequest() + { + var verificationSendRequest = new VerificationSendRequest + { + UserId = "vineethk@exalture.com", + ApiKey = "35d603c1513f2567:", + BrandName = "all", + VerificationType = "$email", + SendTo = "vineethk@exalture.com", + Language = "en", + Event = new VerificationSendEvent() + { + Browser = new VerificationSendBrowser() + { + UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" + }, + IP = "192.168.1.1", + Reason = "$automated_rule", + SessionId = "gigtleqddo84l8cm15qe4il", + VerifiedEvent = "$login" + } + }; + + verificationSendRequest.ApiKey = "35d603c1513f2567"; + + Assert.Equal(Convert.ToBase64String(Encoding.Default.GetBytes("35d603c1513f2567")), + verificationSendRequest.Request.Headers.Authorization.Parameter); + + Assert.Equal("https://api.sift.com/v1.1/verification/send", + verificationSendRequest.Request.RequestUri.ToString()); + } + + [Fact] + public void TestVerificationReSendRequest() + { + var verificationResendRequest = new VerificationReSendRequest + { + + + UserId = "vineethk@exalture.com", + ApiKey = "35d603c1513f2567:" + + + }; + + verificationResendRequest.ApiKey = "35d603c1513f2567"; + + Assert.Equal(Convert.ToBase64String(Encoding.Default.GetBytes("35d603c1513f2567")), + verificationResendRequest.Request.Headers.Authorization.Parameter); + + + Assert.Equal("https://api.sift.com/v1.1/verification/resend", + verificationResendRequest.Request.RequestUri.ToString()); + } + + + [Fact] + public void TestWebHookValidation() + { + String secretKey = "1d708fe409f22591"; + String requestBody = "{\n" + + " \"entity\": {\n" + + " \"type\": \"user\",\n" + + " \"id\": \"USER123\"\n" + + " },\n" + + " \"decision\": {\n" + + " \"id\": \"block_user_payment_abuse\"\n" + + " },\n" + + " \"time\": 1461963439151\n" + + "}"; + byte[] key = Encoding.ASCII.GetBytes("1d708fe409f22591"); + HMACSHA1 myhmacsha1 = new HMACSHA1(key); + byte[] byteArray = Encoding.ASCII.GetBytes(requestBody); + MemoryStream stream = new MemoryStream(byteArray); + string signatureCore = myhmacsha1.ComputeHash(stream).Aggregate("", (s, e) => s + String.Format("{0:x2}", e), s => s); + String signature = "sha1=" + signatureCore; + WebhookValidator webhook = new WebhookValidator(); + Assert.True(webhook.IsValidWebhook(requestBody, secretKey, signature)); + + } + + [Fact] + public void TestWebHookValidationForInvalidSecretKey() + { + String secretKey = "1d708fe409f22591"; + String requestBody = "{\n" + + " \"entity\": {\n" + + " \"type\": \"user\",\n" + + " \"id\": \"USER123\"\n" + + " },\n" + + " \"decision\": {\n" + + " \"id\": \"block_user_payment_abuse\"\n" + + " },\n" + + " \"time\": 1461963439151\n" + + "}"; + + WebhookValidator webhook = new WebhookValidator(); + Assert.False(webhook.IsValidWebhook(requestBody, secretKey, "InValid Key")); + + + } + + [Fact] + public void TestGetMerchantsRequest() + { + var getMerchantRequest = new GetMerchantsRequest + { + AccountId = "5f053f004025ca08a187fad6" + }; + + getMerchantRequest.ApiKey = "09f7f361575d11ff"; + + Assert.Equal("https://api.sift.com/v3/accounts/5f053f004025ca08a187fad6/psp_management/merchants", + getMerchantRequest.Request.RequestUri.ToString()); + + } + + [Fact] + public void TestCreateMerchantRequest() + { + var createMerchantRequest = new CreateMerchantRequest + { + AccountId = "5f053f004025ca08a187fad6", + ApiKey = "09f7f361575d11ff", + Id = "test-vineeth-5", + Name = "Wonderful Payments Inc", + Description = "Wonderful Payments payment provider", + Address = new MerchantAddress + { + Name = "Alany", + Address1 = "Big Payment blvd, 22", + Address2 = "apt, 8", + City = "New Orleans", + Country = "US", + Phone = "0394888320", + Region = "NA", + ZipCode = "76830" + + }, + Category = "1002", + ServiceLevel = "Platinum", + Status = "active", + RiskProfile = new MerchantRiskProfile + { + Level = "low", + Score = 10 + } + }; + + createMerchantRequest.ApiKey = "09f7f361575d11ff"; + + Assert.Equal(Convert.ToBase64String(Encoding.Default.GetBytes("09f7f361575d11ff")), + createMerchantRequest.Request.Headers.Authorization.Parameter); + + + Assert.Equal("https://api.sift.com/v3/accounts/5f053f004025ca08a187fad6/psp_management/merchants", + createMerchantRequest.Request.RequestUri.ToString()); + } + + [Fact] + public void TestUpdateMerchantRequest() + { + var updateMerchantRequest = new UpdateMerchantRequest + { + AccountId = "5f053f004025ca08a187fad6", + MerchantId = "test2", + ApiKey = "09f7f361575d11ff", + Id = "test-vineeth-5", + Name = "Wonderful Payments Inc", + Description = "Wonderful Payments payment provider", + Address = new MerchantAddress + { + Name = "Alany", + Address1 = "Big Payment blvd, 22", + Address2 = "apt, 8", + City = "New Orleans", + Country = "US", + Phone = "0394888320", + Region = "NA", + ZipCode = "76830" + + }, + Category = "1002", + ServiceLevel = "Platinum", + Status = "active", + RiskProfile = new MerchantRiskProfile + { + Level = "low", + Score = 10 + } + }; + + updateMerchantRequest.ApiKey = "09f7f361575d11ff"; + + Assert.Equal(Convert.ToBase64String(Encoding.Default.GetBytes("09f7f361575d11ff")), + updateMerchantRequest.Request.Headers.Authorization.Parameter); + + Assert.Equal("https://api.sift.com/v3/accounts/5f053f004025ca08a187fad6/psp_management/merchants/test2", + updateMerchantRequest.Request.RequestUri.ToString()); + + + Assert.Equal("{\"id\":\"test-vineeth-5\"," + + "\"name\":\"Wonderful Payments Inc\"," + + "\"description\":\"Wonderful Payments payment provider\"," + + "\"address\":{\"name\":\"Alany\"," + + "\"address_1\":\"Big Payment blvd, 22\"," + + "\"address_2\":\"apt, 8\"," + + "\"city\":\"New Orleans\"," + + "\"region\":\"NA\"," + + "\"country\":\"US\"," + + "\"zipcode\":\"76830\"," + + "\"phone\":\"0394888320\"}," + + "\"category\":\"1002\"," + + "\"service_level\":\"Platinum\"," + + "\"status\":\"active\"," + + "\"risk_profile\":{\"level\":\"low\",\"score\":10}}", + Newtonsoft.Json.JsonConvert.SerializeObject(updateMerchantRequest)); + + } + + [Fact] + public void TestGetMerchantDetailsRequest() + { + var getMerchantDetailRequest = new GetMerchantDetailsRequest + { + AccountId = "5f053f004025ca08a187fad6", + MerchantId = "test-merchat-id", + }; + + getMerchantDetailRequest.ApiKey = "09f7f361575d11ff"; + + Assert.Equal(Convert.ToBase64String(Encoding.Default.GetBytes("09f7f361575d11ff")), + getMerchantDetailRequest.Request.Headers.Authorization.Parameter); + + Assert.Equal("https://api.sift.com/v3/accounts/5f053f004025ca08a187fad6/psp_management/merchants/test-merchat-id", + getMerchantDetailRequest.Request.RequestUri.ToString()); + } + [Fact] public void TestChargebackEvent() {