|
|
@@ -0,0 +1,287 @@
|
|
|
+package ocr
|
|
|
+
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+ "net/url"
|
|
|
+
|
|
|
+ "github.com/silenceper/wechat/v2/officialaccount/context"
|
|
|
+ "github.com/silenceper/wechat/v2/util"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ ocrIDCardURL = "https://api.weixin.qq.com/cv/ocr/idcard"
|
|
|
+ ocrBankCardURL = "https://api.weixin.qq.com/cv/ocr/bankcard"
|
|
|
+ ocrDrivingURL = "https://api.weixin.qq.com/cv/ocr/driving"
|
|
|
+ ocrDrivingLicenseURL = "https://api.weixin.qq.com/cv/ocr/drivinglicense"
|
|
|
+ ocrBizLicenseURL = "https://api.weixin.qq.com/cv/ocr/bizlicense"
|
|
|
+ ocrCommonURL = "https://api.weixin.qq.com/cv/ocr/comm"
|
|
|
+ ocrPlateNumberURL = "https://api.weixin.qq.com/cv/ocr/platenum"
|
|
|
+)
|
|
|
+
|
|
|
+//OCR struct
|
|
|
+type OCR struct {
|
|
|
+ *context.Context
|
|
|
+}
|
|
|
+
|
|
|
+//coordinate 坐标
|
|
|
+type coordinate struct {
|
|
|
+ X int64 `json:"x,omitempty"`
|
|
|
+ Y int64 `json:"y,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//position 位置
|
|
|
+type position struct {
|
|
|
+ LeftTop coordinate `json:"left_top"`
|
|
|
+ RightTop coordinate `json:"right_top"`
|
|
|
+ RightBottom coordinate `json:"right_bottom"`
|
|
|
+ LeftBottom coordinate `json:"left_bottom"`
|
|
|
+}
|
|
|
+
|
|
|
+//imageSize 图片尺寸
|
|
|
+type imageSize struct {
|
|
|
+ Width int64 `json:"w,omitempty"`
|
|
|
+ Height int64 `json:"h,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResDriving 行驶证返回结果
|
|
|
+type ResDriving struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ PlateNumber string `json:"plate_num,omitempty"`
|
|
|
+ VehicleType string `json:"vehicle_type,omitempty"`
|
|
|
+ Owner string `json:"owner,omitempty"`
|
|
|
+ Address string `json:"addr,omitempty"`
|
|
|
+ UseCharacter string `json:"use_character,omitempty"`
|
|
|
+ Model string `json:"model,omitempty"`
|
|
|
+ Vin string `json:"vin,omitempty"`
|
|
|
+ EngineNumber string `json:"engine_num,omitempty"`
|
|
|
+ RegisterDate string `json:"register_date,omitempty"`
|
|
|
+ IssueDate string `json:"issue_date,omitempty"`
|
|
|
+ PlateNumberB string `json:"plate_num_b,omitempty"`
|
|
|
+ Record string `json:"record,omitempty"`
|
|
|
+ PassengersNumber string `json:"passengers_num,omitempty"`
|
|
|
+ TotalQuality string `json:"total_quality,omitempty"`
|
|
|
+ PrepareQuality string `json:"prepare_quality,omitempty"`
|
|
|
+ OverallSize string `json:"overall_size,omitempty"`
|
|
|
+ CardPositionFront map[string]position `json:"card_position_front,omitempty"`
|
|
|
+ CardPositionBack map[string]position `json:"card_position_back,omitempty"`
|
|
|
+ ImageSize imageSize `json:"img_size,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResIDCard 身份证返回结果
|
|
|
+type ResIDCard struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ Type string `json:"type,omitempty"`
|
|
|
+ Name string `json:"name,omitempty"`
|
|
|
+ ID string `json:"id,omitempty"`
|
|
|
+ Address string `json:"addr,omitempty"`
|
|
|
+ Gender string `json:"gender,omitempty"`
|
|
|
+ Nationality string `json:"nationality,omitempty"`
|
|
|
+ ValidDate string `json:"valid_date,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResBankCard 银行卡返回结果
|
|
|
+type ResBankCard struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ Number string `json:"number,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResDrivingLicense 驾驶证返回结果
|
|
|
+type ResDrivingLicense struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ IDNumber string `json:"id_num,omitempty"`
|
|
|
+ Name string `json:"name,omitempty"`
|
|
|
+ Sex string `json:"sex,omitempty"`
|
|
|
+ Nationality string `json:"nationality,omitempty"`
|
|
|
+ Address string `json:"address,omitempty"`
|
|
|
+ Birthday string `json:"birth_date,omitempty"`
|
|
|
+ IssueDate string `json:"issue_date,omitempty"`
|
|
|
+ CarClass string `json:"car_class,omitempty"`
|
|
|
+ ValidFrom string `json:"valid_from,omitempty"`
|
|
|
+ ValidTo string `json:"valid_to,omitempty"`
|
|
|
+ OfficialSeal string `json:"official_seal,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResBizLicense 营业执照返回结果
|
|
|
+type ResBizLicense struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ RegisterNumber string `json:"reg_num,omitempty"`
|
|
|
+ Serial string `json:"serial,omitempty"`
|
|
|
+ LegalRepresentative string `json:"legal_representative,omitempty"`
|
|
|
+ EnterpriseName string `json:"enterprise_name,omitempty"`
|
|
|
+ TypeOfOrganization string `json:"type_of_organization,omitempty"`
|
|
|
+ Address string `json:"address,omitempty"`
|
|
|
+ TypeOfEnterprise string `json:"type_of_enterprise,omitempty"`
|
|
|
+ BusinessScope string `json:"business_scope,omitempty"`
|
|
|
+ RegisteredCapital string `json:"registered_capital,omitempty"`
|
|
|
+ PaidInCapital string `json:"paid_in_capital,omitempty"`
|
|
|
+ ValidPeriod string `json:"valid_period,omitempty"`
|
|
|
+ RegisterDate string `json:"registered_date,omitempty"`
|
|
|
+ CertPosition map[string]position `json:"cert_position,omitempty"`
|
|
|
+ ImageSize imageSize `json:"img_size,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResCommon 公共印刷品返回结果
|
|
|
+type ResCommon struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ Items []commonItem `json:"items,omitempty"`
|
|
|
+ ImageSize imageSize `json:"img_size,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+//commonItem 公共元素
|
|
|
+type commonItem struct {
|
|
|
+ Position position `json:"pos"`
|
|
|
+ Text string `json:"text"`
|
|
|
+}
|
|
|
+
|
|
|
+//ResPlateNumber 车牌号返回结果
|
|
|
+type ResPlateNumber struct {
|
|
|
+ util.CommonError
|
|
|
+
|
|
|
+ Number string `json:"number"`
|
|
|
+}
|
|
|
+
|
|
|
+//NewOCR 实例
|
|
|
+func NewOCR(c *context.Context) *OCR {
|
|
|
+ ocr := new(OCR)
|
|
|
+ ocr.Context = c
|
|
|
+ return ocr
|
|
|
+}
|
|
|
+
|
|
|
+//IDCard 身份证OCR识别接口
|
|
|
+func (ocr *OCR) IDCard(path string) (ResIDCard ResIDCard, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrIDCardURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResIDCard, "OCRIDCard")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//BankCard 银行卡OCR识别接口
|
|
|
+func (ocr *OCR) BankCard(path string) (ResBankCard ResBankCard, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrBankCardURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResBankCard, "OCRBankCard")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//Driving 行驶证OCR识别接口
|
|
|
+func (ocr *OCR) Driving(path string) (ResDriving ResDriving, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrDrivingURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResDriving, "OCRDriving")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//DrivingLicense 驾驶证OCR识别接口
|
|
|
+func (ocr *OCR) DrivingLicense(path string) (ResDrivingLicense ResDrivingLicense, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrDrivingLicenseURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResDrivingLicense, "OCRDrivingLicense")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//BizLicense 营业执照OCR识别接口
|
|
|
+func (ocr *OCR) BizLicense(path string) (ResBizLicense ResBizLicense, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrBizLicenseURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResBizLicense, "OCRBizLicense")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//Common 通用印刷体OCR识别接口
|
|
|
+func (ocr *OCR) Common(path string) (ResCommon ResCommon, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrCommonURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResCommon, "OCRCommon")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//PlateNumber 车牌OCR识别接口
|
|
|
+func (ocr *OCR) PlateNumber(path string) (ResPlateNumber ResPlateNumber, err error) {
|
|
|
+ accessToken, err := ocr.GetAccessToken()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ uri := fmt.Sprintf("%s?img_url=%s&access_token=%s", ocrPlateNumberURL, url.QueryEscape(path), accessToken)
|
|
|
+
|
|
|
+ response, err := util.HTTPPost(uri, "")
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = util.DecodeWithError(response, &ResPlateNumber, "OCRPlateNumber")
|
|
|
+
|
|
|
+ return
|
|
|
+}
|