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")); }
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); }
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(); } } }
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()); } }
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)); }
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); }
public Task <CancelPayrollStampingResult> CancelPayrollStampingAsync(CancelPayrollStampingParams cancelPayrollStampingParams) { throw new NotImplementedException(); }