417 lines
18 KiB
C#
417 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
using System.Xml.Linq;
|
|
using System.Linq;
|
|
|
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|
{
|
|
/// <summary>
|
|
/// Service for managing orders in InnVoice API
|
|
/// </summary>
|
|
public class InnVoiceOrderService
|
|
{
|
|
private readonly HttpClient _httpClient;
|
|
private readonly string _companyName;
|
|
private readonly string _username;
|
|
private readonly string _password;
|
|
private readonly string _baseUrl;
|
|
|
|
public InnVoiceOrderService(string companyName = "apiteszt", string username = "apiteszt", string password = "dsjfluio4324hjhjfdhkjskjh213kjgsd", string baseUrl = "https://api.innvoice.hu")
|
|
{
|
|
_companyName = companyName ?? throw new ArgumentNullException(nameof(companyName));
|
|
_username = username ?? throw new ArgumentNullException(nameof(username));
|
|
_password = password ?? throw new ArgumentNullException(nameof(password));
|
|
_baseUrl = baseUrl.TrimEnd('/');
|
|
|
|
_httpClient = new HttpClient();
|
|
SetupAuthentication();
|
|
}
|
|
|
|
private void SetupAuthentication()
|
|
{
|
|
var authToken = Convert.ToBase64String(
|
|
System.Text.Encoding.ASCII.GetBytes($"{_username}:{_password}")
|
|
);
|
|
_httpClient.DefaultRequestHeaders.Authorization =
|
|
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create one or more orders
|
|
/// </summary>
|
|
public async Task<List<OrderCreateResponse>> CreateOrdersAsync(List<OrderCreateRequest> orders)
|
|
{
|
|
var url = $"{_baseUrl}/{_companyName}/order";
|
|
|
|
var xml = BuildOrdersXml(orders);
|
|
var content = new FormUrlEncodedContent(new[]
|
|
{
|
|
new KeyValuePair<string, string>("data", xml)
|
|
});
|
|
|
|
try
|
|
{
|
|
var response = await _httpClient.PostAsync(url, content);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
var responseContent = await response.Content.ReadAsStringAsync();
|
|
return ParseOrderResponses(responseContent);
|
|
}
|
|
catch (HttpRequestException ex)
|
|
{
|
|
throw new InnVoiceApiException($"Error creating orders: {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a single order
|
|
/// </summary>
|
|
public async Task<OrderCreateResponse> CreateOrderAsync(OrderCreateRequest order)
|
|
{
|
|
var responses = await CreateOrdersAsync(new List<OrderCreateRequest> { order });
|
|
return responses.FirstOrDefault();
|
|
}
|
|
|
|
private string BuildOrdersXml(List<OrderCreateRequest> orders)
|
|
{
|
|
var ordersElement = new XElement("orders");
|
|
|
|
foreach (var order in orders)
|
|
{
|
|
var orderElement = new XElement("order");
|
|
|
|
orderElement.Add(new XElement("VevoNev", new XCData(order.VevoNev ?? "")));
|
|
orderElement.Add(new XElement("VevoIrsz", new XCData(order.VevoIrsz ?? "")));
|
|
orderElement.Add(new XElement("VevoTelep", new XCData(order.VevoTelep ?? "")));
|
|
orderElement.Add(new XElement("VevoUtcaHsz", new XCData(order.VevoUtcaHsz ?? "")));
|
|
|
|
if (!string.IsNullOrEmpty(order.VevoOrszag))
|
|
orderElement.Add(new XElement("VevoOrszag", new XCData(order.VevoOrszag)));
|
|
|
|
if (!string.IsNullOrEmpty(order.VevoAdoszam))
|
|
orderElement.Add(new XElement("VevoAdoszam", new XCData(order.VevoAdoszam)));
|
|
|
|
if (!string.IsNullOrEmpty(order.SzallNev))
|
|
orderElement.Add(new XElement("SzallNev", new XCData(order.SzallNev)));
|
|
if (!string.IsNullOrEmpty(order.SzallIrsz))
|
|
orderElement.Add(new XElement("SzallIrsz", new XCData(order.SzallIrsz)));
|
|
if (!string.IsNullOrEmpty(order.SzallTelep))
|
|
orderElement.Add(new XElement("SzallTelep", new XCData(order.SzallTelep)));
|
|
if (!string.IsNullOrEmpty(order.SzallUtcaHsz))
|
|
orderElement.Add(new XElement("SzallUtcaHsz", new XCData(order.SzallUtcaHsz)));
|
|
if (!string.IsNullOrEmpty(order.SzallOrszag))
|
|
orderElement.Add(new XElement("SzallOrszag", new XCData(order.SzallOrszag)));
|
|
|
|
orderElement.Add(new XElement("MegrendelestombID", new XCData(order.MegrendelestombID.ToString())));
|
|
orderElement.Add(new XElement("MegrendelesKelte", new XCData(order.MegrendelesKelte.ToString("yyyy.MM.dd."))));
|
|
orderElement.Add(new XElement("Hatarido", new XCData(order.Hatarido.ToString("yyyy.MM.dd."))));
|
|
orderElement.Add(new XElement("Devizanem", new XCData(order.Devizanem ?? "")));
|
|
|
|
if (!string.IsNullOrEmpty(order.FizetesiMod))
|
|
orderElement.Add(new XElement("FizetesiMod", new XCData(order.FizetesiMod)));
|
|
if (!string.IsNullOrEmpty(order.Megjegyzes))
|
|
orderElement.Add(new XElement("Megjegyzes", new XCData(order.Megjegyzes)));
|
|
if (!string.IsNullOrEmpty(order.Email))
|
|
orderElement.Add(new XElement("Email", new XCData(order.Email)));
|
|
if (!string.IsNullOrEmpty(order.Telefon))
|
|
orderElement.Add(new XElement("Telefon", new XCData(order.Telefon)));
|
|
if (!string.IsNullOrEmpty(order.MegrendelesSzamStr))
|
|
orderElement.Add(new XElement("MegrendelesSzamStr", new XCData(order.MegrendelesSzamStr)));
|
|
|
|
// Add items
|
|
foreach (var item in order.Items)
|
|
{
|
|
var tetelElement = new XElement("tetel");
|
|
tetelElement.Add(new XElement("TetelNev", item.TetelNev ?? ""));
|
|
tetelElement.Add(new XElement("AfaSzoveg", item.AfaSzoveg ?? ""));
|
|
tetelElement.Add(new XElement("Brutto", item.Brutto ? "1" : "0"));
|
|
tetelElement.Add(new XElement("EgysegAr", item.EgysegAr.ToString()));
|
|
tetelElement.Add(new XElement("Mennyiseg", item.Mennyiseg.ToString()));
|
|
tetelElement.Add(new XElement("MennyisegEgyseg", new XCData(item.MennyisegEgyseg ?? "")));
|
|
|
|
if (!string.IsNullOrEmpty(item.CikkSzam))
|
|
tetelElement.Add(new XElement("CikkSzam", new XCData(item.CikkSzam)));
|
|
|
|
orderElement.Add(tetelElement);
|
|
}
|
|
|
|
ordersElement.Add(orderElement);
|
|
}
|
|
|
|
return new XDeclaration("1.0", "UTF-8", null).ToString() + "\n" + ordersElement.ToString();
|
|
}
|
|
|
|
private List<OrderCreateResponse> ParseOrderResponses(string xml)
|
|
{
|
|
var responses = new List<OrderCreateResponse>();
|
|
|
|
try
|
|
{
|
|
var doc = XDocument.Parse(xml);
|
|
var orderElements = doc.Descendants("order");
|
|
|
|
foreach (var orderElement in orderElements)
|
|
{
|
|
var response = new OrderCreateResponse
|
|
{
|
|
ErrorCode = orderElement.Element("error")?.Value?.Trim(),
|
|
Message = orderElement.Element("message")?.Value?.Trim(),
|
|
TableId = int.TryParse(orderElement.Element("TABLE_ID")?.Value?.Trim(), out var tid) ? tid : (int?)null,
|
|
TechId = orderElement.Element("techid")?.Value?.Trim(),
|
|
PrintUrl = orderElement.Element("PrintUrl")?.Value?.Trim()
|
|
};
|
|
|
|
responses.Add(response);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InnVoiceApiException($"Error parsing order response XML: {ex.Message}", ex);
|
|
}
|
|
|
|
return responses;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get order by technical ID
|
|
/// </summary>
|
|
public async Task<List<InnVoiceOrder>> GetOrderByTechIdAsync(string techId)
|
|
{
|
|
var url = $"{_baseUrl}/{_companyName}/order/techid/{Uri.EscapeDataString(techId)}";
|
|
return await GetOrdersFromUrlAsync(url);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get order by table ID
|
|
/// </summary>
|
|
public async Task<InnVoiceOrder> GetOrderByIdAsync(int tableId)
|
|
{
|
|
var url = $"{_baseUrl}/{_companyName}/order/id/{tableId}";
|
|
var orders = await GetOrdersFromUrlAsync(url);
|
|
return orders.Count > 0 ? orders[0] : null;
|
|
}
|
|
|
|
private async Task<List<InnVoiceOrder>> GetOrdersFromUrlAsync(string url)
|
|
{
|
|
try
|
|
{
|
|
var response = await _httpClient.GetAsync(url);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
// Parse XML response
|
|
return ParseOrdersFromXml(content);
|
|
}
|
|
catch (HttpRequestException ex)
|
|
{
|
|
throw new InnVoiceApiException($"Error calling InnVoice API: {ex.Message}", ex);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InnVoiceApiException($"Error parsing API response: {ex.Message}", ex);
|
|
}
|
|
}
|
|
|
|
private List<InnVoiceOrder> ParseOrdersFromXml(string xml)
|
|
{
|
|
var orders = new List<InnVoiceOrder>();
|
|
|
|
try
|
|
{
|
|
var doc = XDocument.Parse(xml);
|
|
var orderElements = doc.Descendants("order");
|
|
|
|
foreach (var orderElement in orderElements)
|
|
{
|
|
var order = new InnVoiceOrder
|
|
{
|
|
TableId = GetIntValue(orderElement, "TABLE_ID"),
|
|
VevoID = GetIntValue(orderElement, "VevoID"),
|
|
CustomerName = GetStringValue(orderElement, "VevoNev"),
|
|
CustomerZipCode = GetStringValue(orderElement, "VevoIrsz"),
|
|
CustomerCity = GetStringValue(orderElement, "VevoTelep"),
|
|
CustomerAddress = GetStringValue(orderElement, "VevoUtcaHsz"),
|
|
CustomerCountry = GetStringValue(orderElement, "VevoOrszag"),
|
|
CustomerTaxNumber = GetStringValue(orderElement, "VevoAdoszam"),
|
|
ShippingName = GetStringValue(orderElement, "SzallNev"),
|
|
ShippingZipCode = GetStringValue(orderElement, "SzallIrsz"),
|
|
ShippingCity = GetStringValue(orderElement, "SzallTelep"),
|
|
ShippingAddress = GetStringValue(orderElement, "SzallUtcaHsz"),
|
|
ShippingCountry = GetStringValue(orderElement, "SzallOrszag"),
|
|
OrderBookId = GetIntValue(orderElement, "MegrendelestombID"),
|
|
OrderDate = GetStringValue(orderElement, "MegrendelesKelte"),
|
|
DueDate = GetStringValue(orderElement, "Hatarido"),
|
|
Currency = GetStringValue(orderElement, "Devizanem"),
|
|
PaymentMethod = GetStringValue(orderElement, "FizetesiMod"),
|
|
Notes = GetStringValue(orderElement, "Megjegyzes"),
|
|
Email = GetStringValue(orderElement, "Email"),
|
|
Phone = GetStringValue(orderElement, "Telefon"),
|
|
ExternalOrderNumber = GetStringValue(orderElement, "MegrendelesSzamStr"),
|
|
TotalNet = GetDecimalValue(orderElement, "NettoErtek"),
|
|
TotalVAT = GetDecimalValue(orderElement, "AFAErtek"),
|
|
TotalGross = GetDecimalValue(orderElement, "BruttoErtek"),
|
|
TechId = GetStringValue(orderElement, "techid"),
|
|
PrintUrl = GetStringValue(orderElement, "PrintLink"),
|
|
UpdateTime = GetStringValue(orderElement, "_UpdateTime"),
|
|
QueryTime = GetStringValue(orderElement, "QueryTime")
|
|
};
|
|
|
|
// Parse line items
|
|
var itemElements = orderElement.Descendants("tetel");
|
|
foreach (var itemElement in itemElements)
|
|
{
|
|
order.Items.Add(new InnVoiceOrderLineItem
|
|
{
|
|
TableId = GetIntValue(itemElement, "TABLE_ID"),
|
|
ItemName = GetStringValue(itemElement, "TetelNev"),
|
|
ArticleNumber = GetStringValue(itemElement, "CikkSzam"),
|
|
VATText = GetStringValue(itemElement, "AfaSzoveg"),
|
|
VATRate = GetDecimalValue(itemElement, "AfaKulcs"),
|
|
IsGross = GetIntValue(itemElement, "Brutto") == 1,
|
|
UnitPrice = GetDecimalValue(itemElement, "EgysegAr"),
|
|
Quantity = GetDecimalValue(itemElement, "Mennyiseg"),
|
|
Unit = GetStringValue(itemElement, "MennyisegEgyseg")
|
|
});
|
|
}
|
|
|
|
orders.Add(order);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InnVoiceApiException($"Error parsing XML: {ex.Message}", ex);
|
|
}
|
|
|
|
return orders;
|
|
}
|
|
|
|
private string GetStringValue(XElement element, string name)
|
|
{
|
|
return element.Element(name)?.Value?.Trim() ?? string.Empty;
|
|
}
|
|
|
|
private int GetIntValue(XElement element, string name)
|
|
{
|
|
var value = GetStringValue(element, name);
|
|
return int.TryParse(value, out var result) ? result : 0;
|
|
}
|
|
|
|
private decimal GetDecimalValue(XElement element, string name)
|
|
{
|
|
var value = GetStringValue(element, name);
|
|
return decimal.TryParse(value, out var result) ? result : 0m;
|
|
}
|
|
}
|
|
|
|
// Order Models
|
|
public class OrderCreateRequest
|
|
{
|
|
public string VevoNev { get; set; }
|
|
public string VevoIrsz { get; set; }
|
|
public string VevoTelep { get; set; }
|
|
public string VevoUtcaHsz { get; set; }
|
|
public string VevoOrszag { get; set; }
|
|
public string VevoAdoszam { get; set; }
|
|
public string SzallNev { get; set; }
|
|
public string SzallIrsz { get; set; }
|
|
public string SzallTelep { get; set; }
|
|
public string SzallUtcaHsz { get; set; }
|
|
public string SzallOrszag { get; set; }
|
|
public int MegrendelestombID { get; set; }
|
|
public DateTime MegrendelesKelte { get; set; }
|
|
public DateTime Hatarido { get; set; }
|
|
public string Devizanem { get; set; }
|
|
public string FizetesiMod { get; set; }
|
|
public string Megjegyzes { get; set; }
|
|
public string Email { get; set; }
|
|
public string Telefon { get; set; }
|
|
public string MegrendelesSzamStr { get; set; }
|
|
|
|
public List<InnVoiceOrderItem> Items { get; set; } = new List<InnVoiceOrderItem>();
|
|
|
|
public void AddItem(InnVoiceOrderItem item)
|
|
{
|
|
Items.Add(item);
|
|
}
|
|
}
|
|
|
|
public class InnVoiceOrderItem
|
|
{
|
|
public string TetelNev { get; set; }
|
|
public string AfaSzoveg { get; set; }
|
|
public bool Brutto { get; set; }
|
|
public decimal EgysegAr { get; set; }
|
|
public decimal Mennyiseg { get; set; }
|
|
public string MennyisegEgyseg { get; set; }
|
|
public string CikkSzam { get; set; }
|
|
}
|
|
|
|
public class OrderCreateResponse
|
|
{
|
|
public string ErrorCode { get; set; }
|
|
public string Message { get; set; }
|
|
public int? TableId { get; set; }
|
|
public string TechId { get; set; }
|
|
public string PrintUrl { get; set; }
|
|
|
|
public bool IsSuccess => ErrorCode == "200";
|
|
}
|
|
|
|
public class InnVoiceApiException : Exception
|
|
{
|
|
public InnVoiceApiException(string message) : base(message) { }
|
|
public InnVoiceApiException(string message, Exception innerException) : base(message, innerException) { }
|
|
}
|
|
|
|
// Order GET response models
|
|
public class InnVoiceOrder
|
|
{
|
|
public int TableId { get; set; }
|
|
public int VevoID { get; set; }
|
|
public string CustomerName { get; set; }
|
|
public string CustomerZipCode { get; set; }
|
|
public string CustomerCity { get; set; }
|
|
public string CustomerAddress { get; set; }
|
|
public string CustomerCountry { get; set; }
|
|
public string CustomerTaxNumber { get; set; }
|
|
public string ShippingName { get; set; }
|
|
public string ShippingZipCode { get; set; }
|
|
public string ShippingCity { get; set; }
|
|
public string ShippingAddress { get; set; }
|
|
public string ShippingCountry { get; set; }
|
|
public int OrderBookId { get; set; }
|
|
public string OrderDate { get; set; }
|
|
public string DueDate { get; set; }
|
|
public string Currency { get; set; }
|
|
public string PaymentMethod { get; set; }
|
|
public string Notes { get; set; }
|
|
public string Email { get; set; }
|
|
public string Phone { get; set; }
|
|
public string ExternalOrderNumber { get; set; }
|
|
public decimal TotalNet { get; set; }
|
|
public decimal TotalVAT { get; set; }
|
|
public decimal TotalGross { get; set; }
|
|
public string TechId { get; set; }
|
|
public string PrintUrl { get; set; }
|
|
public string UpdateTime { get; set; }
|
|
public string QueryTime { get; set; }
|
|
|
|
public List<InnVoiceOrderLineItem> Items { get; set; } = new List<InnVoiceOrderLineItem>();
|
|
}
|
|
|
|
public class InnVoiceOrderLineItem
|
|
{
|
|
public int TableId { get; set; }
|
|
public string ItemName { get; set; }
|
|
public string ArticleNumber { get; set; }
|
|
public string VATText { get; set; }
|
|
public decimal VATRate { get; set; }
|
|
public bool IsGross { get; set; }
|
|
public decimal UnitPrice { get; set; }
|
|
public decimal Quantity { get; set; }
|
|
public string Unit { get; set; }
|
|
}
|
|
} |