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

     1  package pefisa
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"strings"
     7  	"sync"
     8  
     9  	. "github.com/PMoneda/flow"
    10  	"github.com/mundipagg/boleto-api/config"
    11  	"github.com/mundipagg/boleto-api/log"
    12  	"github.com/mundipagg/boleto-api/metrics"
    13  	"github.com/mundipagg/boleto-api/models"
    14  	"github.com/mundipagg/boleto-api/tmpl"
    15  	"github.com/mundipagg/boleto-api/util"
    16  	"github.com/mundipagg/boleto-api/validations"
    17  )
    18  
    19  var o = &sync.Once{}
    20  var m map[string]string
    21  
    22  type bankPefisa struct {
    23  	validate *models.Validator
    24  	log      *log.Log
    25  }
    26  
    27  func New() bankPefisa {
    28  	b := bankPefisa{
    29  		validate: models.NewValidator(),
    30  		log:      log.CreateLog(),
    31  	}
    32  
    33  	b.validate.Push(validations.ValidateAmount)
    34  	b.validate.Push(validations.ValidateExpireDate)
    35  	b.validate.Push(validations.ValidateBuyerDocumentNumber)
    36  	b.validate.Push(validations.ValidateRecipientDocumentNumber)
    37  	b.validate.Push(pefisaBoletoTypeValidate)
    38  
    39  	return b
    40  }
    41  
    42  func (b bankPefisa) Log() *log.Log {
    43  	return b.log
    44  }
    45  
    46  func (b bankPefisa) GetToken(boleto *models.BoletoRequest) (string, error) {
    47  
    48  	pipe := NewFlow()
    49  	url := config.Get().URLPefisaToken
    50  
    51  	pipe.From("message://?source=inline", boleto, getRequestToken(), tmpl.GetFuncMaps())
    52  	pipe.To("log://?type=request&format=json&url="+url, b.log)
    53  
    54  	duration := util.Duration(func() {
    55  		pipe.To(url, map[string]string{"method": "POST", "insecureSkipVerify": "true", "timeout": config.Get().TimeoutToken})
    56  	})
    57  	metrics.PushTimingMetric("pefisa-get-token-boleto-time", duration.Seconds())
    58  	pipe.To("log://?type=response&format=json&url="+url, b.log)
    59  	ch := pipe.Choice()
    60  	ch.When(Header("status").IsEqualTo("200"))
    61  	ch.To("transform://?format=json", getTokenResponse(), `{{.access_token}}`, tmpl.GetFuncMaps())
    62  
    63  	ch.When(Header("status").IsEqualTo("401"))
    64  	ch.To("transform://?format=json", getTokenErrorResponse(), `{{.error_description}}`, tmpl.GetFuncMaps())
    65  	ch.To("set://?prop=body", errors.New(pipe.GetBody().(string)))
    66  
    67  	ch.Otherwise()
    68  	ch.To("log://?type=request&url="+url, b.log).To("print://?msg=${body}").To("set://?prop=body", errors.New("integration error"))
    69  	switch t := pipe.GetBody().(type) {
    70  	case string:
    71  
    72  		return t, nil
    73  	case error:
    74  		return "", t
    75  	}
    76  	return "", nil
    77  
    78  }
    79  
    80  func (b bankPefisa) RegisterBoleto(boleto *models.BoletoRequest) (models.BoletoResponse, error) {
    81  	pefisaURL := config.Get().URLPefisaRegister
    82  
    83  	boleto.Title.BoletoType, boleto.Title.BoletoTypeCode = getBoletoType(boleto)
    84  
    85  	exec := NewFlow().From("message://?source=inline", boleto, getRequestPefisa(), tmpl.GetFuncMaps())
    86  	exec.To("log://?type=request&url="+pefisaURL, b.log)
    87  
    88  	var response string
    89  	var status int
    90  	var err error
    91  	duration := util.Duration(func() {
    92  		response, status, err = b.sendRequest(exec.GetBody().(string), boleto.Authentication.AuthorizationToken)
    93  	})
    94  	if err != nil {
    95  		return models.BoletoResponse{}, err
    96  	}
    97  
    98  	metrics.PushTimingMetric("pefisa-register-boleto-time", duration.Seconds())
    99  	exec.To("set://?prop=header", map[string]string{"status": strconv.Itoa(status)})
   100  	exec.To("set://?prop=body", response)
   101  	exec.To("log://?type=response&url="+pefisaURL, b.log)
   102  
   103  	if status == 200 || status == 401 {
   104  		exec.To("set://?prop=body", response)
   105  	} else {
   106  		dataError := util.ParseJSON(response, new(models.ArrayDataError)).(*models.ArrayDataError)
   107  		exec.To("set://?prop=body", strings.Replace(util.Stringify(dataError.Error[0]), "\\\"", "", -1))
   108  	}
   109  
   110  	ch := exec.Choice()
   111  	ch.When(Header("status").IsEqualTo("200"))
   112  	ch.To("transform://?format=json", getResponsePefisa(), getAPIResponsePefisa(), tmpl.GetFuncMaps())
   113  	ch.To("unmarshall://?format=json", new(models.BoletoResponse))
   114  
   115  	ch.When(Header("status").IsEqualTo("400"))
   116  	ch.To("transform://?format=json", getResponseErrorPefisaArray(), getAPIResponsePefisa(), tmpl.GetFuncMaps())
   117  	ch.To("unmarshall://?format=json", new(models.BoletoResponse))
   118  
   119  	ch.When(Header("status").IsEqualTo("401"))
   120  	ch.To("transform://?format=json", getResponseErrorPefisa(), getAPIResponsePefisa(), tmpl.GetFuncMaps())
   121  	ch.To("unmarshall://?format=json", new(models.BoletoResponse))
   122  
   123  	ch.Otherwise()
   124  	ch.To("log://?type=response&url="+pefisaURL, b.log).To("apierro://")
   125  
   126  	switch t := exec.GetBody().(type) {
   127  	case *models.BoletoResponse:
   128  		return *t, nil
   129  	case error:
   130  		return models.BoletoResponse{}, t
   131  	}
   132  	return models.BoletoResponse{}, models.NewInternalServerError("MP500", "Internal error")
   133  }
   134  
   135  func (b bankPefisa) ProcessBoleto(boleto *models.BoletoRequest) (models.BoletoResponse, error) {
   136  	errs := b.ValidateBoleto(boleto)
   137  
   138  	if len(errs) > 0 {
   139  		return models.BoletoResponse{Errors: errs}, nil
   140  	}
   141  	if token, err := b.GetToken(boleto); err != nil {
   142  		return models.BoletoResponse{Errors: errs}, err
   143  	} else {
   144  		boleto.Authentication.AuthorizationToken = token
   145  	}
   146  
   147  	return b.RegisterBoleto(boleto)
   148  
   149  }
   150  
   151  func (b bankPefisa) ValidateBoleto(boleto *models.BoletoRequest) models.Errors {
   152  	return models.Errors(b.validate.Assert(boleto))
   153  }
   154  
   155  //GetBankNumber retorna o codigo do banco
   156  func (b bankPefisa) GetBankNumber() models.BankNumber {
   157  	return models.Pefisa
   158  }
   159  
   160  func (b bankPefisa) GetBankNameIntegration() string {
   161  	return "Pefisa"
   162  }
   163  
   164  func (b bankPefisa) GetErrorsMap() map[string]int {
   165  	return nil
   166  }
   167  
   168  func (b bankPefisa) sendRequest(body string, token string) (string, int, error) {
   169  	serviceURL := config.Get().URLPefisaRegister
   170  
   171  	h := map[string]string{"Authorization": "Bearer " + token, "Content-Type": "application/json"}
   172  	return util.Post(serviceURL, body, config.Get().TimeoutRegister, h)
   173  }
   174  
   175  func pefisaBoletoTypes() map[string]string {
   176  	o.Do(func() {
   177  		m = make(map[string]string)
   178  
   179  		m["DM"] = "1"   //Duplicata Mercantil
   180  		m["DS"] = "2"   //Duplicata de serviços
   181  		m["NP"] = "3"   //Nota promissória
   182  		m["SE"] = "4"   //Seguro
   183  		m["CH"] = "10"  //Cheque
   184  		m["OUT"] = "99" //Outros
   185  	})
   186  	return m
   187  }
   188  
   189  func getBoletoType(boleto *models.BoletoRequest) (bt string, btc string) {
   190  	if len(boleto.Title.BoletoType) < 1 {
   191  		return "DM", "1"
   192  	}
   193  	btm := pefisaBoletoTypes()
   194  
   195  	if btm[strings.ToUpper(boleto.Title.BoletoType)] == "" {
   196  		return "DM", "1"
   197  	}
   198  
   199  	return boleto.Title.BoletoType, btm[strings.ToUpper(boleto.Title.BoletoType)]
   200  }