diff --git a/.gitignore b/.gitignore index dfcfd56..f5b4c14 100644 --- a/.gitignore +++ b/.gitignore @@ -348,3 +348,5 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ + +.idea/ diff --git a/Sicoob.Cobranca/DataAnotation/CustomDateTimeWithZoneConverter.cs b/Sicoob.Cobranca/DataAnotation/CustomDateTimeWithZoneConverter.cs new file mode 100644 index 0000000..14f5fea --- /dev/null +++ b/Sicoob.Cobranca/DataAnotation/CustomDateTimeWithZoneConverter.cs @@ -0,0 +1,17 @@ +using Newtonsoft.Json.Converters; + +public class CustomDateTimeWithZoneConverter : IsoDateTimeConverter +{ + public CustomDateTimeWithZoneConverter() + { + DateTimeFormat = "yyyy-MM-ddTHH:mm:sszzz"; + } +} + +public class CustomDateTimeConverter : IsoDateTimeConverter +{ + public CustomDateTimeConverter() + { + DateTimeFormat = "yyyy-MM-dd"; + } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Helpers.cs b/Sicoob.Cobranca/Helpers.cs index 2142b9e..4280a7b 100644 --- a/Sicoob.Cobranca/Helpers.cs +++ b/Sicoob.Cobranca/Helpers.cs @@ -1,6 +1,7 @@ -namespace Sicoob.Cobranca; +using Sicoob.Cobranca.Models.v2; + +namespace Sicoob.Cobranca; -using Sicoob.Cobranca.Models; using System; using System.Collections.Generic; using System.IO.Compression; diff --git a/Sicoob.Cobranca/Models/Shared/Beneficiariofinal.cs b/Sicoob.Cobranca/Models/Shared/Beneficiariofinal.cs new file mode 100644 index 0000000..7c9fe68 --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/Beneficiariofinal.cs @@ -0,0 +1,7 @@ +namespace Sicoob.Cobranca.Models.Shared; + +public class Beneficiariofinal +{ + public string? numeroCpfCnpj { get; set; } + public string? nome { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/DadosPagador.cs b/Sicoob.Cobranca/Models/Shared/DadosPagador.cs similarity index 88% rename from Sicoob.Cobranca/Models/DadosPagador.cs rename to Sicoob.Cobranca/Models/Shared/DadosPagador.cs index 9037938..310eafb 100644 --- a/Sicoob.Cobranca/Models/DadosPagador.cs +++ b/Sicoob.Cobranca/Models/Shared/DadosPagador.cs @@ -1,4 +1,4 @@ -namespace Sicoob.Cobranca.Models; +namespace Sicoob.Cobranca.Models.Shared; public class DadosPagador { diff --git a/Sicoob.Cobranca/Models/Shared/Enum.cs b/Sicoob.Cobranca/Models/Shared/Enum.cs new file mode 100644 index 0000000..baaa971 --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/Enum.cs @@ -0,0 +1,93 @@ +namespace Sicoob.Cobranca.Models.Shared; + + + public enum IdentificacaoEmissaoBoleto: int + { + BancoEmite = 1, + ClienteEmite = 2 + } + + public enum IdentificacaoDistribuicaoBoleto : int + { + BancoDistribui = 1, + ClienteDistribui = 2 + } + + public enum TipoDesconto : int + { + SemDesconto = 0, + ValorFixoAteDataInformada = 1, + PercentualAteDataInformada = 2, + ValorPorAntecipacaoDiaCorrido = 3, + ValorPorAntecipacaoDiaUtil = 4, + PercentualPorAntecipacaoDiaCorrido = 5, + PercentualPorAntecipacaoDiaUtil = 6 + } + + public enum TipoJurosMora : int + { + ValorPorDia = 1, + TaxaMensal = 2, + Isento = 3 + } + + public enum TipoMulta : int + { + Isento = 0, + ValorFixo = 1, + Percentual = 2 + } + + public enum CodigoNegativacao : int + { + NegativarDiasUteis = 2, + NaoNegativar = 3 + } + + public enum CodigoProtesto : int + { + ProtestarDiasCorridos = 1, + ProtestarDiasUteis = 2, + NaoProtestar = 3, + } + + public enum CodigoCadastrarPIX : int + { + Padrao = 0, + ComPIX = 1, + SemPIX = 1 + } + + public enum Modalidade : int + { + SimplesComRegistro = 1, + CarneDePagamentos = 5, + Indexada = 6, + CartaoDeCredito = 14 + } + public struct SituacaoBoleto + { + public const string Liquidado = "Liquidado"; + public const string EmAberto = "Em Aberto"; + public const string Baixado = "Baixado"; + } + + public enum TipoHistorico : int + { + Entrada = 1, + Alteracao = 2, + Prorrogacao = 3, + Terifas = 4, + Protesto = 5, + LiquidacaoBaixa = 6 + } + + public enum Tipo + { + Entrada = 1, + Prorrogacao = 2, + A_Vencer = 3, + Vencido = 4, + Liquidacao = 5, + Baixa = 6, + } \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/Shared/Listahistorico.cs b/Sicoob.Cobranca/Models/Shared/Listahistorico.cs new file mode 100644 index 0000000..75d3925 --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/Listahistorico.cs @@ -0,0 +1,10 @@ +using System; + +namespace Sicoob.Cobranca.Models.Shared; + +public class Listahistorico +{ + public DateTime? dataHistorico { get; set; } + public int? tipoHistorico { get; set; } + public string? descricaoHistorico { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/Shared/Rateiocredito.cs b/Sicoob.Cobranca/Models/Shared/Rateiocredito.cs new file mode 100644 index 0000000..292ec39 --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/Rateiocredito.cs @@ -0,0 +1,18 @@ +namespace Sicoob.Cobranca.Models.Shared; + +public class Rateiocredito +{ + public int numeroBanco { get; set; } + public int numeroAgencia { get; set; } + public int numeroContaCorrente { get; set; } + public bool contaPrincipal { get; set; } + public int codigoTipoValorRateio { get; set; } + public decimal valorRateio { get; set; } + public int codigoTipoCalculoRateio { get; set; } + public string? numeroCpfCnpjTitular { get; set; } + public string? nomeTitular { get; set; } + public int codigoFinalidadeTed { get; set; } + public string? codigoTipoContaDestinoTed { get; set; } + public int quantidadeDiasFloat { get; set; } + public string? dataFloatCredito { get; set; } +} diff --git a/Sicoob.Cobranca/Models/Shared/RetornoArquivoMovimentacao.cs b/Sicoob.Cobranca/Models/Shared/RetornoArquivoMovimentacao.cs new file mode 100644 index 0000000..2b590fd --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/RetornoArquivoMovimentacao.cs @@ -0,0 +1,7 @@ +namespace Sicoob.Cobranca.Models.Shared; + +public class RetornoArquivoMovimentacao +{ + public string arquivo { get; set; } + public string nomeArquivo { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/Shared/RetornoConsultaMovimentacoes.cs b/Sicoob.Cobranca/Models/Shared/RetornoConsultaMovimentacoes.cs new file mode 100644 index 0000000..062ba28 --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/RetornoConsultaMovimentacoes.cs @@ -0,0 +1,9 @@ +namespace Sicoob.Cobranca.Models.Shared; + +public class RetornoConsultaMovimentacoes +{ + public string quantidadeTotalRegistros { get; set; } + public int quantidadeRegistrosArquivo { get; set; } + public int quantidadeArquivo { get; set; } + public int[] idArquivos { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/Shared/RetornoSolicitacaoMovimentacoesCarteira.cs b/Sicoob.Cobranca/Models/Shared/RetornoSolicitacaoMovimentacoesCarteira.cs new file mode 100644 index 0000000..a442ae0 --- /dev/null +++ b/Sicoob.Cobranca/Models/Shared/RetornoSolicitacaoMovimentacoesCarteira.cs @@ -0,0 +1,7 @@ +namespace Sicoob.Cobranca.Models.Shared; + +public class RetornoSolicitacaoMovimentacoesCarteira +{ + public string mensagem { get; set; } + public int codigoSolicitacao { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v2/AlterarDataVencimento.cs b/Sicoob.Cobranca/Models/v2/AlterarDataVencimento.cs new file mode 100644 index 0000000..73a61e8 --- /dev/null +++ b/Sicoob.Cobranca/Models/v2/AlterarDataVencimento.cs @@ -0,0 +1,21 @@ +using System; +using Newtonsoft.Json; + +namespace Sicoob.Cobranca.Models.v2; + +public class AlterarDataVencimentoRequest : BoletoBase +{ + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] + public DateTime dataVencimento { get; set; } +} + +public class AlterarDataVencimentoResponse +{ + public DadosDataVencimento[]? resultado { get; set; } + public ResultadoInfo?[] mensagens { get; set; } +} +public class DadosDataVencimento +{ + public ResultadoInfo? status { get; set; } + public AlterarDataVencimentoRequest? boleto { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v2/BaixarBoleto.cs b/Sicoob.Cobranca/Models/v2/BaixarBoleto.cs new file mode 100644 index 0000000..929e446 --- /dev/null +++ b/Sicoob.Cobranca/Models/v2/BaixarBoleto.cs @@ -0,0 +1,17 @@ +namespace Sicoob.Cobranca.Models.v2; + +public class BaixarBoletoRequest : BoletoBase +{ + public string seuNumero { get; set; } +} + +public class BaixarBoletoResponse +{ + public DadosBaixa[]? resultado { get; set; } + public ResultadoInfo? mensagens { get; set; } +} +public class DadosBaixa +{ + public ResultadoInfo? status { get; set; } + public BaixarBoletoRequest? boleto { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v2/BoletoBase.cs b/Sicoob.Cobranca/Models/v2/BoletoBase.cs new file mode 100644 index 0000000..2daead3 --- /dev/null +++ b/Sicoob.Cobranca/Models/v2/BoletoBase.cs @@ -0,0 +1,11 @@ +using Newtonsoft.Json; + +namespace Sicoob.Cobranca.Models.v2; + +public abstract class BoletoBase +{ + public int numeroContrato { get; set; } + public int modalidade { get; set; } = 1; // Simples com Registro + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public int? nossoNumero { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/ConsultaBoleto.cs b/Sicoob.Cobranca/Models/v2/ConsultaBoleto.cs similarity index 74% rename from Sicoob.Cobranca/Models/ConsultaBoleto.cs rename to Sicoob.Cobranca/Models/v2/ConsultaBoleto.cs index 83ede78..4d0c952 100644 --- a/Sicoob.Cobranca/Models/ConsultaBoleto.cs +++ b/Sicoob.Cobranca/Models/v2/ConsultaBoleto.cs @@ -1,6 +1,7 @@ -namespace Sicoob.Cobranca.Models; +using System; +using Sicoob.Cobranca.Models.Shared; -using System; +namespace Sicoob.Cobranca.Models.v2; public class ConsultaBoletoRequest { @@ -51,7 +52,7 @@ public class DadosBoleto public DateTime dataVencimento { get; set; } public DateTime dataLimitePagamento { get; set; } public decimal valorAbatimento { get; set; } - public int tipoDesconto { get; set; } + public string tipoDesconto { get; set; } public DateTime dataPrimeiroDesconto { get; set; } public decimal valorPrimeiroDesconto { get; set; } public DateTime dataSegundoDesconto { get; set; } @@ -81,38 +82,8 @@ public class DadosBoleto public string? qrCode { get; set; } } -public class Beneficiariofinal -{ - public string? numeroCpfCnpj { get; set; } - public string? nome { get; set; } -} - public class Mensagensinstrucao { public int tipoInstrucao { get; set; } public string[] mensagens { get; set; } -} - -public class Listahistorico -{ - public DateTime dataHistorico { get; set; } - public string? tipoHistorico { get; set; } - public string? descricaoHistorico { get; set; } -} - -public class Rateiocredito -{ - public int numeroBanco { get; set; } - public int numeroAgencia { get; set; } - public int numeroContaCorrente { get; set; } - public bool contaPrincipal { get; set; } - public int codigoTipoValorRateio { get; set; } - public decimal valorRateio { get; set; } - public int codigoTipoCalculoRateio { get; set; } - public string? numeroCpfCnpjTitular { get; set; } - public string? nomeTitular { get; set; } - public int codigoFinalidadeTed { get; set; } - public string? codigoTipoContaDestinoTed { get; set; } - public int quantidadeDiasFloat { get; set; } - public string? dataFloatCredito { get; set; } -} +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/IncluirBoletos.cs b/Sicoob.Cobranca/Models/v2/IncluirBoletos.cs similarity index 54% rename from Sicoob.Cobranca/Models/IncluirBoletos.cs rename to Sicoob.Cobranca/Models/v2/IncluirBoletos.cs index 45b515c..f5a4495 100644 --- a/Sicoob.Cobranca/Models/IncluirBoletos.cs +++ b/Sicoob.Cobranca/Models/v2/IncluirBoletos.cs @@ -1,34 +1,47 @@ -namespace Sicoob.Cobranca.Models; +using System; +using Newtonsoft.Json; +using Sicoob.Cobranca.Models.Shared; -using System; +namespace Sicoob.Cobranca.Models.v2; -public class IncluirBoletosRequest +public class IncluirBoletosRequest : BoletoBase { - public int numeroContrato { get; set; } - public int modalidade { get; set; } = 1; // Simples com Registro public int numeroContaCorrente { get; set; } public string especieDocumento { get; set; } = "DM"; // Duplicata Mercantil, ver lista + + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] public DateTime dataEmissao { get; set; } - public int nossoNumero { get; set; } public string seuNumero { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] public string identificacaoBoletoEmpresa { get; set; } public int identificacaoEmissaoBoleto { get; set; } public int identificacaoDistribuicaoBoleto { get; set; } public decimal valor { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] public DateTime dataVencimento { get; set; } - public DateTime dataLimitePagamento { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime? dataLimitePagamento { get; set; } public int valorAbatimento { get; set; } public int tipoDesconto { get; set; } - public DateTime dataPrimeiroDesconto { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime? dataPrimeiroDesconto { get; set; } public decimal valorPrimeiroDesconto { get; set; } - public DateTime dataSegundoDesconto { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime? dataSegundoDesconto { get; set; } public decimal valorSegundoDesconto { get; set; } - public DateTime dataTerceiroDesconto { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime? dataTerceiroDesconto { get; set; } public decimal valorTerceiroDesconto { get; set; } public int tipoMulta { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] public DateTime dataMulta { get; set; } public decimal valorMulta { get; set; } public int tipoJurosMora { get; set; } + [JsonConverter(typeof(CustomDateTimeWithZoneConverter))] public DateTime dataJurosMora { get; set; } public decimal valorJurosMora { get; set; } public int numeroParcela { get; set; } @@ -41,12 +54,14 @@ public class IncluirBoletosRequest public Beneficiariofinal beneficiarioFinal { get; set; } public Mensagensinstrucao mensagensInstrucao { get; set; } public bool gerarPdf { get; set; } - public Rateiocredito[] rateioCreditos { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public Rateiocredito?[] rateioCreditos { get; set; } /// /// 0: Padrão, 1: Com PIX, 2: Sem PIX /// public int codigoCadastrarPIX { get; set; } - public int numeroContratoCobranca { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public int? numeroContratoCobranca { get; set; } } public class IncluirBoletosResponse @@ -55,11 +70,6 @@ public class IncluirBoletosResponse } public class DadosInclusao { - public ResultadoInclusao? status { get; set; } + public ResultadoInfo? status { get; set; } public DadosBoleto? boleto { get; set; } -} -public class ResultadoInclusao -{ - public int codigo { get; set; } - public string mensagem { get; set; } = string.Empty; } \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/Movimentacoes.cs b/Sicoob.Cobranca/Models/v2/Movimentacoes.cs similarity index 71% rename from Sicoob.Cobranca/Models/Movimentacoes.cs rename to Sicoob.Cobranca/Models/v2/Movimentacoes.cs index 37a8dfc..cafb192 100644 --- a/Sicoob.Cobranca/Models/Movimentacoes.cs +++ b/Sicoob.Cobranca/Models/v2/Movimentacoes.cs @@ -1,19 +1,9 @@ -namespace Sicoob.Cobranca.Models; +using System; -using System; +namespace Sicoob.Cobranca.Models.v2; public class SolicitacaoMovimentacoesCarteira { - public enum Tipo - { - Entrada = 1, - Prorrogacao = 2, - A_Vencer = 3, - Vencido = 4, - Liquidacao = 5, - Baixa = 6, - } - public int numeroContrato { get; set; } /// /// 1. Entrada 2. Prorrogação 3. A Vencer 4. Vencido 5. Liquidação 6. Baixa @@ -27,23 +17,7 @@ public class ResponseMovimentacao { public T resultado { get; set; } } -public class RetornoSolicitacaoMovimentacoesCarteira -{ - public string mensagem { get; set; } - public int codigoSolicitacao { get; set; } -} -public class RetornoConsultaMovimentacoes -{ - public string quantidadeTotalRegistros { get; set; } - public int quantidadeRegistrosArquivo { get; set; } - public int quantidadeArquivo { get; set; } - public int[] idArquivos { get; set; } -} -public class RetornoArquivoMovimentacao -{ - public string arquivo { get; set; } - public string nomeArquivo { get; set; } -} + public class MovimentacoesArquivos { public int codigoSolicitacao { get; set; } diff --git a/Sicoob.Cobranca/Models/v2/ProtestarBoleto.cs b/Sicoob.Cobranca/Models/v2/ProtestarBoleto.cs new file mode 100644 index 0000000..9d29698 --- /dev/null +++ b/Sicoob.Cobranca/Models/v2/ProtestarBoleto.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; + +namespace Sicoob.Cobranca.Models.v2; + +public class ProtestarBoletoRequest: BoletoBase +{ + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public int? numeroContratoCobranca { get; set; } +} + +public class ProtestarBoletoResponse +{ + public DadosProtestar[]? resultado { get; set; } + public ResultadoInfo[]? mensagens { get; set; } +} +public class DadosProtestar +{ + public ResultadoInfo? status { get; set; } + public ProtestarBoletoRequest? boleto { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v2/ResultadoInfo.cs b/Sicoob.Cobranca/Models/v2/ResultadoInfo.cs new file mode 100644 index 0000000..fbba67d --- /dev/null +++ b/Sicoob.Cobranca/Models/v2/ResultadoInfo.cs @@ -0,0 +1,7 @@ +namespace Sicoob.Cobranca.Models.v2; + +public class ResultadoInfo +{ + public int codigo { get; set; } + public string mensagem { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v3/AlterarBoletoRequest.cs b/Sicoob.Cobranca/Models/v3/AlterarBoletoRequest.cs new file mode 100644 index 0000000..c754896 --- /dev/null +++ b/Sicoob.Cobranca/Models/v3/AlterarBoletoRequest.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Sicoob.Cobranca.Models.v3; + +public class AlterarBoletoRequest +{ + public long numeroCliente { get; set; } + public int codigoModalidade { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public EspecieDocumento? especieDocumento { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public SeuNumero? seuNumero { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public Desconto? desconto { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public Abatimento? abatimento { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public Multa? multa { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public JurosMora? jurosMora { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public RateioCredito? rateioCredito { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public Pix? pix { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public ProrrogacaoVencimento? prorrogacaoVencimento { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public ProrrogacaoLimitePagamento? prorrogacaoLimitePagamento { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public ValorNominal? valorNominal { get; set; } +} + +public class EspecieDocumento +{ + public string codigoEspecieDocumento { get; set; } +} + +public class SeuNumero +{ + public string seuNumero { get; set; } + public string identificacaoBoletoEmpresa { get; set; } +} + +public class Desconto +{ + public int tipoDesconto { get; set; } + public DateTime dataPrimeiroDesconto { get; set; } + public decimal valorPrimeiroDesconto { get; set; } + public DateTime? dataSegundoDesconto { get; set; } + public decimal? valorSegundoDesconto { get; set; } + public DateTime? dataTerceiroDesconto { get; set; } + public decimal? valorTerceiroDesconto { get; set; } +} + +public class Abatimento +{ + public decimal valorAbatimento { get; set; } +} + +public class Multa +{ + public int tipoMulta { get; set; } + public DateTime dataMulta { get; set; } + public decimal valorMulta { get; set; } +} + +public class JurosMora +{ + public int tipoJurosMora { get; set; } + public DateTime dataJurosMora { get; set; } + public decimal valorJurosMora { get; set; } +} + +public class RateioCredito +{ + public int tipoOperacao { get; set; } + public List rateioCreditos { get; set; } +} + +public class RateioCreditoDetalhe +{ + public int numeroBanco { get; set; } + public int numeroAgencia { get; set; } + public int numeroContaCorrente { get; set; } + public bool contaPrincipal { get; set; } + public int codigoTipoValorRateio { get; set; } + public decimal valorRateio { get; set; } + public int codigoTipoCalculoRateio { get; set; } + public string numeroCpfCnpjTitular { get; set; } + public string nomeTitular { get; set; } + public int codigoFinalidadeTed { get; set; } + public string codigoTipoContaDestinoTed { get; set; } + public int quantidadeDiasFloat { get; set; } + public DateTime dataFloatCredito { get; set; } +} + +public class Pix +{ + public bool utilizarPix { get; set; } +} + +public class ProrrogacaoVencimento +{ + public DateTime dataVencimento { get; set; } +} + +public class ProrrogacaoLimitePagamento +{ + public DateTime dataLimitePagamento { get; set; } +} + +public class ValorNominal +{ + public decimal valor { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v3/BaixarBoletoRequest.cs b/Sicoob.Cobranca/Models/v3/BaixarBoletoRequest.cs new file mode 100644 index 0000000..1bd1cb6 --- /dev/null +++ b/Sicoob.Cobranca/Models/v3/BaixarBoletoRequest.cs @@ -0,0 +1,7 @@ +namespace Sicoob.Cobranca.Models.v3; + +public class BaixarBoletoRequest +{ + public long numeroCliente { get; set; } + public int codigoModalidade { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v3/ConsultaBoletoRequest.cs b/Sicoob.Cobranca/Models/v3/ConsultaBoletoRequest.cs new file mode 100644 index 0000000..41c8d95 --- /dev/null +++ b/Sicoob.Cobranca/Models/v3/ConsultaBoletoRequest.cs @@ -0,0 +1,89 @@ +using System; +using Sicoob.Cobranca.Models.Shared; +using Sicoob.Cobranca.Models.v2; + +namespace Sicoob.Cobranca.Models.v3; + +public class ConsultaBoletoRequest +{ + public int numeroCliente { get; set; } + public int codigoModalidade { get; set; } = 1; // Só tem a opção de `1` + public int? nossoNumero { get; set; } + public string? linhaDigitavel { get; set; } + public string? codigoBarras { get; set; } + public bool? gerarPdf { get; set; } +} + +public class ConsultaBoletoPagadorRequest +{ + public int numeroCliente { get; set; } + /// + /// 1: Em Aberto + /// 2: Baixado + /// 3: Liquidado + /// + public int? codigoSituação { get; set; } + + public string? dataInicio { get; set; } + public string? dataFim { get; set; } +} + +public class IncluirBoletosResponse +{ + public DadosBoleto? resultado { get; set; } +} + +public class ConsultaBoletoResponse +{ + public DadosBoleto? resultado { get; set; } +} + +public class ConsultaBoletosPagadorResponse +{ + public DadosBoleto[]? resultado { get; set; } +} + +public class DadosBoleto +{ + public int numeroCliente { get; set; } + public int codigoModalidade { get; set; } + public int numeroContaCorrente { get; set; } + public string? especieDocumento { get; set; } + public DateTime dataEmissao { get; set; } + public int nossoNumero { get; set; } + public string? seuNumero { get; set; } + public string? identificacaoBoletoEmpresa { get; set; } + public string? codigoBarras { get; set; } + public string? linhaDigitavel { get; set; } + public decimal valor { get; set; } + public DateTime dataVencimento { get; set; } + public DateTime dataLimitePagamento { get; set; } + public decimal valorAbatimento { get; set; } + public int tipoDesconto { get; set; } + public DateTime dataPrimeiroDesconto { get; set; } + public decimal valorPrimeiroDesconto { get; set; } + public DateTime dataSegundoDesconto { get; set; } + public decimal valorSegundoDesconto { get; set; } + public DateTime dataTerceiroDesconto { get; set; } + public decimal valorTerceiroDesconto { get; set; } + public int tipoMulta { get; set; } + public DateTime dataMulta { get; set; } + public decimal valorMulta { get; set; } + public int tipoJurosMora { get; set; } + public DateTime dataJurosMora { get; set; } + public decimal valorJurosMora { get; set; } + public int numeroParcela { get; set; } + public bool aceite { get; set; } + public int codigoNegativacao { get; set; } + public int codigoProtesto { get; set; } + public int numeroDiasProtesto { get; set; } + public int quantidadeDiasFloat { get; set; } + public DadosPagador? pagador { get; set; } + public Beneficiariofinal? beneficiarioFinal { get; set; } + public string[]? mensagensInstrucao { get; set; } + public Listahistorico[]? listaHistorico { get; set; } + public string? situacaoBoleto { get; set; } + public Rateiocredito[]? rateioCreditos { get; set; } + public string? pdfBoleto { get; set; } + public string? qrCode { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v3/IncluirBoleto.cs b/Sicoob.Cobranca/Models/v3/IncluirBoleto.cs new file mode 100644 index 0000000..3ab5805 --- /dev/null +++ b/Sicoob.Cobranca/Models/v3/IncluirBoleto.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Sicoob.Cobranca.Models.Shared; + +namespace Sicoob.Cobranca.Models.v3; + +public class IncluirBoletoRequest +{ + public long numeroCliente { get; set; } + public int codigoModalidade { get; set; } + public int numeroContaCorrente { get; set; } + public string codigoEspecieDocumento { get; set; } = "DM"; // Duplicata Mercantil, ver lista + [JsonConverter(typeof(CustomDateTimeConverter))] + public DateTime? dataEmissao { get; set; } + public long nossoNumero { get; set; } + public string seuNumero { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public string? identificacaoBoletoEmpresa { get; set; } + public int identificacaoEmissaoBoleto { get; set; } + public int identificacaoDistribuicaoBoleto { get; set; } + public decimal valor { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + public DateTime dataVencimento { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime? dataLimitePagamento { get; set; } + public decimal valorAbatimento { get; set; } + public int tipoDesconto { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime dataPrimeiroDesconto { get; set; } + public decimal valorPrimeiroDesconto { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime dataSegundoDesconto { get; set; } + public decimal valorSegundoDesconto { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public DateTime dataTerceiroDesconto { get; set; } + public decimal valorTerceiroDesconto { get; set; } + public int tipoMulta { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + public DateTime dataMulta { get; set; } + public decimal valorMulta { get; set; } + public int tipoJurosMora { get; set; } + [JsonConverter(typeof(CustomDateTimeConverter))] + public DateTime dataJurosMora { get; set; } + public decimal valorJurosMora { get; set; } + public int numeroParcela { get; set; } + public bool aceite { get; set; } + public int codigoNegativacao { get; set; } + public int numeroDiasNegativacao { get; set; } + public int codigoProtesto { get; set; } + public int numeroDiasProtesto { get; set; } + public DadosPagador pagador { get; set; } + public Beneficiariofinal beneficiarioFinal { get; set; } + public string[] mensagensInstrucao { get; set; } + public bool gerarPdf { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public Rateiocredito[] rateioCreditos { get; set; } + /// + /// 0: Padrão, 1: Com PIX, 2: Sem PIX + /// + public int codigoCadastrarPIX { get; set; } + [JsonProperty(NullValueHandling=NullValueHandling.Ignore)] + public int? numeroContratoCobranca { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v3/MovimentacaoRequest.cs b/Sicoob.Cobranca/Models/v3/MovimentacaoRequest.cs new file mode 100644 index 0000000..74e82c4 --- /dev/null +++ b/Sicoob.Cobranca/Models/v3/MovimentacaoRequest.cs @@ -0,0 +1,14 @@ +using System; + +namespace Sicoob.Cobranca.Models.v3; + +public class MovimentacaoRequest +{ + public int numeroCliente { get; set; } + /// + /// 1. Entrada 2. Prorrogação 3. A Vencer 4. Vencido 5. Liquidação 6. Baixa + /// + public int tipoMovimento { get; set; } + public DateTime dataInicial { get; set; } + public DateTime dataFinal { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Models/v3/ProtestoRequest.cs b/Sicoob.Cobranca/Models/v3/ProtestoRequest.cs new file mode 100644 index 0000000..c84d7a5 --- /dev/null +++ b/Sicoob.Cobranca/Models/v3/ProtestoRequest.cs @@ -0,0 +1,7 @@ +namespace Sicoob.Cobranca.Models.v3; + +public class ProtestoRequest +{ + public long numeroCliente { get; set; } + public int codigoModalidade { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Cobranca/Sicoob.Cobranca.csproj b/Sicoob.Cobranca/Sicoob.Cobranca.csproj index 3ffa868..0d792cb 100644 --- a/Sicoob.Cobranca/Sicoob.Cobranca.csproj +++ b/Sicoob.Cobranca/Sicoob.Cobranca.csproj @@ -5,7 +5,7 @@ 10.0 enable disable - 0.0.3-alpha + 0.0.6-alpha RafaelEstevam.Net SHARP SISTEMAS LTDA Sicoob Cobrança for C# diff --git a/Sicoob.Cobranca/SicoobCobranca.cs b/Sicoob.Cobranca/SicoobCobrancaV2.cs similarity index 71% rename from Sicoob.Cobranca/SicoobCobranca.cs rename to Sicoob.Cobranca/SicoobCobrancaV2.cs index a6dcbda..256e9bc 100644 --- a/Sicoob.Cobranca/SicoobCobranca.cs +++ b/Sicoob.Cobranca/SicoobCobrancaV2.cs @@ -3,9 +3,13 @@ * Autor: Rafael Estevam * * gh/SharpSistemas/SicoobAPI * \**************************************/ + +using Sicoob.Cobranca.Models.Shared; +using Sicoob.Cobranca.Models.v2; +using Sicoob.Shared.Models; + namespace Sicoob.Cobranca; -using Sicoob.Cobranca.Models; using Sicoob.Shared.Models.Acesso; using Sicoob.Shared.Models.Geral; using Simple.API; @@ -19,7 +23,7 @@ namespace Sicoob.Cobranca; /// /// Classe para comunicação com as APIs de Cobrança do Sicoob /// -public sealed class SicoobCobranca : Shared.Sicoob +public sealed class SicoobCobrancaV2 : Shared.Sicoob { // Documentações // > APIs tipo "Swagger": @@ -31,8 +35,10 @@ public sealed class SicoobCobranca : Shared.Sicoob private ClientInfo clientApi; public Shared.Models.ConfiguracaoAPI ConfigApi { get; } public string? PastaCopiaMovimentacoes { get; set; } + public delegate void UpdateToken(ConfiguracaoToken token); + public event UpdateToken UpdateTokenEvent; - public SicoobCobranca(Shared.Models.ConfiguracaoAPI configApi, int NumeroContrato, System.Security.Cryptography.X509Certificates.X509Certificate2? certificado = null) + public SicoobCobrancaV2(Shared.Models.ConfiguracaoAPI configApi, int NumeroContrato, System.Security.Cryptography.X509Certificates.X509Certificate2? certificado = null) : base(configApi, certificado) { numeroContrato = NumeroContrato; @@ -43,10 +49,22 @@ public SicoobCobranca(Shared.Models.ConfiguracaoAPI configApi, int NumeroContrat protected override void setupClients(HttpClientHandler handler) { clientApi = new ClientInfo(ConfigApi.UrlApi, handler); - clientApi.SetHeader("x-sicoob-clientid", ConfigApi.ClientId); + clientApi.SetHeader("client_id", ConfigApi.ClientId); + + if (ConfigApi.Token is not null) + clientApi.SetAuthorizationBearer(ConfigApi.Token.Token); } protected override void atualizaClients(TokenResponse token) { + ConfigApi.Token = new ConfiguracaoToken() + { + ExpiresAtUTC = DateTime.UtcNow.AddSeconds(token.expires_in), + Token = token.access_token + }; + //Notificar quando o token foi atualizado + if (UpdateTokenEvent is not null) + UpdateTokenEvent(ConfigApi.Token); + clientApi.SetAuthorizationBearer(token.access_token); } @@ -55,22 +73,22 @@ protected override void atualizaClients(TokenResponse token) /// /// Consulta boleto utilizando um dos três métodos de busca /// - /// Número que identifica o contrato do beneficiário no Sisbr + /// /// Número identificador do boleto no Sisbr. Caso seja infomado, não é necessário infomar a linha digitável ou código de barras /// Número da linha digitável do boleto com 47 posições. Caso seja informado, não é necessário informar o nosso número ou código de barras /// Número de código de barras do boleto com 44 posições.Caso seja informado, não é necessário informar o nosso número ou linha digitável /// Boleto buscado - public async Task ConsultarBoleto(int? nossoNumero = null, string? linhaDigitavel = null, string? codigoBarras = null) + public async Task ConsultarBoleto(int? nossoNumero = null, string? linhaDigitavel = null, string? codigoBarras = null, int modalidade = (int)Modalidade.SimplesComRegistro) { var consulta = new ConsultaBoletoRequest() { - modalidade = 1, + modalidade = modalidade, numeroContrato = numeroContrato, nossoNumero = nossoNumero, linhaDigitavel = linhaDigitavel, codigoBarras = codigoBarras }; - return await ExecutaChamadaAsync(() => clientApi.GetAsync("/cobranca-bancaria/v2/cobranca-bancaria/v2/boletos", consulta)); + return await ExecutaChamadaAsync(() => clientApi.GetAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos", consulta)); } /// @@ -91,7 +109,7 @@ public async Task ConsultarBoletosPagador(string dataInicio = dataVencimentoInicio?.ToString("yyyy-MM-dd"), dataFim = dataVencimentoFim?.ToString("yyyy-MM-dd") }; - return await ExecutaChamadaAsync(() => clientApi.GetAsync("/cobranca-bancaria/v2/cobranca-bancaria/v2/boletos/pagadores/" + numeroCpfCnpj, consulta)); + return await ExecutaChamadaAsync(() => clientApi.GetAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/pagadores/" + numeroCpfCnpj, consulta)); } public async Task ConsultarSegundaViaBoleto(int modalidade, int? nossoNumero = null, string? linhaDigitavel = null, string? codigoBarras = null, bool gerarPdf = false) @@ -105,32 +123,47 @@ public async Task ConsultarBoletosPagador(string codigoBarras = codigoBarras, gerarPdf = gerarPdf }; - return await ExecutaChamadaAsync(() => clientApi.GetAsync("/cobranca-bancaria/v2/cobranca-bancaria/v2/boletos/segunda-via", consulta)); + return await ExecutaChamadaAsync(() => clientApi.GetAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/segunda-via", consulta)); } public async Task IncluirBoletos(IncluirBoletosRequest[] boletos) { - return await ExecutaChamadaAsync(() => clientApi.PostAsync("/cobranca-bancaria/v2/cobranca-bancaria/v2/boletos", boletos)); + return await ExecutaChamadaAsync(() => clientApi.PostAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos", boletos)); + } + + public async Task BaixarBoletos(BaixarBoletoRequest[] boletos) + { + return await ExecutaChamadaAsync(() => clientApi.PatchAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/baixa", boletos)); + } + + public async Task ProtestarBoletos(ProtestarBoletoRequest[] boletos) + { + return await ExecutaChamadaAsync(() => clientApi.PostAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/protestos", boletos)); + } + + public async Task AlterarDataVencimento(AlterarDataVencimentoRequest[] boletos) + { + return await ExecutaChamadaAsync(() => clientApi.PatchAsync(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/prorrogacoes/data-vencimento", boletos)); } /* Movimentação */ - public async Task SolicitarMovimentacao(SolicitacaoMovimentacoesCarteira.Tipo tipoMovimento, DateTime data) + public async Task SolicitarMovimentacao(Tipo tipoMovimento, DateTime data) { var di = data.Date; var df = data.Date.AddDays(1).AddSeconds(-1); return await SolicitarMovimentacao(tipoMovimento, di, df); } - public async Task SolicitarMovimentacao(SolicitacaoMovimentacoesCarteira.Tipo tipoMovimento, DateTime dataInicial, DateTime dataFinal) + public async Task SolicitarMovimentacao(Tipo tipoMovimento, DateTime dataInicial, DateTime dataFinal) => await SolicitarMovimentacao(new SolicitacaoMovimentacoesCarteira() { numeroContrato = numeroContrato, tipoMovimento = (int)tipoMovimento, dataInicial = dataInicial, dataFinal = dataFinal }); private async Task SolicitarMovimentacao(SolicitacaoMovimentacoesCarteira solicitacao) { - var retorno = await ExecutaChamadaAsync(() => clientApi.PostAsync>("/cobranca-bancaria/v2/boletos/solicitacoes/movimentacao", solicitacao)); + var retorno = await ExecutaChamadaAsync(() => clientApi.PostAsync>(ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/solicitacoes/movimentacao", solicitacao)); return retorno.resultado; } public async Task ConsultarSituacaoSolicitacao(int codigoSolicitacao) { await VerificaAtualizaCredenciaisAsync(); - var result = await clientApi.GetAsync>("/cobranca-bancaria/v2/boletos/solicitacoes/movimentacao", new { numeroContrato, codigoSolicitacao }); + var result = await clientApi.GetAsync>( ConfigApi.UrlApi + "cobranca-bancaria/v2/boletos/solicitacoes/movimentacao", new { numeroContrato, codigoSolicitacao }); if (result.IsSuccessStatusCode) return result.Data.resultado; @@ -148,7 +181,7 @@ private async Task SolicitarMovimentaca } internal async Task DownloadArquivoMovimentacao(int codigoSolicitacao, int idArquivo) { - var retorno = await ExecutaChamadaAsync(() => clientApi.GetAsync>("/cobranca-bancaria/v2/boletos/movimentacao-download", new { numeroContrato, codigoSolicitacao, idArquivo })); + var retorno = await ExecutaChamadaAsync(() => clientApi.GetAsync>(ConfigApi.UrlApi + "/cobranca-bancaria/v2/boletos/movimentacao-download", new { numeroContrato, codigoSolicitacao, idArquivo })); return retorno.resultado; } public async Task BaixarMovimentacoes(int codigoSolicitacao, int[] arquivos) diff --git a/Sicoob.Cobranca/SicoobCobrancaV3.cs b/Sicoob.Cobranca/SicoobCobrancaV3.cs new file mode 100644 index 0000000..b35b87e --- /dev/null +++ b/Sicoob.Cobranca/SicoobCobrancaV3.cs @@ -0,0 +1,235 @@ +/**************************************\ + * Biblioteca C# para APIs do SICOOB * + * Autor: Rafael Estevam * + * gh/SharpSistemas/SicoobAPI * +\**************************************/ + +using Sicoob.Cobranca.Models.Shared; +using Sicoob.Cobranca.Models.v2; +using Sicoob.Cobranca.Models.v3; +using Sicoob.Shared.Models; +using BaixarBoletoRequest = Sicoob.Cobranca.Models.v3.BaixarBoletoRequest; +using ConsultaBoletoRequest = Sicoob.Cobranca.Models.v3.ConsultaBoletoRequest; +using ConsultaBoletoResponse = Sicoob.Cobranca.Models.v3.ConsultaBoletoResponse; +using ConsultaBoletosPagadorResponse = Sicoob.Cobranca.Models.v3.ConsultaBoletosPagadorResponse; +using IncluirBoletosResponse = Sicoob.Cobranca.Models.v3.IncluirBoletosResponse; + +namespace Sicoob.Cobranca; + +using Sicoob.Shared.Models.Acesso; +using Sicoob.Shared.Models.Geral; +using Simple.API; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; + +/// +/// Classe para comunicação com as APIs de Cobrança do Sicoob +/// +public sealed class SicoobCobrancaV3 : Shared.Sicoob +{ + // Documentações + // > APIs tipo "Swagger": + // https://developers.sicoob.com.br/#!/apis + // > Link que o Suporte do Sicoob enviou + // https://documenter.getpostman.com/view/20565799/Uzs6yNhe#6447c293-f67b-44ba-b7be-41f5c3de978d + + private readonly int numeroContrato; + private ClientInfo clientApi; + private Shared.Models.ConfiguracaoAPI ConfigApi { get; } + public string? PastaCopiaMovimentacoes { get; set; } + public delegate void UpdateToken(ConfiguracaoToken token); + public event UpdateToken? UpdateTokenEvent; + + public SicoobCobrancaV3(ConfiguracaoAPI configApi, int nroContrato, System.Security.Cryptography.X509Certificates.X509Certificate2? certificado = null) + : base(configApi, certificado) + { + numeroContrato = nroContrato; + ConfigApi = configApi; + clientApi = new ClientInfo(ConfigApi.UrlApi); + } + + protected override void setupClients(HttpClientHandler handler) + { + clientApi = new ClientInfo(ConfigApi.UrlApi, handler); + clientApi.SetHeader("client_id", ConfigApi.ClientId); + + if (ConfigApi.Token is not null) + clientApi.SetAuthorizationBearer(ConfigApi.Token.Token); + } + protected override void atualizaClients(TokenResponse token) + { + ConfigApi.Token = new ConfiguracaoToken() + { + ExpiresAtUTC = DateTime.UtcNow.AddSeconds(token.expires_in), + Token = token.access_token + }; + //Notificar quando o token foi atualizado + if (UpdateTokenEvent is not null) + UpdateTokenEvent(ConfigApi.Token); + + clientApi.SetAuthorizationBearer(token.access_token); + } + + /* Boletos */ + + /// + /// Consulta boleto utilizando um dos três métodos de busca + /// + /// + /// Número identificador do boleto no Sisbr. Caso seja infomado, não é necessário infomar a linha digitável ou código de barras + /// Número da linha digitável do boleto com 47 posições. Caso seja informado, não é necessário informar o nosso número ou código de barras + /// Número de código de barras do boleto com 44 posições.Caso seja informado, não é necessário informar o nosso número ou linha digitável + /// Boleto buscado + public async Task ConsultarBoleto(int? nossoNumero = null, string? linhaDigitavel = null, string? codigoBarras = null, int modalidade = (int)Modalidade.SimplesComRegistro) + { + var consulta = new ConsultaBoletoRequest() + { + codigoModalidade = modalidade, + numeroCliente = numeroContrato, + nossoNumero = nossoNumero, + linhaDigitavel = linhaDigitavel, + codigoBarras = codigoBarras + }; + return await ExecutaChamadaAsync(() => clientApi.GetAsync(ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos", consulta)); + } + + /// + /// Consulta boletos de um Pagador + /// + /// CPF/CNPJ do Pagador + /// Código da Situação do Boleto. 1: Em aberto, 2: Baixado, 3: Liquidado + /// Data de Vencimento Inicial + /// Data de Vencimento Final + /// Boletos do Pagador + public async Task ConsultarBoletosPagador(string numeroCpfCnpj, int? codigoSituacao = null, DateTime? dataVencimentoInicio = null, DateTime? dataVencimentoFim = null) + { + var consulta = new ConsultaBoletoPagadorRequest() + { + numeroCliente = numeroContrato, + codigoSituação = codigoSituacao, + dataInicio = dataVencimentoInicio?.ToString("yyyy-MM-dd"), + dataFim = dataVencimentoFim?.ToString("yyyy-MM-dd") + }; + return await ExecutaChamadaAsync(() => clientApi.GetAsync(ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos/pagadores/" + numeroCpfCnpj, consulta)); + } + + public async Task ConsultarSegundaViaBoleto(int modalidade, int? nossoNumero = null, string? linhaDigitavel = null, string? codigoBarras = null, bool gerarPdf = false) + { + var consulta = new ConsultaBoletoRequest() + { + codigoModalidade = modalidade, + numeroCliente = numeroContrato, + nossoNumero = nossoNumero, + linhaDigitavel = linhaDigitavel, + codigoBarras = codigoBarras, + gerarPdf = gerarPdf + }; + return await ExecutaChamadaAsync(() => clientApi.GetAsync(ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos/segunda-via", consulta)); + } + + public async Task IncluirBoletos(IncluirBoletoRequest boleto) + { + return await ExecutaChamadaAsync(() => clientApi.PostAsync(ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos", boleto)); + } + + public async Task BaixarBoletos(int nossoNumero, int codigoModalidade) + { + var baixa = new BaixarBoletoRequest + { + numeroCliente = numeroContrato, + codigoModalidade = codigoModalidade + }; + await ExecutaChamadaAsync(() => clientApi.PatchAsync(ConfigApi.UrlApi + $"cobranca-bancaria/v3/boletos/{nossoNumero}/baixar", baixa)); + } + + public async Task ProtestarBoletos(int nossoNumero, int codigoModalidade) + { + var protesto = new ProtestoRequest + { + numeroCliente = numeroContrato, + codigoModalidade = codigoModalidade, + }; + await ExecutaChamadaAsync(() => clientApi.PostAsync(ConfigApi.UrlApi + $"cobranca-bancaria/v3/boletos/{nossoNumero}/protestos", protesto)); + } + + public async Task AlterarBoleto(int nossoNumero, AlterarBoletoRequest boletos) + { + await ExecutaChamadaAsync(() => clientApi.PatchAsync(ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos/" + nossoNumero, boletos)); + } + + /* Movimentação */ + public async Task SolicitarMovimentacao(Tipo tipoMovimento, DateTime data) + { + var di = data.Date; + var df = data.Date.AddDays(1).AddSeconds(-1); + return await SolicitarMovimentacao(tipoMovimento, di, df); + } + public async Task SolicitarMovimentacao(Tipo tipoMovimento, DateTime dataInicial, DateTime dataFinal) + => await SolicitarMovimentacao(new MovimentacaoRequest() { numeroCliente = numeroContrato, tipoMovimento = (int)tipoMovimento, dataInicial = dataInicial, dataFinal = dataFinal }); + private async Task SolicitarMovimentacao(MovimentacaoRequest movimentacao) + { + var retorno = await ExecutaChamadaAsync(() => clientApi.PostAsync>(ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos/movimentacoes", movimentacao)); + return retorno.resultado; + } + public async Task ConsultarSituacaoSolicitacao(int codigoSolicitacao) + { + await VerificaAtualizaCredenciaisAsync(); + var result = await clientApi.GetAsync>( ConfigApi.UrlApi + "cobranca-bancaria/v3/boletos/solicitacoes/movimentacao", new { numeroCliente = numeroContrato, codigoSolicitacao }); + + if (result.IsSuccessStatusCode) return result.Data.resultado; + + // "{\"mensagens\":[{\"mensagem\":\"Solicitação ainda em processamento.\",\"codigo\":\"5004\"}]}" + if (result.TryParseErrorResponseData(out ErroRequisicao err)) + { + if (err.mensagens == null) { } + + if (err.mensagens.Any(o => o.codigo == 5004)) return null; + + throw new ErroRequisicaoException(err); + } + result.EnsureSuccessStatusCode(); // Erro comum + return null; // a linha de cima vai arremessar o erro padrão + } + + private async Task DownloadArquivoMovimentacao(int codigoSolicitacao, int idArquivo) + { + var retorno = await ExecutaChamadaAsync(() => clientApi.GetAsync>(ConfigApi.UrlApi + "/cobranca-bancaria/v3/boletos/movimentacoes/download", new { numeroCliente = numeroContrato, codigoSolicitacao, idArquivo })); + return retorno.resultado; + } + public async Task BaixarMovimentacoes(int codigoSolicitacao, int[] arquivos) + { + var lst = new List(); + foreach (var idArquivo in arquivos) + { + var retorno = await DownloadArquivoMovimentacao(codigoSolicitacao, idArquivo); + + var bytesZip = Convert.FromBase64String(retorno.arquivo); + SalvarCopiaMovimentacao(bytesZip, retorno.nomeArquivo); + + var registros = Helpers.ProcessarArquivoMovimentacao(bytesZip); + lst.Add(new MovimentacoesArquivos + { + codigoSolicitacao = codigoSolicitacao, + idArquivo = idArquivo, + nomeArquivo = retorno.nomeArquivo, + Movimentacoes = registros.ToArray(), + }); + } + return lst.ToArray(); + } + + private void SalvarCopiaMovimentacao(byte[] bytesZip, string nomeArquivo) + { + if (PastaCopiaMovimentacoes == null) return; + if (!Directory.Exists(PastaCopiaMovimentacoes)) Directory.CreateDirectory(PastaCopiaMovimentacoes); + + var path = Path.Combine(PastaCopiaMovimentacoes, nomeArquivo); + if (File.Exists(path)) return; + + File.WriteAllBytes(path, bytesZip); + } +} diff --git a/Sicoob.Conta/Sicoob.Conta.csproj b/Sicoob.Conta/Sicoob.Conta.csproj index 0ce4bb4..b7c7d61 100644 --- a/Sicoob.Conta/Sicoob.Conta.csproj +++ b/Sicoob.Conta/Sicoob.Conta.csproj @@ -5,7 +5,7 @@ 10.0 warnings disable - 0.9.2 + 0.9.3 RafaelEstevam.Net SHARP SISTEMAS LTDA Sicoob Conta for C# diff --git a/Sicoob.PIX/Sicoob.PIX.csproj b/Sicoob.PIX/Sicoob.PIX.csproj index 8d35f5e..04b2df3 100644 --- a/Sicoob.PIX/Sicoob.PIX.csproj +++ b/Sicoob.PIX/Sicoob.PIX.csproj @@ -5,7 +5,7 @@ 10.0 warnings disable - 0.9.7.4 + 0.9.7.5 RafaelEstevam.Net SHARP SISTEMAS LTDA Sicoob PIX for C# diff --git a/Sicoob.Shared/Models/Configuracao.cs b/Sicoob.Shared/Models/Configuracao.cs index 3be92a5..21010b1 100644 --- a/Sicoob.Shared/Models/Configuracao.cs +++ b/Sicoob.Shared/Models/Configuracao.cs @@ -3,6 +3,9 @@ * Autor: Rafael Estevam * * gh/SharpSistemas/SicoobAPI * \**************************************/ + +using System; + namespace Sicoob.Shared.Models; public class Configuracao @@ -16,6 +19,17 @@ public class Configuracao /// Id do cliente gerado pelo Sicoob no momento do cadastro do Aplicativo /// public string? ClientId { get; set; } + + /// + /// Teste de Comunicação com API + /// + public bool SandBox { get; set; } + + /// + /// Ultimo token gerado + /// + public ConfiguracaoToken? Token { get; set; } + /// /// Caminho do certificado com chave pública /// @@ -36,3 +50,16 @@ public class ConfiguracaoAPI : Configuracao /// public string UrlApi { get; set; } = "https://api.sicoob.com.br/"; } + +public class ConfiguracaoToken +{ + /// + /// Último token gerado + /// + public string? Token { get; set; } + + /// + /// Data de expiração do Útimo token gerado + /// + public DateTime ExpiresAtUTC { get; set; } +} \ No newline at end of file diff --git a/Sicoob.Shared/Sicoob.Shared.csproj b/Sicoob.Shared/Sicoob.Shared.csproj index 8d5a679..5bee967 100644 --- a/Sicoob.Shared/Sicoob.Shared.csproj +++ b/Sicoob.Shared/Sicoob.Shared.csproj @@ -5,7 +5,7 @@ 10.0 disable enable - 1.0.2 + 1.0.3 RafaelEstevam.Net SHARP SISTEMAS LTDA Base library for Sicoob APIs for C# diff --git a/Sicoob.Shared/Sicoob.cs b/Sicoob.Shared/Sicoob.cs index 46bcb1a..c43512e 100644 --- a/Sicoob.Shared/Sicoob.cs +++ b/Sicoob.Shared/Sicoob.cs @@ -3,6 +3,9 @@ * Autor: Rafael Estevam * * gh/SharpSistemas/SicoobAPI * \**************************************/ + +using Sicoob.Shared.Models.Acesso; + namespace Sicoob.Shared; using global::Sicoob.Shared.Models.Geral; @@ -17,6 +20,7 @@ public abstract class Sicoob private readonly Models.Configuracao config; private readonly HttpClientHandler httpHandler; private ClientInfo clientAuth; + private const string SandBoxToken = "1301865f-c6bc-38f3-9f49-666dbcfc59c3"; public DateTime ExpiresAtUTC { get; private set; } public TimeSpan ExpiresIn => ExpiresAtUTC - DateTime.UtcNow; @@ -77,14 +81,19 @@ private void debugLog(string direciton, string content) public async Task SetupAsync() { setupClients(httpHandler); - await atualizaCredenciaisAsync(); + if (config.Token is null) + await atualizaCredenciaisAsync(); + else + { + ExpiresAtUTC = config.Token.ExpiresAtUTC; + } } protected abstract void setupClients(HttpClientHandler handler); protected abstract void atualizaClients(Models.Acesso.TokenResponse token); public async Task AtualizarCredenciaisAsync() => await atualizaCredenciaisAsync(); - private async Task atualizaCredenciaisAsync() + private async Task atualizaCredenciaisAsync() { var response = await clientAuth.FormUrlEncodedPostAsync("token", new { @@ -92,20 +101,33 @@ private async Task atualizaCredenciaisAsync() grant_type = "client_credentials", scope = config.Scope.ToScopeString(), }); + + if (config.SandBox) + { + atualizaClients(new TokenResponse(){ access_token = SandBoxToken }); + var data = DateTime.Now.AddHours(1); + var totalSeconds = Convert.ToInt32((DateTime.Now - data).TotalSeconds); + ExpiresAtUTC = DateTime.UtcNow.AddSeconds(totalSeconds); + + return new TokenResponse() + { + access_token = SandBoxToken, + expires_in = totalSeconds + }; + } + response.EnsureSuccessStatusCode(); atualizaClients(response.Data); ExpiresAtUTC = DateTime.UtcNow.AddSeconds(response.Data.expires_in); + return response.Data; } - protected async Task VerificaAtualizaCredenciaisAsync() + protected async Task VerificaAtualizaCredenciaisAsync() { if (ExpiresIn.TotalSeconds >= 5) - { - return false; - } + return null; - await atualizaCredenciaisAsync(); - return true; + return await atualizaCredenciaisAsync(); } protected async Task ExecutaChamadaAsync(Func>> func) { diff --git a/Sicoob.Testes/TestesApiCobranca.cs b/Sicoob.Testes/TestesApiCobranca.cs index 2a49739..29d4538 100644 --- a/Sicoob.Testes/TestesApiCobranca.cs +++ b/Sicoob.Testes/TestesApiCobranca.cs @@ -3,6 +3,10 @@ * Autor: Rafael Estevam * * gh/SharpSistemas/SicoobAPI * \**************************************/ + +using Sicoob.Cobranca.Models.Shared; +using Sicoob.Cobranca.Models.v2; + namespace Sicoob.Testes; using Newtonsoft.Json; @@ -22,17 +26,106 @@ internal static async Task Run_Cobranca() //cfg.Scope.Cobranca_Setar(true); //File.WriteAllText("config_Cob.json", JsonConvert.SerializeObject(cfg)); - var cobranca = new SicoobCobranca(cfg, NumeroContrato: 000); + var cobranca = new SicoobCobrancaV2(cfg, NumeroContrato: 000); await cobranca.SetupAsync(); + /*var boleto = await cobranca.IncluirBoletos(new [] + { + new IncluirBoletosRequest() + { + numeroContrato= 25546454, + modalidade= (int)Modalidade.SimplesComRegistro, + numeroContaCorrente= 0, + especieDocumento= "DM", + dataEmissao= new DateTime(2018,09, 20).ToUniversalTime(), + nossoNumero= 2588658, + seuNumero= "1235512", + identificacaoBoletoEmpresa= "4562", + identificacaoEmissaoBoleto= (int)IdentificacaoEmissaoBoleto.BancoEmite, + identificacaoDistribuicaoBoleto= (int)IdentificacaoDistribuicaoBoleto.BancoDistribui, + valor= 156.23m, + dataVencimento= new DateTime(2018,09, 20).ToUniversalTime(), + dataLimitePagamento= new DateTime(2018,09, 20).ToUniversalTime(), + valorAbatimento= 1, + tipoDesconto= (int)TipoDesconto.ValorFixoAteDataInformada, + dataPrimeiroDesconto= new DateTime(2018,09, 20).ToUniversalTime(), + valorPrimeiroDesconto= 1, + dataSegundoDesconto= new DateTime(2018,09, 20).ToUniversalTime(), + valorSegundoDesconto= 0, + dataTerceiroDesconto= new DateTime(2018,09, 20).ToUniversalTime(), + valorTerceiroDesconto= 0, + tipoMulta= (int)TipoMulta.ValorFixo, + dataMulta= new DateTime(2018,09, 20).ToUniversalTime(), + valorMulta= 5, + tipoJurosMora= (int)TipoJurosMora.ValorPorDia, + dataJurosMora= new DateTime(2018,09, 20).ToUniversalTime(), + valorJurosMora= 4, + numeroParcela= 1, + aceite= true, + codigoNegativacao= (int)CodigoNegativacao.NegativarDiasUteis, + numeroDiasNegativacao= 60, + codigoProtesto= (int)CodigoProtesto.ProtestarDiasCorridos, + numeroDiasProtesto= 30, + pagador = new DadosPagador() + { + numeroCpfCnpj = "98765432185", + nome = "Marcelo dos Santos", + endereco = "Rua 87 Quadra 1 Lote 1 casa 1", + bairro = "Santa Rosa", + cidade = "Luziânia", + cep = "72320000", + uf = "DF", + email = new[] { + "pagador@dominio.com.br" + }, + }, + beneficiarioFinal = new Beneficiariofinal() + { + numeroCpfCnpj = "98784978699", + nome = "Lucas de Lima" + }, + mensagensInstrucao = new Mensagensinstrucao() + { + tipoInstrucao = 1, + mensagens = new [] { + "Descrição da Instrução 1", + "Descrição da Instrução 2", + "Descrição da Instrução 3", + "Descrição da Instrução 4", + "Descrição da Instrução 5" + } + }, + rateioCreditos = new [] { + new Rateiocredito() + { + numeroBanco = 756, + numeroAgencia = 4027, + numeroContaCorrente = 0, + contaPrincipal = true, + codigoTipoValorRateio = 1, + valorRateio = 156.23m, + codigoTipoCalculoRateio = 1, + numeroCpfCnpjTitular = "98765432185", + nomeTitular = "Marcelo dos Santos", + codigoFinalidadeTed = 10, + codigoTipoContaDestinoTed = "CC", + quantidadeDiasFloat = 1, + dataFloatCredito = "2020-12-30" + } + }, + gerarPdf = true, + codigoCadastrarPIX = (int)CodigoCadastrarPIX.Padrao + } + });*/ + //var bol = await cobranca.ConsultarBoletosPagador("98765432185", dataVencimentoInicio: new DateTime(2024,01,01), dataVencimentoFim: new DateTime(2024,02,24) ); //var boleto = await cobranca.ConsultarBoleto(nossoNumero: 0); //var consulta = await cobranca.ConsultarBoletosPagador(numeroCpfCnpj: "00000000000000"); //var segVia = await cobranca.ConsultarSegundaViaBoleto(1, nossoNumero: 0, gerarPdf: true); - var p1 = await cobranca.SolicitarMovimentacao(Cobranca.Models.SolicitacaoMovimentacoesCarteira.Tipo.Liquidacao, new DateTime(2023, 12, 14)); + var p1 = await cobranca.SolicitarMovimentacao(Tipo.Liquidacao, new DateTime(2024, 02, 20), new DateTime(2024, 02, 23)); int codigo = p1.codigoSolicitacao; - Cobranca.Models.RetornoConsultaMovimentacoes? p2 = null; + RetornoConsultaMovimentacoes? p2 = null; while (p2 == null) { Console.WriteLine("Consultando ...");