package model import ( "bytes" "encoding/json" "errors" "fmt" "io" "io/ioutil" "net/http" "net/url" "strconv" "time" "unicode/utf8" ) const ( grant_type = "client_credentials" ) var accessToken string var expires_in uint64 type OcrQuery struct { IdCardUrl string `json:"idCardUrl"` Side int `json:"side"` // 1 正面 2 反面 } type OcrRes struct { RealName string `json:"realName"` IDNum string `json:"iDNum"` Path string `json:"path"` Age int `json:"age"` Birthday string `json:"birthday"` Sex string `json:"sex"` IssueDate string `json:"issueDate"` ExpirationDate string `json:"expirationDate"` } const ( ocr_client_id = "cLg2dUH1pqopsj22tShw8FQU" ocr_client_secret = "diriz5PmhLOB8hwE4KnEEiaBMV6WfBR1" ) type OrcRes struct { Path string `json:"path"` Name string `json:"name"` IdCard string `json:"idCard"` Age int `json:"age"` Birthday string `json:"birthday"` Sex string `json:"sex"` IssueDate string `json:"issueDate"` ExpirationDate string `json:"expirationDate"` } type OcrGetIdCardRes struct { WordsResult WordsResult `json:"words_result"` IdcardNumberType int `json:"idcard_number_type"` WordsResultNum int `json:"words_result_num"` ImageStatus string `json:"image_status"` LogId uint64 `json:"log_id"` } type WordsResult struct { Name WordsResultDetail `json:"姓名"` Address WordsResultDetail `json:"住址"` IdCard WordsResultDetail `json:"公民身份号码"` Birthday WordsResultDetail `json:"出生"` Sex WordsResultDetail `json:"性别"` IssueDate WordsResultDetail `json:"签发日期"` ExpirationDate WordsResultDetail `json:"失效日期"` } type WordsResultDetail struct { Words string } type AccessToken struct { Refresh_token string `json:"refresh_token"` Expires_in uint64 `json:"expires_in"` Scope string `json:"scope"` Session_key string `json:"session_key"` Access_token string `json:"access_token"` Session_secret string `json:"session_secret"` Error string `json:"error"` Error_description string `json:"error_description"` } func OcrGetIdCard(image string, side string) (*OrcRes, error) { var ( accesstoken string response string err error ) if accesstoken, err = GetOcrAccessToken(); err != nil { fmt.Println(err.Error()) return nil, err } if response, err = PostForm("https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=["+accesstoken+"]", url.Values{"image": {image}, "id_card_side": {side}}); err != nil { fmt.Println(err.Error()) return nil, err } var res OcrGetIdCardRes if err = json.Unmarshal([]byte(response), &res); err != nil { return nil, err } fmt.Printf("%+v\n", res) switch res.ImageStatus { case "normal": case "reversed_side": return nil, errors.New("身份证正反面颠倒") case "non_idcard": return nil, errors.New("上传的图片中不包含身份证") case "blurred": return nil, errors.New("身份证模糊") case "other_type_card": return nil, errors.New("其他类型证照") case "over_exposure": return nil, errors.New("身份证关键字段反光或过曝") case "over_dark": return nil, errors.New("身份证欠曝(亮度过低)") case "unknown": return nil, errors.New("未知状态") default: return nil, errors.New("未知状态") } if side == "front" { switch res.IdcardNumberType { case -1: return nil, errors.New("身份证正面所有字段全为空") case 0: return nil, errors.New(" 身份证证号不合法,此情况下不返回身份证证号") case 1: case 2: return nil, errors.New("身份证证号和性别、出生信息都不一致") case 3: return nil, errors.New("身份证证号和出生信息不一致") case 4: return nil, errors.New("身份证证号和性别信息不一致") default: return nil, errors.New("未知状态") } } var result OrcRes fmt.Println(res.WordsResult.Name.Words) if side == "front" { result.Name = res.WordsResult.Name.Words result.Birthday = res.WordsResult.Birthday.Words result.IdCard = res.WordsResult.IdCard.Words result.Sex = res.WordsResult.Sex.Words result.Path = res.WordsResult.Address.Words var age int birYear, _ := strconv.Atoi(result.Birthday[0:4]) birMonth, _ := strconv.Atoi(result.Birthday[4:6]) fmt.Println(birYear) fmt.Println(time.Now().Year()) age = time.Now().Year() - birYear if int(time.Now().Month()) < birMonth { age-- } result.Age = age } else { issueDate := res.WordsResult.IssueDate.Words[:4] + "-" + res.WordsResult.IssueDate.Words[4:6] + "-" + res.WordsResult.IssueDate.Words[6:8] result.IssueDate = issueDate expirationDate := res.WordsResult.ExpirationDate.Words[:4] + "-" + res.WordsResult.ExpirationDate.Words[4:6] + "-" + res.WordsResult.ExpirationDate.Words[6:8] result.ExpirationDate = expirationDate } return &result, nil } func (m *OcrRes) CheckIdAndName() { if utf8.RuneCountInString(m.RealName) == 18 && utf8.RuneCountInString(m.IDNum) != 18 { m.IDNum, m.RealName = m.RealName, m.IDNum } } func GetOcrAccessToken() (string, error) { var ( resObj AccessToken err error // daoAccessToken entity.AccessToken ) if expires_in == 0 || expires_in < uint64(time.Now().Unix()) { fmt.Println(1) // if daoAccessToken, err = dao.GetAccessToken("baidu", "accesstoken"); err != nil { //查询是否有记录 // return "", err // } // fmt.Println(2) if resObj, err = getOcrAccessToken(); err != nil { //从链上获取 return "", err } // var tmp = entity.AccessToken{ // Platform: "baidu", // Types: "accesstoken", // Txt: resObj.Access_token, // Expires_in: uint64(time.Now().Unix()) + resObj.Expires_in, // } // if daoAccessToken.Uid == 0 { // if err = dao.AddAccessToken(tmp); err != nil { // return "", err // } // } else { // if _, err = dao.UpdateAccessToken(tmp); err != nil { // return "", err // } // } accessToken = resObj.Access_token expires_in = resObj.Expires_in } return accessToken, nil } func getOcrAccessToken() (AccessToken, error) { var ( resObj AccessToken err error ) url := "https://aip.baidubce.com/oauth/2.0/token" urlReq := "?grant_type=" + grant_type + "&client_id=" + ocr_client_id + "&client_secret=" + ocr_client_secret fmt.Println(urlReq) res := Get(url + urlReq) if err = json.Unmarshal([]byte(res), &resObj); err != nil { return resObj, err } if resObj.Error != "" { return resObj, errors.New(resObj.Error_description) } return resObj, err } func PostForm(urlStr string, data url.Values) (string, error) { resp, err := http.PostForm(urlStr, data) if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { // handle error } return string(body), err } func Get(url string) string { // 超时时间:5秒 client := &http.Client{Timeout: 5 * time.Second} resp, err := client.Get(url) if err != nil { panic(err) } defer resp.Body.Close() var buffer [512]byte result := bytes.NewBuffer(nil) for { n, err := resp.Body.Read(buffer[0:]) result.Write(buffer[0:n]) if err != nil && err == io.EOF { break } else if err != nil { panic(err) } } return result.String() }