From a1659f014953239def8578f57d66be3877fb601d Mon Sep 17 00:00:00 2001 From: Luis Jorge Date: Tue, 24 Mar 2026 15:53:58 -0300 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20ajuste=20no=20c=C3=B3digo=20para=20?= =?UTF-8?q?suporte=20ao=20Pix=20e=20refatora=C3=A7=C3=A3o=20de=20estilos?= =?UTF-8?q?=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adicionado suporte para renderização das informações do Pix no boleto, incluindo QrCode nas instruções. - Criado novo arquivo HTML parcial para instruções do Pix (`PixInstrucoes.html`) e atualizado a lógica de renderização. - Refatoração de estilos CSS para uniformizar indentação. - Melhorias gerais na organização e legibilidade do código. Refs: master --- .../BoletoImpressao/BoletoBancario.cs | 411 +++++------------- BoletoNetCore/BoletoImpressao/BoletoNet.css | 202 ++++----- .../BoletoImpressao/BoletoNetPDF.css | 231 +++++----- BoletoNetCore/BoletoImpressao/Parts/Pix.html | 14 +- .../BoletoImpressao/Parts/PixInstrucoes.html | 1 + .../Parts/ReciboBeneficiarioParte11.html | 4 +- .../Parts/ReciboBeneficiarioParte6.html | 13 +- 7 files changed, 352 insertions(+), 524 deletions(-) create mode 100644 BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html diff --git a/BoletoNetCore/BoletoImpressao/BoletoBancario.cs b/BoletoNetCore/BoletoImpressao/BoletoBancario.cs index d8808df8..829f6621 100644 --- a/BoletoNetCore/BoletoImpressao/BoletoBancario.cs +++ b/BoletoNetCore/BoletoImpressao/BoletoBancario.cs @@ -16,13 +16,15 @@ namespace BoletoNetCore [Serializable()] public class BoletoBancario { - String _vLocalLogoBeneficiario = String.Empty; - #region Variaveis - private string _instrucoesHtml = string.Empty; - private bool _mostrarCodigoCarteira = false; - private bool _formatoCarne = false; + string _vLocalLogoBeneficiario = string.Empty; + + private readonly CultureInfo _culture = CultureInfo.GetCultureInfo("pt-BR"); + + private bool _formatoCarne; + private bool _mostrarCodigoCarteira; + #endregion Variaveis #region Propriedades @@ -32,8 +34,8 @@ public class BoletoBancario /// public bool MostrarCodigoCarteira { - get { return _mostrarCodigoCarteira; } - set { _mostrarCodigoCarteira = value; } + get => _mostrarCodigoCarteira; + set => _mostrarCodigoCarteira = value; } public bool ExibirDemonstrativo { get; set; } @@ -43,8 +45,8 @@ public bool MostrarCodigoCarteira /// public bool FormatoCarne { - get { return _formatoCarne; } - set { _formatoCarne = value; } + get => _formatoCarne; + set => _formatoCarne = value; } public Boleto Boleto { get; set; } @@ -52,6 +54,7 @@ public bool FormatoCarne public IBanco Banco { get; set; } #region Propriedades + public bool MostrarComprovanteEntregaLivre { get; set; } public bool MostrarComprovanteEntrega { get; set; } @@ -63,17 +66,17 @@ public bool FormatoCarne public bool OcultarReciboPagador { get; set; } public bool GerarArquivoRemessa { get; set; } + /// /// Mostra o termo "Contra Apresentação" na data de vencimento do boleto /// public bool MostrarContraApresentacaoNaDataVencimento { get; set; } public bool MostrarEnderecoBeneficiario { get; set; } - #endregion Propriedades #endregion Propriedades - + #endregion Propriedades #region Override @@ -100,18 +103,10 @@ private string GetCodBarraCode(string code) return Convert.ToBase64String(new BarCode2of5i(code, 1, 50, code.Length).ToByte()); } - protected string Render() - { - var urlImagemLogo = "data:image/jpg;base64," + GetResourceImage("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); - var urlImagemBarra = "data:image/jpg;base64," + GetResourceImage("BoletoNetCore.Imagens.barra.gif"); - - //Atribui os valores ao html do boleto bancário - return MontaHtml(urlImagemLogo, urlImagemBarra, "\"Código"); - } - #endregion Override #region Html + public string GeraHtmlInstrucoes() { try @@ -137,13 +132,19 @@ public string GeraHtmlInstrucoes() private string GeraHtmlPix(string pixStr, int tamanhoImagem = 200) { - var html = new StringBuilder(); - - html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.Pix.html")); - - return html.ToString() + var html = GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.Pix.html") .Replace("@PIXSTRING", pixStr) .Replace("@PIXIMAGEMTAMANHO", tamanhoImagem.ToString()); + + return html; + } + + private string GeraHtmlPixInstrucoes(string pixStr) + { + var html = GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.PixInstrucoes.html") + .Replace("@PIXINSTRUCOESSTRING", pixStr); + + return html; } private string GeraHtmlCarne(string telefone, string htmlBoleto) @@ -170,6 +171,7 @@ public string GeraHtmlReciboPagador() { html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte10.html")); } + html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte4.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte5.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte6.html")); @@ -221,14 +223,16 @@ public string HtmlComprovanteEntrega html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega5.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega6.html")); - html.Append(MostrarComprovanteEntregaLivre ? GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega71.html") : GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega7.html")); + html.Append(MostrarComprovanteEntregaLivre + ? GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega71.html") + : GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega7.html")); html.Append("
"); return html.ToString(); } } - private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string imagemCodigoBarras, string pixStr = null, int pixTamanhoImagem = 200) + private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string imagemCodigoBarras, string pixStr = null, int pixTamanhoImagem = 200, bool pixInstrucoes = false) { var html = new StringBuilder(); var enderecoBeneficiario = ""; @@ -247,7 +251,6 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima { html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboBeneficiarioRelatorioValores.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboBeneficiarioParte5.html")); - html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.CabecalhoTabelaDemonstrativo.html")); var grupoDemonstrativo = new StringBuilder(); @@ -273,13 +276,11 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima grupoDemonstrativo = grupoDemonstrativo.Replace("@DESCRICAOITEM", item.Descricao); grupoDemonstrativo = grupoDemonstrativo.Replace("@REFERENCIAITEM", item.Referencia); - grupoDemonstrativo = grupoDemonstrativo.Replace("@VALORITEM", item.Valor.ToString("C", CultureInfo.GetCultureInfo("pt-BR"))); + grupoDemonstrativo = grupoDemonstrativo.Replace("@VALORITEM", item.Valor.ToString("C", _culture)); } grupoDemonstrativo.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.TotalDemonstrativo.html")); - grupoDemonstrativo = grupoDemonstrativo.Replace( - "@VALORTOTALGRUPO", - relatorio.Itens.Sum(c => c.Valor).ToString("C", CultureInfo.GetCultureInfo("pt-BR"))); + grupoDemonstrativo = grupoDemonstrativo.Replace("@VALORTOTALGRUPO", relatorio.Itens.Sum(c => c.Valor).ToString("C", _culture)); } html = html.Replace("@ITENSDEMONSTRATIVO", grupoDemonstrativo.ToString()); @@ -308,14 +309,14 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima throw new ArgumentNullException("Endereço do Beneficiário"); enderecoBeneficiario = string.Format("{0} - {1} - {2}/{3} - CEP: {4}", - Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(0), - Boleto.Banco.Beneficiario.Endereco.Bairro, - Boleto.Banco.Beneficiario.Endereco.Cidade, - Boleto.Banco.Beneficiario.Endereco.UF, - Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); + Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(0), + Boleto.Banco.Beneficiario.Endereco.Bairro, + Boleto.Banco.Beneficiario.Endereco.Cidade, + Boleto.Banco.Beneficiario.Endereco.UF, + Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); enderecoBeneficiarioCompacto = string.Format("{0} - CEP: {1}", - Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(25), - Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); + Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(25), + Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); } } } @@ -331,15 +332,16 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima pagador += string.Format(" - CNPJ: " + Utils.FormataCNPJ(Boleto.Pagador.CPFCNPJ)); break; } + if (Boleto.Pagador.Observacoes != string.Empty) pagador += " - " + Boleto.Pagador.Observacoes; var enderecoPagador = string.Empty; if (!OcultarEnderecoPagador) { - enderecoPagador = Boleto.Pagador.Endereco.FormataLogradouro(0) + "
" + string.Format("{0} - {1}/{2}", Boleto.Pagador.Endereco.Bairro, Boleto.Pagador.Endereco.Cidade, Boleto.Pagador.Endereco.UF); + enderecoPagador = Boleto.Pagador.Endereco.FormataLogradouro(0) + "
" + $"{Boleto.Pagador.Endereco.Bairro} - {Boleto.Pagador.Endereco.Cidade}/{Boleto.Pagador.Endereco.UF}"; if (Boleto.Pagador.Endereco.CEP != String.Empty) - enderecoPagador += string.Format(" - CEP: {0}", Utils.FormataCEP(Boleto.Pagador.Endereco.CEP)); + enderecoPagador += $" - CEP: {Utils.FormataCEP(Boleto.Pagador.Endereco.CEP)}"; } // Dados do Avalista @@ -356,6 +358,7 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima avalista += string.Format(" - CNPJ: " + Utils.FormataCNPJ(Boleto.Avalista.CPFCNPJ)); break; } + if (Boleto.Avalista.Observacoes != string.Empty) avalista += " - " + Boleto.Avalista.Observacoes; } @@ -373,12 +376,15 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima if (MostrarContraApresentacaoNaDataVencimento) dataVencimento = "Contra Apresentação"; - if (String.IsNullOrWhiteSpace(_vLocalLogoBeneficiario)) + if (string.IsNullOrWhiteSpace(_vLocalLogoBeneficiario)) _vLocalLogoBeneficiario = urlImagemLogo; + html.Replace("@PIXINSTRUCOES", + pixInstrucoes && !string.IsNullOrWhiteSpace(pixStr) ? GeraHtmlPixInstrucoes(pixStr) : string.Empty); + return html .Replace("@CODIGOBANCO", Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3)) - .Replace("@DIGITOBANCO", Boleto.Banco.Digito.ToString()) + .Replace("@DIGITOBANCO", Boleto.Banco.Digito) .Replace("@URLIMAGEMLOGO", urlImagemLogo) .Replace("@URLIMGBENEFICIARIO", _vLocalLogoBeneficiario) .Replace("@URLIMAGEMBARRA", urlImagemBarra) @@ -387,8 +393,8 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima .Replace("@MENSAGEMFIXATOPOBOLETO", Boleto.Banco.Beneficiario.ContaBancaria.MensagemFixaTopoBoleto) .Replace("@MENSAGEMFIXAPAGADOR", Boleto.Banco.Beneficiario.ContaBancaria.MensagemFixaPagador) .Replace("@DATAVENCIMENTO", dataVencimento) - .Replace("@BENEFICIARIO_BOLETO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : string.Format("{0} - {1}", Boleto.Banco.Beneficiario.Nome, Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ))) - .Replace("@BENEFICIARIO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : string.Format("{0} - {1}", Boleto.Banco.Beneficiario.Nome, Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ))) + .Replace("@BENEFICIARIO_BOLETO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : $"{Boleto.Banco.Beneficiario.Nome} - {Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ)}") + .Replace("@BENEFICIARIO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : $"{Boleto.Banco.Beneficiario.Nome} - {Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ)}") .Replace("@DATADOCUMENTO", Boleto.DataEmissao.ToString("dd/MM/yyyy")) .Replace("@NUMERODOCUMENTO", Boleto.NumeroDocumento) .Replace("@ESPECIEDOCUMENTO", Boleto.EspecieDocumento.ToString()) @@ -396,14 +402,14 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima .Replace("@NOSSONUMERO", Boleto.NossoNumeroFormatado) .Replace("@CARTEIRA", Boleto.CarteiraImpressaoBoleto) .Replace("@ESPECIE", Boleto.EspecieMoeda) - .Replace("@QUANTIDADE", (Boleto.QuantidadeMoeda == 0 ? "" : Boleto.QuantidadeMoeda.ToString())) + .Replace("@QUANTIDADE", Boleto.QuantidadeMoeda == 0 ? "" : Boleto.QuantidadeMoeda.ToString()) .Replace("@VALORDOCUMENTO", Boleto.ValorMoeda) - .Replace("@=VALORDOCUMENTO", (Boleto.ValorTitulo == 0 ? "" : Boleto.ValorTitulo.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@DESCONTOS", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorDesconto == 0 ? "" : Boleto.ValorDesconto.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@OUTRASDEDUCOES", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorAbatimento == 0 ? "" : Boleto.ValorAbatimento.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@MORAMULTA", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorMulta == 0 ? "" : Boleto.ValorMulta.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@OUTROSACRESCIMOS", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorOutrasDespesas == 0 ? "" : Boleto.ValorOutrasDespesas.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@VALORCOBRADO", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorPago == 0 ? "" : Boleto.ValorPago.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) + .Replace("@=VALORDOCUMENTO", Boleto.ValorTitulo == 0 ? "" : Boleto.ValorTitulo.ToString("C", _culture)) + .Replace("@DESCONTOS", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorDesconto == 0 ? "" : Boleto.ValorDesconto.ToString("C", _culture)) + .Replace("@OUTRASDEDUCOES", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorAbatimento == 0 ? "" : Boleto.ValorAbatimento.ToString("C", _culture)) + .Replace("@MORAMULTA", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorMulta == 0 ? "" : Boleto.ValorMulta.ToString("C", _culture)) + .Replace("@OUTROSACRESCIMOS", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorOutrasDespesas == 0 ? "" : Boleto.ValorOutrasDespesas.ToString("C", _culture)) + .Replace("@VALORCOBRADO", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorPago == 0 ? "" : Boleto.ValorPago.ToString("C", _culture)) .Replace("@AGENCIACONTA", Boleto.Banco.Beneficiario.CodigoFormatado) .Replace("@PAGADOR", pagador) .Replace("@ENDERECOPAGADOR", enderecoPagador) @@ -414,7 +420,7 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima .Replace("@USODOBANCO", Boleto.UsoBanco) .Replace("@IMAGEMCODIGOBARRA", imagemCodigoBarras) .Replace("@ACEITE", Boleto.Aceite).ToString() - .Replace("@ENDERECOBENEFICIARIO_BOLETO", MostrarEnderecoBeneficiario ? string.Format(" - {0}", enderecoBeneficiarioCompacto) : "") + .Replace("@ENDERECOBENEFICIARIO_BOLETO", MostrarEnderecoBeneficiario ? $" - {enderecoBeneficiarioCompacto}" : "") .Replace("@ENDERECOBENEFICIARIO", MostrarEnderecoBeneficiario ? enderecoBeneficiario : "") .Replace("@INSTRUCOES", Boleto.MensagemInstrucoesCaixaFormatado.Replace(Environment.NewLine, "
")) .Replace("@PARCELAS", Boleto.ParcelaInformativo != string.Empty ? ("Parcela: " + Boleto.ParcelaInformativo) : ""); @@ -427,32 +433,34 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima /// /// Função utilizada para gerar o html do boleto sem que o mesmo esteja dentro de uma página Web. /// + /// O texto a ser incluído no início do e-mail. /// Local apontado pela imagem de logo. /// Local apontado pela imagem de barra. /// Local apontado pela imagem do código de barras. + /// Indica se os estilos CSS para renderização em PDF devem ser aplicados. + /// A string de pagamento PIX a ser incluída no HTML, se aplicável. + /// O tamanho da imagem PIX em pixels. + /// Indica se o QrCode de pagamento PIX deve ser incluído nas instruções. /// StringBuilder conténdo o código html do boleto bancário. - protected StringBuilder HtmlOffLine(string textoNoComecoDoEmail, string srcLogo, string srcBarra, string srcCodigoBarra, bool usaCsspdf = false, string pixStr = null, int pixTamanhoImagem = 200) - {//protected StringBuilder HtmlOffLine(string srcCorte, string srcLogo, string srcBarra, string srcPonto, string srcBarraInterna, string srcCodigoBarra) - //OnLoad(EventArgs.Empty); - + protected StringBuilder HtmlOffLine(string textoNoComecoDoEmail, string srcLogo, string srcBarra, string srcCodigoBarra, bool usaCsspdf = false, string pixStr = null, int pixTamanhoImagem = 200, bool pixInstrucoes = false) + { var html = new StringBuilder(); HtmlOfflineHeader(html, usaCsspdf); if (!string.IsNullOrEmpty(textoNoComecoDoEmail)) { html.Append(textoNoComecoDoEmail); } - html.Append(MontaHtml(srcLogo, srcBarra, "\"Código", pixStr, pixTamanhoImagem)); + + html.Append(MontaHtml(srcLogo, srcBarra, srcCodigoBarra, pixStr, pixTamanhoImagem, pixInstrucoes)); HtmlOfflineFooter(html); return html; } - - - /// /// Monta o Header de um email com pelo menos um boleto dentro. /// - /// StringBuilder onde o conteudo sera salvo. + /// StringBuilder usado para construir o conteúdo HTML. + /// Indica se os estilos CSS para renderização em PDF devem ser aplicados. protected static void HtmlOfflineHeader(StringBuilder html, bool usaCsspdf = false) { html.Append("\n"); @@ -463,6 +471,7 @@ protected static void HtmlOfflineHeader(StringBuilder html, bool usaCsspdf = fal html.Append(" Boleto.Net\n"); #region Css + { var arquivoCss = usaCsspdf ? "BoletoNetCore.BoletoImpressao.BoletoNetPDF.css" : "BoletoNetCore.BoletoImpressao.BoletoNet.css"; var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(arquivoCss); @@ -473,16 +482,15 @@ protected static void HtmlOfflineHeader(StringBuilder html, bool usaCsspdf = fal html.Append(sr.ReadToEnd()); html.Append("\n"); sr.Close(); - sr.Dispose(); } } + #endregion Css html.Append(" \n"); html.Append("\n"); } - /// /// Monta o Footer de um email com pelo menos um boleto dentro. /// @@ -493,7 +501,6 @@ protected static void HtmlOfflineFooter(StringBuilder saida) saida.Append("\n"); } - /// /// Junta varios boletos em uma unica AlternateView, para todos serem mandados juntos no mesmo email /// @@ -516,22 +523,22 @@ public static AlternateView GeraHtmlDeVariosBoletosParaEmail(string textoNoComec var linkedResources = new List(); HtmlOfflineHeader(corpoDoEmail); - if (textoNoComecoDoEmail != null && textoNoComecoDoEmail != "") + if (!string.IsNullOrEmpty(textoNoComecoDoEmail)) { corpoDoEmail.Append(textoNoComecoDoEmail); } + foreach (var umBoleto in arrayDeBoletos) { if (umBoleto != null) { - LinkedResource lrImagemLogo; - LinkedResource lrImagemBarra; - LinkedResource lrImagemCodigoBarra; - umBoleto.GeraGraficosParaEmailOffLine(out lrImagemLogo, out lrImagemBarra, out lrImagemCodigoBarra); + umBoleto.GeraGraficosParaEmailOffLine(out LinkedResource lrImagemLogo, + out LinkedResource lrImagemBarra, + out LinkedResource lrImagemCodigoBarra); var theOutput = umBoleto.MontaHtml( - "cid:" + lrImagemLogo.ContentId, - "cid:" + lrImagemBarra.ContentId, - "\"Código"); + $"cid:{lrImagemLogo.ContentId}", + $"cid:{lrImagemBarra.ContentId}", + $"cid:{lrImagemCodigoBarra.ContentId}"); corpoDoEmail.Append(theOutput); @@ -540,9 +547,8 @@ public static AlternateView GeraHtmlDeVariosBoletosParaEmail(string textoNoComec linkedResources.Add(lrImagemCodigoBarra); } } - HtmlOfflineFooter(corpoDoEmail); - + HtmlOfflineFooter(corpoDoEmail); var av = AlternateView.CreateAlternateViewFromString(corpoDoEmail.ToString(), Encoding.Default, "text/html"); foreach (var theResource in linkedResources) @@ -550,12 +556,9 @@ public static AlternateView GeraHtmlDeVariosBoletosParaEmail(string textoNoComec av.LinkedResources.Add(theResource); } - - return av; } - /// /// Função utilizada gerar o AlternateView necessário para enviar um boleto bancário por e-mail. /// @@ -565,7 +568,6 @@ public AlternateView HtmlBoletoParaEnvioEmail() return HtmlBoletoParaEnvioEmail(null); } - /// /// Função utilizada gerar o AlternateView necessário para enviar um boleto bancário por e-mail. /// @@ -573,12 +575,8 @@ public AlternateView HtmlBoletoParaEnvioEmail() /// AlternateView com os dados do boleto. public AlternateView HtmlBoletoParaEnvioEmail(string textoNoComecoDoEmail) { - LinkedResource lrImagemLogo; - LinkedResource lrImagemBarra; - LinkedResource lrImagemCodigoBarra; - - GeraGraficosParaEmailOffLine(out lrImagemLogo, out lrImagemBarra, out lrImagemCodigoBarra); - var html = HtmlOffLine(textoNoComecoDoEmail, "cid:" + lrImagemLogo.ContentId, "cid:" + lrImagemBarra.ContentId, "cid:" + lrImagemCodigoBarra.ContentId); + GeraGraficosParaEmailOffLine(out LinkedResource lrImagemLogo, out LinkedResource lrImagemBarra, out LinkedResource lrImagemCodigoBarra); + var html = HtmlOffLine(textoNoComecoDoEmail, $"cid:{lrImagemLogo.ContentId}", $"cid:{lrImagemBarra.ContentId}", $"cid:{lrImagemCodigoBarra.ContentId}"); var av = AlternateView.CreateAlternateViewFromString(html.ToString(), Encoding.Default, "text/html"); @@ -596,263 +594,71 @@ public AlternateView HtmlBoletoParaEnvioEmail(string textoNoComecoDoEmail) /// O Código de Barras void GeraGraficosParaEmailOffLine(out LinkedResource lrImagemLogo, out LinkedResource lrImagemBarra, out LinkedResource lrImagemCodigoBarra) { - //OnLoad(EventArgs.Empty); - var randomSufix = new Random().Next().ToString(); // para podermos colocar no mesmo email varios boletos diferentes - var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); + var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"BoletoNetCore.Imagens.{Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3)}.jpg"); lrImagemLogo = new LinkedResource(stream, MediaTypeNames.Image.Jpeg) { - ContentId = "logo" + randomSufix + ContentId = $"logo{randomSufix}" }; var assembly = Assembly.GetExecutingAssembly(); var ms = assembly.GetManifestResourceStream("BoletoNetCore.Imagens.barra.jpg"); lrImagemBarra = new LinkedResource(ms, MediaTypeNames.Image.Jpeg) { - ContentId = "barra" + randomSufix + ContentId = $"barra{randomSufix}" }; - var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); + var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, + Boleto.CodigoBarra.CodigoDeBarras.Length); ms = new MemoryStream(Utils.ConvertImageToByte(cb.ToBitmap())); lrImagemCodigoBarra = new LinkedResource(ms, MediaTypeNames.Image.Gif) { - ContentId = "codigobarra" + randomSufix + ContentId = $"codigobarra{randomSufix}" }; - } - - /// - /// Função utilizada para gravar em um arquivo local o conteúdo do boleto. Este arquivo pode ser aberto em um browser sem que o site esteja no ar. - /// - /// Path do arquivo que deve conter o código html. - //public void MontaHtmlNoArquivoLocal(string fileName) - //{ - // using (var f = new FileStream(fileName, FileMode.Create)) - // { - // var w = new StreamWriter(f, Encoding.Default); - // w.Write(MontaHtml()); - // w.Close(); - // f.Close(); - // } - //} - - /// - /// Monta o Html do boleto bancário - /// - /// string - //public string MontaHtml() - //{ - // return MontaHtml(null, null); - //} - - - /// - /// Monta o Html do boleto bancário - /// - /// Caminho do arquivo - /// Caminho do logo do beneficiario - /// Html do boleto gerado - //public string MontaHtml(string fileName, string logoBeneficiario) - //{ - // if (fileName == null) - // fileName = Path.GetTempPath(); - - // if (logoBeneficiario != null) - // _vLocalLogoBeneficiario = logoBeneficiario; - - // //OnLoad(EventArgs.Empty); - - // var fnLogo = fileName + @"BoletoNet" + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"; - - // if (!File.Exists(fnLogo)) - // { - // var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); - // using (Stream file = File.Create(fnLogo)) - // { - // CopiarStream(stream, file); - // } - // } - - // var fnBarra = fileName + @"BoletoNetBarra.gif"; - // if (!File.Exists(fnBarra)) - // { - // var imgConverter = new ImageConverter(); - // var imgBuffer = (byte[])imgConverter.ConvertTo(Html.barra, typeof(byte[])); - // var ms = new MemoryStream(imgBuffer); - - // using (Stream stream = File.Create(fnBarra)) - // { - // CopiarStream(ms, stream); - // ms.Flush(); - // ms.Dispose(); - // } - // } - - // var fnCodigoBarras = Path.GetTempFileName(); - // var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); - // cb.ToBitmap().Save(fnCodigoBarras); - - // //return HtmlOffLine(fnCorte, fnLogo, fnBarra, fnPonto, fnBarraInterna, fnCodigoBarras).ToString(); - // return HtmlOffLine(null, fnLogo, fnBarra, fnCodigoBarras).ToString(); - //} - - /// - /// Monta o Html do boleto bancário para View ASP.Net MVC - /// - /// Exemplo: - /// public ActionResult VisualizarBoleto(string Id) - /// { - /// BoletoBancario bb = new BoletoBancario(); - /// //... - /// ViewBag.Boleto = bb.MontaHtml("/Content/Boletos/", "teste1"); - /// return View(); - /// } - /// //Na view - /// @{Layout = null;}@Html.Raw(ViewBag.Boleto) - /// - /// - /// Pasta dos boletos. Exemplo MontaHtml("/Content/Boletos/", "000100") - /// Nome do arquivo para o boleto - /// Html do boleto gerado - /// Sandro Ribeiro - /// 16/11/2012 - //public string MontaHtml(string url, string fileName, bool useMapPathSecure = true) - //{ - // //Variável para o caminho físico do servidor - // var pathServer = ""; - - // //Verifica se o usuário informou uma url válida - // if (url == null) - // { - // //Obriga o usuário a especificar uma url válida - // throw new ArgumentException("Você precisa informar uma pasta padrão."); - // } - // else - // { - // if (useMapPathSecure) - // { - // //Verifica se o usuário usou barras no início e no final da url - // if (url.Substring(url.Length - 1, 1) != "/") - // url = url + "/"; - // if (url.Substring(0, 1) != "/") - // url = url + "/"; - // //Mapeia o caminho físico dos arquivos - // pathServer = MapPathSecure(string.Format("~{0}", url)); - // } - - // //Verifica se o caminho existe - // if (!Directory.Exists(pathServer)) - // throw new ArgumentException("A o caminho físico '{0}' não existe.", pathServer); - // } - // //Verifica o nome do arquivo - // if (fileName == null) - // { - // fileName = DateTime.Now.Ticks.ToString(); - // } - // else - // { - // if (fileName == "") - // fileName = DateTime.Now.Ticks.ToString(); - // } - - // //Mantive o padrão - // //OnLoad(EventArgs.Empty); - - // //Prepara o arquivo da logo para ser salvo - // var fnLogo = pathServer + @"BoletoNet" + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"; - // //Prepara o arquivo da logo para ser usado no html - // var fnLogoUrl = url + @"BoletoNet" + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"; - - // //Salvo a imagem apenas 1 vez com o código do banco - // if (!File.Exists(fnLogo)) - // { - // var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); - // using (Stream file = File.Create(fnLogo)) - // { - // CopiarStream(stream, file); - // } - // } - - // //Prepara o arquivo da barra para ser salvo - // var fnBarra = pathServer + @"BoletoNetBarra.gif"; - // //Prepara o arquivo da barra para ser usado no html - // var fnBarraUrl = url + @"BoletoNetBarra.gif"; - - // //Salvo a imagem apenas 1 vez - // if (!File.Exists(fnBarra)) - // { - // var imgConverter = new ImageConverter(); - // var imgBuffer = (byte[])imgConverter.ConvertTo(Html.barra, typeof(byte[])); - // var ms = new MemoryStream(imgBuffer); - - // using (Stream stream = File.Create(fnBarra)) - // { - // CopiarStream(ms, stream); - // ms.Flush(); - // ms.Dispose(); - // } - // } - - // //Prepara o arquivo do código de barras para ser salvo - // var fnCodigoBarras = string.Format("{0}{1}_codigoBarras.jpg", pathServer, fileName); - // //Prepara o arquivo do código de barras para ser usado no html - // var fnCodigoBarrasUrl = string.Format("{0}{1}_codigoBarras.jpg", url, fileName); - - // var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); - - // //Salva o arquivo conforme o fileName - // cb.ToBitmap().Save(fnCodigoBarras); - - // //Retorna o Html para ser usado na view - // return HtmlOffLine(null, fnLogoUrl, fnBarraUrl, fnCodigoBarrasUrl).ToString(); - //} - /// /// Monta o Html do boleto bancário com as imagens embutidas no conteúdo, sem necessidade de links externos /// de acordo com o padrão http://en.wikipedia.org/wiki/Data_URI_scheme /// - /// Alterado por Olavo Rocha @ Exodus para utilizar arquivos dentro da própria DLL para .net core 2.2 + /// Alterado por Olavo Rocha @ Exodus para utilizar arquivos dentro da própria DLL para .net core 2.2 /// - /// Converte a Linha Digitável para imagem, com o objetivo de evitar malwares. - /// Url/Imagem Base64 da Logo do Beneficiário - /// Html do boleto gerado - /// Iuri André Stona, Olavo Rocha Neto - /// 23/01/2014 - /// 07/07/2019 - public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool usaCsspdf = false, string urlImagemLogoBeneficiario = null, string pixString = null, int pixTamanhoImagem = 200) + /// Indica se a linha de cobrança deve ser convertida em uma imagem para evitar exploração por malware. + /// Determina se os estilos CSS específicos para renderização em formato PDF devem ser aplicados. + /// Especifica a URL ou a imagem codificada em Base64 do logotipo do beneficiário a ser exibida no comprovante bancário. + /// A string de pagamento PIX a ser incorporada no HTML, se aplicável. + /// O tamanho da imagem do código QR PIX, em pixels. + /// Indica se o QrCode de pagamento PIX deve ser incluído nas instruções. + /// Uma string representando o HTML gerado para o comprovante bancário. + public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool usaCsspdf = false, string urlImagemLogoBeneficiario = null, string pixString = null, int pixTamanhoImagem = 200, bool pixInstrucoes = false) { - //OnLoad(EventArgs.Empty); - var assembly = Assembly.GetExecutingAssembly(); - var imageLogo = "BoletoNetCore.Imagens." + Boleto.Banco.Codigo.ToString("000") + ".jpg"; + var imageLogo = $"BoletoNetCore.Imagens.{Boleto.Banco.Codigo:000}.jpg"; var streamLogo = assembly.GetManifestResourceStream(imageLogo); var base64Logo = Convert.ToBase64String(new BinaryReader(streamLogo).ReadBytes((int)streamLogo.Length)); - var fnLogo = string.Format("data:image/jpg;base64,{0}", base64Logo); + var fnLogo = $"data:image/jpg;base64,{base64Logo}"; var streamBarra = assembly.GetManifestResourceStream("BoletoNetCore.Imagens.barra.jpg"); var base64Barra = Convert.ToBase64String(new BinaryReader(streamBarra).ReadBytes((int)streamBarra.Length)); - var fnBarra = string.Format("data:image/jpg;base64,{0}", base64Barra); + var fnBarra = $"data:image/jpg;base64,{base64Barra}"; var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); var base64CodigoBarras = Convert.ToBase64String(cb.ToByte()); - var fnCodigoBarras = string.Format("data:image/gif;base64,{0}", base64CodigoBarras); + var fnCodigoBarras = $"data:image/gif;base64,{base64CodigoBarras}"; if (convertLinhaDigitavelToImage) { - var linhaDigitavel = Boleto.CodigoBarra.LinhaDigitavel.Replace(" ", " ").Trim(); - var font = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright); + var font = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, + SKFontStyleSlant.Upright); var imagemLinha = Utils.DrawText(linhaDigitavel, 40, font, SKColors.Black, SKColors.White); var base64Linha = Convert.ToBase64String(Utils.ConvertImageToByte(imagemLinha)); - var fnLinha = string.Format("data:image/gif;base64,{0}", base64Linha); - - Boleto.CodigoBarra.LinhaDigitavel = @""; + Boleto.CodigoBarra.LinhaDigitavel = $@""; } if (!string.IsNullOrEmpty(urlImagemLogoBeneficiario)) @@ -860,7 +666,7 @@ public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool _vLocalLogoBeneficiario = urlImagemLogoBeneficiario; } - var s = HtmlOffLine(null, fnLogo, fnBarra, fnCodigoBarras, usaCsspdf, pixString, pixTamanhoImagem).ToString(); + var s = HtmlOffLine(null, fnLogo, fnBarra, fnCodigoBarras, usaCsspdf, pixString, pixTamanhoImagem, pixInstrucoes).ToString(); if (convertLinhaDigitavelToImage) { @@ -870,7 +676,6 @@ public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool return s; } - #endregion Geração do Html OffLine public SKBitmap GeraImagemCodigoBarras(Boleto boleto) @@ -881,7 +686,7 @@ public SKBitmap GeraImagemCodigoBarras(Boleto boleto) private void CopiarStream(Stream entrada, Stream saida) { - var bytesLidos = 0; + int bytesLidos; var imgBuffer = new byte[entrada.Length]; while ((bytesLidos = entrada.Read(imgBuffer, 0, imgBuffer.Length)) > 0) @@ -890,4 +695,4 @@ private void CopiarStream(Stream entrada, Stream saida) } } } -} +} \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/BoletoNet.css b/BoletoNetCore/BoletoImpressao/BoletoNet.css index 56b66d28..b241ce6e 100644 --- a/BoletoNetCore/BoletoImpressao/BoletoNet.css +++ b/BoletoNetCore/BoletoImpressao/BoletoNet.css @@ -1,13 +1,13 @@ body { - color: #000000; - background-color: #ffffff; - margin-top: 0; - margin-right: 0; + color: #000000; + background-color: #ffffff; + margin-top: 0; + margin-right: 0; } * { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } table { @@ -17,7 +17,7 @@ table { } img { - border: 0; + border: 0; } .cp { @@ -26,16 +26,16 @@ img { } .ti { - font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; + font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; } .ld { - font: bold 15px Arial, "Liberation Sans", sans-serif; - color: #000000; + font: bold 15px Arial, "Liberation Sans", sans-serif; + color: #000000; } .w150:empty { - display: none; + display: none; } .ct { @@ -59,29 +59,29 @@ img { } .cut { - width: 665px; - height: 1px; - border-top: dashed 1px #000; + width: 665px; + height: 1px; + border-top: dashed 1px #000; } .Ac { - text-align: center; + text-align: center; } .Ar { - text-align: right; + text-align: right; } .Al { - text-align: left; + text-align: left; } .At { - vertical-align: top; + vertical-align: top; } .Ab { - vertical-align: bottom; + vertical-align: bottom; } .ct td, .cp td { @@ -102,59 +102,59 @@ img { } .pL0 { - padding-left: 0px; + padding-left: 0px; } .pL6 { - padding-left: 6px; + padding-left: 6px; } .pL10 { - padding-left: 10px; + padding-left: 10px; } .imgLogo { - width: 150px; + width: 150px; } - .imgLogo img { - width: 150px; - height: 40px; - } +.imgLogo img { + width: 150px; + height: 40px; +} .barra { - width: 3px; - height: 22px; - vertical-align: bottom; + width: 3px; + height: 22px; + vertical-align: bottom; } - .barra img { - width: 2px; - height: 22px; - } +.barra img { + width: 2px; + height: 22px; +} .rBb td { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BB { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BL { - border-left: solid 1px #000; + border-left: solid 1px #000; } .BR { - border-right: solid 1px #000; + border-right: solid 1px #000; } .BT1 { - border-top: dashed 1px #000; + border-top: dashed 1px #000; } .BT2 { - border-top: solid 2px #000; + border-top: solid 2px #000; } .bgcGray { @@ -162,83 +162,83 @@ img { } .h1 { - height: 1px; + height: 1px; } .h13 { - height: 13px; + height: 13px; } .h12 { - height: 12px; + height: 12px; } .h13 td { - vertical-align: top; + vertical-align: top; } .h12 td { - vertical-align: top; + vertical-align: top; } .w6 { - width: 6px; + width: 6px; } .w7 { - width: 7px; + width: 7px; } .w34 { - width: 34px; + width: 34px; } .w40 { - width: 40px; + width: 40px; } .w45 { - width: 45px; + width: 45px; } .w53 { - width: 53px; + width: 53px; } .w62 { - width: 62px; + width: 62px; } .w65 { - width: 65px; + width: 65px; } .w72 { - width: 72px; + width: 72px; } .w83 { - width: 83px; + width: 83px; } .w88 { - width: 88px; + width: 88px; } .w104 { - width: 104px; + width: 104px; } .w105 { - width: 105px; + width: 105px; } .w106 { - width: 106px; + width: 106px; } .w112 { - width: 112px; + width: 112px; } .w113 { @@ -246,59 +246,63 @@ img { } .w123 { - width: 123px; + width: 123px; } .w126 { - width: 126px; + width: 126px; } .w128 { - width: 128px; + width: 128px; } .w132 { - width: 132px; + width: 132px; } .w134 { - width: 134px; + width: 134px; } .w150 { - width: 150px; + width: 150px; } .w163 { - width: 163px; + width: 163px; } .w164 { - width: 164px; + width: 164px; } .w180 { - width: 180px; + width: 180px; } .w182 { - width: 182px; + width: 182px; } .w186 { - width: 186px; + width: 186px; } .w192 { - width: 192px; + width: 192px; } .w250 { - width: 250px; + width: 250px; +} + +.w286 { + width: 286px; } .w298 { - width: 298px; + width: 298px; } .w409 { @@ -310,49 +314,49 @@ img { } .w472 { - width: 472px; + width: 472px; } .w478 { - width: 478px; + width: 478px; } .w500 { - width: 500px; + width: 500px; } .w544 { - width: 544px; + width: 544px; } .w564 { - width: 564px; + width: 564px; } .w659 { - width: 659px; + width: 659px; } .w666 { - width: 100%; + width: 100%; } .w667 { - width: 667px; + width: 667px; } .w900 { - width: 900px; + width: 900px; } .BHead td { - border-bottom: solid 2px #000; + border-bottom: solid 2px #000; } .EcdBar { - height: 50px; - vertical-align: bottom; + height: 50px; + vertical-align: bottom; } .rc6 td { @@ -363,32 +367,32 @@ img { } .rc6 div { - padding-left: 6px; + padding-left: 6px; } .rc6 .t { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; - height: 13px; + font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; + color: #000033; + height: 13px; } .rc6 .c { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; - height: 12px; + font: bold 10px Arial, "Liberation Sans", sans-serif; + color: black; + height: 12px; } .mt23 { - margin-top: 23px; + margin-top: 23px; } .pb4 { - padding-bottom: 14px; + padding-bottom: 14px; } .ebc { - width: 4px; - height: 440px; - border-right: dotted 1px #000000; - margin-right: 4px; + width: 4px; + height: 440px; + border-right: dotted 1px #000000; + margin-right: 4px; } diff --git a/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css b/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css index ce8f76a9..70428075 100644 --- a/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css +++ b/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css @@ -1,13 +1,13 @@ body { - color: #000000; - background-color: #ffffff; - margin-top: 0; - margin-right: 0; + color: #000000; + background-color: #ffffff; + margin-top: 0; + margin-right: 0; } * { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } table { @@ -17,66 +17,66 @@ table { } img { - border: 0; + border: 0; } .cp { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; + font: bold 10px Arial, "Liberation Sans", sans-serif; + color: black; } .ti { - font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; + font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; } .ld { - font: bold 15px Arial, "Liberation Sans", sans-serif; - color: #000000; + font: bold 15px Arial, "Liberation Sans", sans-serif; + color: #000000; } .w150:empty { - display: none; + display: none; } .ct { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; + font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; + color: #000033; } .cn { - font: 9px Arial, "Liberation Sans", sans-serif; - color: black; + font: 9px Arial, "Liberation Sans", sans-serif; + color: black; } .bc { - font: bold 22px Arial, "Liberation Sans", sans-serif; - color: #000000; + font: bold 22px Arial, "Liberation Sans", sans-serif; + color: #000000; } .cut { - width: 665px; - height: 1px; - border-top: dashed 1px #000; + width: 665px; + height: 1px; + border-top: dashed 1px #000; } .Ac { - text-align: center; + text-align: center; } .Ar { - text-align: right; + text-align: right; } .Al { - text-align: left; + text-align: left; } .At { - vertical-align: top; + vertical-align: top; } .Ab { - vertical-align: bottom; + vertical-align: bottom; } .ct td, .cp td { @@ -87,69 +87,69 @@ img { } .cpN { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; + font: bold 10px Arial, "Liberation Sans", sans-serif; + color: black; } .ctN { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; + font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; + color: #000033; } .pL0 { - padding-left: 0px; + padding-left: 0px; } .pL6 { - padding-left: 6px; + padding-left: 6px; } .pL10 { - padding-left: 10px; + padding-left: 10px; } .imgLogo { - width: 150px; + width: 150px; } - .imgLogo img { - width: 150px; - height: 40px; - } +.imgLogo img { + width: 150px; + height: 40px; +} .barra { - width: 3px; - height: 22px; - vertical-align: bottom; + width: 3px; + height: 22px; + vertical-align: bottom; } - .barra img { - width: 2px; - height: 22px; - } +.barra img { + width: 2px; + height: 22px; +} .rBb td { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BB { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BL { - border-left: solid 1px #000; + border-left: solid 1px #000; } .BR { - border-right: solid 1px #000; + border-right: solid 1px #000; } .BT1 { - border-top: dashed 1px #000; + border-top: dashed 1px #000; } .BT2 { - border-top: solid 2px #000; + border-top: solid 2px #000; } .bgcGray { @@ -161,191 +161,196 @@ img { } .h13 { - height: 13px; + height: 13px; } .h12 { - height: 12px; + height: 12px; } .h13 td { - vertical-align: top; + vertical-align: top; } .h12 td { - vertical-align: top; + vertical-align: top; } .w6 { - width: 6px; + width: 6px; } .w7 { - width: 7px; + width: 7px; } .w34 { - width: 34px; + width: 34px; } .w40 { - width: 40px; + width: 40px; } .w45 { - width: 45px; + width: 45px; } .w53 { - width: 53px; + width: 53px; } .w62 { - width: 62px; + width: 62px; } .w65 { - width: 65px; + width: 65px; } .w72 { - width: 72px; + width: 72px; } .w83 { - width: 83px; + width: 83px; } .w88 { - width: 88px; + width: 88px; } .w104 { - width: 104px; + width: 104px; } .w105 { - width: 105px; + width: 105px; } .w106 { - width: 106px; + width: 106px; } .w113 { - width: 113px; + width: 113px; } .w112 { - width: 112px; + width: 112px; } .w123 { - width: 123px; + width: 123px; } .w126 { - width: 126px; + width: 126px; } .w128 { - width: 128px; + width: 128px; } .w132 { - width: 132px; + width: 132px; } .w134 { - width: 134px; + width: 134px; } .w150 { - width: 150px; + width: 150px; } .w163 { - width: 163px; + width: 163px; } .w164 { - width: 164px; + width: 164px; } .w180 { - width: 180px; + width: 180px; } .w182 { - width: 182px; + width: 182px; } .w186 { - width: 186px; + width: 186px; } .w192 { - width: 192px; + width: 192px; } .w250 { - width: 250px; + width: 250px; +} + +.w286 { + width: 286px; } .w298 { - width: 298px; + width: 298px; } .w409 { - width: 409px; + width: 409px; } .w450 { - width: 450px; + width: 450px; } .w472 { - width: 472px; + width: 472px; } .w478 { - width: 478px; + width: 478px; } .w500 { - width: 500px; + width: 500px; } .w544 { - width: 544px; + width: 544px; } .w564 { - width: 564px; + width: 564px; } .w659 { - width: 659px; + width: 659px; } .w666 { - width: 100%; + width: 100%; } .w667 { - width: 667px; + width: 667px; } .w900 { - width: 900px; + width: 900px; } + .BHead td { - border-bottom: solid 2px #000; + border-bottom: solid 2px #000; } .EcdBar { - height: 50px; - vertical-align: bottom; + height: 50px; + vertical-align: bottom; } .rc6 td { @@ -356,32 +361,32 @@ img { } .rc6 div { - padding-left: 6px; + padding-left: 6px; } .rc6 .t { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; - height: 13px; + font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; + color: #000033; + height: 13px; } .rc6 .c { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; - height: 12px; + font: bold 10px Arial, "Liberation Sans", sans-serif; + color: black; + height: 12px; } .mt23 { - margin-top: 23px; + margin-top: 23px; } .pb4 { - padding-bottom: 14px; + padding-bottom: 14px; } .ebc { - width: 4px; - height: 440px; - border-right: dotted 1px #000000; - margin-right: 4px; + width: 4px; + height: 440px; + border-right: dotted 1px #000000; + margin-right: 4px; } diff --git a/BoletoNetCore/BoletoImpressao/Parts/Pix.html b/BoletoNetCore/BoletoImpressao/Parts/Pix.html index a506e368..de9ab200 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/Pix.html +++ b/BoletoNetCore/BoletoImpressao/Parts/Pix.html @@ -1,8 +1,10 @@ -
-

