github.com/mundipagg/boleto-api@v0.0.0-20230620145841-3f9ec742599f/citibank/citi.go (about) 1 package citibank 2 3 import ( 4 "fmt" 5 "net/http" 6 "strconv" 7 "sync" 8 9 "github.com/PMoneda/flow" 10 "github.com/mundipagg/boleto-api/certificate" 11 "github.com/mundipagg/boleto-api/config" 12 "github.com/mundipagg/boleto-api/issuer" 13 "github.com/mundipagg/boleto-api/log" 14 "github.com/mundipagg/boleto-api/metrics" 15 "github.com/mundipagg/boleto-api/models" 16 "github.com/mundipagg/boleto-api/tmpl" 17 "github.com/mundipagg/boleto-api/util" 18 "github.com/mundipagg/boleto-api/validations" 19 ) 20 21 var ( 22 onceTransport = &sync.Once{} 23 transportTLS *http.Transport 24 ) 25 26 type bankCiti struct { 27 validate *models.Validator 28 log *log.Log 29 transport *http.Transport 30 } 31 32 func New() (bankCiti, error) { 33 var err error 34 b := bankCiti{ 35 validate: models.NewValidator(), 36 log: log.CreateLog(), 37 } 38 39 certificates := certificate.TLSCertificate{ 40 Crt: config.Get().CitibankCertificateSSLName, 41 Key: config.Get().CitibankCertificateSSLName, 42 } 43 44 onceTransport.Do(func() { 45 transportTLS, err = util.BuildTLSTransport(certificates) 46 }) 47 b.transport = transportTLS 48 49 if err != nil || (b.transport == nil && !config.Get().MockMode) { 50 return bankCiti{}, fmt.Errorf("fail on load TLSTransport: %v", err) 51 } 52 53 b.validate.Push(validations.ValidateAmount) 54 b.validate.Push(validations.ValidateExpireDate) 55 b.validate.Push(validations.ValidateBuyerDocumentNumber) 56 b.validate.Push(validations.ValidateRecipientDocumentNumber) 57 b.validate.Push(validations.ValidatePayeeGuarantorDocumentNumber) 58 b.validate.Push(validations.ValidatePayeeGuarantorName) 59 b.validate.Push(citiValidateAgency) 60 b.validate.Push(citiValidateAccount) 61 b.validate.Push(citiValidateWallet) 62 63 return b, nil 64 } 65 66 //Log retorna a referencia do log 67 func (b bankCiti) Log() *log.Log { 68 return b.log 69 } 70 71 func (b bankCiti) RegisterBoleto(boleto *models.BoletoRequest) (models.BoletoResponse, error) { 72 73 boleto.Title.BoletoType, boleto.Title.BoletoTypeCode = getBoletoType() 74 75 boleto.Title.OurNumber = calculateOurNumber(boleto) 76 r := flow.NewFlow() 77 serviceURL := config.Get().URLCiti 78 from := getResponseCiti() 79 to := getAPIResponseCiti() 80 bod := r.From("message://?source=inline", boleto, getRequestCiti(), tmpl.GetFuncMaps()) 81 bod.To("log://?type=request&format=xml&url="+serviceURL, b.log) 82 var responseCiti string 83 var status int 84 var err error 85 duration := util.Duration(func() { 86 responseCiti, status, err = b.sendRequest(bod.GetBody().(string)) 87 }) 88 if err != nil { 89 return models.BoletoResponse{}, err 90 } 91 metrics.PushTimingMetric("citibank-register-boleto-online", duration.Seconds()) 92 bod.To("set://?prop=header", map[string]string{"status": strconv.Itoa(status)}) 93 bod.To("set://?prop=body", responseCiti) 94 bod.To("log://?type=response&format=xml&url="+serviceURL, b.log) 95 ch := bod.Choice() 96 ch.When(flow.Header("status").IsEqualTo("200")) 97 ch.To("transform://?format=xml", from, to, tmpl.GetFuncMaps()) 98 ch.Otherwise() 99 ch.To("log://?type=response&url="+serviceURL, b.log).To("apierro://") 100 101 switch t := bod.GetBody().(type) { 102 case string: 103 response := util.ParseJSON(t, new(models.BoletoResponse)).(*models.BoletoResponse) 104 issuer := issuer.NewIssuer(response.BarCodeNumber, response.DigitableLine) 105 if !((issuer.IsValidBarCode() && issuer.IsValidDigitableLine()) || response.HasErrors()) { 106 return models.BoletoResponse{}, models.NewBadGatewayError("BadGateway") 107 } 108 return *response, nil 109 case models.BoletoResponse: 110 return t, nil 111 } 112 return models.BoletoResponse{}, models.NewInternalServerError("MP500", "Internal error") 113 } 114 115 func (b bankCiti) ProcessBoleto(boleto *models.BoletoRequest) (models.BoletoResponse, error) { 116 errs := b.ValidateBoleto(boleto) 117 if len(errs) > 0 { 118 return models.BoletoResponse{Errors: errs}, nil 119 } 120 return b.RegisterBoleto(boleto) 121 } 122 123 func (b bankCiti) ValidateBoleto(boleto *models.BoletoRequest) models.Errors { 124 return models.Errors(b.validate.Assert(boleto)) 125 } 126 127 func (b bankCiti) sendRequest(body string) (string, int, error) { 128 serviceURL := config.Get().URLCiti 129 if config.Get().MockMode { 130 return util.Post(serviceURL, body, config.Get().TimeoutDefault, map[string]string{"Soapaction": "RegisterBoleto"}) 131 } else { 132 return util.PostTLS(serviceURL, body, config.Get().TimeoutDefault, map[string]string{"Soapaction": "RegisterBoleto"}, b.transport) 133 } 134 } 135 136 //GetBankNumber retorna o codigo do banco 137 func (b bankCiti) GetBankNumber() models.BankNumber { 138 return models.Citibank 139 } 140 141 func calculateOurNumber(boleto *models.BoletoRequest) uint { 142 ourNumberWithDigit := strconv.Itoa(int(boleto.Title.OurNumber)) + util.OurNumberDv(strconv.Itoa(int(boleto.Title.OurNumber)), util.MOD11) 143 value, _ := strconv.Atoi(ourNumberWithDigit) 144 return uint(value) 145 } 146 147 func (b bankCiti) GetBankNameIntegration() string { 148 return "Citibank" 149 } 150 151 func (b bankCiti) GetErrorsMap() map[string]int { 152 return nil 153 } 154 155 func getBoletoType() (bt string, btc string) { 156 return "DMI", "03" 157 }