API Sage One возвращает 500 внутренних служебных ошибок при создании счета на оплату
У меня возникла проблема при создании "Счета на покупку" в API Sage One. Независимо от того, какие изменения я внесу в передаваемые данные, я, похоже, получаю 500 Internal Service Error, и нет подробного ответа, содержащего какую-либо значимую информацию. Ответ всегда один и тот же, независимо от того, какие данные я ввожу (только с тем, что похоже на GUID в поле errorCode и время сервера меняется). Ответ таков:
{
"$diagnoses": [
{
"$severity": "error",
"$dataCode": "UnexpectedError",
"$message": "Unexpected error",
"$source": {
"serverTime": "2016-04-29T15:48:11.637+00:00",
"errorCode": "3b83e1b5-164d-42d4-95b3-3479b09c93f1",
"requestPath": "/api/v2/purchase_invoices",
"queryString": "",
"requestMethod": "POST"
}
}
]
}
Я уверен, что это не проблема авторизации, так как я получаю и создаю другие типы данных до этого. Это включает в себя контакты, которые необходимы для создания счета на покупку.
Я следил за информацией, представленной на их сайте самообслуживания. Я также начал с их голого SDK в качестве основы для большинства базовых процессов, с которыми я работаю. С тех пор я переписал большую часть базовой структуры, изначально думая, что это могло быть вызвано SDK, что привело меня к той же ситуации - когда я получаю только 500 внутренних служебных ошибок в качестве ответа.
Это наводит меня на мысль, что это проблема самих параметров, поскольку в документации есть некоторые различия между параметрами, перечисленными в среднем столбце, и данными в примере вызова в правом столбце. В частности, в примере есть дополнительные поля, такие как "extra_reference" и в позициях "product_id" и "product_code", которые не перечислены в среднем столбце.
Вот некоторый соответствующий код для вызова, снова помня, что базовая архитектура принадлежит им, с некоторыми процедурными изменениями, чтобы соответствовать моей текущей архитектуре, которые не влияют на фактический вызов:
protected override List<KeyValuePair<string, string>> GetPostDataValuesForCreate(
SageOnePurchaseInvoice objectToCreate)
{
List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("expense[contact_id]", objectToCreate.ContactId.ToString()));
postData.Add(new KeyValuePair<string, string>("expense[date]", objectToCreate.Date));
postData.Add(new KeyValuePair<string, string>("expense[due_date]", objectToCreate.DueDate));
if (!string.IsNullOrWhiteSpace(objectToCreate.Reference))
{
postData.Add(new KeyValuePair<string, string>("expense[reference]", objectToCreate.Reference));
}
if (objectToCreate.ProjectId != 0)
{
postData.Add(new KeyValuePair<string, string>("expense[project_id]", objectToCreate.ProjectId.ToString()));
}
if (!string.IsNullOrWhiteSpace(objectToCreate.Notes))
{
postData.Add(new KeyValuePair<string, string>("expense[notes]", objectToCreate.Notes));
}
for (int i = 0; i < objectToCreate.LineItems.Length; i++)
{
string index = "expense[line_items_attributes][" + i.ToString() + "][";
postData.Add(new KeyValuePair<string, string>(index + "description]", objectToCreate.LineItems[i].Description));
postData.Add(new KeyValuePair<string, string>(index + "ledger_account_id]", objectToCreate.LineItems[i].LedgerAccount.Id.ToString()));
postData.Add(new KeyValuePair<string, string>(index + "quantity]", objectToCreate.LineItems[i].Quantity.ToString()));
postData.Add(new KeyValuePair<string, string>(index + "unit_price]", objectToCreate.LineItems[i].UnitPrice.ToString()));
}
return postData;
}
Вот фактический метод, который создает и выполняет веб-запрос:
открытая статическая строка Create(Uri baseUrl, List> bodyParams, строковый токен, string signatureSecret) { string result;
string nonce = GenerateNonce();
HttpWebRequest sageOneWebRequest = WebRequest.Create(baseUrl) as HttpWebRequest;
string PostParams = ConvertPostParams(bodyParams);
string signatureString = GetSignatureString(baseUrl, null, bodyParams, nonce, WebRequestMethods.Http.Post);
string signingKey = GetSigningKey(token, signingSecret);
string signature = GenerateHmac(signingKey, signatureString);
sageOneWebRequest.AllowAutoRedirect = true;
sageOneWebRequest.Accept = "*/*";
sageOneWebRequest.UserAgent = "Itemize";
sageOneWebRequest.Headers.Add("X-Signature", signature);
sageOneWebRequest.Headers.Add("X-Nonce", nonce);
sageOneWebRequest.ContentType = "application/x-www-form-urlencoded";
sageOneWebRequest.Timeout = 100000;
sageOneWebRequest.Headers.Add("Authorization", "Bearer " + token);
sageOneWebRequest.Method = WebRequestMethods.Http.Post;
using (StreamWriter requestWriter = new StreamWriter(sageOneWebRequest.GetRequestStream()))
{
try
{
requestWriter.Write(PostParams);
}
catch(Exception ex)
{
throw new Exception("Exception thrown writing Post Params to Body", ex);
}
}
try
{
using (WebResponse response = sageOneWebRequest.GetResponse())
{
Stream dataStream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(dataStream))
{
result = reader.ReadToEnd();
}
}
}
catch (WebException webex)
{
//This is where the error is caught
Logger.Error("Web Exception while processing Sage One Web Request: ", webex);
string text;
using (var sr = new StreamReader(webex.Response.GetResponseStream()))
{
text = sr.ReadToEnd();
}
result = null;
throw new Exception("Web Exception thrown processing Sage One Request", webex);
}
catch (Exception ex)
{
Logger.Error("Exception while processing Sage One Web Request: ", ex);
result = null;
throw new Exception("Exception thrown processing Sage One Request", ex);
}
return result;
}
Любая помощь с этим вопросом будет принята с благодарностью! Спасибо!
Изменить: Что касается предложения, приведенного ниже, фактический путь URL-адреса является "api.sageone.com/accounts/v2/purchase_invoices", а не путь запроса, указанный в полученной ошибке.
2 ответа
Вы отправляете на /purchase_invoices
, но ваши параметры для expense
, Пожалуйста, используйте purchase_invoice
имя, чтобы обернуть ваши параметры.
Путь запроса выглядит неверно согласно ответу об ошибке. Он показывает "requestPath": "/api/v2/purchase_invoices"
но документация показывает /account / v2 / purchase_invoices