Skip to content

Commit fc47d7e

Browse files
committed
Refactor error handling in wrappers to use centralized exception throwing
- Updated `FacturapiException` to include an optional status code. - Introduced `ThrowIfErrorAsync` method in `BaseWrapper` to handle HTTP response errors consistently across all wrappers. - Removed redundant error handling code from `CatalogWrapper`, `CustomerWrapper`, `InvoiceWrapper`, `OrganizationWrapper`, `ProductWrapper`, `ReceiptWrapper`, `RetentionWrapper`, `ToolWrapper`, and `WebhookWrapper`. - Ensured all wrappers now utilize the new error handling method for improved maintainability and readability.
1 parent 6e1ad4f commit fc47d7e

11 files changed

+134
-386
lines changed

FacturAPIException.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
62

73
namespace Facturapi
84
{
95
public class FacturapiException : Exception
106
{
7+
public int? Status { get; private set; }
8+
119
public FacturapiException() : base() { }
12-
public FacturapiException(string message) : base(message) { }
10+
public FacturapiException(string message, int? status = null) : base(message)
11+
{
12+
Status = status;
13+
}
1314
}
1415
}

Wrappers/BaseWrapper.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
23
using System;
34
using System.Net.Http;
45
using System.Text;
6+
using System.Threading.Tasks;
57

68
namespace Facturapi.Wrappers
79
{
@@ -27,5 +29,56 @@ public BaseWrapper(string apiKey, string apiVersion = "v2")
2729
NullValueHandling = NullValueHandling.Ignore
2830
};
2931
}
32+
33+
protected FacturapiException CreateException(string resultString, HttpResponseMessage response)
34+
{
35+
JObject error = null;
36+
37+
try
38+
{
39+
error = JsonConvert.DeserializeObject<JObject>(resultString, this.jsonSettings);
40+
}
41+
catch (JsonException)
42+
{
43+
}
44+
45+
var message = error?["message"]?.ToString() ?? "An error occurred";
46+
47+
int? status = null;
48+
var statusToken = error?["status"];
49+
if (statusToken != null)
50+
{
51+
if (statusToken.Type == JTokenType.Integer)
52+
{
53+
status = statusToken.Value<int>();
54+
}
55+
else if (statusToken.Type == JTokenType.Float)
56+
{
57+
status = Convert.ToInt32(statusToken.Value<double>());
58+
}
59+
else if (int.TryParse(statusToken.ToString(), out var parsedStatus))
60+
{
61+
status = parsedStatus;
62+
}
63+
}
64+
65+
if (status == null && response != null)
66+
{
67+
status = (int)response.StatusCode;
68+
}
69+
70+
return new FacturapiException(message, status);
71+
}
72+
73+
protected async Task ThrowIfErrorAsync(HttpResponseMessage response)
74+
{
75+
if (response.IsSuccessStatusCode)
76+
{
77+
return;
78+
}
79+
80+
var resultString = await response.Content.ReadAsStringAsync();
81+
throw CreateException(resultString, response);
82+
}
3083
}
3184
}