-

- Pague esse boleto com PIX. É seguro e imediato! +
+
+
+

+ Pague esse boleto com PIX. É seguro e imediato!
-
- +
+
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html b/BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html new file mode 100644 index 00000000..c3e3c34c --- /dev/null +++ b/BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html index 6be88336..7cfafc5b 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html @@ -1,5 +1,7 @@  - +
@IMAGEMCODIGOBARRA + +
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html index 99664aa7..ddf4d7a0 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html @@ -1,8 +1,17 @@  - - + +
-
Instruções (Texto de responsabilidade do beneficiário)
-
@INSTRUCOES
+ + + + + +
+
Instruções (Texto de responsabilidade do beneficiário)
+
@INSTRUCOES
+
+ @PIXINSTRUCOES +
(-) Desconto / Abatimentos
From 6eabe95785152d06e6e711580200e0bb19a0a20b Mon Sep 17 00:00:00 2001 From: Luis Jorge Date: Tue, 24 Mar 2026 15:53:58 -0300 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20ajuste=20no=20c=C3=B3digo=20para=20?= =?UTF-8?q?suporte=20ao=20Pix=20e=20refatora=C3=A7=C3=A3o=20de=20estilos?= =?UTF-8?q?=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adicionado suporte para renderização das informações do Pix no boleto, incluindo QrCode nas instruções. - Criado novo arquivo HTML parcial para instruções do Pix (`PixInstrucoes.html`) e atualizado a lógica de renderização. - Refatoração de estilos CSS para uniformizar indentação. - Melhorias gerais na organização e legibilidade do código. Refs: master --- .../BoletoImpressao/BoletoBancario.cs | 411 +++++------------- BoletoNetCore/BoletoImpressao/BoletoNet.css | 231 +++++----- .../BoletoImpressao/BoletoNetPDF.css | 262 +++++------ BoletoNetCore/BoletoImpressao/Parts/Pix.html | 14 +- .../BoletoImpressao/Parts/PixInstrucoes.html | 1 + .../Parts/ReciboBeneficiarioParte11.html | 4 +- .../Parts/ReciboBeneficiarioParte2.html | 4 +- .../Parts/ReciboBeneficiarioParte3.html | 4 +- .../Parts/ReciboBeneficiarioParte4.html | 20 +- .../Parts/ReciboBeneficiarioParte5.html | 22 +- .../Parts/ReciboBeneficiarioParte6.html | 53 ++- BoletoNetCore/Imagens/085.jpg | Bin 5953 -> 2554 bytes 12 files changed, 443 insertions(+), 583 deletions(-) create mode 100644 BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html diff --git a/BoletoNetCore/BoletoImpressao/BoletoBancario.cs b/BoletoNetCore/BoletoImpressao/BoletoBancario.cs index d8808df8..829f6621 100644 --- a/BoletoNetCore/BoletoImpressao/BoletoBancario.cs +++ b/BoletoNetCore/BoletoImpressao/BoletoBancario.cs @@ -16,13 +16,15 @@ namespace BoletoNetCore [Serializable()] public class BoletoBancario { - String _vLocalLogoBeneficiario = String.Empty; - #region Variaveis - private string _instrucoesHtml = string.Empty; - private bool _mostrarCodigoCarteira = false; - private bool _formatoCarne = false; + string _vLocalLogoBeneficiario = string.Empty; + + private readonly CultureInfo _culture = CultureInfo.GetCultureInfo("pt-BR"); + + private bool _formatoCarne; + private bool _mostrarCodigoCarteira; + #endregion Variaveis #region Propriedades @@ -32,8 +34,8 @@ public class BoletoBancario /// public bool MostrarCodigoCarteira { - get { return _mostrarCodigoCarteira; } - set { _mostrarCodigoCarteira = value; } + get => _mostrarCodigoCarteira; + set => _mostrarCodigoCarteira = value; } public bool ExibirDemonstrativo { get; set; } @@ -43,8 +45,8 @@ public bool MostrarCodigoCarteira /// public bool FormatoCarne { - get { return _formatoCarne; } - set { _formatoCarne = value; } + get => _formatoCarne; + set => _formatoCarne = value; } public Boleto Boleto { get; set; } @@ -52,6 +54,7 @@ public bool FormatoCarne public IBanco Banco { get; set; } #region Propriedades + public bool MostrarComprovanteEntregaLivre { get; set; } public bool MostrarComprovanteEntrega { get; set; } @@ -63,17 +66,17 @@ public bool FormatoCarne public bool OcultarReciboPagador { get; set; } public bool GerarArquivoRemessa { get; set; } + /// /// Mostra o termo "Contra Apresentação" na data de vencimento do boleto /// public bool MostrarContraApresentacaoNaDataVencimento { get; set; } public bool MostrarEnderecoBeneficiario { get; set; } - #endregion Propriedades #endregion Propriedades - + #endregion Propriedades #region Override @@ -100,18 +103,10 @@ private string GetCodBarraCode(string code) return Convert.ToBase64String(new BarCode2of5i(code, 1, 50, code.Length).ToByte()); } - protected string Render() - { - var urlImagemLogo = "data:image/jpg;base64," + GetResourceImage("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); - var urlImagemBarra = "data:image/jpg;base64," + GetResourceImage("BoletoNetCore.Imagens.barra.gif"); - - //Atribui os valores ao html do boleto bancário - return MontaHtml(urlImagemLogo, urlImagemBarra, "\"Código"); - } - #endregion Override #region Html + public string GeraHtmlInstrucoes() { try @@ -137,13 +132,19 @@ public string GeraHtmlInstrucoes() private string GeraHtmlPix(string pixStr, int tamanhoImagem = 200) { - var html = new StringBuilder(); - - html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.Pix.html")); - - return html.ToString() + var html = GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.Pix.html") .Replace("@PIXSTRING", pixStr) .Replace("@PIXIMAGEMTAMANHO", tamanhoImagem.ToString()); + + return html; + } + + private string GeraHtmlPixInstrucoes(string pixStr) + { + var html = GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.PixInstrucoes.html") + .Replace("@PIXINSTRUCOESSTRING", pixStr); + + return html; } private string GeraHtmlCarne(string telefone, string htmlBoleto) @@ -170,6 +171,7 @@ public string GeraHtmlReciboPagador() { html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte10.html")); } + html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte4.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte5.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboPagadorParte6.html")); @@ -221,14 +223,16 @@ public string HtmlComprovanteEntrega html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega5.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega6.html")); - html.Append(MostrarComprovanteEntregaLivre ? GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega71.html") : GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega7.html")); + html.Append(MostrarComprovanteEntregaLivre + ? GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega71.html") + : GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ComprovanteEntrega7.html")); html.Append("
"); return html.ToString(); } } - private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string imagemCodigoBarras, string pixStr = null, int pixTamanhoImagem = 200) + private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string imagemCodigoBarras, string pixStr = null, int pixTamanhoImagem = 200, bool pixInstrucoes = false) { var html = new StringBuilder(); var enderecoBeneficiario = ""; @@ -247,7 +251,6 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima { html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboBeneficiarioRelatorioValores.html")); html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.ReciboBeneficiarioParte5.html")); - html.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.CabecalhoTabelaDemonstrativo.html")); var grupoDemonstrativo = new StringBuilder(); @@ -273,13 +276,11 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima grupoDemonstrativo = grupoDemonstrativo.Replace("@DESCRICAOITEM", item.Descricao); grupoDemonstrativo = grupoDemonstrativo.Replace("@REFERENCIAITEM", item.Referencia); - grupoDemonstrativo = grupoDemonstrativo.Replace("@VALORITEM", item.Valor.ToString("C", CultureInfo.GetCultureInfo("pt-BR"))); + grupoDemonstrativo = grupoDemonstrativo.Replace("@VALORITEM", item.Valor.ToString("C", _culture)); } grupoDemonstrativo.Append(GetResourceHypertext("BoletoNetCore.BoletoImpressao.Parts.TotalDemonstrativo.html")); - grupoDemonstrativo = grupoDemonstrativo.Replace( - "@VALORTOTALGRUPO", - relatorio.Itens.Sum(c => c.Valor).ToString("C", CultureInfo.GetCultureInfo("pt-BR"))); + grupoDemonstrativo = grupoDemonstrativo.Replace("@VALORTOTALGRUPO", relatorio.Itens.Sum(c => c.Valor).ToString("C", _culture)); } html = html.Replace("@ITENSDEMONSTRATIVO", grupoDemonstrativo.ToString()); @@ -308,14 +309,14 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima throw new ArgumentNullException("Endereço do Beneficiário"); enderecoBeneficiario = string.Format("{0} - {1} - {2}/{3} - CEP: {4}", - Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(0), - Boleto.Banco.Beneficiario.Endereco.Bairro, - Boleto.Banco.Beneficiario.Endereco.Cidade, - Boleto.Banco.Beneficiario.Endereco.UF, - Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); + Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(0), + Boleto.Banco.Beneficiario.Endereco.Bairro, + Boleto.Banco.Beneficiario.Endereco.Cidade, + Boleto.Banco.Beneficiario.Endereco.UF, + Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); enderecoBeneficiarioCompacto = string.Format("{0} - CEP: {1}", - Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(25), - Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); + Boleto.Banco.Beneficiario.Endereco.FormataLogradouro(25), + Utils.FormataCEP(Boleto.Banco.Beneficiario.Endereco.CEP)); } } } @@ -331,15 +332,16 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima pagador += string.Format(" - CNPJ: " + Utils.FormataCNPJ(Boleto.Pagador.CPFCNPJ)); break; } + if (Boleto.Pagador.Observacoes != string.Empty) pagador += " - " + Boleto.Pagador.Observacoes; var enderecoPagador = string.Empty; if (!OcultarEnderecoPagador) { - enderecoPagador = Boleto.Pagador.Endereco.FormataLogradouro(0) + "
" + string.Format("{0} - {1}/{2}", Boleto.Pagador.Endereco.Bairro, Boleto.Pagador.Endereco.Cidade, Boleto.Pagador.Endereco.UF); + enderecoPagador = Boleto.Pagador.Endereco.FormataLogradouro(0) + "
" + $"{Boleto.Pagador.Endereco.Bairro} - {Boleto.Pagador.Endereco.Cidade}/{Boleto.Pagador.Endereco.UF}"; if (Boleto.Pagador.Endereco.CEP != String.Empty) - enderecoPagador += string.Format(" - CEP: {0}", Utils.FormataCEP(Boleto.Pagador.Endereco.CEP)); + enderecoPagador += $" - CEP: {Utils.FormataCEP(Boleto.Pagador.Endereco.CEP)}"; } // Dados do Avalista @@ -356,6 +358,7 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima avalista += string.Format(" - CNPJ: " + Utils.FormataCNPJ(Boleto.Avalista.CPFCNPJ)); break; } + if (Boleto.Avalista.Observacoes != string.Empty) avalista += " - " + Boleto.Avalista.Observacoes; } @@ -373,12 +376,15 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima if (MostrarContraApresentacaoNaDataVencimento) dataVencimento = "Contra Apresentação"; - if (String.IsNullOrWhiteSpace(_vLocalLogoBeneficiario)) + if (string.IsNullOrWhiteSpace(_vLocalLogoBeneficiario)) _vLocalLogoBeneficiario = urlImagemLogo; + html.Replace("@PIXINSTRUCOES", + pixInstrucoes && !string.IsNullOrWhiteSpace(pixStr) ? GeraHtmlPixInstrucoes(pixStr) : string.Empty); + return html .Replace("@CODIGOBANCO", Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3)) - .Replace("@DIGITOBANCO", Boleto.Banco.Digito.ToString()) + .Replace("@DIGITOBANCO", Boleto.Banco.Digito) .Replace("@URLIMAGEMLOGO", urlImagemLogo) .Replace("@URLIMGBENEFICIARIO", _vLocalLogoBeneficiario) .Replace("@URLIMAGEMBARRA", urlImagemBarra) @@ -387,8 +393,8 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima .Replace("@MENSAGEMFIXATOPOBOLETO", Boleto.Banco.Beneficiario.ContaBancaria.MensagemFixaTopoBoleto) .Replace("@MENSAGEMFIXAPAGADOR", Boleto.Banco.Beneficiario.ContaBancaria.MensagemFixaPagador) .Replace("@DATAVENCIMENTO", dataVencimento) - .Replace("@BENEFICIARIO_BOLETO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : string.Format("{0} - {1}", Boleto.Banco.Beneficiario.Nome, Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ))) - .Replace("@BENEFICIARIO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : string.Format("{0} - {1}", Boleto.Banco.Beneficiario.Nome, Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ))) + .Replace("@BENEFICIARIO_BOLETO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : $"{Boleto.Banco.Beneficiario.Nome} - {Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ)}") + .Replace("@BENEFICIARIO", !Boleto.Banco.Beneficiario.MostrarCNPJnoBoleto ? Boleto.Banco.Beneficiario.Nome : $"{Boleto.Banco.Beneficiario.Nome} - {Utils.FormataCNPJ(Boleto.Banco.Beneficiario.CPFCNPJ)}") .Replace("@DATADOCUMENTO", Boleto.DataEmissao.ToString("dd/MM/yyyy")) .Replace("@NUMERODOCUMENTO", Boleto.NumeroDocumento) .Replace("@ESPECIEDOCUMENTO", Boleto.EspecieDocumento.ToString()) @@ -396,14 +402,14 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima .Replace("@NOSSONUMERO", Boleto.NossoNumeroFormatado) .Replace("@CARTEIRA", Boleto.CarteiraImpressaoBoleto) .Replace("@ESPECIE", Boleto.EspecieMoeda) - .Replace("@QUANTIDADE", (Boleto.QuantidadeMoeda == 0 ? "" : Boleto.QuantidadeMoeda.ToString())) + .Replace("@QUANTIDADE", Boleto.QuantidadeMoeda == 0 ? "" : Boleto.QuantidadeMoeda.ToString()) .Replace("@VALORDOCUMENTO", Boleto.ValorMoeda) - .Replace("@=VALORDOCUMENTO", (Boleto.ValorTitulo == 0 ? "" : Boleto.ValorTitulo.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@DESCONTOS", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorDesconto == 0 ? "" : Boleto.ValorDesconto.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@OUTRASDEDUCOES", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorAbatimento == 0 ? "" : Boleto.ValorAbatimento.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@MORAMULTA", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorMulta == 0 ? "" : Boleto.ValorMulta.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@OUTROSACRESCIMOS", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorOutrasDespesas == 0 ? "" : Boleto.ValorOutrasDespesas.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) - .Replace("@VALORCOBRADO", (Boleto.ImprimirValoresAuxiliares == false || Boleto.ValorPago == 0 ? "" : Boleto.ValorPago.ToString("C", CultureInfo.GetCultureInfo("pt-BR")))) + .Replace("@=VALORDOCUMENTO", Boleto.ValorTitulo == 0 ? "" : Boleto.ValorTitulo.ToString("C", _culture)) + .Replace("@DESCONTOS", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorDesconto == 0 ? "" : Boleto.ValorDesconto.ToString("C", _culture)) + .Replace("@OUTRASDEDUCOES", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorAbatimento == 0 ? "" : Boleto.ValorAbatimento.ToString("C", _culture)) + .Replace("@MORAMULTA", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorMulta == 0 ? "" : Boleto.ValorMulta.ToString("C", _culture)) + .Replace("@OUTROSACRESCIMOS", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorOutrasDespesas == 0 ? "" : Boleto.ValorOutrasDespesas.ToString("C", _culture)) + .Replace("@VALORCOBRADO", !Boleto.ImprimirValoresAuxiliares || Boleto.ValorPago == 0 ? "" : Boleto.ValorPago.ToString("C", _culture)) .Replace("@AGENCIACONTA", Boleto.Banco.Beneficiario.CodigoFormatado) .Replace("@PAGADOR", pagador) .Replace("@ENDERECOPAGADOR", enderecoPagador) @@ -414,7 +420,7 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima .Replace("@USODOBANCO", Boleto.UsoBanco) .Replace("@IMAGEMCODIGOBARRA", imagemCodigoBarras) .Replace("@ACEITE", Boleto.Aceite).ToString() - .Replace("@ENDERECOBENEFICIARIO_BOLETO", MostrarEnderecoBeneficiario ? string.Format(" - {0}", enderecoBeneficiarioCompacto) : "") + .Replace("@ENDERECOBENEFICIARIO_BOLETO", MostrarEnderecoBeneficiario ? $" - {enderecoBeneficiarioCompacto}" : "") .Replace("@ENDERECOBENEFICIARIO", MostrarEnderecoBeneficiario ? enderecoBeneficiario : "") .Replace("@INSTRUCOES", Boleto.MensagemInstrucoesCaixaFormatado.Replace(Environment.NewLine, "
")) .Replace("@PARCELAS", Boleto.ParcelaInformativo != string.Empty ? ("Parcela: " + Boleto.ParcelaInformativo) : ""); @@ -427,32 +433,34 @@ private string MontaHtml(string urlImagemLogo, string urlImagemBarra, string ima /// /// Função utilizada para gerar o html do boleto sem que o mesmo esteja dentro de uma página Web. /// + /// O texto a ser incluído no início do e-mail. /// Local apontado pela imagem de logo. /// Local apontado pela imagem de barra. /// Local apontado pela imagem do código de barras. + /// Indica se os estilos CSS para renderização em PDF devem ser aplicados. + /// A string de pagamento PIX a ser incluída no HTML, se aplicável. + /// O tamanho da imagem PIX em pixels. + /// Indica se o QrCode de pagamento PIX deve ser incluído nas instruções. /// StringBuilder conténdo o código html do boleto bancário. - protected StringBuilder HtmlOffLine(string textoNoComecoDoEmail, string srcLogo, string srcBarra, string srcCodigoBarra, bool usaCsspdf = false, string pixStr = null, int pixTamanhoImagem = 200) - {//protected StringBuilder HtmlOffLine(string srcCorte, string srcLogo, string srcBarra, string srcPonto, string srcBarraInterna, string srcCodigoBarra) - //OnLoad(EventArgs.Empty); - + protected StringBuilder HtmlOffLine(string textoNoComecoDoEmail, string srcLogo, string srcBarra, string srcCodigoBarra, bool usaCsspdf = false, string pixStr = null, int pixTamanhoImagem = 200, bool pixInstrucoes = false) + { var html = new StringBuilder(); HtmlOfflineHeader(html, usaCsspdf); if (!string.IsNullOrEmpty(textoNoComecoDoEmail)) { html.Append(textoNoComecoDoEmail); } - html.Append(MontaHtml(srcLogo, srcBarra, "\"Código", pixStr, pixTamanhoImagem)); + + html.Append(MontaHtml(srcLogo, srcBarra, srcCodigoBarra, pixStr, pixTamanhoImagem, pixInstrucoes)); HtmlOfflineFooter(html); return html; } - - - /// /// Monta o Header de um email com pelo menos um boleto dentro. /// - /// StringBuilder onde o conteudo sera salvo. + /// StringBuilder usado para construir o conteúdo HTML. + /// Indica se os estilos CSS para renderização em PDF devem ser aplicados. protected static void HtmlOfflineHeader(StringBuilder html, bool usaCsspdf = false) { html.Append("\n"); @@ -463,6 +471,7 @@ protected static void HtmlOfflineHeader(StringBuilder html, bool usaCsspdf = fal html.Append(" Boleto.Net\n"); #region Css + { var arquivoCss = usaCsspdf ? "BoletoNetCore.BoletoImpressao.BoletoNetPDF.css" : "BoletoNetCore.BoletoImpressao.BoletoNet.css"; var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(arquivoCss); @@ -473,16 +482,15 @@ protected static void HtmlOfflineHeader(StringBuilder html, bool usaCsspdf = fal html.Append(sr.ReadToEnd()); html.Append("\n"); sr.Close(); - sr.Dispose(); } } + #endregion Css html.Append(" \n"); html.Append("\n"); } - /// /// Monta o Footer de um email com pelo menos um boleto dentro. /// @@ -493,7 +501,6 @@ protected static void HtmlOfflineFooter(StringBuilder saida) saida.Append("\n"); } - /// /// Junta varios boletos em uma unica AlternateView, para todos serem mandados juntos no mesmo email /// @@ -516,22 +523,22 @@ public static AlternateView GeraHtmlDeVariosBoletosParaEmail(string textoNoComec var linkedResources = new List(); HtmlOfflineHeader(corpoDoEmail); - if (textoNoComecoDoEmail != null && textoNoComecoDoEmail != "") + if (!string.IsNullOrEmpty(textoNoComecoDoEmail)) { corpoDoEmail.Append(textoNoComecoDoEmail); } + foreach (var umBoleto in arrayDeBoletos) { if (umBoleto != null) { - LinkedResource lrImagemLogo; - LinkedResource lrImagemBarra; - LinkedResource lrImagemCodigoBarra; - umBoleto.GeraGraficosParaEmailOffLine(out lrImagemLogo, out lrImagemBarra, out lrImagemCodigoBarra); + umBoleto.GeraGraficosParaEmailOffLine(out LinkedResource lrImagemLogo, + out LinkedResource lrImagemBarra, + out LinkedResource lrImagemCodigoBarra); var theOutput = umBoleto.MontaHtml( - "cid:" + lrImagemLogo.ContentId, - "cid:" + lrImagemBarra.ContentId, - "\"Código"); + $"cid:{lrImagemLogo.ContentId}", + $"cid:{lrImagemBarra.ContentId}", + $"cid:{lrImagemCodigoBarra.ContentId}"); corpoDoEmail.Append(theOutput); @@ -540,9 +547,8 @@ public static AlternateView GeraHtmlDeVariosBoletosParaEmail(string textoNoComec linkedResources.Add(lrImagemCodigoBarra); } } - HtmlOfflineFooter(corpoDoEmail); - + HtmlOfflineFooter(corpoDoEmail); var av = AlternateView.CreateAlternateViewFromString(corpoDoEmail.ToString(), Encoding.Default, "text/html"); foreach (var theResource in linkedResources) @@ -550,12 +556,9 @@ public static AlternateView GeraHtmlDeVariosBoletosParaEmail(string textoNoComec av.LinkedResources.Add(theResource); } - - return av; } - /// /// Função utilizada gerar o AlternateView necessário para enviar um boleto bancário por e-mail. /// @@ -565,7 +568,6 @@ public AlternateView HtmlBoletoParaEnvioEmail() return HtmlBoletoParaEnvioEmail(null); } - /// /// Função utilizada gerar o AlternateView necessário para enviar um boleto bancário por e-mail. /// @@ -573,12 +575,8 @@ public AlternateView HtmlBoletoParaEnvioEmail() /// AlternateView com os dados do boleto. public AlternateView HtmlBoletoParaEnvioEmail(string textoNoComecoDoEmail) { - LinkedResource lrImagemLogo; - LinkedResource lrImagemBarra; - LinkedResource lrImagemCodigoBarra; - - GeraGraficosParaEmailOffLine(out lrImagemLogo, out lrImagemBarra, out lrImagemCodigoBarra); - var html = HtmlOffLine(textoNoComecoDoEmail, "cid:" + lrImagemLogo.ContentId, "cid:" + lrImagemBarra.ContentId, "cid:" + lrImagemCodigoBarra.ContentId); + GeraGraficosParaEmailOffLine(out LinkedResource lrImagemLogo, out LinkedResource lrImagemBarra, out LinkedResource lrImagemCodigoBarra); + var html = HtmlOffLine(textoNoComecoDoEmail, $"cid:{lrImagemLogo.ContentId}", $"cid:{lrImagemBarra.ContentId}", $"cid:{lrImagemCodigoBarra.ContentId}"); var av = AlternateView.CreateAlternateViewFromString(html.ToString(), Encoding.Default, "text/html"); @@ -596,263 +594,71 @@ public AlternateView HtmlBoletoParaEnvioEmail(string textoNoComecoDoEmail) /// O Código de Barras void GeraGraficosParaEmailOffLine(out LinkedResource lrImagemLogo, out LinkedResource lrImagemBarra, out LinkedResource lrImagemCodigoBarra) { - //OnLoad(EventArgs.Empty); - var randomSufix = new Random().Next().ToString(); // para podermos colocar no mesmo email varios boletos diferentes - var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); + var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"BoletoNetCore.Imagens.{Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3)}.jpg"); lrImagemLogo = new LinkedResource(stream, MediaTypeNames.Image.Jpeg) { - ContentId = "logo" + randomSufix + ContentId = $"logo{randomSufix}" }; var assembly = Assembly.GetExecutingAssembly(); var ms = assembly.GetManifestResourceStream("BoletoNetCore.Imagens.barra.jpg"); lrImagemBarra = new LinkedResource(ms, MediaTypeNames.Image.Jpeg) { - ContentId = "barra" + randomSufix + ContentId = $"barra{randomSufix}" }; - var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); + var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, + Boleto.CodigoBarra.CodigoDeBarras.Length); ms = new MemoryStream(Utils.ConvertImageToByte(cb.ToBitmap())); lrImagemCodigoBarra = new LinkedResource(ms, MediaTypeNames.Image.Gif) { - ContentId = "codigobarra" + randomSufix + ContentId = $"codigobarra{randomSufix}" }; - } - - /// - /// Função utilizada para gravar em um arquivo local o conteúdo do boleto. Este arquivo pode ser aberto em um browser sem que o site esteja no ar. - /// - /// Path do arquivo que deve conter o código html. - //public void MontaHtmlNoArquivoLocal(string fileName) - //{ - // using (var f = new FileStream(fileName, FileMode.Create)) - // { - // var w = new StreamWriter(f, Encoding.Default); - // w.Write(MontaHtml()); - // w.Close(); - // f.Close(); - // } - //} - - /// - /// Monta o Html do boleto bancário - /// - /// string - //public string MontaHtml() - //{ - // return MontaHtml(null, null); - //} - - - /// - /// Monta o Html do boleto bancário - /// - /// Caminho do arquivo - /// Caminho do logo do beneficiario - /// Html do boleto gerado - //public string MontaHtml(string fileName, string logoBeneficiario) - //{ - // if (fileName == null) - // fileName = Path.GetTempPath(); - - // if (logoBeneficiario != null) - // _vLocalLogoBeneficiario = logoBeneficiario; - - // //OnLoad(EventArgs.Empty); - - // var fnLogo = fileName + @"BoletoNet" + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"; - - // if (!File.Exists(fnLogo)) - // { - // var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); - // using (Stream file = File.Create(fnLogo)) - // { - // CopiarStream(stream, file); - // } - // } - - // var fnBarra = fileName + @"BoletoNetBarra.gif"; - // if (!File.Exists(fnBarra)) - // { - // var imgConverter = new ImageConverter(); - // var imgBuffer = (byte[])imgConverter.ConvertTo(Html.barra, typeof(byte[])); - // var ms = new MemoryStream(imgBuffer); - - // using (Stream stream = File.Create(fnBarra)) - // { - // CopiarStream(ms, stream); - // ms.Flush(); - // ms.Dispose(); - // } - // } - - // var fnCodigoBarras = Path.GetTempFileName(); - // var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); - // cb.ToBitmap().Save(fnCodigoBarras); - - // //return HtmlOffLine(fnCorte, fnLogo, fnBarra, fnPonto, fnBarraInterna, fnCodigoBarras).ToString(); - // return HtmlOffLine(null, fnLogo, fnBarra, fnCodigoBarras).ToString(); - //} - - /// - /// Monta o Html do boleto bancário para View ASP.Net MVC - /// - /// Exemplo: - /// public ActionResult VisualizarBoleto(string Id) - /// { - /// BoletoBancario bb = new BoletoBancario(); - /// //... - /// ViewBag.Boleto = bb.MontaHtml("/Content/Boletos/", "teste1"); - /// return View(); - /// } - /// //Na view - /// @{Layout = null;}@Html.Raw(ViewBag.Boleto) - /// - /// - /// Pasta dos boletos. Exemplo MontaHtml("/Content/Boletos/", "000100") - /// Nome do arquivo para o boleto - /// Html do boleto gerado - /// Sandro Ribeiro - /// 16/11/2012 - //public string MontaHtml(string url, string fileName, bool useMapPathSecure = true) - //{ - // //Variável para o caminho físico do servidor - // var pathServer = ""; - - // //Verifica se o usuário informou uma url válida - // if (url == null) - // { - // //Obriga o usuário a especificar uma url válida - // throw new ArgumentException("Você precisa informar uma pasta padrão."); - // } - // else - // { - // if (useMapPathSecure) - // { - // //Verifica se o usuário usou barras no início e no final da url - // if (url.Substring(url.Length - 1, 1) != "/") - // url = url + "/"; - // if (url.Substring(0, 1) != "/") - // url = url + "/"; - // //Mapeia o caminho físico dos arquivos - // pathServer = MapPathSecure(string.Format("~{0}", url)); - // } - - // //Verifica se o caminho existe - // if (!Directory.Exists(pathServer)) - // throw new ArgumentException("A o caminho físico '{0}' não existe.", pathServer); - // } - // //Verifica o nome do arquivo - // if (fileName == null) - // { - // fileName = DateTime.Now.Ticks.ToString(); - // } - // else - // { - // if (fileName == "") - // fileName = DateTime.Now.Ticks.ToString(); - // } - - // //Mantive o padrão - // //OnLoad(EventArgs.Empty); - - // //Prepara o arquivo da logo para ser salvo - // var fnLogo = pathServer + @"BoletoNet" + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"; - // //Prepara o arquivo da logo para ser usado no html - // var fnLogoUrl = url + @"BoletoNet" + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"; - - // //Salvo a imagem apenas 1 vez com o código do banco - // if (!File.Exists(fnLogo)) - // { - // var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BoletoNetCore.Imagens." + Utils.FormatCode(Boleto.Banco.Codigo.ToString(), 3) + ".jpg"); - // using (Stream file = File.Create(fnLogo)) - // { - // CopiarStream(stream, file); - // } - // } - - // //Prepara o arquivo da barra para ser salvo - // var fnBarra = pathServer + @"BoletoNetBarra.gif"; - // //Prepara o arquivo da barra para ser usado no html - // var fnBarraUrl = url + @"BoletoNetBarra.gif"; - - // //Salvo a imagem apenas 1 vez - // if (!File.Exists(fnBarra)) - // { - // var imgConverter = new ImageConverter(); - // var imgBuffer = (byte[])imgConverter.ConvertTo(Html.barra, typeof(byte[])); - // var ms = new MemoryStream(imgBuffer); - - // using (Stream stream = File.Create(fnBarra)) - // { - // CopiarStream(ms, stream); - // ms.Flush(); - // ms.Dispose(); - // } - // } - - // //Prepara o arquivo do código de barras para ser salvo - // var fnCodigoBarras = string.Format("{0}{1}_codigoBarras.jpg", pathServer, fileName); - // //Prepara o arquivo do código de barras para ser usado no html - // var fnCodigoBarrasUrl = string.Format("{0}{1}_codigoBarras.jpg", url, fileName); - - // var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); - - // //Salva o arquivo conforme o fileName - // cb.ToBitmap().Save(fnCodigoBarras); - - // //Retorna o Html para ser usado na view - // return HtmlOffLine(null, fnLogoUrl, fnBarraUrl, fnCodigoBarrasUrl).ToString(); - //} - /// /// Monta o Html do boleto bancário com as imagens embutidas no conteúdo, sem necessidade de links externos /// de acordo com o padrão http://en.wikipedia.org/wiki/Data_URI_scheme /// - /// Alterado por Olavo Rocha @ Exodus para utilizar arquivos dentro da própria DLL para .net core 2.2 + /// Alterado por Olavo Rocha @ Exodus para utilizar arquivos dentro da própria DLL para .net core 2.2 /// - /// Converte a Linha Digitável para imagem, com o objetivo de evitar malwares. - /// Url/Imagem Base64 da Logo do Beneficiário - /// Html do boleto gerado - /// Iuri André Stona, Olavo Rocha Neto - /// 23/01/2014 - /// 07/07/2019 - public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool usaCsspdf = false, string urlImagemLogoBeneficiario = null, string pixString = null, int pixTamanhoImagem = 200) + /// Indica se a linha de cobrança deve ser convertida em uma imagem para evitar exploração por malware. + /// Determina se os estilos CSS específicos para renderização em formato PDF devem ser aplicados. + /// Especifica a URL ou a imagem codificada em Base64 do logotipo do beneficiário a ser exibida no comprovante bancário. + /// A string de pagamento PIX a ser incorporada no HTML, se aplicável. + /// O tamanho da imagem do código QR PIX, em pixels. + /// Indica se o QrCode de pagamento PIX deve ser incluído nas instruções. + /// Uma string representando o HTML gerado para o comprovante bancário. + public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool usaCsspdf = false, string urlImagemLogoBeneficiario = null, string pixString = null, int pixTamanhoImagem = 200, bool pixInstrucoes = false) { - //OnLoad(EventArgs.Empty); - var assembly = Assembly.GetExecutingAssembly(); - var imageLogo = "BoletoNetCore.Imagens." + Boleto.Banco.Codigo.ToString("000") + ".jpg"; + var imageLogo = $"BoletoNetCore.Imagens.{Boleto.Banco.Codigo:000}.jpg"; var streamLogo = assembly.GetManifestResourceStream(imageLogo); var base64Logo = Convert.ToBase64String(new BinaryReader(streamLogo).ReadBytes((int)streamLogo.Length)); - var fnLogo = string.Format("data:image/jpg;base64,{0}", base64Logo); + var fnLogo = $"data:image/jpg;base64,{base64Logo}"; var streamBarra = assembly.GetManifestResourceStream("BoletoNetCore.Imagens.barra.jpg"); var base64Barra = Convert.ToBase64String(new BinaryReader(streamBarra).ReadBytes((int)streamBarra.Length)); - var fnBarra = string.Format("data:image/jpg;base64,{0}", base64Barra); + var fnBarra = $"data:image/jpg;base64,{base64Barra}"; var cb = new BarCode2of5i(Boleto.CodigoBarra.CodigoDeBarras, 1, 50, Boleto.CodigoBarra.CodigoDeBarras.Length); var base64CodigoBarras = Convert.ToBase64String(cb.ToByte()); - var fnCodigoBarras = string.Format("data:image/gif;base64,{0}", base64CodigoBarras); + var fnCodigoBarras = $"data:image/gif;base64,{base64CodigoBarras}"; if (convertLinhaDigitavelToImage) { - var linhaDigitavel = Boleto.CodigoBarra.LinhaDigitavel.Replace(" ", " ").Trim(); - var font = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright); + var font = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, + SKFontStyleSlant.Upright); var imagemLinha = Utils.DrawText(linhaDigitavel, 40, font, SKColors.Black, SKColors.White); var base64Linha = Convert.ToBase64String(Utils.ConvertImageToByte(imagemLinha)); - var fnLinha = string.Format("data:image/gif;base64,{0}", base64Linha); - - Boleto.CodigoBarra.LinhaDigitavel = @""; + Boleto.CodigoBarra.LinhaDigitavel = $@""; } if (!string.IsNullOrEmpty(urlImagemLogoBeneficiario)) @@ -860,7 +666,7 @@ public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool _vLocalLogoBeneficiario = urlImagemLogoBeneficiario; } - var s = HtmlOffLine(null, fnLogo, fnBarra, fnCodigoBarras, usaCsspdf, pixString, pixTamanhoImagem).ToString(); + var s = HtmlOffLine(null, fnLogo, fnBarra, fnCodigoBarras, usaCsspdf, pixString, pixTamanhoImagem, pixInstrucoes).ToString(); if (convertLinhaDigitavelToImage) { @@ -870,7 +676,6 @@ public string MontaHtmlEmbedded(bool convertLinhaDigitavelToImage = false, bool return s; } - #endregion Geração do Html OffLine public SKBitmap GeraImagemCodigoBarras(Boleto boleto) @@ -881,7 +686,7 @@ public SKBitmap GeraImagemCodigoBarras(Boleto boleto) private void CopiarStream(Stream entrada, Stream saida) { - var bytesLidos = 0; + int bytesLidos; var imgBuffer = new byte[entrada.Length]; while ((bytesLidos = entrada.Read(imgBuffer, 0, imgBuffer.Length)) > 0) @@ -890,4 +695,4 @@ private void CopiarStream(Stream entrada, Stream saida) } } } -} +} \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/BoletoNet.css b/BoletoNetCore/BoletoImpressao/BoletoNet.css index 56b66d28..add13cec 100644 --- a/BoletoNetCore/BoletoImpressao/BoletoNet.css +++ b/BoletoNetCore/BoletoImpressao/BoletoNet.css @@ -1,13 +1,13 @@ body { - color: #000000; - background-color: #ffffff; - margin-top: 0; - margin-right: 0; + color: #000000; + background-color: #ffffff; + margin-top: 0; + margin-right: 0; } * { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } table { @@ -17,7 +17,7 @@ table { } img { - border: 0; + border: 0; } .cp { @@ -26,16 +26,16 @@ img { } .ti { - font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; + font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; } .ld { - font: bold 15px Arial, "Liberation Sans", sans-serif; - color: #000000; + font: bold 15px Arial, "Liberation Sans", sans-serif; + color: #000000; } .w150:empty { - display: none; + display: none; } .ct { @@ -59,32 +59,33 @@ img { } .cut { - width: 665px; - height: 1px; - border-top: dashed 1px #000; + width: 665px; + height: 1px; + border-top: dashed 1px #000; } .Ac { - text-align: center; + text-align: center; } .Ar { - text-align: right; + text-align: right; } .Al { - text-align: left; + text-align: left; } .At { - vertical-align: top; + vertical-align: top; } .Ab { - vertical-align: bottom; + vertical-align: bottom; } .ct td, .cp td { + padding-top: 2px; padding-left: 3px; border-left: solid 1px #000; padding-right: 3px; @@ -102,59 +103,60 @@ img { } .pL0 { - padding-left: 0px; + padding-left: 0px; } .pL6 { - padding-left: 6px; + padding-left: 6px; } .pL10 { - padding-left: 10px; + padding-left: 10px; } .imgLogo { - width: 150px; + width: 150px; } - .imgLogo img { - width: 150px; - height: 40px; - } +.imgLogo img { + width: auto; + height: 40px; + margin-bottom: 1px; +} .barra { - width: 3px; - height: 22px; - vertical-align: bottom; + width: 3px; + height: 22px; + vertical-align: bottom; } - .barra img { - width: 2px; - height: 22px; - } +.barra img { + width: 2px; + height: 22px; +} .rBb td { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BB { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BL { - border-left: solid 1px #000; + border-left: solid 1px #000; } .BR { - border-right: solid 1px #000; + border-right: solid 1px #000; } .BT1 { - border-top: dashed 1px #000; + border-top: dashed 1px #000; } .BT2 { - border-top: solid 2px #000; + border-top: solid 2px #000; } .bgcGray { @@ -162,83 +164,87 @@ img { } .h1 { - height: 1px; + height: 1px; } .h13 { - height: 13px; + height: 13px; } .h12 { - height: 12px; + height: 12px; } .h13 td { - vertical-align: top; + vertical-align: top; } .h12 td { - vertical-align: top; + vertical-align: top; +} + +.h25 { + height: 25px; } .w6 { - width: 6px; + width: 6px; } .w7 { - width: 7px; + width: 7px; } .w34 { - width: 34px; + width: 34px; } .w40 { - width: 40px; + width: 40px; } .w45 { - width: 45px; + width: 45px; } .w53 { - width: 53px; + width: 53px; } .w62 { - width: 62px; + width: 62px; } .w65 { - width: 65px; + width: 65px; } .w72 { - width: 72px; + width: 72px; } .w83 { - width: 83px; + width: 83px; } .w88 { - width: 88px; + width: 88px; } .w104 { - width: 104px; + width: 104px; } .w105 { - width: 105px; + width: 105px; } .w106 { - width: 106px; + width: 106px; } .w112 { - width: 112px; + width: 112px; } .w113 { @@ -246,59 +252,63 @@ img { } .w123 { - width: 123px; + width: 123px; } .w126 { - width: 126px; + width: 126px; } .w128 { - width: 128px; + width: 128px; } .w132 { - width: 132px; + width: 132px; } .w134 { - width: 134px; + width: 134px; } .w150 { - width: 150px; + width: 150px; } .w163 { - width: 163px; + width: 163px; } .w164 { - width: 164px; + width: 164px; } .w180 { - width: 180px; + width: 180px; } .w182 { - width: 182px; + width: 182px; } .w186 { - width: 186px; + width: 186px; } .w192 { - width: 192px; + width: 192px; } .w250 { - width: 250px; + width: 250px; +} + +.w286 { + width: 286px; } .w298 { - width: 298px; + width: 298px; } .w409 { @@ -310,85 +320,88 @@ img { } .w472 { - width: 472px; + width: 472px; } .w478 { - width: 478px; + width: 478px; } .w500 { - width: 500px; + width: 500px; } .w544 { - width: 544px; + width: 544px; } .w564 { - width: 564px; + width: 564px; } .w659 { - width: 659px; + width: 659px; } .w666 { - width: 100%; + width: 100%; } .w667 { - width: 667px; + width: 667px; } .w900 { - width: 900px; + width: 900px; } - .BHead td { - border-bottom: solid 2px #000; + border-bottom: solid 2px #000; } .EcdBar { - height: 50px; - vertical-align: bottom; + height: 50px; + vertical-align: bottom; } -.rc6 td { - vertical-align: top; +.rc6 { border-bottom: solid 1px #000; border-left: solid 1px #000; border-right: solid 1px #000; } -.rc6 div { - padding-left: 6px; -} - -.rc6 .t { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; - height: 13px; -} - -.rc6 .c { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; - height: 12px; +.rc6 td { + vertical-align: top; + border-bottom: solid 1px #000; + border-left: solid 1px #000; + border-right: solid 1px #000; + padding-top: 2px; + padding-left: 3px; + padding-right: 3px; } .mt23 { - margin-top: 23px; + margin-top: 23px; } .pb4 { - padding-bottom: 14px; + padding-bottom: 14px; } .ebc { - width: 4px; - height: 440px; - border-right: dotted 1px #000000; - margin-right: 4px; + width: 4px; + height: 440px; + border-right: dotted 1px #000000; + margin-right: 4px; +} + +.diL { + float: left; + width: calc(100% - 135px); } + +.diR { + float: right; + width: 125px; + padding: 5px; +} \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css b/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css index ce8f76a9..126951b5 100644 --- a/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css +++ b/BoletoNetCore/BoletoImpressao/BoletoNetPDF.css @@ -1,13 +1,13 @@ body { - color: #000000; - background-color: #ffffff; - margin-top: 0; - margin-right: 0; + color: #000000; + background-color: #ffffff; + margin-top: 0; + margin-right: 0; } * { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } table { @@ -17,69 +17,75 @@ table { } img { - border: 0; + border: 0; } .cp { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; + font: bold 10px Arial, "Liberation Sans", sans-serif; + color: #000000; } .ti { - font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; + font: 9px Arial, "Liberation Sans", Helvetica, sans-serif; } .ld { - font: bold 15px Arial, "Liberation Sans", sans-serif; - color: #000000; + font: bold 15px Arial, "Liberation Sans", sans-serif; + color: #000000; } .w150:empty { - display: none; + display: none; } .ct { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; + font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; + color: #000000; } .cn { - font: 9px Arial, "Liberation Sans", sans-serif; - color: black; + font: 9px Arial, "Liberation Sans", sans-serif; + color: #000000; +} + +.cn8 { + font: 8px Arial, "Liberation Sans", sans-serif; + color: #000000; } .bc { - font: bold 22px Arial, "Liberation Sans", sans-serif; - color: #000000; + font: bold 22px Arial, "Liberation Sans", sans-serif; + color: #000000; } .cut { - width: 665px; - height: 1px; - border-top: dashed 1px #000; + width: 665px; + height: 1px; + border-top: dashed 1px #000; } .Ac { - text-align: center; + text-align: center; } .Ar { - text-align: right; + text-align: right; } .Al { - text-align: left; + text-align: left; } .At { - vertical-align: top; + vertical-align: top; } .Ab { - vertical-align: bottom; + vertical-align: bottom; } .ct td, .cp td { + padding-top: 2px; padding-left: 3px; border-left: solid 1px #000; padding-right: 3px; @@ -87,69 +93,70 @@ img { } .cpN { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; + font: bold 10px Arial, "Liberation Sans", sans-serif; + color: #000000; } .ctN { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; + font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; + color: #000000; } .pL0 { - padding-left: 0px; + padding-left: 0px; } .pL6 { - padding-left: 6px; + padding-left: 6px; } .pL10 { - padding-left: 10px; + padding-left: 10px; } .imgLogo { - width: 150px; + width: 150px; } - .imgLogo img { - width: 150px; - height: 40px; - } +.imgLogo img { + width: auto; + height: 40px; + margin-bottom: 1px; +} .barra { - width: 3px; - height: 22px; - vertical-align: bottom; + width: 3px; + height: 22px; + vertical-align: bottom; } - .barra img { - width: 2px; - height: 22px; - } +.barra img { + width: 2px; + height: 22px; +} .rBb td { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BB { - border-bottom: solid 1px #000; + border-bottom: solid 1px #000; } .BL { - border-left: solid 1px #000; + border-left: solid 1px #000; } .BR { - border-right: solid 1px #000; + border-right: solid 1px #000; } .BT1 { - border-top: dashed 1px #000; + border-top: dashed 1px #000; } .BT2 { - border-top: solid 2px #000; + border-top: solid 2px #000; } .bgcGray { @@ -161,191 +168,200 @@ img { } .h13 { - height: 13px; + height: 13px; } .h12 { - height: 12px; + height: 12px; } .h13 td { - vertical-align: top; + vertical-align: top; } .h12 td { - vertical-align: top; + vertical-align: top; +} + +.h25 { + height: 25px; } .w6 { - width: 6px; + width: 6px; } .w7 { - width: 7px; + width: 7px; } .w34 { - width: 34px; + width: 34px; } .w40 { - width: 40px; + width: 40px; } .w45 { - width: 45px; + width: 45px; } .w53 { - width: 53px; + width: 53px; } .w62 { - width: 62px; + width: 62px; } .w65 { - width: 65px; + width: 65px; } .w72 { - width: 72px; + width: 72px; } .w83 { - width: 83px; + width: 83px; } .w88 { - width: 88px; + width: 88px; } .w104 { - width: 104px; + width: 104px; } .w105 { - width: 105px; + width: 105px; } .w106 { - width: 106px; + width: 106px; } -.w113 { - width: 113px; +.w112 { + width: 112px; } -.w112 { - width: 112px; +.w113 { + width: 113px; } .w123 { - width: 123px; + width: 123px; } .w126 { - width: 126px; + width: 126px; } .w128 { - width: 128px; + width: 128px; } .w132 { - width: 132px; + width: 132px; } .w134 { - width: 134px; + width: 134px; } .w150 { - width: 150px; + width: 150px; } .w163 { - width: 163px; + width: 163px; } .w164 { - width: 164px; + width: 164px; } .w180 { - width: 180px; + width: 180px; } .w182 { - width: 182px; + width: 182px; } .w186 { - width: 186px; + width: 186px; } .w192 { - width: 192px; + width: 192px; } .w250 { - width: 250px; + width: 250px; +} + +.w286 { + width: 286px; } .w298 { - width: 298px; + width: 298px; } .w409 { - width: 409px; + width: 409px; } .w450 { - width: 450px; + width: 450px; } .w472 { - width: 472px; + width: 472px; } .w478 { - width: 478px; + width: 478px; } .w500 { - width: 500px; + width: 500px; } .w544 { - width: 544px; + width: 544px; } .w564 { - width: 564px; + width: 564px; } .w659 { - width: 659px; + width: 659px; } .w666 { - width: 100%; + width: 100%; } .w667 { - width: 667px; + width: 667px; } .w900 { - width: 900px; + width: 900px; } + .BHead td { - border-bottom: solid 2px #000; + border-bottom: solid 2px #000; } .EcdBar { - height: 50px; - vertical-align: bottom; + height: 50px; + vertical-align: bottom; } .rc6 td { @@ -353,35 +369,33 @@ img { border-bottom: solid 1px #000; border-left: solid 1px #000; border-right: solid 1px #000; -} - -.rc6 div { - padding-left: 6px; -} - -.rc6 .t { - font: 9px "Arial Narrow", "Liberation Sans Narrow", sans-serif; - color: #000033; - height: 13px; -} - -.rc6 .c { - font: bold 10px Arial, "Liberation Sans", sans-serif; - color: black; - height: 12px; + padding-top: 2px; + padding-left: 3px; + padding-right: 3px; } .mt23 { - margin-top: 23px; + margin-top: 23px; } .pb4 { - padding-bottom: 14px; + padding-bottom: 14px; } .ebc { - width: 4px; - height: 440px; - border-right: dotted 1px #000000; - margin-right: 4px; + width: 4px; + height: 440px; + border-right: dotted 1px #000000; + margin-right: 4px; +} + +.diL { + float: left; + width: calc(100% - 135px); } + +.diR { + float: right; + width: 125px; + padding: 5px; +} \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/Pix.html b/BoletoNetCore/BoletoImpressao/Parts/Pix.html index a506e368..de9ab200 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/Pix.html +++ b/BoletoNetCore/BoletoImpressao/Parts/Pix.html @@ -1,8 +1,10 @@ -
-

