Skip to content

Instantly share code, notes, and snippets.

@jhonata-menezes
Created April 19, 2019 20:49
Show Gist options
  • Save jhonata-menezes/69d54048942e8d7bc796b4eb4749474a to your computer and use it in GitHub Desktop.
Save jhonata-menezes/69d54048942e8d7bc796b4eb4749474a to your computer and use it in GitHub Desktop.
teste com http.client e libcurl
package main
// teste com biblioteca http.client e go-curl
// instalar as seguintes libs
// go get github.com/andelf/go-curl && github.com/mmcloughlin/spherand && go get github.com/parnurzeal/gorequest
// no momento a lib github.com/andelf/go-curl não é compativel com go 1.12, use a 1,11
// necessário ter a libcurl instalada
// o segundo parametro serve para usar com libcurl
// go run sinesp.go aaa0010 1
import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"encoding/xml"
"fmt"
"github.com/andelf/go-curl"
"github.com/mmcloughlin/spherand"
"github.com/parnurzeal/gorequest"
"math/rand"
"net"
"os"
"regexp"
"strings"
"time"
"log"
)
const URL_API_SINESP = "https://cidadao.sinesp.gov.br/sinesp-cidadao/mobile/consultar-placa/v4"
const USER_AGENT = "SinespCidadao / 3.0.2.1 CFNetwork / 758.2.8 Darwin / 15.0.0"
const SECRET = "#8.1.0#g8LzUadkEHs7mbRqbX5l"
func main() {
sinespPlaca := GetPlacaVeicular(os.Args[1])
log.Printf("%#v", sinespPlaca)
}
type RetornoSinesp struct {
CodigoRetorno int `xml:"codigoRetorno"` // 0
MensagemRetorno string `xml:"mensagemRetorno"` // Sem erros.
CodigoSituacao int `xml:"codigoSituacao"` // 0
Situacao string `xml:"situacao"` // Sem restrição
Modelo string `xml:"modelo"` // FORD/ESCORT 1.8 XR3
Marca string `xml:"marca"` // FORD/ESCORT 1.8 XR3
Cor string `xml:"cor"` // Cinza
Ano int `xml:"ano"` // 1990
AnoModelo int `xml:"anoModelo"` // 1990
Placa string `xml:"placa"` // AAA0001
Data string `xml:"data"` // 02/04/2019 às 22:08:06
Uf string `xml:"uf"` // PR
Municipio string `xml:"municipio"` // CURITIBA
Chassi string `xml:"chassi"` // 49500
DataAtualizacaoCaracteristicasVeiculo string `xml:"dataAtualizacaoCaracteristicasVeiculo"` // 22/02/2019
DataAtualizacaoRouboFurto string `xml:"dataAtualizacaoRouboFurto"` // 01/04/2019
DataAtualizacaoAlarme string `xml:"dataAtualizacaoAlarme"` // 01/04/2019
}
type SinespPlacaAPI struct {
CodigoRetorno int `xml:"codigoRetorno" json:"codigo_retorno"`
MensagemRetorno string `xml:"mensagemRetorno" json:"mensagem_retorno"`
CodigoSituacao int `xml:"codigoSituacao" json:"codigo_situacao"`
Situacao string `xml:"situacao" json:"situacao"`
Modelo string `xml:"modelo" json:"modelo"`
Marca string `xml:"marca" json:"marca"`
Cor string `xml:"cor" json:"cor"`
Ano int `xml:"ano" json:"ano"`
AnoModelo int `xml:"anoModelo" json:"ano_modelo"`
Placa string `xml:"placa" json:"placa"`
Data time.Time `xml:"data" json:"data"`
Uf string `xml:"uf" json:"uf"`
Municipio string `xml:"municipio" json:"municipio"`
Chassi string `xml:"chassi" json:"chassi"`
DataAtualizacaoCaracteristicasVeiculo time.Time `xml:"dataAtualizacaoCaracteristicasVeiculo" json:"data_atualizacao_caracteristicas_veiculo"`
DataAtualizacaoRouboFurto time.Time `xml:"dataAtualizacaoRouboFurto" json:"data_atualizacao_roubo_furto"`
DataAtualizacaoAlarme time.Time `xml:"dataAtualizacaoAlarme" json:"data_atualizacao_alarme"`
}
func (r *SinespPlacaAPI) Parse(sinesp *RetornoSinesp) {
r.CodigoRetorno = sinesp.CodigoRetorno
r.MensagemRetorno = sinesp.MensagemRetorno
r.CodigoSituacao = sinesp.CodigoSituacao
r.Situacao = sinesp.Situacao
r.Cor = sinesp.Cor
r.Ano = sinesp.Ano
r.AnoModelo = sinesp.AnoModelo
r.Placa = strings.ToLower(sinesp.Placa)
r.Uf = sinesp.Uf
r.Municipio = sinesp.Municipio
r.Chassi = sinesp.Chassi
r.Modelo = sinesp.Modelo
r.Marca = sinesp.Marca
marca := strings.SplitN(sinesp.Marca, "/", 2)
if len(marca) == 2 {
r.Marca = marca[0]
r.Modelo = marca[1]
}
if sinesp.Data != "" {
t, err := time.Parse("02/01/2006 às 15:04:05", sinesp.Data)
if err == nil {
r.Data = t
}
}
if sinesp.DataAtualizacaoCaracteristicasVeiculo != "" {
t, err := time.Parse("02/01/2006", sinesp.DataAtualizacaoCaracteristicasVeiculo)
if err == nil {
r.DataAtualizacaoCaracteristicasVeiculo = t
}
}
if sinesp.DataAtualizacaoRouboFurto != "" {
t, err := time.Parse("02/01/2006", sinesp.DataAtualizacaoRouboFurto)
if err == nil {
r.DataAtualizacaoRouboFurto = t
}
}
if sinesp.DataAtualizacaoAlarme != "" {
t, err := time.Parse("02/01/2006", sinesp.DataAtualizacaoAlarme)
if err == nil {
r.DataAtualizacaoAlarme = t
}
}
}
func GetPlacaVeicular(placa string) *SinespPlacaAPI {
f := CreateFromPlaca(placa)
dadosPlaca := new (RetornoSinesp)
if len(os.Args) == 3 {
dadosPlaca, _ = f.RequestCurl()
} else {
dadosPlaca, _ = f.Request()
}
if dadosPlaca == nil {
return nil
}
return ToResponseAPI(dadosPlaca)
}
type ResponseAPI struct {
XMLName xml.Name `xml:"Envelope"`
Text string `xml:",chardata"`
Soap string `xml:"soap,attr"`
Body struct {
Text string `xml:",chardata"`
GetStatusResponse struct {
Text string `xml:",chardata"`
Ns2 string `xml:"ns2,attr"`
Return RetornoSinesp `xml:"return"`
} `xml:"getStatusResponse"`
} `xml:"Body"`
}
type Form struct {
Envelope Envelope2 `xml:"v:Envelope"`
}
type Envelope2 struct{
XMLNS string `xml:"xmlns:v,attr"`
Header struct {
Aparelho string `xml:"b"`
SO string `xml:"c"`
Versao string `xml:"d"`
Latitude string `xml:"i"`
Versao2 string `xml:"e"`
IP string `xml:"f"`
Token string `xml:"g"`
Vazio string `xml:"k"`
Longitude string `xml:"h"`
Hora string `xml:"l"`
Hash string `xml:"m"`
} `xml:"v:Header"`
Body struct {
N0 struct{
XMLNS string `xml:"xmlns:n0,attr"`
Placa string `xml:"a"`
} `xml:"n0:getStatus"`
} `xml:"v:Body"`
}
func CreateFromPlaca(placa string) *Form {
f := new(Form)
lat, lng := spherand.Geographical()
f.Envelope.XMLNS = "http://schemas.xmlsoap.org/soap/envelope/"
f.Envelope.Body.N0.XMLNS = "http://soap.ws.placa.service.sinesp.serpro.gov.br/"
f.Envelope.Header.Aparelho = "samsung GT-I9192"
f.Envelope.Header.SO = "ANDROID"
f.Envelope.Header.Versao = "8.1.0"
f.Envelope.Header.Latitude = fmt.Sprintf("%f", lat)
f.Envelope.Header.Versao2 = "4.1.5"
f.Envelope.Header.IP = RandomIPV4()
f.Envelope.Header.Longitude = fmt.Sprintf("%f", lng)
f.Envelope.Header.Hora = time.Now().Format("2006-01-02 15:04:05")
f.Envelope.Header.Hash = "8797e74f0d6eb7b1ff3dc114d4aa12d3"
f.Envelope.Body.N0.Placa = placa
f.GenerateToken()
return f
}
func RandomIPV4() string {
size := 4
ip := make([]byte, size)
for i := 0; i < size; i++ {
ip[i] = byte(rand.Intn(256))
}
return net.IP(ip).To4().String()
}
func (f *Form) GenerateToken() {
h := hmac.New(sha1.New, []byte(f.Envelope.Body.N0.Placa + SECRET))
h.Write([]byte(f.Envelope.Body.N0.Placa))
f.Envelope.Header.Token = hex.EncodeToString(h.Sum(nil))
}
func (f *Form) ToXML() (string) {
by, err := xml.Marshal(f)
if err != nil {
return ""
}
byStr := string(by)[6:]
byStr = byStr[:(len(byStr) - 7)]
byStr = fmt.Sprintf("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>%s", byStr)
return byStr
}
func (f *Form) RequestCurl() (*RetornoSinesp, error) {
easy := RequestCurl()
defer easy.Cleanup()
by := []byte{}
if easy != nil {
easy.Setopt(curl.OPT_URL, URL_API_SINESP)
easy.Setopt(curl.OPT_POST, true)
easy.Setopt(curl.OPT_POSTFIELDS, f.ToXML())
callback := func (buf []byte, userdata interface{}) bool {
by = buf
return true
}
easy.Setopt(curl.OPT_WRITEFUNCTION, callback)
err := easy.Perform()
if err != nil {
return nil, err
}
}
return &ToResponseApi(by).Body.GetStatusResponse.Return, nil
}
func (f *Form) Request() (*RetornoSinesp, error) {
g := Request()
//g.SetDebug(true)
res, by, errs := g.Post(URL_API_SINESP).
Set("Content-type", "application/xml;charset=\"utf-8\"").
Set("User-Agent", USER_AGENT).
Set("cache-control", "no-cache").
Set("Pragma", "no-cache").
Set("Accept", "*/*").
Timeout(10 * time.Second).
Proxy("http://177.185.159.62:8080").Type("xml").SendString(f.ToXML()).EndBytes()
if len(errs) > 0 {
log.Println(errs, res)
return nil, errs[0]
}
return &ToResponseApi(by).Body.GetStatusResponse.Return, nil
}
func ToResponseAPI(api *RetornoSinesp) *SinespPlacaAPI {
r := new(SinespPlacaAPI)
r.Parse(api)
return r // alterar proxy, adquirido em 19/04/2019
}
func ToResponseApi(res []byte) *ResponseAPI {
r := new(ResponseAPI)
err := xml.Unmarshal(res, r)
if err != nil {
log.Println(err)
}
return r
}
var validacaoPlacaVeicular, _ = regexp.Compile("^[A-Za-z]{3}[0-9][A-Za-z0-9][0-9]{2}$")
func PlacaValidacao(placa string) bool {
return validacaoPlacaVeicular.MatchString(placa)
}
func Request() *gorequest.SuperAgent {
g := gorequest.New()
// alterar proxy, adquirido em 19/04/2019
return g
}
func RequestCurl() *curl.CURL {
easy := curl.EasyInit()
easy.Setopt(curl.OPT_HTTPHEADER, []string{
"Content-type: application/xml;charset=\"utf-8\"",
"User-Agent: "+ USER_AGENT,
"cache-control: no-cache",
"Pragma: no-cache",
"Accept: */*",
})
easy.Setopt(curl.OPT_PROXY, "http://177.185.159.62:8080")
easy.Setopt(curl.OPT_TIMEOUT, 10)
return easy
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment