using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using StampSOAP;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
namespace MisIngredientesVue.Core.Models
{
public class EInvoicing
{
public static string ObtenerNombreFormaPago(string id)
{
switch (id)
{
case "01": return "Efectivo";
case "02": return "Cheque";
case "03": return "Transferencia electrónica";
case "04": return "Tarjeta de crédito";
case "05": return "Monedero electrónico";
case "06": return "Dinero electrónico";
case "07": return "Tarjeta digital";
case "08": return "Vales de despensa";
case "09": return "Bienes";
case "10": return "Servicio";
case "11": return "Por cuenta de tercero";
case "12": return "Dación en pago";
case "13": return "Pago por subrogación";
case "14": return "Pago por consignación";
case "15": return "Condonación";
case "16": return "Cancelación";
case "17": return "Compensación";
case "28": return "Tarjeta de débito";
case "29": return "Tarjeta de servicios";
case "99": return "Por definir";
}
return id;
}
public static string ObtenerNombreUsoCFDI(string id)
{
switch (id)
{
case "G01": return "Adquisición de mercancías";
case "G02": return "Devoluciones, descuentos o bonificaciones";
case "G03": return "Gastos en general";
case "I01": return "Construcciones";
case "I02": return "Mobilario y equipo de oficina por inversiones";
case "I03": return "Equipo de transporte";
case "I04": return "Equipo de computo y accesorios";
case "I05": return "Dados, troqueles, moldes, matrices y herramental";
case "I06": return "Comunicaciones telefónicas";
case "I07": return "Comunicaciones satelitales";
case "I08": return "Otra maquinaria y equipo";
case "D01": return "Honorarios médicos, dentales y gastos hospitalarios";
case "D02": return "Gastos médicos por incapacidad o discapacidad";
case "D03": return "Gastos funerales";
case "D04": return "Donativos";
case "D05": return "Intereses reales efectivamente pagados por créditos hipotecarios (casa habitación).";
case "D06": return "Aportaciones voluntarias al SAR.";
case "D07": return "Primas por seguros de gastos médicos.";
case "D08": return "Gastos de transportación escolar obligatoria.";
case "D09": return "Depósitos en cuentas para el ahorro, primas que tengan como base planes de pensiones.";
case "D10": return "Pagos por servicios educativos(colegiaturas)";
case "P01": return "Por definir";
}
return id;
}
public static string ObtenerNombreMetodoPago(string id)
{
switch (id)
{
//case "01": return "Efectivo";
//case "02": return "Cheque";
//case "03": return "Transferencia electrónica";
//case "04": return "Tarjeta de crédito";
//case "05": return "Monedero electrónico";
//case "06": return "Dinero electrónico";
//case "07": return "Tarjeta digital";
//case "08": return "Vales de despensa";
//case "09": return "Bienes";
//case "10": return "Servicio";
//case "11": return "Por cuenta de tercero";
//case "12": return "Dación en pago";
//case "13": return "Pago por subrogación";
//case "14": return "Pago por consignación";
//case "15": return "Condonación";
//case "16": return "Cancelación";
//case "17": return "Compensación";
//case "28": return "Tarjeta de débito";
//case "29": return "Tarjeta de servicio";
//case "98": return "No aplica";
//case "99": return "Otros";
case "PUE": return "Pago en una sola exhibición";
case "PIP": return "Pago inicial y parcialidades";
case "PPD": return "Pago en parcialidades o diferido";
}
return id;
}
public static string ObtenerNombreClaveUnidad(string claveUnidad)
{
switch (claveUnidad)
{
case "H87": return "PIEZA";
case "X3H": return "BIDON";
case "KGM": return "KILOGRAMO";
case "ACT": return "ACTIVIDAD";
case "XBH": return "MANOJO";
case "X4H": return "DOMO (CAJA PLASTICO)";
case "XCX": return "LATA CILINDRICA ";
case "E54": return "VIAJE";
case "DPC": return "DOCENA";
case "LTR": return "LITRO";
case "E48": return "UNIDAD DE SERVICIO";
case "XDP": return "GARRAFA";
};
return claveUnidad;
}
//public static string ObtenerClaveUnidad(Unit unit)
//{
// switch (unit)
// {
// case Unit.KG: return "KGM";
// case Unit.L: return "LTR";
// case Unit.M: return "MTR";
// case Unit.Service: return "E48";
// case Unit.Units: return "XUN";
// }
// return "H87";
//}
public static string ObtenerNombreTipoComprobante(string id)
{
switch (id)
{
case "I": return "Ingreso";
case "E": return "Egreso";
case "T": return "Traslado";
case "N": return "Nómina";
case "P": return "Pago";
}
return id;
}
public static string ObtenerNombreImpuesto(string id)
{
switch (id)
{
case "001": return "ISR";
case "002": return "IVA";
case "003": return "IEPS";
}
return id;
}
public static string ObtenerNombreRegimen(string id)
{
switch (id)
{
case "601": return "General de Ley Personas Morales";
case "603": return "Personas Morales con Fines no Lucrativos";
case "605": return "Sueldos y Salarios e Ingresos Asimilados a Salarios";
case "606": return "Arrendamiento";
case "608": return "Demás ingresos";
case "609": return "Consolidación";
case "610": return "Residentes en el Extranjero sin Establecimiento Permanente en México";
case "611": return "Ingresos por Dividendos(socios y accionistas)";
case "612": return "Personas Físicas con Actividades Empresariales y Profesionales";
case "614": return "Ingresos por intereses";
case "616": return "Sin obligaciones fiscales";
case "620": return "Sociedades Cooperativas de Producción que optan por diferir sus ingresos";
case "621": return "Incorporación Fiscal";
case "622": return "Actividades Agrícolas, Ganaderas, Silvícolas y Pesqueras";
case "623": return "Opcional para Grupos de Sociedades";
case "624": return "Coordinados";
case "628": return "Hidrocarburos";
case "607": return "Régimen de Enajenación o Adquisición de Bienes";
case "629": return "De los Regímenes Fiscales Preferentes y de las Empresas Multinacionales";
case "630": return "Enajenación de acciones en bolsa de valores";
case "615": return "Régimen de los ingresos por obtención de premios";
}
return id;
}
}
public class FinkokService
{
/*Documentación: https://wiki.finkok.com/doku.php
usuario: integracion
contraseña. 1nT36R4c!0N
Portal: https://facturacion.finkok.com/ https://demo-facturacion.finkok.com/
*/
private static readonly string DEMO_USERNAME = "raulbojalil@gmail.com";
private static readonly string DEMO_PASSWORD = "mvpNUXmQfK8=";
private static readonly string USERNAME = "javo@huerto.com.mx";
private static readonly string PASSWORD = "Misingredientes_13";
private static readonly string SERVICE_URL = "https://facturacion.finkok.com/servicios";
private static readonly string DEMO_SERVICE_URL = "https://demo-facturacion.finkok.com/servicios";
//private static readonly string DEMO_RFC_EMISOR = "LAN7008173R5"; //LAN7008173R7
//private static readonly string DEMO_RFC_RECEPTOR = "LAN7008173R5"; //LAN7008173R7
//(Tipo de usuario O = OnDemand , P = Prepago)
public static void registration_add(string rfc, string cer, string key, string passphrase, string userType = "O", bool isDemo = false)
{
//if (isDemo) rfc = DEMO_RFC_EMISOR;
var soapRequest = $@"
{(isDemo ? DEMO_USERNAME : USERNAME)}
{(isDemo ? DEMO_PASSWORD : PASSWORD)}
{rfc}
{userType}
{cer}
{key}
{passphrase}
";
var response = CallSoapAction("/soap/registration", "\"add\"", soapRequest, isDemo);
if (response.Contains("false"))
{
var status = GetTextInTag(response, "s0:message");
if (string.IsNullOrEmpty(status))
status = response;
throw new EInvoicingException(status);
}
}
public static void registration_edit(string rfc, string cer, string key, string passphrase, bool isDemo = false)
{
//if (isDemo) rfc = DEMO_RFC_EMISOR;
var soapRequest = $@"
{(isDemo ? DEMO_USERNAME : USERNAME)}
{(isDemo ? DEMO_PASSWORD : PASSWORD)}
{rfc}
{cer}
{key}
{passphrase}
";
var response = CallSoapAction("/soap/registration", "\"edit\"", soapRequest, isDemo);
if (response.Contains("false"))
{
var status = GetTextInTag(response, "s0:message");
if (string.IsNullOrEmpty(status))
status = response;
throw new EInvoicingException(status);
}
}
public static int report_total(string rfc, DateTime dateFrom, DateTime dateTo, bool isDemo = false)
{
//if (isDemo) rfc = DEMO_RFC_EMISOR;
var soapRequest = $@"
{(isDemo ? DEMO_USERNAME : USERNAME)}
{(isDemo ? DEMO_PASSWORD : PASSWORD)}
{rfc}
{dateFrom.ToString("yyyy-MM-dd")}T00:00:00
{dateTo.ToString("yyyy-MM-dd")}T00:00:01
'I'
";
var response = CallSoapAction("/soap/utilities", "\"report_total\"", soapRequest, isDemo);
if (response.Contains("Error") || response.Contains("Invalid"))
{
var status = GetTextInTag(response, "s0:CodEstatus");
if (string.IsNullOrEmpty(status))
status = response;
throw new EInvoicingException(status);
}
return Convert.ToInt32(GetTextInTag(response, "s0:total"));
}
public static sign_stampResponse sign_stamp(string xml, bool isDemo = false)
{
//if (isDemo)
//{
// xml = xml.Replace("Rfc=\"LUDJ870913F34\"", "Rfc=\"" + DEMO_RFC_EMISOR + "\"");
// xml = xml.Replace("RegimenFiscal=\"612\"", "RegimenFiscal=\"601\"");
// xml = xml.Replace("Rfc=\"RFC01\"", "Rfc=\"AAA010101AAA\"");
//}
xml = FixNamespaces(xml);
//Console.WriteLine("----------------\r\n\r\n" + xml);
byte[] bytes = Encoding.UTF8.GetBytes(xml);
var comprobanteXmlBase64 = Convert.ToBase64String(bytes);
var soapRequest = $@"
{comprobanteXmlBase64}
{(isDemo ? DEMO_USERNAME : USERNAME)}
{(isDemo ? DEMO_PASSWORD : PASSWORD)}
";
//var soapRequest = $@"
// {comprobanteXmlBase64}
// raulbojalil@gmail.com
// mvpNUXmQfK8=
//";
var response = CallSoapAction("/soap/stamp", "\"sign_stamp\"", soapRequest, isDemo);
//var xmlDocument = new XmlDocument();
//xmlDocument.LoadXml(response);
//var mgr = new XmlNamespaceManager(xmlDocument.NameTable);
//mgr.AddNamespace("s0", "apps.services.soap.core.views");
//mgr.AddNamespace("tns", "http://facturacion.finkok.com/stamp");
var sresponse = new sign_stampResponse();
sresponse.sign_stampResult = new AcuseRecepcionCFDI()
{
xml = HttpUtility.HtmlDecode(GetTextInTag(response, "s0:xml")),
Incidencias = new Incidencia[1] { new Incidencia() { CodigoError = GetTextInTag(response, "s0:CodigoError"), MensajeIncidencia = GetTextInTag(response, "s0:MensajeIncidencia") } },
CodEstatus = GetTextInTag(response, "s0:CodEstatus"),
UUID = GetTextInTag(response, "s0:UUID"),
SatSeal = GetTextInTag(response, "s0:SatSeal"),
NoCertificadoSAT = GetTextInTag(response, "s0:NoCertificadoSAT"),
};
if (!string.IsNullOrEmpty(sresponse.sign_stampResult.xml))
sresponse.sign_stampResult.Incidencias = new Incidencia[0] { };
return sresponse;
//response = xmlDocument.LastChild.FirstChild.InnerXml;
//var serializer = new XmlSerializer(typeof(AcuseRecepcionCFDI));
//using (var strReader = new StringReader(response))
//{
// using (var reader = new NamespaceIgnorantXmlTextReader(strReader))
// {
// return new sign_stampResponse { sign_stampResult = (AcuseRecepcionCFDI)serializer.Deserialize(reader) };
// }
//}
}
private static string FixNamespaces(string xml)
{
xml = xml.Replace("",
"");
xml = xml.Replace("", "")
.Replace("", "");
if (!xml.Contains("http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd"))
xml = xml.Replace("xmlns:cfdi=\"http://www.sat.gob.mx/cfd/3\"",
"xmlns:cfdi=\"http://www.sat.gob.mx/cfd/3\" xmlns:pago10=\"http://www.sat.gob.mx/Pagos\" xsi:schemaLocation=\"http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd http://www.sat.gob.mx/Pagos http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos10.xsd\"");
return xml;
}
public static string sign_cancel(string folioUUID, string rfc, string noCertificado, string motivo, bool isDemo = false)
{
//if (isDemo) rfc = DEMO_RFC_EMISOR;
//TODO: hacer esto
string folioSustitucion = "";
var soapRequest = $@"
{(isDemo ? DEMO_USERNAME : USERNAME)}
{(isDemo ? DEMO_PASSWORD : PASSWORD)}
{rfc}
{noCertificado}
";
Console.WriteLine(soapRequest);
var response = CallSoapAction("/soap/cancel", "\"sign_cancel\"", soapRequest, isDemo);
Console.WriteLine(response);
if (response.Contains("Error") || response.Contains("Invalid"))
{
var status = GetTextInTag(response, "s0:CodEstatus");
if (string.IsNullOrEmpty(status))
status = response;
throw new EInvoicingException(status);
}
var acuse = GetTextInTag(response, "s0:Acuse");
if (string.IsNullOrEmpty(acuse))
{
Console.WriteLine("Sin acuse " + response);
throw new EInvoicingException("Sin acuse");
}
acuse = WebUtility.HtmlDecode(acuse);
return acuse.Contains("" + acuse);
}
private static string GetTextInTag(string xml, string tag)
{
try
{
if (xml.Contains($"<{tag}/>")) return string.Empty;
var openingTag = "<" + tag + ">";
var closingTag = "" + tag + ">";
var temp = xml.Substring(xml.IndexOf(openingTag) + openingTag.Length);
return temp.Substring(0, temp.IndexOf(closingTag));
}
catch
{
return string.Empty;
}
}
private static string CallSoapAction(string url, string soapAction, string xmlRequest, bool isDemo, bool rethrowException = true)
{
url = (isDemo ? DEMO_SERVICE_URL : SERVICE_URL) + url;
if (string.IsNullOrEmpty(xmlRequest.Trim()))
return "Empty request body";
var request = (HttpWebRequest)WebRequest.Create(url);
var xml = xmlRequest;
if (!xmlRequest.Contains(":Envelope>") && !xmlRequest.Contains(":Body>"))
{
var soapRequest = "{0}";
xml = string.Format(soapRequest, xmlRequest.Replace("\n", "").Replace("\r", ""));
}
try
{
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
}
catch (Exception ex)
{
throw new Exception("XML Parsing error: " + ex.Message);
}
var data = Encoding.ASCII.GetBytes(xml);
request.Headers.Add("SOAPAction", soapAction);
request.Method = "POST";
request.ContentType = "text/xml;charset=UTF-8";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var res = string.Empty;
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var streamReader = new StreamReader(responseStream))
{
res = streamReader.ReadToEnd();
}
}
}
}
catch (WebException ex)
{
using (var responseStream = ex.Response.GetResponseStream())
{
res = new StreamReader(responseStream).ReadToEnd();
}
throw ex;
}
return res;
}
}
public class EInvoicingException : Exception
{
public bool RanOutOfFolios { get; private set; }
public EInvoicingException(string message, bool ranOutOfFolios = false)
: base(message)
{
RanOutOfFolios = ranOutOfFolios;
}
}
}