You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
7.3 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()
}