-

- Pague esse boleto com PIX. É seguro e imediato! +
+
+
+

+ Pague esse boleto com PIX. É seguro e imediato!
-
- +
+
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html b/BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html new file mode 100644 index 00000000..ab9e9c0a --- /dev/null +++ b/BoletoNetCore/BoletoImpressao/Parts/PixInstrucoes.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html index 6be88336..7cfafc5b 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte11.html @@ -1,5 +1,7 @@  - +
@IMAGEMCODIGOBARRA + +
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte2.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte2.html index 2c3f293c..5d6ffe38 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte2.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte2.html @@ -4,7 +4,7 @@
Vencimento
@LOCALPAGAMENTO@DATAVENCIMENTO@LOCALPAGAMENTO@DATAVENCIMENTO
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte3.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte3.html index dc80f494..81b46c4e 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte3.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte3.html @@ -4,7 +4,7 @@ Agência / Código Beneficiário - @BENEFICIARIO_BOLETO@ENDERECOBENEFICIARIO_BOLETO - @AGENCIACONTA + @BENEFICIARIO_BOLETO@ENDERECOBENEFICIARIO_BOLETO + @AGENCIACONTA \ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte4.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte4.html index 77f603ea..3a43b4be 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte4.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte4.html @@ -1,18 +1,18 @@  - - - - + + + + - - - - - - + + + + + +
Data do documentoNo documentoEspécie doc.AceiteData do documentoNo documentoEspécie doc.Aceite Data processamento Carteira / Nosso número
@DATADOCUMENTO@NUMERODOCUMENTO@ESPECIEDOCUMENTO@ACEITE@DATAPROCESSAMENTO@NOSSONUMERO@DATADOCUMENTO@NUMERODOCUMENTO@ESPECIEDOCUMENTO@ACEITE@DATAPROCESSAMENTO@NOSSONUMERO
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte5.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte5.html index 1123fed8..a8d9182e 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte5.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte5.html @@ -1,20 +1,20 @@  - - - - + + + + - - - - - - - + + + + + + +
Uso do bancoC I PCarteiraEspécieQuantidadeC I PCarteiraEspécieQuantidade (x) Valor (=) Valor documento
  @CARTEIRA@ESPECIE@QUANTIDADE@VALORDOCUMENTO@=VALORDOCUMENTO@CARTEIRA@ESPECIE@QUANTIDADE@VALORDOCUMENTO@=VALORDOCUMENTO
