public async Task <JsonResult> CancelCFDI(Guid overdraftID)
        {
            var cancelationParms = new CancelPayrollStampingParams()
            {
                FiscalStampingVersion = FiscalStampingVersion.CFDI33_Nom12,
                IdentityWorkID        = SessionModel.CompanyID,
                InstanceID            = SessionModel.InstanceID,
                user         = SessionModel.IdentityID,
                OverdraftIDs = new List <Guid> {
                    overdraftID
                }
            };
            var result = await cancelStampingClient.CancelPayrollStampingAsync(cancelationParms);

            if (result.WithErrors)
            {
                throw new CotorraException(108, "108", result.Message, null);
            }

            var cancelationDetail = result.CancelPayrollStampingResultDetails.FirstOrDefault();

            if (cancelationDetail.PayrollStampingResultStatus == PayrollStampingResultStatus.Fail)
            {
                throw new CotorraException(108, "108", cancelationDetail.Message, null);
            }

            return(Json("OK"));
        }
Example #2
0
        private (byte[], byte[], string) Crypto(CancelPayrollStampingParams cancelPayrollStampingParams, string certificateCER,
                                                string certificateKey, string certPassword)
        {
            var clsCryptoToCreate = new ClsCrypto(
                cancelPayrollStampingParams.IdentityWorkID.ToString().ToLower().Replace("-", ""),
                cancelPayrollStampingParams.InstanceID.ToString().ToLower().Replace("-", ""),
                cancelPayrollStampingParams.InstanceID.ToString().ToLower().Replace("-", "").Substring(0, 19));
            var certificatebytesCER  = Convert.FromBase64String(clsCryptoToCreate.Decrypt(certificateCER));
            var certificatebytesKEY  = Convert.FromBase64String(clsCryptoToCreate.Decrypt(certificateKey));
            var certPasswordToResult = StringCipher.Decrypt(certPassword);

            return(certificatebytesCER, certificatebytesKEY, certPasswordToResult);
        }
Example #3
0
        private async Task saveCancelFiscalStamping(CancelPayrollStampingParams cancelPayrollStampingParams,
                                                    Guid cancelationRequestXMLID,
                                                    Guid cancelationResponseXMLID,
                                                    List <CancelationStoreProcedureParams> cancelationStoreProcedureParams)
        {
            using (var connection = new SqlConnection(ConnectionManager.ConfigConnectionString))
            {
                if (connection.State != ConnectionState.Open)
                {
                    await connection.OpenAsync();
                }

                using (var command = connection.CreateCommand())
                {
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = "CreateCancelationStamp";

                    DataTable dtGuidList = new DataTable();
                    dtGuidList.Columns.Add("OverdraftID", typeof(string));
                    dtGuidList.Columns.Add("CancelationFiscalDocumentStatus", typeof(int));
                    cancelationStoreProcedureParams.ForEach(p =>
                    {
                        dtGuidList.Rows.Add(p.OverdraftID, (int)p.CancelationFiscalDocumentStatus);
                    });
                    SqlParameter param = new SqlParameter("@Cancelstampoverdraft", SqlDbType.Structured)
                    {
                        TypeName = "dbo.cancelstampoverdrafttabletype",
                        Value    = dtGuidList
                    };
                    command.Parameters.Add(param);

                    command.Parameters.AddWithValue("@CancelationRequestXMLID", cancelationRequestXMLID);
                    command.Parameters.AddWithValue("@CancelationResponseXMLID", cancelationResponseXMLID);
                    command.Parameters.AddWithValue("@InstanceId", cancelPayrollStampingParams.InstanceID);
                    command.Parameters.AddWithValue("@company", cancelPayrollStampingParams.IdentityWorkID);
                    command.Parameters.AddWithValue("@user", cancelPayrollStampingParams.user);

                    //Execute SP de autorización
                    await command.ExecuteNonQueryAsync();
                }
            }
        }
