github.com/mundipagg/boleto-api@v0.0.0-20230620145841-3f9ec742599f/models/boleto.go (about)

     1  package models
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/mundipagg/boleto-api/util"
     7  	"go.mongodb.org/mongo-driver/bson/primitive"
     8  
     9  	"github.com/mundipagg/boleto-api/config"
    10  
    11  	"github.com/PMoneda/flow"
    12  	"github.com/google/uuid"
    13  
    14  	"fmt"
    15  
    16  	"encoding/json"
    17  	"strconv"
    18  )
    19  
    20  // BoletoRequest entidade de entrada para o boleto
    21  type BoletoRequest struct {
    22  	Authentication Authentication  `json:"authentication"`
    23  	Agreement      Agreement       `json:"agreement"`
    24  	Title          Title           `json:"title"`
    25  	Recipient      Recipient       `json:"recipient"`
    26  	PayeeGuarantor *PayeeGuarantor `json:"payeeGuarantor,omitempty"`
    27  	Buyer          Buyer           `json:"buyer"`
    28  	BankNumber     BankNumber      `json:"bankNumber"`
    29  	RequestKey     string          `json:"requestKey,omitempty"`
    30  }
    31  
    32  // BoletoResponse entidade de saída para o boleto
    33  type BoletoResponse struct {
    34  	StatusCode    int    `json:"-"`
    35  	Errors        Errors `json:"errors,omitempty"`
    36  	ID            string `json:"id,omitempty"`
    37  	DigitableLine string `json:"digitableLine,omitempty"`
    38  	BarCodeNumber string `json:"barCodeNumber,omitempty"`
    39  	OurNumber     string `json:"ourNumber,omitempty"`
    40  	Links         []Link `json:"links,omitempty"`
    41  }
    42  
    43  //Link é um tipo padrão no restfull para satisfazer o HATEOAS
    44  type Link struct {
    45  	Href   string `json:"href,omitempty"`
    46  	Rel    string `json:"rel,omitempty"`
    47  	Method string `json:"method,omitempty"`
    48  }
    49  
    50  // BoletoView contem as informações que serão preenchidas no boleto
    51  type BoletoView struct {
    52  	ID            primitive.ObjectID `bson:"_id,omitempty"`
    53  	UID           string             `json:"uid,omitempty"`
    54  	SecretKey     string             `json:"secretkey,omitempty"`
    55  	PublicKey     string             `json:"publickey,omitempty"`
    56  	Format        string             `json:"format,omitempty"`
    57  	Boleto        BoletoRequest      `json:"boleto,omitempty"`
    58  	BankID        BankNumber         `json:"bankId,omitempty"`
    59  	CreateDate    time.Time          `json:"createDate,omitempty"`
    60  	BankNumber    string             `json:"bankNumber,omitempty"`
    61  	DigitableLine string             `json:"digitableLine,omitempty"`
    62  	OurNumber     string             `json:"ourNumber,omitempty"`
    63  	Barcode       string             `json:"barcode,omitempty"`
    64  	Barcode64     string             `json:"barcode64,omitempty"`
    65  	Links         []Link             `json:"links,omitempty"`
    66  }
    67  
    68  // NewBoletoView cria um novo objeto view de boleto a partir de um boleto request, codigo de barras e linha digitavel
    69  func NewBoletoView(boleto BoletoRequest, response BoletoResponse, bankName string) BoletoView {
    70  	boleto.Authentication = Authentication{}
    71  	uid, _ := uuid.NewUUID()
    72  	id := primitive.NewObjectID()
    73  	view := BoletoView{
    74  		ID:            id,
    75  		UID:           uid.String(),
    76  		SecretKey:     uid.String(),
    77  		BankID:        boleto.BankNumber,
    78  		Boleto:        boleto,
    79  		Barcode:       response.BarCodeNumber,
    80  		DigitableLine: response.DigitableLine,
    81  		OurNumber:     response.OurNumber,
    82  		BankNumber:    boleto.BankNumber.GetBoletoBankNumberAndDigit(),
    83  		CreateDate:    time.Now(),
    84  	}
    85  	view.GeneratePublicKey()
    86  	view.Links = view.CreateLinks()
    87  	if len(response.Links) > 0 && bankName == "BradescoShopFacil" {
    88  		view.Links = append(view.Links, response.Links[0])
    89  	}
    90  	return view
    91  }
    92  
    93  //EncodeURL tranforma o boleto view na forma que será escrito na url
    94  func (b *BoletoView) EncodeURL(format string) string {
    95  	idBson := b.ID.Hex()
    96  	url := fmt.Sprintf("%s?fmt=%s&id=%s&pk=%s", config.Get().AppURL, format, idBson, b.PublicKey)
    97  
    98  	return url
    99  }
   100  
   101  //CreateLinks cria a lista de links com os formatos suportados
   102  func (b *BoletoView) CreateLinks() []Link {
   103  	links := make([]Link, 0, 3)
   104  	for _, f := range []string{"html", "pdf"} {
   105  		links = append(links, Link{Href: b.EncodeURL(f), Rel: f, Method: "GET"})
   106  	}
   107  	return links
   108  }
   109  
   110  //ToJSON tranforma o boleto view em json
   111  func (b BoletoView) ToJSON() string {
   112  	json, _ := json.Marshal(b)
   113  	return string(json)
   114  }
   115  
   116  //ToMinifyJSON converte um model BoletoView para um JSON/STRING
   117  func (b BoletoView) ToMinifyJSON() string {
   118  	return util.MinifyString(b.ToJSON(), "application/json")
   119  }
   120  
   121  //GeneratePublicKey Gera a chave pública criptografada para geração da URL do boleto
   122  func (b *BoletoView) GeneratePublicKey() {
   123  	s := b.SecretKey + b.CreateDate.String() + b.Barcode + b.Boleto.Buyer.Document.Number + strconv.FormatUint(b.Boleto.Title.AmountInCents, 10)
   124  	b.PublicKey = util.Sha256(s, "hex")
   125  }
   126  
   127  // BankNumber número de identificação do banco
   128  type BankNumber int
   129  
   130  // IsBankNumberValid verifica se o banco enviado existe
   131  func (b BankNumber) IsBankNumberValid() bool {
   132  	switch b {
   133  	case BancoDoBrasil, Itau, Santander, Caixa, Bradesco, Citibank, Pefisa, Stone, JPMorgan:
   134  		return true
   135  	default:
   136  		return false
   137  	}
   138  }
   139  
   140  //GetBoletoBankNumberAndDigit Retorna o numero da conta do banco do boleto
   141  func (b BankNumber) GetBoletoBankNumberAndDigit() string {
   142  	switch b {
   143  	case BancoDoBrasil:
   144  		return "001-9"
   145  	case Caixa:
   146  		return "104-0"
   147  	case Citibank:
   148  		return "745-5"
   149  	case Santander:
   150  		return "033-7"
   151  	case Itau:
   152  		return "341-7"
   153  	case Bradesco:
   154  		return "237-2"
   155  	case Pefisa:
   156  		return "174"
   157  	case Stone:
   158  		return "197-1"
   159  	case JPMorgan:
   160  		return "376"
   161  	default:
   162  		return ""
   163  	}
   164  }
   165  
   166  const (
   167  	// BancoDoBrasil constante do Banco do Brasil
   168  	BancoDoBrasil = 1
   169  
   170  	// Santander constante do Santander
   171  	Santander = 33
   172  
   173  	// Itau constante do Itau
   174  	Itau = 341
   175  
   176  	//Bradesco constante do Bradesco
   177  	Bradesco = 237
   178  	// Caixa constante do Caixa
   179  	Caixa = 104
   180  
   181  	// Citibank constante do Citi
   182  	Citibank = 745
   183  
   184  	//Real constante do REal
   185  	Real = 9
   186  
   187  	// Pefisa constante do Pefisa
   188  	Pefisa = 174
   189  
   190  	// Stone constante do Stone
   191  	Stone = 197
   192  
   193  	JPMorgan = 376
   194  )
   195  
   196  // BoletoErrorConector é um connector flow para criar um objeto de erro
   197  func BoletoErrorConector(e *flow.ExchangeMessage, u flow.URI, params ...interface{}) error {
   198  	b := "Erro interno"
   199  	switch t := e.GetBody().(type) {
   200  	case error:
   201  		b = t.Error()
   202  	case string:
   203  		b = t
   204  	case *BoletoResponse:
   205  		if len(t.Errors) > 0 {
   206  			return nil
   207  		}
   208  	}
   209  
   210  	st, err := strconv.Atoi(e.GetHeader("status"))
   211  	if err != nil {
   212  		st = 0
   213  	}
   214  	resp := BoletoResponse{}
   215  	resp.Errors = make(Errors, 0, 0)
   216  	resp.Errors.Append("MP"+e.GetHeader("status"), b)
   217  	resp.StatusCode = st
   218  	e.SetBody(resp)
   219  	return nil
   220  }
   221  
   222  //HasErrors verify if Response has any error
   223  func (b *BoletoResponse) HasErrors() bool {
   224  	return b.Errors != nil && len(b.Errors) > 0
   225  }
   226  
   227  //HasPayeeGuarantor verify if PayeeGuarantor is not nil
   228  func (b BoletoRequest) HasPayeeGuarantor() bool {
   229  	return b.PayeeGuarantor != nil
   230  }
   231  
   232  //MaskBoletoRequest Retorna um BoletoRequest com os campos sensiveis mascarados
   233  func (b BoletoRequest) MaskBoletoRequest() BoletoRequest {
   234  	return BoletoRequest{
   235  		Authentication: b.Authentication.maskAuthenticationNode(),
   236  		Agreement:      b.Agreement,
   237  		Title:          b.Title,
   238  		Recipient:      b.Recipient,
   239  		PayeeGuarantor: b.PayeeGuarantor,
   240  		Buyer:          b.Buyer,
   241  		BankNumber:     b.BankNumber,
   242  		RequestKey:     b.RequestKey,
   243  	}
   244  }
   245  
   246  //GetBoletoResponseError Retorna um BoletoResponse com um erro específico
   247  func GetBoletoResponseError(code, message string) BoletoResponse {
   248  	resp := BoletoResponse{}
   249  	resp.Errors = make(Errors, 0, 0)
   250  	resp.Errors.Append(code, message)
   251  	return resp
   252  }