Example #1
0
        /**
         * Llenado del modelo de CFDI, de una forma general
         * - Se especifica: la moneda, método de pago, forma de pago, cliente, y lugar de expedición
         */
        private static Facturama.Models.Request.Cfdi CreateModelCfdiGeneral(FacturamaApi facturama)
        {
            var products = facturama.Products.List().Where(p => p.Taxes.Any()).ToList();

            var nameId        = facturama.Catalogs.NameIds.First(); //Nombre en el pdf: "Factura"
            var currency      = facturama.Catalogs.Currencies.First(m => m.Value == "MXN");
            var paymentMethod = facturama.Catalogs.PaymentMethods.First(p => p.Value == "PUE");
            var paymentForm   = facturama.Catalogs.PaymentForms.First(p => p.Name == "Efectivo");
            var cliente       = facturama.Clients.List().First();

            var branchOffice = facturama.BranchOffices.List().First();

            var cfdi = new Cfdi
            {
                NameId          = nameId.Value,
                CfdiType        = CfdiType.Ingreso,
                PaymentForm     = paymentForm.Value,
                PaymentMethod   = paymentMethod.Value,
                Currency        = currency.Value,
                Date            = null,
                ExpeditionPlace = "83170",
                //Items = new List<Item>(),
                Receiver = new Receiver
                {
                    CfdiUse = "P01",
                    Name    = "Público en general",
                    Rfc     = "XAXX010101000"
                },
            };

            return(cfdi);
        }
        /// <summary>
        /// Termina de llenar los campos faltantes de un modelo Cfdi como cadena original complemento, etc
        /// </summary>
        /// <param name="cfdi"></param>
        /// <returns>Cfdi</returns>
        public static Cfdi complementarCfdiTimbrado(Cfdi cfdi)
        {
            string rutaTemporalXmlSinSello   = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiSinSello);
            string rutaTemporalXmlSinTimbrar = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiSinTimbrar);
            string rutaTemporalXmlTimbrado   = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiTimbrado);

            if (File.Exists(rutaTemporalXmlTimbrado))
            {
                File.Delete(rutaTemporalXmlTimbrado);
            }

            XDocument xDoc = cfdi.xmlCfdiTimbrado.toXDocument();

            xDoc.Save(rutaTemporalXmlTimbrado);
            cfdi.bytesCfdiTimbrado = File.ReadAllBytes(rutaTemporalXmlTimbrado);

            cfdi.comprobanteTimbrado       = castXmlToCfdi <Comprobante>(cfdi.xmlCfdiTimbrado.InnerXml, typeof(Comprobante));
            cfdi.cadenaOriginalComplemento = obtenerCadenaOriginalComplemento(cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.version, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.uuid, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.fechaTimbrado, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.rfcProvCertif, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.selloCfd, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.noCertificadoSat);
            cfdi.cadenaCodigoQr            = obtenerCadenaCodigoQr(decimal.Parse(cfdi.comprobante.total), cfdi.comprobante.emisor.rfc, cfdi.comprobante.receptor.rfc, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.uuid, cfdi.comprobanteTimbrado.complemento.timbreFiscalDigital.selloCfd);
            cfdi.bytesCodigoQr             = generarImagenQr(cfdi.cadenaCodigoQr);

            File.Delete(rutaTemporalXmlSinSello);
            File.Delete(rutaTemporalXmlSinTimbrar);

            return(cfdi);
        }
Example #3
0
        /**
         * Llenado del modelo de CFDI, de una forma general
         * - Se especifica: la moneda, método de pago, forma de pago, cliente, y lugar de expedición
         */
        private static Facturama.Models.Request.Cfdi CreateModelCfdiGeneral(FacturamaApi facturama)
        {
            var products = facturama.Products.List().Where(p => p.Taxes.Any()).ToList();

            var nameId        = facturama.Catalogs.NameIds.First(); //Nombre en el pdf: "Factura"
            var currency      = facturama.Catalogs.Currencies.First(m => m.Value == "MXN");
            var paymentMethod = facturama.Catalogs.PaymentMethods.First(p => p.Value == "PUE");
            var paymentForm   = facturama.Catalogs.PaymentForms.First(p => p.Name == "Efectivo");
            var cliente       = facturama.Clients.List().First(c => c.Rfc == "ESO1202108R2");

            var branchOffice = facturama.BranchOffices.List().First();

            var cfdi = new Cfdi
            {
                NameId          = nameId.Value,
                CfdiType        = CfdiType.Ingreso,
                PaymentForm     = paymentForm.Value,
                PaymentMethod   = paymentMethod.Value,
                Currency        = currency.Value,
                Date            = DateTime.Now,
                ExpeditionPlace = branchOffice.Address.ZipCode,
                //Items = new List<Item>(),
                Receiver = new Receiver
                {
                    CfdiUse = cliente.CfdiUse,
                    Name    = cliente.Name,
                    Rfc     = cliente.Rfc
                },
            };

            return(cfdi);
        }