Example #4
0
        public async Task Should_Stamp_Payroll_CFDI_Valid()
        {
            var xmlCancelacion = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Acuse xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" Fecha=\"2020-07-02T16:02:07.2838838\" RfcEmisor=\"KAHO641101B39\">  <Folios xmlns=\"http://cancelacfd.sat.gob.mx\">    <UUID>3377E0AA-C54B-4E9E-BFF2-1D8BA96D5DD4</UUID>    <EstatusUUID>201</EstatusUUID>  </Folios>  <Signature Id=\"SelloSAT\" xmlns=\"http://www.w3.org/2000/09/xmldsig#\">    <SignedInfo>      <CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\" />      <SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#hmac-sha512\" />      <Reference URI=\"\">        <Transforms>          <Transform Algorithm=\"http://www.w3.org/TR/1999/REC-xpath-19991116\">            <XPath>not(ancestor-or-self::*[local-name()='Signature'])</XPath>          </Transform>        </Transforms>        <DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha512\" />        <DigestValue>BThmOyTf26Ax25v8Li0oqcP3wyrhW3kjjxOcO1zamRYasNIPcHSnBiRyxmJ449a3gdgAWaz/UKVil3pqcper+g==</DigestValue>      </Reference>    </SignedInfo>    <SignatureValue>6qDGoWoHW5tK2MGNiXU7fI6hfpkbrYTMHafVvIsGRkl9xq2H2YQRvId4CO7B9GGJFbuVMku2IBkpKU/Tscqo9Q==</SignatureValue>    <KeyInfo>      <KeyName>BF66E582888CC845</KeyName>      <KeyValue>        <RSAKeyValue>          <Modulus>n5YsGT0w5Z70ONPbqszhExfJU+KY3Bscftc2jxUn4wxpSjEUhnCuTd88OK5QbDW3Mupoc61jr83lRhUCjchFAmCigpC10rEntTfEU+7qtX8ud/jJJDB1a9lTIB6bhBN//X8IQDjhmHrfKvfen3p7RxLrFoxzWgpwKriuGI5wUlU=</Modulus>          <Exponent>AQAB</Exponent>        </RSAKeyValue>      </KeyValue>    </KeyInfo>  </Signature></Acuse>";
            var acuse          = SerializerXml.DeserializeObject <Schema.CFDI33Nom12.Acuse>(xmlCancelacion);

            using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);

            try
            {
                var identityWorkId = Guid.NewGuid();
                var instanceID     = Guid.NewGuid();

                var overdraft      = await new PayrollStampingManagerUT().CreateRealOverdraftAsync(identityWorkId, instanceID);
                var periodDetailID = overdraft.PeriodDetailID;

                //Recalculate
                var calculateParams = new CalculateOverdraftParams()
                {
                    DeleteAccumulates = true,
                    IdentityWorkID    = identityWorkId,
                    InstanceID        = instanceID,
                    OverdraftID       = overdraft.ID,
                    ResetCalculation  = true,
                    SaveOverdraft     = true,
                    UserID            = Guid.Empty
                };

                var calculationResult = await new OverdraftCalculationManager().CalculateAsync(calculateParams);
                overdraft = (calculationResult as CalculateOverdraftResult).OverdraftResult;
                Assert.True(overdraft.OverdraftDetails.Sum(p => p.Amount) > 0);

                //Autorización de la nómina
                var authorizationManager = new AuthorizationManager();
                var authorizationParams  = new AuthorizationParams()
                {
                    IdentityWorkID            = identityWorkId,
                    InstanceID                = instanceID,
                    PeriodDetailIDToAuthorize = periodDetailID,
                    ResourceID                = Guid.Empty,
                    user = Guid.Empty
                };

                //autorizacion de la nómina
                var historicOverdrafts = await authorizationManager.AuthorizationAsync(authorizationParams);

                //Timbrado

                var overdraftManager   = new MiddlewareManager <Overdraft>(new BaseRecordManager <Overdraft>(), new OverdraftValidator());
                var overdraftsPrevious = await overdraftManager.FindByExpressionAsync(p => p.PeriodDetailID == periodDetailID, identityWorkId);

                var manager       = new PayrollStampingManager();
                var dateTime      = DateTime.Now;
                var stampingParms = new PayrollStampingParams()
                {
                    FiscalStampingVersion = FiscalStampingVersion.CFDI33_Nom12,
                    IdentityWorkID        = identityWorkId,
                    InstanceID            = instanceID,
                    PeriodDetailID        = periodDetailID,
                    Detail = new List <PayrollStampingDetail>()
                    {
                        new PayrollStampingDetail()
                        {
                            Folio             = "2020",
                            Series            = "S1",
                            PaymentDate       = dateTime.AddDays(-2),
                            RFCOriginEmployer = null,
                            SNCFEntity        = null,
                            OverdraftID       = overdraftsPrevious.FirstOrDefault().ID,
                        }
                    },

                    Currency = Currency.MXN
                };

                var payrollStampingResult = await manager.PayrollStampingAsync(stampingParms);

                Assert.Contains(payrollStampingResult.PayrollStampingResultDetails, p => p.PayrollStampingResultStatus == PayrollStampingResultStatus.Success);

                //cancel payroll
                var cancelStampingManager = new CancelStampingManager();
                var cancelParams          = new CancelPayrollStampingParams()
                {
                    FiscalStampingVersion = FiscalStampingVersion.CFDI33_Nom12,
                    IdentityWorkID        = identityWorkId,
                    InstanceID            = instanceID,
                    OverdraftIDs          = overdraftsPrevious.Select(p => p.ID).ToList(),
                    user = Guid.Empty
                };

                await Task.Delay(10000);

                var cancelationResult = await cancelStampingManager.CancelPayrollStampingAsync(cancelParams);

                Assert.False(cancelationResult.WithErrors);

                var cancelManager = new MiddlewareManager <CancelationFiscalDocument>(new BaseRecordManager <CancelationFiscalDocument>(),
                                                                                      new CancelationFiscalDocumentValidator());
                var cancelations = await cancelManager.FindByExpressionAsync(p => p.InstanceID == instanceID, identityWorkId,
                                                                             new string[] { "CancelationFiscalDocumentDetails" });

                Assert.True(cancelations.Any());

                var overIds         = overdraftsPrevious.Select(p => p.ID).ToList();
                var olderOverdrafts = await overdraftManager.FindByExpressionAsync(p => overIds.Contains(p.ID), identityWorkId);

                Assert.False(olderOverdrafts.Any(p => p.OverdraftStatus != OverdraftStatus.Canceled));

                var newOverdrafts = await overdraftManager.FindByExpressionAsync(p => overIds.Contains(p.OverdraftPreviousCancelRelationshipID.Value), identityWorkId);

                Assert.False(newOverdrafts.Any(p => p.OverdraftPreviousCancelRelationshipID == null));
            }
            catch (Exception ex)
            {
                var t = ex.ToString();
                Assert.True(false, ex.ToString());
            }
        }