\ No newline at end of file diff --git a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html index 99664aa7..d4019fce 100644 --- a/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html +++ b/BoletoNetCore/BoletoImpressao/Parts/ReciboBeneficiarioParte6.html @@ -1,20 +1,43 @@  - - + + - + + + + + + + + + + + + + + +
-
Instruções (Texto de responsabilidade do beneficiário)
-
@INSTRUCOES
+
+
+
Instruções (Texto de responsabilidade do beneficiário)
+
@INSTRUCOES
+
+ @PIXINSTRUCOES
-
(-) Desconto / Abatimentos
-
@DESCONTOS
-
(-) Outras deduções
-
@OUTRASDEDUCOES
-
(+) Mora / Multa
-
@MORAMULTA
-
(+) Outros acréscimos
-
@OUTROSACRESCIMOS
-
(=) Valor cobrado
-
@VALORCOBRADO
+
+
(-) Desconto / Abatimentos
+
@DESCONTOS
+
+
(-) Outras deduções
+
@OUTRASDEDUCOES
+
+
(+) Mora / Multa
+
@MORAMULTA
+
+
(+) Outros acréscimos
+
@OUTROSACRESCIMOS
+
+
(=) Valor cobrado
+
@VALORCOBRADO
\ No newline at end of file diff --git a/BoletoNetCore/Imagens/085.jpg b/BoletoNetCore/Imagens/085.jpg index e64c535f93d86076d451b2a277d86af7bd39ab85..b5d12ab60ec4891965f62231ee0f7fe00f98e8d5 100644 GIT binary patch delta 2106 zcmV-A2*vloF8ULY6@S|RLjVQ@1qKBK1_lKN2L}cS3J?kk2?+`m4i5|v7Zey67Zes2 z8XYAc8XF@V78W2ZAR{IxDJm%$A1yE~C@>``DJcKj07C%>2L}oW3KI$n6DS%M8Yn0z zC@3f>C@3f>C@3f>C@3f>C@3f>C@3f>C@3f>C@3f>C@3f>C=)0sC@3f>C@3f>|G)qd z2mmesmb1+R$N_))qKr{R02Pg`c%wzpay30h-ra!C)@+~1R}Jxh#}jEI`yWY>qr8!K zOEUie0-W$Y{rgud@blrv{3PIO9wvDuv3_EN$lInlIV^hP)0)B6ytyEGRWlbV{{UCR ztI2QK9l-dfq}|*Yw6})i9XCG0et?R(ACAaz=h*3~}| zl4rK*{z1DxiRiN!>x!2K6mPLv-l12)O3o{;o zSD9*`8+`90`VvUynx!``RJA47rlZc~q3ASM3EFdG72xiIiYTcpDI1}sppFd!XUiJf zzOCbng}7o&*Ty1GI2-o=04n+~TfL9No)(g5kRKv7ju^nk=Qvd#nHAxm6EumuJL5*W zjR=BiKGO^K&T>c88ui94<39{(m)bqlaZ7(3i!c(d<=(s%a6JukVIgVDo4NB@N_6Vi zgZR#8Qqr#cGi_xaogqt|dLd(Q;Nurk62@cdMr8dfqVUz69u)B_XjaLx#_|C@zozsX zTzzl>{A-Q9UlRDrSsC8i-hCNe{{YlK%{s`~E1vj8{{X(LqVTl($BZs?{aW$u?X7<- zW(=qyWs#f8!wjC;Vh8AlO1wz8Z2x}JZHd~_vCl{@l(Ry;wpnY?dp<9`$~GdvEB4>|A1 z{16KFUxGT>*1jES##h~OXr|UrUz3IZ0LOOMnfNQ=Z;0;vDQ`Weh_4c^7xVDwqaS>p^oa2s!9QCXr3Huiat!{MGsZHV|IX`yWkoYDSi&0r;1zw~KUtwj|QX(Y%NlfLMQ!>$`)IT?fMU zlf}Oobx#t(1c_j!-Cc$~6#@6auG?Jro!~3BxvT zuVbDNi>J-a%d54{gTUJFg#1Ka>%(!{E!1NYD1b*Q1M9|d`d49JGJF}f`)9@GzVP+D z(P(iQO9tq%lwhF$0Kk8U;=Y@%EKM~|c1-kebzNF_Yp+0}iYuJ!3Jnxc20w}XKV{-Q zG3@W-1Rhbq`H{Uvc|+;GBKTi?ZY(BEM@OB$Xqc4e+;SBAjInh2#?v^P+!+ai3$6pTr8l@jt~0 zt}Udt(CwPlSbwf^H;hjZ@aMz!GpycB*9^RY zJMIJU09U69xCndPt-j3h>S6PWzq@jZUD3t-BJi!u`l|SYQB&ohV+Q_N-0)lS&3d-2 zqiNd0Mw+FSz1n|9NkK9O3VlXu>Y}2BP!&f23Uzt-j6|zc=h*geSSVpA`z5b;-He79 z;E5uI6(d1~RTuzzRS)bPEBjdLf7$lG+63g>d1HS}b^2D8Xsi=x>~T+YX6d>XnWkLL zai`c@ThBN8$Brfc#Z4AvP zK+?2#k+i)!*3qN@F@`XuhoQw()I1&G-9mPn^G30jRyi(VT$Arx)Klk@cepxnYRwfi z?KaCyw-)+!tQOFYc0_?k=~)+k3Gmh2%`L`>VDd5CTghCL>T9B+g()X=!PARYXs4y= kb~;=>R+}1U1*~V1u%J+XD!D}!Ew{NzB&>ppD4=Km*;*A3$p8QV literal 5953 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 Date: Fri, 27 Mar 2026 16:25:06 -0300 Subject: [PATCH 3/3] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20da=20logo=20da=20ai?= =?UTF-8?q?los=20no=20projeto=20questpdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BoletoNetCore.QuestPdf/logos/085.bmp | Bin 28206 -> 20848 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/BoletoNetCore.QuestPdf/logos/085.bmp b/BoletoNetCore.QuestPdf/logos/085.bmp index 2db0648577450aad71c59558f371728aa0caddba..ad6341b39c002467ea9097e2bd32a50d00dc8f2d 100644 GIT binary patch literal 20848 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 PC!O+*%DX+pw5mHIR@g>Pjz1ueVrc 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 Dbgwi6 literal 28206 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