Example #4
0
        static void Main(string[] args)
        {
            Cfdi cfdi = new Cfdi();

            cfdi.Moneda            = "MXN";
            cfdi.FormaPago         = "03";
            cfdi.TipoDeComprobante = "I";
            cfdi.MetodoPago        = "PUE";
            cfdi.LugarExpedicion   = "72000";
            cfdi.Fecha             = DateTime.Now;


            cfdi.Emisor = new Emisor();
            cfdi.Emisor.RegimenFiscal = "601";

            cfdi.Receptor         = new Receptor();
            cfdi.Receptor.Rfc     = "XAXX010101000";
            cfdi.Receptor.Nombre  = "Publico en general";
            cfdi.Receptor.UsoCFDI = "G03";

            cfdi.Conceptos = new Conceptos();
            Concepto c = new Concepto();

            cfdi.Conceptos.Concepto = new List <Concepto>();
            cfdi.Conceptos.Concepto.Add(c);
            c.Cantidad      = 1;
            c.ClaveProdServ = "01010101";
            c.ClaveUnidad   = "H87";
            c.Descripcion   = "Producto XYZ";
            c.ValorUnitario = "10.000000";

            c.Impuestos           = new Impuestos();
            c.Impuestos.Traslados = new Traslados();
            Traslado t = new Traslado();

            c.Impuestos.Traslados.Traslado = new List <Traslado>();
            c.Impuestos.Traslados.Traslado.Add(t);

            t.Impuesto   = "002";//IVA=002
            t.TasaOCuota = "0.160000";
            t.TipoFactor = "Tasa";
            t.Base       = "10.000";//Lo más común es que se ponga el producto de c.ValorUnitario*c.Cantidad


            Cfdi33Client cliente = new Cfdi33Client("uq4ZWSWme1m6LwoDO3KuCXkM0tlNCuoW", "crkQ0FZTkAtqcy4zqRrWlIpMv2nbuJRz");

            try
            {
                ApiResult result = cliente.timbrar(cfdi);

                Console.WriteLine("Cfdi generado exitosamente con id " + result.cfdiId
                                  + " Descarga el pdf desde " + result.pdfUrl);
                //result.xml
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        /// <summary>
        /// Genera el archivo Xml del cfdi, incluyendo la lista de namespaces que utilizara
        /// </summary>
        /// <param name="cfdi"></param>
        /// <param name="namespaces"></param>
        /// <returns>Cfdi</returns>
        public static Cfdi generarCfdi33(Cfdi cfdi, List <XmlNamespace> namespaces)
        {
            try
            {
                string rutaTemporalXmlSinSello   = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiSinSello);
                string rutaTemporalXmlSinTimbrar = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiSinTimbrar);

                if (!Directory.Exists(cfdi.rutaCfdi))
                {
                    Directory.CreateDirectory(cfdi.rutaCfdi);
                }

                if (File.Exists(rutaTemporalXmlSinSello))
                {
                    File.Delete(rutaTemporalXmlSinSello);
                }

                if (File.Exists(rutaTemporalXmlSinTimbrar))
                {
                    File.Delete(rutaTemporalXmlSinTimbrar);
                }

                XmlTextWriter xmlTextW = new XmlTextWriter(rutaTemporalXmlSinSello, Encoding.UTF8);

                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

                if (namespaces == null || !namespaces.Any())
                {
                    ns.Add("cfdi", Constantes.CFDI_NAMESPACE);
                    ns.Add("xsi", Constantes.XML_NAMESPACE);
                }
                else
                {
                    namespaces.ForEach(n =>
                    {
                        ns.Add(n.nombre, n.url);
                    });
                }

                XmlSerializer serialize = new XmlSerializer(typeof(Comprobante));
                serialize.Serialize(xmlTextW, cfdi.comprobante, ns);

                xmlTextW.Close();
                XDocument xDoc = XDocument.Load(rutaTemporalXmlSinSello);
                cfdi.xmlCfdiSinSello = xDoc.toXmlDocument();
                firmarXml(cfdi, ref xDoc);
                xDoc.Save(rutaTemporalXmlSinTimbrar);
                cfdi.xmlCfdiSinTimbrar   = xDoc.toXmlDocument();
                cfdi.bytesCfdiSinTimbrar = File.ReadAllBytes(rutaTemporalXmlSinTimbrar);

                return(cfdi);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// Obtiene el xml timbrado desde un archivo zip
        /// </summary>
        /// <param name="cfdi"></param>
        /// <returns>Boolean</returns>
        public static Boolean obtenerDatosDesdeZip(Cfdi cfdi)
        {
            try
            {
                string rutaZip          = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiZip);
                string rutaCfdiTimbrado = Path.Combine(cfdi.rutaCfdi, cfdi.nombreCfdiTimbrado);
                using (ZipInputStream sz = new ZipInputStream(File.OpenRead(rutaZip)))
                {
                    ICSharpCode.SharpZipLib.Zip.ZipEntry theEntry;
                    while ((theEntry = sz.GetNextEntry()) != null)
                    {
                        string fileName = Path.GetFileName(theEntry.Name);

                        if (fileName != string.Empty)
                        {
                            using (FileStream streamWriter = File.Create(rutaCfdiTimbrado))
                            {
                                int    size = 2048;
                                byte[] data = new byte[2048];

                                while (true)
                                {
                                    size = sz.Read(data, 0, data.Length);
                                    if (size > 0)
                                    {
                                        streamWriter.Write(data, 0, size);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                streamWriter.Close();
                            }
                        }
                    }
                }

                XmlReader reader = XmlReader.Create(rutaCfdiTimbrado);
                XDocument xDoc   = XDocument.Load(rutaCfdiTimbrado);
                cfdi.xmlCfdiTimbrado     = xDoc.toXmlDocument();
                cfdi.comprobanteTimbrado = castXmlToCfdi <Comprobante>(cfdi.xmlCfdiTimbrado.InnerXml, typeof(Comprobante));
                cfdi.bytesCfdiTimbrado   = File.ReadAllBytes(rutaCfdiTimbrado);

                return(true);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private static Cfdi AddItemsToCfdi(FacturamaApi facturama, Cfdi cfdi)
        {
            // Lista de todos los productos
            List <Product> lstProducts = facturama.Products.List();
            Random         random      = new Random();
            var            currency    = facturama.Catalogs.Currencies.First(m => m.Value == "MXN");

            int nItems   = random.Next(lstProducts.Count) % 10 + 1;
            int decimals = (int)currency.Decimals;


            // Lista de Items en el cfdi (los articulos a facturar)
            List <Item> lstItems = new List <Item>();

            // Creacion del CFDI
            for (int i = lstProducts.Count - nItems; i < lstProducts.Count && i > 0; i++)
            {
                Product product  = lstProducts.ElementAt(i); // Un producto cualquiera
                int     quantity = random.Next(1, 5) + 1;    // una cantidad aleatoria de elementos de este producto
                Double  discount = Decimal.ToDouble(product.Price % (product.Price == 0 ? 1 : random.Next(1, Decimal.ToInt32(product.Price))));

                // Redondeo del precio del producto, de acuerdo a la moneda
                Double numberOfDecimals = Math.Pow(10, decimals);
                Double subTotal         = Math.Round((Decimal.ToDouble(product.Price) * quantity) * numberOfDecimals) / numberOfDecimals;


                // Llenado del item (que va en el cfdi)
                Item item = new Item
                {
                    ProductCode          = product.CodeProdServ,
                    UnitCode             = product.UnitCode,
                    Unit                 = product.Unit,
                    Description          = product.Description,
                    IdentificationNumber = product.IdentificationNumber,
                    Quantity             = quantity,
                    Discount             = Convert.ToDecimal(Math.Round(discount * numberOfDecimals) / numberOfDecimals),
                    UnitPrice            = Convert.ToDecimal(Math.Round(Decimal.ToDouble(product.Price) * numberOfDecimals) / numberOfDecimals),
                    Subtotal             = Convert.ToDecimal(subTotal)
                };

                // ---- Llenado de los impuestos del item ----
                item = AddTaxesToItem(item, product, numberOfDecimals);
                if (item.UnitPrice > 0m)
                {
                    lstItems.Add(item);
                }
            }
            cfdi.Items = lstItems;

            return(cfdi);
        }
Example #8
0
        public ApiResult timbrar(Cfdi cfdi)
        {
            string json = JsonConvert.SerializeObject(cfdi, Newtonsoft.Json.Formatting.None,
                                                      new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore
            });

            var httpWebRequest = (HttpWebRequest)WebRequest.Create(endpoint + "/Cfdi33/timbrar");

            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Method      = "POST";

            String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(apiId + ":" + apiSecret));

            httpWebRequest.Headers.Add("Authorization", "Basic " + encoded);

            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                streamWriter.Write(json);
            }
            try
            {
                var    httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                string result;
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    result = streamReader.ReadToEnd();
                    streamReader.Close();
                    return(new ApiResult(result));
                }
            }
            catch (WebException e)
            {
                var response = ((HttpWebResponse)e.Response);
                var content  = response.GetResponseStream();
                using (var streamReader = new StreamReader(content))
                {
                    string result = streamReader.ReadToEnd();
                    streamReader.Close();
                    throw new Exception(result);
                }
            }
        }
Example #9
0
        static void Main(string[] args)
        {
            var sourceQueue = QueueClient.CreateFromConnectionString(InternalConfiguration.QueueConnectionString, "04ToCosmosDb");

            DocumentDBRepository <Cfdi> .Initialize();

            var count = 0;

            do
            {
                try
                {
                    var files = sourceQueue.ReceiveBatch(1000);
                    count = files.Count();
                    Console.WriteLine(count);
                    if (count > 0)
                    {
                        Parallel.ForEach(files, (currentFile) =>
                        {
                            try
                            {
                                Cfdi cfdi = currentFile.GetBody <Cfdi>();

                                DocumentDBRepository <Cfdi> .CreateItemAsync(cfdi).GetAwaiter().GetResult();
                                currentFile.Complete();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                                currentFile.Abandon();
                            }
                        });
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                if (count == 0)
                {
                    Thread.Sleep(1000);
                }
            } while (true);
        }
Example #10
0
        public UnitTestTimbrado()
        {
            cliente = new Cfdi33Client("uq4ZWSWme1m6LwoDO3KuCXkM0tlNCuoW", "crkQ0FZTkAtqcy4zqRrWlIpMv2nbuJRz");
            //cliente = new Cfdi33Client("StWJNHkw8JrPTPJ2aBfV2DeOtoE0KR4x", "7CU/1sZhUkosm39pF+2Qs3mPrVH9l04i");
            cfdi                   = new Cfdi();
            cfdi.Moneda            = "MXN";
            cfdi.FormaPago         = "03";
            cfdi.TipoDeComprobante = "I";
            cfdi.MetodoPago        = "PUE";
            cfdi.LugarExpedicion   = "72000";


            cfdi.Emisor = new Emisor();
            cfdi.Emisor.RegimenFiscal = "601";

            cfdi.Receptor         = new Receptor();
            cfdi.Receptor.Rfc     = "XAXX010101000";
            cfdi.Receptor.Nombre  = "Publico en general";
            cfdi.Receptor.UsoCFDI = "G03";

            cfdi.Conceptos = new Conceptos();
            Concepto c = new Concepto();

            cfdi.Conceptos.Concepto = new List <Concepto>();
            cfdi.Conceptos.Concepto.Add(c);
            c.Cantidad      = 1;
            c.ClaveProdServ = "01010101";
            c.ClaveUnidad   = "H87";
            c.Descripcion   = "Producto XYZ";
            c.ValorUnitario = "10.000000";

            c.Impuestos           = new Impuestos();
            c.Impuestos.Traslados = new Traslados();
            Traslado t = new Traslado();

            c.Impuestos.Traslados.Traslado = new List <Traslado>();
            c.Impuestos.Traslados.Traslado.Add(t);

            t.Impuesto   = "002";
            t.TasaOCuota = "0.160000";
            t.TipoFactor = "Tasa";
            t.Base       = "10.000";
        }
        public void Run()
        {
            try
            {
                Console.WriteLine("----- Inicio del ejemplo PayrollExample -----");


                // Cfdi Incial (debe ser "PPD")
                // -------- Creacion del cfdi en su forma general (sin items / productos) asociados --------
                Cfdi payroll = CreatePayrollModel(facturama);

                // Se manda timbrar mediante Facturama
                Facturama.Models.Response.Cfdi cfdiInicial = facturama.Cfdis.Create(payroll);

                Console.WriteLine("Se creó exitosamente el CFDI de Nómina con el folio fiscal: " + cfdiInicial.Complement.TaxStamp.Uuid);

                // Descarga de los archivos de la Nómina (en este caso se especifica que el tipo de comprobante es "Payroll")
                String filePath = "nomina" + cfdiInicial.Complement.TaxStamp.Uuid;
                facturama.Cfdis.SavePdf(filePath + ".pdf", cfdiInicial.Id, Facturama.Services.CfdiService.InvoiceType.Payroll);
                facturama.Cfdis.SaveXml(filePath + ".xml", cfdiInicial.Id, Facturama.Services.CfdiService.InvoiceType.Payroll);

                // Posibilidad de mandar las nóminas por correo
                Console.WriteLine(facturama.Cfdis.SendByMail(cfdiInicial.Id, "*****@*****.**", null, Facturama.Services.CfdiService.InvoiceType.Payroll));


                Console.WriteLine("----- Fin del ejemplo de PayrollExample -----");
            }
            catch (FacturamaException ex)
            {
                Console.WriteLine(ex.Message);
                foreach (var messageDetail in ex.Model.Details)
                {
                    Console.WriteLine($"{messageDetail.Key}: {string.Join(",", messageDetail.Value)}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error inesperado: ", ex.Message);
            }
        }
        /**
         * Llenado del modelo de CFDI para Nóminas
         */
        private static Cfdi CreatePayrollModel(FacturamaApi facturama)
        {
            var products = facturama.Products.List().Where(p => p.Taxes.Any()).ToList();

            var nameId        = "16"; // "Nomina" de acuerdo al catálogo de nombres https://apisandbox.facturama.mx/guias/catalogos/nombres-cfdi
            var currency      = facturama.Catalogs.Currencies.First(m => m.Value == "MXN");
            var paymentMethod = facturama.Catalogs.PaymentMethods.First(p => p.Value == "PUE");
            var paymentForm   = "99";                             // 99 = por definir
            var cliente       = facturama.Clients.List().First(); // Puedes seleccionar el cliente de tu catálogo de clientes

            var branchOffice = facturama.BranchOffices.List().First();


            var lstPerceptions = new List <PerceptionsDetail>();

            lstPerceptions.Add(new PerceptionsDetail
            {
                PerceptionType = "046",
                Code           = "046",
                Description    = "ASIMILIADOS A SALARIOS",
                TaxedAmount    = 3621.18m,
                ExemptAmount   = 0m
            });


            var lstDeductions = new List <DeductionsDetail>();

            lstDeductions.Add(new DeductionsDetail
            {
                DeduccionType = "002",
                Code          = "002",
                Description   = "ISR",
                Amount        = 172.60M
            });

            var lstOtherPayments = new List <OtherPayment>();

            lstOtherPayments.Add(new OtherPayment
            {
                EmploymentSubsidy = new EmploymentSubsidy
                {
                    Amount = 10
                },
                OtherPaymentType = "002",
                Code             = "000",
                Description      = "Subsidio",
                Amount           = 10
            });


            var payroll = new Cfdi
            {
                NameId          = nameId,
                CfdiType        = CfdiType.Nomina,
                PaymentForm     = paymentForm,
                PaymentMethod   = "PUE",         // Pago en una exhibicion
                Currency        = currency.Value,
                Date            = null,
                ExpeditionPlace = "78220",



                Receiver = new Receiver  // En este caso pudimos poner los datos de cliente tomado del catálogo, o colocar los datos de otra fuente
                {
                    CfdiUse = "P01",
                    Name    = "ADRIANA GARCIA MORALES",
                    Rfc     = "CACX7605101P8"
                },
                Complement = new Complement
                {
                    Payroll = new Payroll
                    {
                        Type               = "O",        // Tipo de nomina [O = ordinaria, E = exenta]
                        DailySalary        = 0m,
                        BaseSalary         = 0m,
                        PaymentDate        = Convert.ToDateTime("2020-10-06"),
                        InitialPaymentDate = Convert.ToDateTime("2020-10-06"),
                        FinalPaymentDate   = Convert.ToDateTime("2020-10-06"),
                        DaysPaid           = 15,
                        Issuer             = new PayrollIssuer
                        {
                            EmployerRegistration = "SampleRegistration"
                        },
                        Employee = new Employee
                        {
                            Curp = "GAMA800912MSPRRD05",
                            SocialSecurityNumber    = "92919084431",
                            PositionRisk            = "1",
                            ContractType            = "01",
                            RegimeType              = "02",
                            Unionized               = false,
                            TypeOfJourney           = "01",
                            EmployeeNumber          = "006",
                            Department              = null,
                            Position                = null,
                            FrequencyPayment        = "04",
                            FederalEntityKey        = "SLP",
                            DailySalary             = 50,
                            StartDateLaborRelations = Convert.ToDateTime("2019-10-06"),
                        },
                        Perceptions = new Perceptions
                        {
                            Details = lstPerceptions.ToArray()
                        },
                        Deductions = new Deductions
                        {
                            Details = lstDeductions.ToArray()
                        },
                        OtherPayments = lstOtherPayments.ToArray()
                    }
                }
            };

            return(payroll);
        }
Example #13
0
        static void Main(string[] args)
        {
            ServicePointManager.DefaultConnectionLimit = 50; //(Or More)
            ThreadPool.SetMinThreads(50, 50);
            var sourceQueue      = QueueClient.CreateFromConnectionString(InternalConfiguration.QueueConnectionString, "02ConsumerToValidaRFC");
            var destinationQueue = QueueClient.CreateFromConnectionString(InternalConfiguration.QueueConnectionString, "03ValidaRFCToSigner");

            //DocumentDBRepository<Cfdi>.Initialize();

            IDatabase cache = null;

            if (InternalConfiguration.EnableRedisCache)
            {
                Console.WriteLine("Redis Cache enabled");
                cache = Connection.GetDatabase();
            }

            var count = 0;

            do
            {
                try
                {
                    Stopwatch swProcess = Stopwatch.StartNew();

                    var files = sourceQueue.ReceiveBatch(1000);
                    count = files.Count();
                    Console.WriteLine(count);
                    if (count > 0)
                    {
                        Parallel.ForEach(files, (currentFile) =>
                        {
                            try
                            {
                                CfdiFile file = currentFile.GetBody <CfdiFile>();
                                var cfdi      = new Cfdi();
                                if (file.Storage == "inline")
                                {
                                    cfdi = new Cfdi(file.FileContent, file.Guid);
                                }
                                else
                                {
                                    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(file.Storage);
                                    CloudBlockBlob blob = new CloudBlockBlob(new Uri(file.FileContent), storageAccount.Credentials);

                                    var enableTableStorage = false;
                                    if (enableTableStorage)
                                    {
                                        CloudTableClient tableClient     = storageAccount.CreateCloudTableClient();
                                        CloudTable table                 = tableClient.GetTableReference("cfdi");
                                        TableOperation retrieveOperation = TableOperation.Retrieve <CfdiEntity>("none", file.Guid);
                                        TableResult retrievedResult      = table.Execute(retrieveOperation);

                                        if (retrievedResult.Result != null)
                                        {
                                            var xml = ((CfdiEntity)retrievedResult.Result).Xml;
                                            cfdi    = new Cfdi(xml, file.Guid);
                                        }
                                    }
                                    else
                                    {
                                        using (var stream = blob.OpenRead())
                                        {
                                            cfdi = new Cfdi(stream, file.Guid);
                                        }
                                    }
                                }
                                if (InternalConfiguration.EnableRedisCache)
                                {
                                    Stopwatch sw = Stopwatch.StartNew();
                                    cfdi.ValidaRfcEmision(cache.StringGet(cfdi.RfcEmisor));
                                    cfdi.ValidaRfcReceptor(cache.StringGet(cfdi.RfcReceptor));
                                    cfdi.ValidationTimeSpend = sw.ElapsedMilliseconds;
                                }
                                //Guarda en Cosmos DB
                                //DocumentDBRepository<Cfdi>.CreateItemAsync(cfdi).GetAwaiter().GetResult();
                                //Fin de guardado en cosmos
                                destinationQueue.Send(new BrokeredMessage(new Tuple <CfdiFile, Cfdi>(file, cfdi))
                                {
                                    SessionId = file.Guid
                                });

                                currentFile.Complete();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                                currentFile.Abandon();
                            }
                        }
                                         );
                    }
                    if (swProcess.ElapsedMilliseconds > 1000)
                    {
                        Console.WriteLine($"-> [{count} / {swProcess.ElapsedMilliseconds / 1000}] = {count / (swProcess.ElapsedMilliseconds / 1000)} x segundo");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                if (count == 0)
                {
                    Thread.Sleep(1000);
                }
            } while (true);
        }
Example #14
0
        public void Run()
        {
            Console.WriteLine("----- Inicio del ejemplo InvoiceExample -----");

            var products = facturama.Products.List().Where(p => p.Taxes.Any()).ToList();

            var nameId        = facturama.Catalogs.NameIds.ElementAt(0); //Nombre en el pdf: "Factura"
            var currency      = facturama.Catalogs.Currencies.First(m => m.Value == "MXN");
            var paymentMethod = facturama.Catalogs.PaymentMethods.First(p => p.Name == "Pago en una sola exhibición");
            var paymentForm   = facturama.Catalogs.PaymentForms.First(p => p.Name == "Efectivo");
            var cliente       = facturama.Clients.List().First(c => c.Rfc == "XAXX010101000");

            var branchOffice = facturama.BranchOffices.List().First();
            var random       = new Random();
            var nitems       = random.Next(1, products.Count) % 2 + 1; // Cantidad de items para la factura
            var decimals     = (int)currency.Decimals;

            var cfdi = new Cfdi
            {
                NameId          = nameId.Value,
                CfdiType        = CfdiType.Ingreso,
                PaymentForm     = paymentForm.Value,
                PaymentMethod   = paymentMethod.Value,
                Currency        = currency.Value,
                Date            = null,                         // Al especificar null, Facturama asigna la fecha y hora actual, de acuerdo al "ExpeditionPlace"
                ExpeditionPlace = "78140",
                Items           = new List <Item>(),

                Exportation = "01",

                GlobalInformation = new GlobalInformation
                {
                    Periodicity = "04",
                    Months      = "04",
                    Year        = "2022",
                },

                Receiver = new Receiver
                {
                    Rfc          = "XAXX010101000",
                    Name         = "PUBLICO EN GENERAL",
                    CfdiUse      = "S01",
                    FiscalRegime = "616",
                    TaxZipCode   = "78140",

                    /*
                     * Address = new Address                       // El nodo Address es opcional (puedes colocarlo nulo o no colocarlo). En el caso de no colcoarlo, tomará la correspondiente al RFC en el catálogo de clientes
                     *                  {
                     *  Street = "Avenida de los pinos",
                     *  ExteriorNumber = "110",
                     *  InteriorNumber = "A",
                     *  Neighborhood = "Las villerías",
                     *  ZipCode = "78000",
                     *  Municipality = "San Luis Potosí",
                     *  State = "San Luis Potosí",
                     *  Country = "México"
                     *                  }*/
                },
            };

            for (var i = products.Count - nitems; i < products.Count; i++)
            {
                var product  = products[i];
                var quantity = random.Next(1, 5);                                                             //Una cantidad aleatoria
                var discount = product.Price % (product.Price == 0 ? 1 : random.Next(1, (int)product.Price)); //Un descuento aleatorio
                var subtotal = Math.Round(product.Price * quantity, decimals);

                var item = new Item
                {
                    ProductCode          = product.CodeProdServ,
                    UnitCode             = product.UnitCode,
                    Unit                 = product.Unit,
                    Description          = string.IsNullOrEmpty(product.Description) ? "Producto de ejemplo" : product.Description,
                    IdentificationNumber = product.IdentificationNumber,
                    Quantity             = quantity,
                    Discount             = Math.Round(discount, decimals),
                    UnitPrice            = Math.Round(product.Price, decimals),
                    Subtotal             = subtotal,
                    TaxObject            = "02", //Elemento usado para CFDI 4.0
                    Taxes                = product.Taxes?.Select(
                        t =>
                    {
                        var baseAmount = Math.Round(subtotal - discount, decimals);
                        return(new Tax
                        {
                            Name = t.Name,
                            IsQuota = t.IsQuota,
                            IsRetention = t.IsRetention,

                            Rate = Math.Round(t.Rate, 6),
                            Base = Math.Round(subtotal - discount, decimals),
                            Total = Math.Round(baseAmount * t.Rate, decimals)
                        });
                    }).ToList()
                };
                var retenciones = item.Taxes?.Where(t => t.IsRetention).Sum(t => t.Total) ?? 0;
                var traslados   = item.Taxes?.Where(t => !t.IsRetention).Sum(t => t.Total) ?? 0;
                item.Total = item.Subtotal - (item.Discount ?? 0) + traslados - retenciones;
                cfdi.Items.Add(item);
            }

            try
            {
                //var cfdiCreated = facturama.Cfdis.Create(cfdi); //CFDI 3.3
                var cfdiCreated = facturama.Cfdis.Create3(cfdi); // Probar CFDI 4.0
                Console.WriteLine($"Se creó exitosamente el cfdi con el folio fiscal: {cfdiCreated.Complement.TaxStamp.Uuid}");

                //Descargar PDF y XML
                //facturama.Cfdis.SavePdf($"factura{cfdiCreated.Complement.TaxStamp.Uuid}.pdf", cfdiCreated.Id);
                //facturama.Cfdis.SaveXml($"factura{cfdiCreated.Complement.TaxStamp.Uuid}.xml", cfdiCreated.Id);


                //var list = facturama.Cfdis.List("Expresion en Software");
                //Console.WriteLine($"Se encontraron: {list.Length} elementos en la busqueda");
                //list = facturama.Cfdis.List(rfc: "EWE1709045U0"); //RFC receptor en especifico
                //Console.WriteLine($"Se encontraron: {list.Length} elementos en la busqueda");


                //Enviar CFDI por correo

                /*
                 * if (facturama.Cfdis.SendByMail(cfdiCreated.Id, "*****@*****.**"))
                 * {
                 *  Console.WriteLine("Se envió correctamente el CFDI");
                 * }
                 */

                /*
                 * var cancelationStatus = facturama.Cfdis.Cancel(cfdiCreated.Id);
                 * if (cancelationStatus.Status == "canceled")
                 * {
                 *  Console.WriteLine($"Se canceló exitosamente el CFDI con el folio fiscal: {cfdiCreated.Complement.TaxStamp.Uuid}");
                 * }
                 * else if (cancelationStatus.Status == "pending")
                 * {
                 *  Console.WriteLine($"El CFDI está en proceso de cancelacion, require aprobacion por parte del receptor UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                 * }
                 * else if (cancelationStatus.Status == "active")
                 * {
                 *  Console.WriteLine($"El CFDI no pudo ser cancelado, se deben revisar docuementos relacionados on cancelar directo en el SAT UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                 * }
                 * else
                 * {
                 *  Console.WriteLine($"Estado de cancelacin del CFDI desconocido UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                 * }
                 */
            }
            catch (FacturamaException ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.Model.Details != null)
                {
                    foreach (var messageDetail in ex.Model.Details)
                    {
                        Console.WriteLine($"{messageDetail.Key}: {string.Join(",", messageDetail.Value)}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error inesperado: ", ex.Message);
            }

            Console.WriteLine("----- Fin del ejemplo InvoiceExample -----");
        }
Example #15
0
        /**
         * Modelo "Complemento de pago"
         * - Se especifica: la moneda, método de pago, forma de pago, cliente, y lugar de expedición
         */
        private static Facturama.Models.Request.Cfdi CreateModelCfdiPaymentComplement(FacturamaApi facturama, Facturama.Models.Response.Cfdi cfdiInicial)
        {
            Cfdi cfdi = new Cfdi();

            // Lista del catálogo de nombres en el PDF
            var nameForPdf = facturama.Catalogs.NameIds.First(m => m.Value == "14"); // Nombre en el pdf: "Complemento de pago"

            cfdi.NameId = nameForPdf.Value;

            // Receptor de comprobante (se toma como cliente el mismo a quien se emitió el CFDI Inicial),
            String clientRfc = cfdiInicial.Receiver.Rfc;
            Client client    = facturama.Clients.List().Where(p => p.Rfc.Equals(clientRfc)).First();

            Receiver receiver = new Receiver
            {
                CfdiUse = "P01",
                Name    = client.Name,
                Rfc     = client.Rfc
            };

            cfdi.Receiver = receiver;

            // Lugar de expedición (es necesario por lo menos tener una sucursal)
            BranchOffice branchOffice = facturama.BranchOffices.List().First();

            cfdi.ExpeditionPlace = "78240";

            // Fecha y hora de expecidión del comprobante
            //DateTime bindingDate;
            //DateTime.TryParse(cfdiBinding.Date, null, DateTimeStyles.RoundtripKind, out bindingDate);

            cfdi.Date     = null; // Puedes especificar una fecha por ejemplo:  DateTime.Now
            cfdi.CfdiType = CfdiType.Pago;
            // Complemento de pago ---
            Complement complement = new Complement();

            // Pueden representarse más de un pago en un solo CFDI
            List <Facturama.Models.Complements.Payment> lstPagos = new List <Facturama.Models.Complements.Payment>();

            Facturama.Models.Complements.Payment pago = new Facturama.Models.Complements.Payment();

            // Fecha y hora en que se registró el pago en el formato: "yyyy-MM-ddTHH:mm:ss"
            // (la fecha del pago debe ser menor que la fecha en que se emite el CFDI)
            // Para este ejemplo, se considera que  el pago se realizó hace una hora
            pago.Date = DateTime.Now.AddHours(-6).ToString("yyyy-MM-dd HH:mm:ss");


            // Forma de pago (Efectivo, Tarjeta, etc)
            Facturama.Models.Response.Catalogs.CatalogViewModel paymentForm = facturama.Catalogs.PaymentForms.Where(p => p.Name.Equals("Efectivo")).First();
            pago.PaymentForm = paymentForm.Value;

            // Selección de la moneda del catálogo
            // La Moneda, puede ser diferente a la del documento inicial
            // (En el caso de que sea diferente, se debe colocar el tipo de cambio)
            List <CurrencyCatalog> lstCurrencies = facturama.Catalogs.Currencies.ToList();
            CurrencyCatalog        currency      = lstCurrencies.Where(p => p.Value.Equals("MXN")).First();

            pago.Currency = currency.Value;

            // Monto del pago
            // Este monto se puede distribuir entre los documentos relacionados al pago
            pago.Amount = 100.00m;

            // Documentos relacionados con el pago
            // En este ejemplo, los datos se obtiene el cfdiInicial, pero puedes colocar solo los datos
            // aun sin tener el "Objeto" del cfdi Inicial, ya que los valores son del tipo "String"
            List <Facturama.Models.Complements.RelatedDocument> lstRelatedDocuments = new List <Facturama.Models.Complements.RelatedDocument>();

            Facturama.Models.Complements.RelatedDocument relatedDocument = new Facturama.Models.Complements.RelatedDocument
            {
                Uuid                  = cfdiInicial.Complement.TaxStamp.Uuid, // "27568D31-E579-442F-BA77-798CBF30BD7D"
                Serie                 = "A",                                  //cfdiInicial.Serie, // "EA"
                Folio                 = cfdiInicial.Folio,                    // 34853
                Currency              = currency.Value,
                PaymentMethod         = "PUE",                                // En el complemento de pago tiene que ser PUE
                PartialityNumber      = 1,
                PreviousBalanceAmount = 100.00m,
                AmountPaid            = 100.00m
            };
            lstRelatedDocuments.Add(relatedDocument);

            pago.RelatedDocuments = lstRelatedDocuments;

            lstPagos.Add(pago);

            complement.Payments = lstPagos;

            cfdi.Complement = complement;


            return(cfdi);
        }
Example #16
0
        public void Run()
        {
            Console.WriteLine("----- Inicio del ejemplo EducationalInstitutionComplementExample -----");

            var cfdi = new Cfdi
            {
                NameId          = "1",                          // Factura
                CfdiType        = CfdiType.Ingreso,
                PaymentForm     = "03",                         // Transferencia electrónica de fondos
                PaymentMethod   = "PUE",                        // Pago en una exhibición
                Date            = null,                         // Al especificar null, Facturama asigna la fecha y hora actual, de acuerdo al "ExpeditionPlace"
                ExpeditionPlace = "78000",                      // Codigo postal del la sucursal desde donde se expide el CFDI, (este debe pertenecer al catálogo de sucursales)  https://apisandbox.facturama.mx/guias/perfil-fiscal#lugares-expedicion-series
                Items           = new List <Item>(),
                Receiver        = new Receiver
                {
                    CfdiUse = "P01",
                    Name    = "José Perez Leon",
                    Rfc     = "JUFA7608212V6",
                    Address = new Address                       // El nodo Address es opcional (puedes colocarlo nulo o no colocarlo). En el caso de no colcoarlo, tomará la correspondiente al RFC en el catálogo de clientes
                    {
                        Street         = "Avenida de los pinos",
                        ExteriorNumber = "110",
                        InteriorNumber = "A",
                        Neighborhood   = "Las villerías",
                        ZipCode        = "78000",
                        Municipality   = "San Luis Potosí",
                        State          = "San Luis Potosí",
                        Country        = "México"
                    }
                },
            };

            // Complemento IEDU
            var itemComplement = new Facturama.Models.Complements.ItemComplement();

            itemComplement.EducationalInstitution = new EducationalInstitution
            {
                AutRvoe        = "234",
                Curp           = "POAJ890718HSPMLS05",
                EducationLevel = "Profesional técnico",
                StudentsName   = "Emilio Perez Lopez",
                PaymentRfc     = "XAMA620210DQ5"
            };

            var item = new Item
            {
                ProductCode          = "86121503",              // Reacionado con institucion educativa
                UnitCode             = "E48",                   // Servicio
                Unit                 = "Unidad de servicio",
                Description          = "Colegiatura del mes de marzo",
                IdentificationNumber = "1234",                  // Numero de identificación interno del producto (opcional)
                Quantity             = 1,
                Discount             = 0,
                UnitPrice            = 2300,
                Subtotal             = 2300,
                Taxes                = new [] { new Tax
                                                {
                                                    Name        = "IVA",
                                                    IsQuota     = false,
                                                    IsRetention = false,

                                                    Rate  = 0.16m,
                                                    Base  = 2300,
                                                    Total = 368
                                                } }.ToList(),
                Complement = itemComplement                     // Complemento IEDU
            };
            var retenciones = item.Taxes?.Where(t => t.IsRetention).Sum(t => t.Total) ?? 0;
            var traslados   = item.Taxes?.Where(t => !t.IsRetention).Sum(t => t.Total) ?? 0;

            item.Total = item.Subtotal - (item.Discount ?? 0) + traslados - retenciones;
            cfdi.Items.Add(item);

            try
            {
                var cfdiCreated = facturama.Cfdis.Create(cfdi);
                Console.WriteLine(
                    $"Se creó exitosamente el cfdi con el folio fiscal: {cfdiCreated.Complement.TaxStamp.Uuid}");
                facturama.Cfdis.SavePdf($"factura{cfdiCreated.Complement.TaxStamp.Uuid}.pdf", cfdiCreated.Id);
                facturama.Cfdis.SaveXml($"factura{cfdiCreated.Complement.TaxStamp.Uuid}.xml", cfdiCreated.Id);


                if (facturama.Cfdis.SendByMail(cfdiCreated.Id, "*****@*****.**"))
                {
                    Console.WriteLine("Se envió correctamente el CFDI");
                }


                var cancelationStatus = facturama.Cfdis.Cancel(cfdiCreated.Id);
                if (cancelationStatus.Status == "canceled")
                {
                    Console.WriteLine($"Se canceló exitosamente el CFDI con el folio fiscal: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
                else if (cancelationStatus.Status == "pending")
                {
                    Console.WriteLine($"El CFDI está en proceso de cancelacion, require aprobacion por parte del receptor UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
                else if (cancelationStatus.Status == "active")
                {
                    Console.WriteLine($"El CFDI no pudo ser cancelado, se deben revisar docuementos relacionados on cancelar directo en el SAT UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
                else
                {
                    Console.WriteLine($"Estado de cancelacin del CFDI desconocido UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
            }
            catch (FacturamaException ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.Model.Details != null)
                {
                    foreach (var messageDetail in ex.Model.Details)
                    {
                        Console.WriteLine($"{messageDetail.Key}: {string.Join(",", messageDetail.Value)}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error inesperado: ", ex.Message);
            }

            Console.WriteLine("----- Fin del ejemplo EducationalInstitutionComplementExample -----");
        }
        /// <summary>
        /// Obtiene la informnacion del certificado, lo desencripta y aplica digestion SHA-256 para generar el sello.
        /// </summary>
        /// <param name="cfdi"></param>
        /// <param name="xml"></param>
        private static void firmarXml(Cfdi cfdi, ref XDocument xml)
        {
            try
            {
                obtenerCertificado(cfdi.rutaArchivoCer, ref xml);
                string cadenaOriginal  = obtenerCadenaOriginal(cfdi.rutaXsltCadenaOriginal, xml);
                string algoritmoHash   = "SHA-256";
                string xmlLlavePrivada = string.Empty;
                string sellobase64     = string.Empty;

                Rsa               rsa          = new Rsa();
                Rsa               rsa2         = new Rsa();
                Cert              certificado  = new Cert();
                PrivateKey        llavePrivada = new PrivateKey();
                Chilkat.PublicKey llavePublica;

                if (llavePrivada.LoadPkcs8EncryptedFile(cfdi.rutaArchivoKey, cfdi.secretArchivoKey) == false)
                {
                    return;
                }

                xmlLlavePrivada = llavePrivada.GetXml();

                if (rsa.UnlockComponent(Constantes.CHILKAT_UNLOCK_CODE) == false)
                {
                    //Debug.Write(rsa.LastErrorText);
                    return;
                }

                if (rsa.ImportPrivateKey(xmlLlavePrivada) == false)
                {
                    //Debug.Write(rsa.LastErrorText);
                    return;
                }

                rsa.Charset      = "utf-8";
                rsa.EncodingMode = "base64";
                rsa.LittleEndian = false;

                if (certificado.LoadFromFile(cfdi.rutaArchivoCer) == false)
                {
                    return;
                }

                sellobase64 = rsa.SignStringENC(cadenaOriginal, algoritmoHash);

                xml.Root.SetAttributeValue("Sello", sellobase64);

                XElement xComprobante = xml.Root;
                xComprobante = HelpersXml.removerAtributosVacios(xml.Root, true);

                llavePublica = certificado.ExportPublicKey();

                if (rsa2.ImportPublicKey(llavePublica.GetXml()) == false)
                {
                    return;
                }

                rsa2.Charset      = "utf-8";
                rsa.EncodingMode  = "base64";
                rsa2.LittleEndian = false;

                if (rsa2.VerifyStringENC(cadenaOriginal, algoritmoHash, sellobase64) == false)
                {
                    return;
                }

                certificado.Dispose();

                cfdi.cadenaOriginal = cadenaOriginal;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /**
         * Ejemplo de creación de un CFDI "complemento de pago"
         * Referencia: https://apisandbox.facturama.mx/guias/api-web/cfdi/complemento-pago
         *
         * En virtud de que el complemento de pago, requiere ser asociado a un CFDI con el campo "PaymentMethod" = "PPD"
         * En este ejemplo se incluye la creacón de este CFDI, para posteriormente realizar el  "Complemento de pago" = "PUE"
         */
        private static Cfdi SamplePaymentComplement(FacturamaApi facturama)
        {
            try
            {
                Console.WriteLine("----- Inicio del ejemplo samplePaymentComplement -----");

                // Cfdi Incial (debe ser "PPD")
                // -------- Creacion del cfdi en su forma general (sin items / productos) asociados --------
                Cfdi cfdi = CreateModelCfdiGeneral(facturama);

                // -------- Agregar los items que lleva el cfdi ( para este ejemplo, se agregan con datos aleatorios) --------
                cfdi = AddItemsToCfdi(facturama, cfdi);

                cfdi.PaymentMethod = "PPD";           // El método de pago del documento inicial debe ser "PPD"

                // Se manda timbrar mediante Facturama
                Facturama.Models.Response.Cfdi cfdiInicial = facturama.Cfdis.Create(cfdi);

                Console.WriteLine("Se creó exitosamente el cfdi Inicial (PPD) con el folio fiscal: " + cfdiInicial.Complement.TaxStamp.Uuid);

                // Descarga de los archivos del documento inicial
                String filePath = "factura" + cfdiInicial.Complement.TaxStamp.Uuid;
                facturama.Cfdis.SavePdf(filePath + ".pdf", cfdiInicial.Id);
                facturama.Cfdis.SaveXml(filePath + ".xml", cfdiInicial.Id);



                // Complemento de pago (debe ser "PUE")
                // Y no lleva "Items" solo especifica el "Complemento"
                Cfdi paymentComplementModel = CreateModelCfdiPaymentComplement(facturama, cfdiInicial);


                // Se manda timbrar el complemento de pago mediante Facturama
                Facturama.Models.Response.Cfdi paymentComplement = facturama.Cfdis.Create(paymentComplementModel);

                Console.WriteLine("Se creó exitosamente el complemento de pago con el folio fiscal: " + cfdiInicial.Complement.TaxStamp.Uuid);


                // Descarga de los archivos del documento inicial
                String filePathPayment = "factura" + paymentComplement.Complement.TaxStamp.Uuid;
                facturama.Cfdis.SavePdf(filePath + ".pdf", paymentComplement.Id);
                facturama.Cfdis.SaveXml(filePath + ".xml", paymentComplement.Id);



                // Posibilidad de mandar  los cfdis por coreo ( el cfdiInical y complemento de pago)
                Console.WriteLine(facturama.Cfdis.SendByMail(cfdiInicial.Id, "*****@*****.**"));
                Console.WriteLine(facturama.Cfdis.SendByMail(paymentComplement.Id, "*****@*****.**"));


                Console.WriteLine("----- Fin del ejemplo de samplePaymentComplement -----");
                return(cfdi);
            }
            catch (FacturamaException ex)
            {
                Console.WriteLine(ex.Message);
                foreach (var messageDetail in ex.Model.Details)
                {
                    Console.WriteLine($"{messageDetail.Key}: {string.Join(",", messageDetail.Value)}");
                }
                return(null);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error inesperado: ", ex.Message);
                return(null);
            }
        }
        public void Run()
        {
            Console.WriteLine("----- Inicio del ejemplo WaybillComplementExample -----");

            var cfdi = new Cfdi
            {
                NameId          = "1",                          // Factura
                CfdiType        = CfdiType.Ingreso,
                PaymentForm     = "03",                         // Transferencia electrónica de fondos
                PaymentMethod   = "PUE",                        // Pago en una exhibición
                Date            = null,                         // Al especificar null, Facturama asigna la fecha y hora actual, de acuerdo al "ExpeditionPlace"
                ExpeditionPlace = "78000",                      // Codigo postal del la sucursal desde donde se expide el CFDI, (este debe pertenecer al catálogo de sucursales)  https://apisandbox.facturama.mx/guias/perfil-fiscal#lugares-expedicion-series
                Items           = new List <Item>(),
                Receiver        = new Receiver
                {
                    CfdiUse = "P01",
                    Name    = "José Perez Leon",
                    Rfc     = "JUFA7608212V6",
                    Address = new Address                       // El nodo Address es opcional (puedes colocarlo nulo o no colocarlo). En el caso de no colcoarlo, tomará la correspondiente al RFC en el catálogo de clientes
                    {
                        Street         = "Avenida de los pinos",
                        ExteriorNumber = "110",
                        InteriorNumber = "A",
                        Neighborhood   = "Las villerías",
                        ZipCode        = "78000",
                        Municipality   = "San Luis Potosí",
                        State          = "San Luis Potosí",
                        Country        = "México"
                    }
                },
            };

            var item = new Item
            {
                ProductCode          = "78101703",              // Reacionado con institucion educativa
                UnitCode             = "E48",                   // Servicio
                Unit                 = "Unidad de servicio",
                Description          = "Colegiatura del mes de marzo",
                IdentificationNumber = "1234",                  // Numero de identificación interno del producto (opcional)
                Quantity             = 1,
                Discount             = 0,
                UnitPrice            = 2300,
                Subtotal             = 2300,
                Taxes                = new [] { new Tax
                                                {
                                                    Name        = "IVA",
                                                    IsQuota     = false,
                                                    IsRetention = false,

                                                    Rate  = 0.16m,
                                                    Base  = 2300,
                                                    Total = 368
                                                } }.ToList()
            };
            var retenciones = item.Taxes?.Where(t => t.IsRetention).Sum(t => t.Total) ?? 0;
            var traslados   = item.Taxes?.Where(t => !t.IsRetention).Sum(t => t.Total) ?? 0;

            item.Total = item.Subtotal - (item.Discount ?? 0) + traslados - retenciones;
            cfdi.Items.Add(item);

            // Complemento Carta Porte
            cfdi.Complement = new Complement
            {
                CartaPorte20 = new ComplementoCartaPorte20
                {
                    TranspInternac = TranspInternac.No,
                    Ubicaciones    = new[] { new Ubicacion
                                             {
                                                 TipoUbicacion            = TipoUbicacion.Origen,
                                                 RFCRemitenteDestinatario = "EKU9003173C9",
                                                 FechaHoraSalidaLlegada   = DateTime.Now.AddHours(-6),
                                                 DistanciaRecorrida       = 1,
                                                 Domicilio = new Domicilio
                                                 {
                                                     Calle        = "Puebla No.1",
                                                     CodigoPostal = "28239",
                                                     Colonia      = "0342",
                                                     Estado       = "COL",
                                                     Municipio    = "007",
                                                     Localidad    = "02",
                                                     Pais         = "MEX",
                                                 }
                                             },
                                             new Ubicacion
                                             {
                                                 TipoUbicacion            = TipoUbicacion.Destino,
                                                 RFCRemitenteDestinatario = "RIFO990729M66",
                                                 FechaHoraSalidaLlegada   = DateTime.Now.AddHours(+6),
                                                 DistanciaRecorrida       = 100,
                                                 Domicilio = new Domicilio
                                                 {
                                                     Calle        = "Morelos No.1",
                                                     CodigoPostal = "28219",
                                                     Colonia      = "0575",
                                                     Estado       = "COL",
                                                     Municipio    = "007",
                                                     Localidad    = "02",
                                                     Pais         = "MEX",
                                                 }
                                             } },
                    Mercancias = new Mercancias
                    {
                        UnidadPeso = "KGM",
                        Mercancia  = new [] {
                            new Mercancia
                            {
                                Cantidad     = 1,
                                BienesTransp = "10101500",
                                Descripcion  = "Animales vivos de granja",
                                ClaveUnidad  = "KGM",
                                PesoEnKg     = 120,
                            }
                        },
                        Autotransporte = new Autotransporte
                        {
                            PermSCT       = "TPAF01",
                            NumPermisoSCT = "123abc",
                            Seguros       = new Seguros
                            {
                                AseguraRespCivil = "Seguros SA",
                                PolizaRespCivil  = "123123"
                            },
                            IdentificacionVehicular = new IdentificacionVehicular
                            {
                                AnioModeloVM    = 1990,
                                ConfigVehicular = "C2R3",
                                PlacaVM         = "XXX000",
                            },
                            Remolques = new []
                            {
                                new Remolque
                                {
                                    SubTipoRem = "CTR001",
                                    Placa      = "21132H"
                                }
                            }
                        }
                    },
                    FiguraTransporte = new[] { new TiposFigura {
                                                   TipoFigura   = "01",
                                                   RFCFigura    = "MISC491214B86",
                                                   NombreFigura = "Juan",
                                                   NumLicencia  = "000001",
                                               },
                                               new TiposFigura
                                               {
                                                   TipoFigura       = "02",
                                                   RFCFigura        = "XAMA620210DQ5",
                                                   NombreFigura     = "Juan Jose Perez Lopez",
                                                   PartesTransporte = new [] { new PartesTransporte {
                                                                                   ParteTransporte = "PT01"
                                                                               } },
                                                   Domicilio = new Domicilio
                                                   {
                                                       Calle        = "Morelos No.1",
                                                       CodigoPostal = "28219",
                                                       Colonia      = "0575",
                                                       Estado       = "COL",
                                                       Municipio    = "007",
                                                       Localidad    = "02",
                                                       Pais         = "MEX",
                                                   }
                                               } }
                }
            };


            try
            {
                var cfdiCreated = facturama.Cfdis.Create(cfdi);
                Console.WriteLine(
                    $"Se creó ex la carta porte 2.0 con el folio fiscal: {cfdiCreated.Complement.TaxStamp.Uuid}");
                facturama.Cfdis.SavePdf($"factura{cfdiCreated.Complement.TaxStamp.Uuid}.pdf", cfdiCreated.Id);
                facturama.Cfdis.SaveXml($"factura{cfdiCreated.Complement.TaxStamp.Uuid}.xml", cfdiCreated.Id);


                if (facturama.Cfdis.SendByMail(cfdiCreated.Id, "*****@*****.**"))
                {
                    Console.WriteLine("Se envió correctamente la carta porte 2.0");
                }


                var cancelationStatus = facturama.Cfdis.Cancel(cfdiCreated.Id);
                if (cancelationStatus.Status == "canceled")
                {
                    Console.WriteLine($"Se canceló exitosamente el CFDI con el folio fiscal: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
                else if (cancelationStatus.Status == "pending")
                {
                    Console.WriteLine($"El CFDI está en proceso de cancelacion, require aprobacion por parte del receptor UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
                else if (cancelationStatus.Status == "active")
                {
                    Console.WriteLine($"El CFDI no pudo ser cancelado, se deben revisar docuementos relacionados on cancelar directo en el SAT UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
                else
                {
                    Console.WriteLine($"Estado de cancelacin del CFDI desconocido UUID: {cfdiCreated.Complement.TaxStamp.Uuid}");
                }
            }
            catch (FacturamaException ex)
            {
                Console.WriteLine(ex.Message);
                if (ex.Model.Details != null)
                {
                    foreach (var messageDetail in ex.Model.Details)
                    {
                        Console.WriteLine($"{messageDetail.Key}: {string.Join(",", messageDetail.Value)}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error inesperado: ", ex.Message);
            }

            Console.WriteLine("----- Fin del ejemplo WaybillComplementExample -----");
        }
        public void Test()
        {
            var facturama = new FacturamaApi("pruebas", "pruebas2011");
            var cfdi      = new Cfdi
            {
                Serie             = "R",
                Currency          = "MXN",
                ExpeditionPlace   = "78116",
                PaymentConditions = "CREDITO A SIETE DIAS",
                CfdiType          = CfdiType.Ingreso,
                PaymentForm       = "03",
                PaymentMethod     = "PUE",
                Receiver          = new Receiver
                {
                    Rfc     = "EKU9003173C9",
                    Name    = "RADIAL SOFTWARE SOLUTIONS",
                    CfdiUse = "P01"
                },
                Items = new List <Item>
                {
                    new Item
                    {
                        ProductCode          = "10101504",
                        IdentificationNumber = "EDL",
                        Description          = "Estudios de viabilidad",
                        Unit      = "NO APLICA",
                        UnitCode  = "MTS",
                        UnitPrice = 50.00m,
                        Quantity  = 2.00m,
                        Subtotal  = 100.00m,
                        Taxes     = new List <Tax>
                        {
                            new Tax
                            {
                                Total       = 16.00m,
                                Name        = "IVA",
                                Base        = 100.00m,
                                Rate        = 0.160000m,
                                IsRetention = false
                            }
                        },
                        Total      = 116.0m,
                        Complement = new ItemComplement
                        {
                            ThirdPartyAccount = new ThirdPartyAccount
                            {
                                Rfc   = "JES900109Q90",
                                Name  = "Expresión en Software",
                                Taxes = new List <ThirdPartyAccountTax>
                                {
                                    new ThirdPartyAccountTax
                                    {
                                        Name   = "IVA",
                                        Rate   = 0.16m,
                                        Amount = 1000.00m
                                    }
                                }
                            }
                        }
                    }
                }
            };
            var cfdiCreated = facturama.Cfdis.Create(cfdi);

            Assert.IsTrue(Guid.TryParse(cfdiCreated.Complement.TaxStamp.Uuid, out _));
        }