Example #5
0
 public async Task <CancelPayrollStampingResult> CancelPayrollStampingAsync(CancelPayrollStampingParams cancelPayrollStampingParams)
 {
     return(await _client.CancelPayrollStampingAsync(cancelPayrollStampingParams));
 }
        public async Task <CancelPayrollStampingResult> CancelPayrollStampingAsync(CancelPayrollStampingParams cancelPayrollStampingParams)
        {
            var cancelStampingManager = new CancelStampingManager();

            return(await cancelStampingManager.CancelPayrollStampingAsync(cancelPayrollStampingParams));
        }
Example #7
0
        public async Task <CancelPayrollStampingResult> CancelPayrollStampingAsync(CancelPayrollStampingParams cancelPayrollStampingParams)
        {
            //Create cancelation instance
            ICancelStamping cancelStamping = CancelStampingFactory.CreateInstance(cancelPayrollStampingParams.FiscalStampingVersion);

            //Get overdrafts and validate
            var overdraftMiddlewareManager = new MiddlewareManager <Overdraft>(new BaseRecordManager <Overdraft>(),
                                                                               new OverdraftValidator());
            var overdraftsIds      = cancelPayrollStampingParams.OverdraftIDs;
            var overdraftsToCancel = await overdraftMiddlewareManager.FindByExpressionAsync(p =>
                                                                                            p.company == cancelPayrollStampingParams.IdentityWorkID &&
                                                                                            p.InstanceID == cancelPayrollStampingParams.InstanceID &&
                                                                                            overdraftsIds.Contains(p.ID) &&
                                                                                            p.OverdraftStatus == OverdraftStatus.Stamped &&
                                                                                            p.Active,
                                                                                            cancelPayrollStampingParams.IdentityWorkID);

            if (!overdraftsToCancel.Any())
            {
                throw new CotorraException(106, "106", "No existen recibos a cancelar con los datos proporcionados.", null);
            }

            //Get configuration company
            var payrollMiddlewareManager = new MiddlewareManager <PayrollCompanyConfiguration>(new BaseRecordManager <PayrollCompanyConfiguration>(),
                                                                                               new PayrollCompanyConfigurationValidator());
            var payrollCompanyConfiguration = await payrollMiddlewareManager.FindByExpressionAsync(p => p.InstanceID == cancelPayrollStampingParams.InstanceID,
                                                                                                   cancelPayrollStampingParams.IdentityWorkID, new string[] { "Address" });

            if (!payrollCompanyConfiguration.Any())
            {
                throw new CotorraException(106, "106", "No existe configuración de la compañia.", null);
            }

            //Get configuration company
            var fiscalInformationManager = new MiddlewareManager <EmployerFiscalInformation>(new BaseRecordManager <EmployerFiscalInformation>(),
                                                                                             new EmployerFiscalInformationValidator());
            var employerFiscalInformations = await fiscalInformationManager.FindByExpressionAsync(p =>
                                                                                                  p.InstanceID == cancelPayrollStampingParams.InstanceID,
                                                                                                  cancelPayrollStampingParams.IdentityWorkID);

            if (!employerFiscalInformations.Any())
            {
                throw new CotorraException(106, "106", "No hay certificados válidos registrados para la compañia.", null);
            }

            //Zipcode Manager
            IEnumerable <string> zipCodesToFind = payrollCompanyConfiguration.Select(p => p.Address?.ZipCode);
            var zipCodeMiddlewareManager        = new MiddlewareManager <catCFDI_CodigoPostal>(
                new BaseRecordManager <catCFDI_CodigoPostal>(),
                new catCFDI_CodigoPostalValidator());
            var zipCodes = await zipCodeMiddlewareManager.FindByExpressionAsync(p =>
                                                                                zipCodesToFind.Contains(p.c_CodigoPostal)
                                                                                , cancelPayrollStampingParams.IdentityWorkID);

            if (!zipCodes.Any())
            {
                throw new CotorraException(106, "106", "No hay codigo postal registrado para la compañia.", null);
            }

            //UUIDs to Cancel
            var uuids = overdraftsToCancel.Select(p => p.UUID).ToList();

            //3. Sign XML
            var certificateCER = employerFiscalInformations.FirstOrDefault().CertificateCER;
            var certificateKey = employerFiscalInformations.FirstOrDefault().CertificateKEY;
            var certPassword   = employerFiscalInformations.FirstOrDefault().CertificatePwd;

            //Decrypt and get certificate
            (var certificatebytesCER, var certificatebytesKEY, var certPasswordResult) = Crypto(cancelPayrollStampingParams,
                                                                                                certificateCER, certificateKey, certPassword);

            //Cancel Document Details
            var cancelDocumentParamsDetails = new List <CancelDocumentParamsDetail>();

            uuids.ForEach(p =>
            {
                var cancelDetail         = new CancelDocumentParamsDetail();
                cancelDetail.OverdraftID = overdraftsToCancel.FirstOrDefault(q => q.UUID == p).ID;
                cancelDetail.UUID        = p;
                cancelDocumentParamsDetails.Add(cancelDetail);
            });

            CancelDocumentParams cancelDocumentParams = new CancelDocumentParams()
            {
                ZipCodes       = zipCodes,
                IssuerZipCode  = payrollCompanyConfiguration.FirstOrDefault().Address?.ZipCode,
                IssuerRFC      = payrollCompanyConfiguration.FirstOrDefault().RFC,
                CertificateCER = certificatebytesCER,
                CertificateKey = certificatebytesKEY,
                Password       = certPasswordResult,
                IdentityWorkID = cancelPayrollStampingParams.IdentityWorkID,
                InstanceID     = cancelPayrollStampingParams.InstanceID,
                user           = cancelPayrollStampingParams.user,
                CancelDocumentParamsDetails = cancelDocumentParamsDetails
            };

            //cancel cfdi document
            var result = await cancelStamping.CancelDocumetAsync(cancelDocumentParams);

            if (result.WithErrors)
            {
                throw new CotorraException(107, "107", $"Error al cancelar el recibo: {result.Message}", null);
            }

            //Fill Save Cancelation Object
            var cancelationRequestXMLID  = Guid.NewGuid();
            var cancelationResponseXMLID = Guid.NewGuid();

            var cancelSPFiscalParams = new List <CancelationStoreProcedureParams>();

            result.CancelPayrollStampingResultDetails.ForEach(p => {
                var cancelationStoreProcedure         = new CancelationStoreProcedureParams();
                cancelationStoreProcedure.OverdraftID = overdraftsToCancel.FirstOrDefault(q => q.UUID == p.UUID).ID;
                cancelationStoreProcedure.CancelationFiscalDocumentStatus =
                    p.PayrollStampingResultStatus == PayrollStampingResultStatus.Success ?
                    CancelationFiscalDocumentStatus.Done : CancelationFiscalDocumentStatus.ErrorInRequest;
                cancelSPFiscalParams.Add(cancelationStoreProcedure);
            });

            //Database
            await saveCancelFiscalStamping(cancelPayrollStampingParams, cancelationRequestXMLID, cancelationResponseXMLID, cancelSPFiscalParams);

            //Save XML of cancelation  in blob (request)
            var blobStorageUtil = new BlobStorageUtil(cancelDocumentParams.InstanceID);
            await blobStorageUtil.InitializeAsync();

            await blobStorageUtil.UploadDocumentAsync($"{cancelationRequestXMLID}.xml", result.CancelacionXMLRequest);

            //Save XML of cancelation acknowledgement in blob (response)
            await blobStorageUtil.InitializeAsync();

            await blobStorageUtil.UploadDocumentAsync($"{cancelationResponseXMLID}.xml", result.CancelacionXMLAcknowledgeResponse);

            return(result);
        }
Example #8
0
 public Task <CancelPayrollStampingResult> CancelPayrollStampingAsync(CancelPayrollStampingParams cancelPayrollStampingParams)
 {
     throw new NotImplementedException();
 }