Wrappers/CatalogWrapper.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Newtonsoft.Json;
2-
using Newtonsoft.Json.Linq;
32
using System.Collections.Generic;
43
using System.Net.Http;
54
using System.Text;
@@ -16,29 +15,19 @@ public CatalogWrapper(string apiKey, string apiVersion = "v2") : base(apiKey, ap
1615
public async Task<SearchResult<CatalogItem>> SearchProducts(Dictionary<string, object> query = null)
1716
{
1817
var response = await client.GetAsync(Router.SearchProductKeys(query));
18+
await this.ThrowIfErrorAsync(response);
1919
var resultString = await response.Content.ReadAsStringAsync();
2020

21-
if (!response.IsSuccessStatusCode)
22-
{
23-
var error = JsonConvert.DeserializeObject<JObject>(resultString, this.jsonSettings);
24-
throw new FacturapiException(error["message"].ToString());
25-
}
26-
2721
var searchResult = JsonConvert.DeserializeObject<SearchResult<CatalogItem>>(resultString, this.jsonSettings);
2822
return searchResult;
2923
}
3024

3125
public async Task<SearchResult<CatalogItem>> SearchUnits(Dictionary<string, object> query = null)
3226
{
3327
var response = await client.GetAsync(Router.SearchUnitKeys(query));
28+
await this.ThrowIfErrorAsync(response);
3429
var resultString = await response.Content.ReadAsStringAsync();
3530

36-
if (!response.IsSuccessStatusCode)
37-
{
38-
var error = JsonConvert.DeserializeObject<JObject>(resultString, this.jsonSettings);
39-
throw new FacturapiException(error["message"].ToString());
40-
}
41-
4231
var searchResult = JsonConvert.DeserializeObject<SearchResult<CatalogItem>>(resultString, this.jsonSettings);
4332
return searchResult;
4433
}

Wrappers/CustomerWrapper.cs

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
using Newtonsoft.Json;
2-
using Newtonsoft.Json.Linq;
3-
using System;
42
using System.Collections.Generic;
5-
using System.Linq;
63
using System.Net.Http;
74
using System.Text;
85
using System.Threading.Tasks;
@@ -18,93 +15,62 @@ public CustomerWrapper(string apiKey, string apiVersion = "v2") : base(apiKey, a
1815
public async Task<SearchResult<Customer>> ListAsync(Dictionary<string, object> query = null)
1916
{
2017
var response = await client.GetAsync(Router.ListCustomers(query));
18+
await this.ThrowIfErrorAsync(response);
2119
var resultString = await response.Content.ReadAsStringAsync();
2220

23-
if (!response.IsSuccessStatusCode)
24-
{
25-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
26-
throw new FacturapiException(error["message"].ToString());
27-
}
28-
2921
var searchResult = JsonConvert.DeserializeObject<SearchResult<Customer>>(resultString, this.jsonSettings);
3022
return searchResult;
3123
}
3224

3325
public async Task<Customer> CreateAsync(Dictionary<string, object> data, Dictionary<string, object> queryParams = null)
3426
{
3527
var response = await client.PostAsync(Router.CreateCustomer(queryParams), new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"));
28+
await this.ThrowIfErrorAsync(response);
3629
var resultString = await response.Content.ReadAsStringAsync();
37-
if (!response.IsSuccessStatusCode)
38-
{
39-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
40-
throw new FacturapiException(error["message"].ToString());
41-
}
4230
var customer = JsonConvert.DeserializeObject<Customer>(resultString, this.jsonSettings);
4331
return customer;
4432
}
4533

4634
public async Task<Customer> RetrieveAsync(string id)
4735
{
4836
var response = await client.GetAsync(Router.RetrieveCustomer(id));
37+
await this.ThrowIfErrorAsync(response);
4938
var resultString = await response.Content.ReadAsStringAsync();
50-
if (!response.IsSuccessStatusCode)
51-
{
52-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
53-
throw new FacturapiException(error["message"].ToString());
54-
}
5539
var customer = JsonConvert.DeserializeObject<Customer>(resultString, this.jsonSettings);
5640
return customer;
5741
}
5842

5943
public async Task<Customer> DeleteAsync(string id)
6044
{
6145
var response = await client.DeleteAsync(Router.DeleteCustomer(id));
46+
await this.ThrowIfErrorAsync(response);
6247
var resultString = await response.Content.ReadAsStringAsync();
63-
if (!response.IsSuccessStatusCode)
64-
{
65-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
66-
throw new FacturapiException(error["message"].ToString());
67-
}
6848
var customer = JsonConvert.DeserializeObject<Customer>(resultString, this.jsonSettings);
6949
return customer;
7050
}
7151

7252
public async Task<Customer> UpdateAsync(string id, Dictionary<string, object> data, Dictionary<string, object> queryParams = null)
7353
{
7454
var response = await client.PutAsync(Router.UpdateCustomer(id, queryParams), new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"));
55+
await this.ThrowIfErrorAsync(response);
7556
var resultString = await response.Content.ReadAsStringAsync();
76-
if (!response.IsSuccessStatusCode)
77-
{
78-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
79-
throw new FacturapiException(error["message"].ToString());
80-
}
81-
var customer = JsonConvert.DeserializeObject<Customer>(resultString, this.jsonSettings);
82-
return customer;
57+
var customer = JsonConvert.DeserializeObject<Customer>(resultString, this.jsonSettings);
58+
return customer;
8359
}
8460

8561
public async Task<TaxInfoValidation> ValidateTaxInfoAsync(string id)
8662
{
8763
var response = await client.GetAsync(Router.ValidateCustomerTaxInfo(id));
64+
await this.ThrowIfErrorAsync(response);
8865
var resultString = await response.Content.ReadAsStringAsync();
89-
if (!response.IsSuccessStatusCode)
90-
{
91-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
92-
throw new FacturapiException(error["message"].ToString());
93-
}
9466
var validation = JsonConvert.DeserializeObject<TaxInfoValidation>(resultString, this.jsonSettings);
9567
return validation;
9668
}
9769

9870
public async Task SendEditLinkByEmailAsync(string id, Dictionary<string, object> data)
9971
{
10072
var response = await client.PostAsync(Router.SendEditLinkByEmail(id), new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"));
101-
if (!response.IsSuccessStatusCode)
102-
{
103-
var resultString = await response.Content.ReadAsStringAsync();
104-
var error = JsonConvert.DeserializeObject<JObject>(resultString);
105-
var errorMessage = error["message"] != null ? error["message"].ToString() : "An error occurred";
106-
throw new FacturapiException(errorMessage);
107-
}
73+
await this.ThrowIfErrorAsync(response);
10874
}
10975
}
11076
}

0 commit comments

Comments
 (0)