diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpOcrService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpOcrService.java index 1748b5536..f7986d24c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpOcrService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpOcrService.java @@ -1,8 +1,11 @@ package me.chanjar.weixin.mp.api; -import lombok.AllArgsConstructor; -import lombok.Getter; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBankCardResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBizLicenseResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrCommResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingLicenseResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingResult; import me.chanjar.weixin.mp.bean.ocr.WxMpOcrIdCardResult; import java.io.File; @@ -15,36 +18,114 @@ import java.io.File; * @date 2019-06-22 */ public interface WxMpOcrService { - @AllArgsConstructor - @Getter - enum ImageType { - /** - * 拍照模型,带背景的图片. - */ - PHOTO("photo"), - /** - * 扫描模式,不带背景的图片. - */ - SCAN("scan"); - - private String type; - } /** * 身份证OCR识别接口. * - * @param imgType 图片类型 * @param imgUrl 图片url地址 + * @return WxMpOcrIdCardResult * @throws WxErrorException . */ - WxMpOcrIdCardResult idCard(ImageType imgType, String imgUrl) throws WxErrorException; + WxMpOcrIdCardResult idCard(String imgUrl) throws WxErrorException; /** * 身份证OCR识别接口. * - * @param imgType 图片类型 * @param imgFile 图片文件对象 + * @return WxMpOcrIdCardResult * @throws WxErrorException . */ - WxMpOcrIdCardResult idCard(ImageType imgType, File imgFile) throws WxErrorException; + WxMpOcrIdCardResult idCard(File imgFile) throws WxErrorException; + + /** + * 银行卡OCR识别接口 + * 文件大小限制:小于2M + * @param imgUrl 图片url地址 + * @return WxMpOcrBankCardResult + * @throws WxErrorException . + */ + WxMpOcrBankCardResult bankCard(String imgUrl) throws WxErrorException; + + /** + * 银行卡OCR识别接口 + * 文件大小限制:小于2M + * @param imgFile 图片文件对象 + * @return WxMpOcrBankCardResult + * @throws WxErrorException . + */ + WxMpOcrBankCardResult bankCard(File imgFile) throws WxErrorException; + + /** + * 行驶证OCR识别接口 + * 文件大小限制:小于2M + * @param imgUrl 图片url地址 + * @return WxMpOcrDrivingResult + * @throws WxErrorException . + */ + WxMpOcrDrivingResult driving(String imgUrl) throws WxErrorException; + + /** + * 行驶证OCR识别接口 + * 文件大小限制:小于2M + * @param imgFile 图片文件对象 + * @return WxMpOcrDrivingResult + * @throws WxErrorException . + */ + WxMpOcrDrivingResult driving(File imgFile) throws WxErrorException; + + /** + * 驾驶证OCR识别接口 + * 文件大小限制:小于2M + * @param imgUrl 图片url地址 + * @return WxMpOcrDrivingLicenseResult + * @throws WxErrorException . + */ + WxMpOcrDrivingLicenseResult drivingLicense(String imgUrl) throws WxErrorException; + + /** + * 驾驶证OCR识别接口 + * 文件大小限制:小于2M + * @param imgFile 图片文件对象 + * @return WxMpOcrDrivingLicenseResult + * @throws WxErrorException . + */ + WxMpOcrDrivingLicenseResult drivingLicense(File imgFile) throws WxErrorException; + + /** + * 营业执照OCR识别接口 + * 文件大小限制:小于2M + * @param imgUrl 图片url地址 + * @return WxMpOcrBizLicenseResult + * @throws WxErrorException . + */ + WxMpOcrBizLicenseResult bizLicense(String imgUrl) throws WxErrorException; + + /** + * 营业执照OCR识别接口 + * 文件大小限制:小于2M + * @param imgFile 图片文件对象 + * @return WxMpOcrBizLicenseResult + * @throws WxErrorException . + */ + WxMpOcrBizLicenseResult bizLicense(File imgFile) throws WxErrorException; + + /** + * 通用印刷体OCR识别接口 + * 文件大小限制:小于2M + * 适用于屏幕截图、印刷体照片等场景 + * @param imgUrl 图片url地址 + * @return WxMpOcrCommResult + * @throws WxErrorException . + */ + WxMpOcrCommResult comm(String imgUrl) throws WxErrorException; + + /** + * 通用印刷体OCR识别接口 + * 文件大小限制:小于2M + * 适用于屏幕截图、印刷体照片等场景 + * @param imgFile 图片文件对象 + * @return WxMpOcrCommResult + * @throws WxErrorException . + */ + WxMpOcrCommResult comm(File imgFile) throws WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImpl.java index 0f52f2aff..118a02c94 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImpl.java @@ -4,6 +4,11 @@ import lombok.RequiredArgsConstructor; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.mp.api.WxMpOcrService; import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBankCardResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBizLicenseResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrCommResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingLicenseResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingResult; import me.chanjar.weixin.mp.bean.ocr.WxMpOcrIdCardResult; import me.chanjar.weixin.mp.util.requestexecuter.ocr.OcrDiscernRequestExecutor; @@ -12,7 +17,17 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.BANK_CARD; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.BIZ_LICENSE; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.COMM; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.DRIVING; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.DRIVING_LICENSE; import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.FILEIDCARD; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.FILE_BANK_CARD; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.FILE_BIZ_LICENSE; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.FILE_COMM; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.FILE_DRIVING; +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.FILE_DRIVING_LICENSE; import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.IDCARD; /** @@ -26,7 +41,7 @@ public class WxMpOcrServiceImpl implements WxMpOcrService { private final WxMpService wxMpService; @Override - public WxMpOcrIdCardResult idCard(ImageType imgType, String imgUrl) throws WxErrorException { + public WxMpOcrIdCardResult idCard(String imgUrl) throws WxErrorException { try { imgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) { @@ -34,14 +49,108 @@ public class WxMpOcrServiceImpl implements WxMpOcrService { } final String result = this.wxMpService.get(String.format(IDCARD.getUrl(this.wxMpService.getWxMpConfigStorage()), - imgType.getType(), imgUrl), null); + imgUrl), null); return WxMpOcrIdCardResult.fromJson(result); } @Override - public WxMpOcrIdCardResult idCard(ImageType imgType, File imgFile) throws WxErrorException { - String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), String.format(FILEIDCARD.getUrl(this.wxMpService.getWxMpConfigStorage()), - imgType.getType()), imgFile); + public WxMpOcrIdCardResult idCard(File imgFile) throws WxErrorException { + String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), FILEIDCARD.getUrl(this.wxMpService.getWxMpConfigStorage()), imgFile); return WxMpOcrIdCardResult.fromJson(result); } + + @Override + public WxMpOcrBankCardResult bankCard(String imgUrl) throws WxErrorException { + try { + imgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + // ignore cannot happen + } + + final String result = this.wxMpService.get(String.format(BANK_CARD.getUrl(this.wxMpService.getWxMpConfigStorage()), + imgUrl), null); + return WxMpOcrBankCardResult.fromJson(result); + } + + @Override + public WxMpOcrBankCardResult bankCard(File imgFile) throws WxErrorException { + String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), FILE_BANK_CARD.getUrl(this.wxMpService.getWxMpConfigStorage()), imgFile); + return WxMpOcrBankCardResult.fromJson(result); + } + + @Override + public WxMpOcrDrivingResult driving(String imgUrl) throws WxErrorException { + try { + imgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + // ignore cannot happen + } + + final String result = this.wxMpService.get(String.format(DRIVING.getUrl(this.wxMpService.getWxMpConfigStorage()), + imgUrl), null); + return WxMpOcrDrivingResult.fromJson(result); + } + + @Override + public WxMpOcrDrivingResult driving(File imgFile) throws WxErrorException { + String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), FILE_DRIVING.getUrl(this.wxMpService.getWxMpConfigStorage()), imgFile); + return WxMpOcrDrivingResult.fromJson(result); + } + + @Override + public WxMpOcrDrivingLicenseResult drivingLicense(String imgUrl) throws WxErrorException { + try { + imgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + // ignore cannot happen + } + + final String result = this.wxMpService.get(String.format(DRIVING_LICENSE.getUrl(this.wxMpService.getWxMpConfigStorage()), + imgUrl), null); + return WxMpOcrDrivingLicenseResult.fromJson(result); + } + + @Override + public WxMpOcrDrivingLicenseResult drivingLicense(File imgFile) throws WxErrorException { + String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), FILE_DRIVING_LICENSE.getUrl(this.wxMpService.getWxMpConfigStorage()), imgFile); + return WxMpOcrDrivingLicenseResult.fromJson(result); + } + + @Override + public WxMpOcrBizLicenseResult bizLicense(String imgUrl) throws WxErrorException { + try { + imgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + // ignore cannot happen + } + + final String result = this.wxMpService.get(String.format(BIZ_LICENSE.getUrl(this.wxMpService.getWxMpConfigStorage()), + imgUrl), null); + return WxMpOcrBizLicenseResult.fromJson(result); + } + + @Override + public WxMpOcrBizLicenseResult bizLicense(File imgFile) throws WxErrorException { + String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), FILE_BIZ_LICENSE.getUrl(this.wxMpService.getWxMpConfigStorage()), imgFile); + return WxMpOcrBizLicenseResult.fromJson(result); + } + + @Override + public WxMpOcrCommResult comm(String imgUrl) throws WxErrorException { + try { + imgUrl = URLEncoder.encode(imgUrl, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + // ignore cannot happen + } + + final String result = this.wxMpService.get(String.format(COMM.getUrl(this.wxMpService.getWxMpConfigStorage()), + imgUrl), null); + return WxMpOcrCommResult.fromJson(result); + } + + @Override + public WxMpOcrCommResult comm(File imgFile) throws WxErrorException { + String result = this.wxMpService.execute(OcrDiscernRequestExecutor.create(this.wxMpService.getRequestHttp()), FILE_COMM.getUrl(this.wxMpService.getWxMpConfigStorage()), imgFile); + return WxMpOcrCommResult.fromJson(result); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrBankCardResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrBankCardResult.java new file mode 100644 index 000000000..9b76a3157 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrBankCardResult.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * 银行卡OCR识别结果 + * @author Theo Nie + */ +@Data +public class WxMpOcrBankCardResult implements Serializable { + + private static final long serialVersionUID = 554136620394204143L; + @SerializedName("number") + private String number; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + + public static WxMpOcrBankCardResult fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpOcrBankCardResult.class); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrBizLicenseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrBizLicenseResult.java new file mode 100644 index 000000000..aa97fc83f --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrBizLicenseResult.java @@ -0,0 +1,107 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Theo Nie + */ +@Data +public class WxMpOcrBizLicenseResult implements Serializable { + private static final long serialVersionUID = -5007671093920178291L; + + /** + * 注册号 + */ + @SerializedName("reg_num") + private String regNum; + /** + * 编号 + */ + @SerializedName("serial") + private String serial; + /** + * 法定代表人姓名 + */ + @SerializedName("legal_representative") + private String legalRepresentative; + /** + * 企业名称 + */ + @SerializedName("enterprise_name") + private String enterpriseName; + /** + * 组成形式 + */ + @SerializedName("type_of_organization") + private String typeOfOrganization; + /** + * 经营场所/企业住所 + */ + @SerializedName("address") + private String address; + /** + * 公司类型 + */ + @SerializedName("type_of_enterprise") + private String typeOfEnterprise; + /** + * 经营范围 + */ + @SerializedName("business_scope") + private String businessScope; + /** + * 注册资本 + */ + @SerializedName("registered_capital") + private String registeredCapital; + /** + * 实收资本 + */ + @SerializedName("paid_in_capital") + private String paidInCapital; + /** + * 营业期限 + */ + @SerializedName("valid_period") + private String validPeriod; + /** + * 注册日期/成立日期 + */ + @SerializedName("registered_date") + private String registeredDate; + /** + * 营业执照位置 + */ + @SerializedName("cert_position") + private CertPosition certPosition; + /** + * 图片大小 + */ + @SerializedName("img_size") + private WxMpOcrImgSize imgSize; + + public static WxMpOcrBizLicenseResult fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpOcrBizLicenseResult.class); + } + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + + @Data + public static class CertPosition implements Serializable { + private static final long serialVersionUID = 290286813344131863L; + @SerializedName("pos") + private WxMpOcrPos pos; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrCommResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrCommResult.java new file mode 100644 index 000000000..cc391bdfe --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrCommResult.java @@ -0,0 +1,45 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * @author Theo Nie + */ +@Data +public class WxMpOcrCommResult implements Serializable { + private static final long serialVersionUID = 455833771627756440L; + + @SerializedName("img_size") + private WxMpOcrImgSize imgSize; + @SerializedName("items") + private List items; + + public static WxMpOcrCommResult fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpOcrCommResult.class); + } + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + + @Data + public static class Items implements Serializable { + + private static final long serialVersionUID = 3066181677009102791L; + @SerializedName("text") + private String text; + @SerializedName("pos") + private WxMpOcrPos pos; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrDrivingLicenseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrDrivingLicenseResult.java new file mode 100644 index 000000000..3ef8fee91 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrDrivingLicenseResult.java @@ -0,0 +1,80 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Theo Nie + */ +@Data +public class WxMpOcrDrivingLicenseResult implements Serializable { + private static final long serialVersionUID = -6984670645802585738L; + + /** + * 证号 + */ + @SerializedName("id_num") + private String idNum; + /** + * 姓名 + */ + @SerializedName("name") + private String name; + /** + * 性别 + */ + @SerializedName("sex") + private String sex; + /** + * 国籍 + */ + @SerializedName("nationality") + private String nationality; + /** + * 住址 + */ + @SerializedName("address") + private String address; + /** + * 出生日期 + */ + @SerializedName("birth_date") + private String birthDate; + /** + * 初次领证日期 + */ + @SerializedName("issue_date") + private String issueDate; + /** + * 准驾车型 + */ + @SerializedName("car_class") + private String carClass; + /** + * 有效期限起始日 + */ + @SerializedName("valid_from") + private String validFrom; + /** + * 有效期限终止日 + */ + @SerializedName("valid_to") + private String validTo; + /** + * 印章文字 + */ + @SerializedName("official_seal") + private String officialSeal; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + + public static WxMpOcrDrivingLicenseResult fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpOcrDrivingLicenseResult.class); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrDrivingResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrDrivingResult.java new file mode 100644 index 000000000..3e5576934 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrDrivingResult.java @@ -0,0 +1,132 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Theo Nie + */ +@Data +public class WxMpOcrDrivingResult implements Serializable { + + private static final long serialVersionUID = -7477484374200211303L; + /** + * 车牌号码 + */ + @SerializedName("plate_num") + private String plateNum; + /** + * 车辆类型 + */ + @SerializedName("vehicle_type") + private String vehicleType; + /** + * 所有人 + */ + @SerializedName("owner") + private String owner; + /** + * 住址 + */ + @SerializedName("addr") + private String addr; + /** + * 使用性质 + */ + @SerializedName("use_character") + private String useCharacter; + /** + * 品牌型号 + */ + @SerializedName("model") + private String model; + /** + * 车辆识别代码 + */ + @SerializedName("vin") + private String vin; + /** + * 发动机号码 + */ + @SerializedName("engine_num") + private String engineNum; + /** + * 注册日期 + */ + @SerializedName("register_date") + private String registerDate; + /** + * 发证日期 + */ + @SerializedName("issue_date") + private String issueDate; + /** + * 车牌号码 + */ + @SerializedName("plate_num_b") + private String plateNumB; + /** + * 号牌 + */ + @SerializedName("record") + private String record; + /** + * 核定载人数 + */ + @SerializedName("passengers_num") + private String passengersNum; + /** + * 总质量 + */ + @SerializedName("total_quality") + private String totalQuality; + /** + * 整备质量 + */ + @SerializedName("prepare_quality") + private String prepareQuality; + /** + * 外廓尺寸 + */ + @SerializedName("overall_size") + private String overallSize; + /** + * 卡片正面位置(检测到卡片正面才会返回) + */ + @SerializedName("card_position_front") + private CardPosition cardPositionFront; + /** + * 卡片反面位置(检测到卡片反面才会返回) + */ + @SerializedName("card_position_back") + private CardPosition cardPositionBack; + /** + * 图片大小 + */ + @SerializedName("img_size") + private WxMpOcrImgSize imgSize; + + @Data + public static class CardPosition implements Serializable { + private static final long serialVersionUID = 2884515165228160517L; + @SerializedName("pos") + private WxMpOcrPos pos; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + } + + public static WxMpOcrDrivingResult fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpOcrDrivingResult.class); + } + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrImgSize.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrImgSize.java new file mode 100644 index 000000000..f30a15399 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrImgSize.java @@ -0,0 +1,25 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Theo Nie + */ +@Data +public class WxMpOcrImgSize implements Serializable { + private static final long serialVersionUID = 5234409123551074168L; + + @SerializedName("w") + private int w; + @SerializedName("h") + private int h; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrPos.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrPos.java new file mode 100644 index 000000000..0a4fe586e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrPos.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * @author Theo Nie + */ +@Data +public class WxMpOcrPos implements Serializable { + private static final long serialVersionUID = 4204160206873907920L; + + @SerializedName("left_top") + private Coordinate leftTop; + @SerializedName("right_top") + private Coordinate rightTop; + @SerializedName("right_bottom") + private Coordinate rightBottom; + @SerializedName("left_bottom") + private Coordinate leftBottom; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + + @Data + public static class Coordinate implements Serializable{ + private static final long serialVersionUID = 8675059935386304399L; + @SerializedName("x") + private int x; + @SerializedName("y") + private int y; + + @Override + public String toString() { + return WxMpGsonBuilder.create().toJson(this); + } + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java index df62324d7..442f0305f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java @@ -440,9 +440,58 @@ public interface WxMpApiUrl { /** * 身份证识别. */ - IDCARD(API_DEFAULT_HOST_URL, "/cv/ocr/idcard?type=%s&img_url=%s"), + IDCARD(API_DEFAULT_HOST_URL, "/cv/ocr/idcard?img_url=%s"), - FILEIDCARD(API_DEFAULT_HOST_URL, "/cv/ocr/idcard?type=%s"); + FILEIDCARD(API_DEFAULT_HOST_URL, "/cv/ocr/idcard"), + + /** + * 银行卡OCR识别 + */ + BANK_CARD(API_DEFAULT_HOST_URL, "/cv/ocr/bankcard?img_url=%s"), + + /** + * 银行卡OCR识别(文件) + */ + FILE_BANK_CARD(API_DEFAULT_HOST_URL, "/cv/ocr/bankcard"), + + /** + * 行驶证OCR识别 + */ + DRIVING(API_DEFAULT_HOST_URL, "/cv/ocr/driving?img_url=%s"), + /** + * 行驶证OCR识别(文件) + */ + FILE_DRIVING(API_DEFAULT_HOST_URL, "/cv/ocr/driving"), + + /** + * 驾驶证OCR识别 + */ + DRIVING_LICENSE(API_DEFAULT_HOST_URL, "/cv/ocr/drivinglicense?img_url=%s"), + + /** + * 驾驶证OCR识别(文件) + */ + FILE_DRIVING_LICENSE(API_DEFAULT_HOST_URL, "/cv/ocr/drivinglicense"), + + /** + * 营业执照OCR识别 + */ + BIZ_LICENSE(API_DEFAULT_HOST_URL, "/cv/ocr/bizlicense?img_url=%s"), + + /** + * 营业执照OCR识别(文件) + */ + FILE_BIZ_LICENSE(API_DEFAULT_HOST_URL, "/cv/ocr/bizlicense"), + + /** + * 通用印刷体OCR识别 + */ + COMM(API_DEFAULT_HOST_URL, "/cv/ocr/comm?img_url=%s"), + + /** + * 通用印刷体OCR识别(文件) + */ + FILE_COMM(API_DEFAULT_HOST_URL, "/cv/ocr/comm"); private String prefix; private String path; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java index 017060656..55bfa0623 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java @@ -1,16 +1,28 @@ package me.chanjar.weixin.mp.api.impl; import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.mp.api.WxMpOcrService; +import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.test.ApiTestModule; +import me.chanjar.weixin.mp.api.test.TestConstants; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBankCardResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrBizLicenseResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrCommResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingLicenseResult; +import me.chanjar.weixin.mp.bean.ocr.WxMpOcrDrivingResult; import me.chanjar.weixin.mp.bean.ocr.WxMpOcrIdCardResult; -import org.testng.annotations.BeforeTest; import org.testng.annotations.Guice; import org.testng.annotations.Test; import javax.inject.Inject; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; @@ -30,12 +42,116 @@ public class WxMpOcrServiceImplTest { @Test public void testIdCard() throws WxErrorException { - final WxMpOcrIdCardResult result = this.mpService.getOcrService().idCard(WxMpOcrService.ImageType.PHOTO, - "http://www.baidu.com"); + final WxMpOcrIdCardResult result = this.mpService.getOcrService().idCard( + "https://res.wx.qq.com/op_res/E_oqdHqP4ETOJsT46sQnXz1HbeHOpqDQTuhkYeaLaJTf-JKld7de3091dwxCQwa6"); assertThat(result).isNotNull(); System.out.println(result); } + @Test + public void testIdCard2() throws Exception { + InputStream inputStream = this.getImageStream("https://res.wx.qq.com/op_res/E_oqdHqP4ETOJsT46sQnXz1HbeHOpqDQTuhkYeaLaJTf-JKld7de3091dwxCQwa6"); + File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), TestConstants.FILE_JPG); + final WxMpOcrIdCardResult result = this.mpService.getOcrService().idCard(tempFile); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testBankCard() throws WxErrorException { + final WxMpOcrBankCardResult result = this.mpService.getOcrService().bankCard("https://res.wx.qq.com/op_res/eP7PObYbBJj-_19EbGBL4PWe_zQ1NwET5NXSugjEWc-4ayns4Q-HFJrp-AOog8ih"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testBankCard2() throws Exception { + InputStream inputStream = this.getImageStream("https://res.wx.qq.com/op_res/eP7PObYbBJj-_19EbGBL4PWe_zQ1NwET5NXSugjEWc-4ayns4Q-HFJrp-AOog8ih"); + File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), TestConstants.FILE_JPG); + final WxMpOcrBankCardResult result = this.mpService.getOcrService().bankCard(tempFile); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testDriving() throws WxErrorException { + final WxMpOcrDrivingResult result = this.mpService.getOcrService().driving("https://res.wx.qq.com/op_res/T051P5uWvh9gSJ9j78tWib53WiNi2pHSSZhoO8wnY3Av-djpsA4kA9whbtt6_Tb6"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testDriving2() throws Exception { + InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg"); + File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), TestConstants.FILE_JPG); + final WxMpOcrDrivingResult result = this.mpService.getOcrService().driving(tempFile); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testDrivingLicense() throws WxErrorException { + final WxMpOcrDrivingLicenseResult result = this.mpService.getOcrService().drivingLicense("https://res.wx.qq.com/op_res/kD4YXjYVAW1eaQqn9uTA0rrOFoZRvVINitNDSGo5gJ7SzTCezNq_ZDDmU1I08kGn"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testDrivingLicense2() throws Exception { + InputStream inputStream = this.getImageStream("https://res.wx.qq.com/op_res/kD4YXjYVAW1eaQqn9uTA0rrOFoZRvVINitNDSGo5gJ7SzTCezNq_ZDDmU1I08kGn"); + File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), TestConstants.FILE_JPG); + final WxMpOcrDrivingLicenseResult result = this.mpService.getOcrService().drivingLicense(tempFile); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testBizLicense() throws WxErrorException { + final WxMpOcrBizLicenseResult result = this.mpService.getOcrService().bizLicense("https://res.wx.qq.com/op_res/apCy0YbnEdjYsa_cjW6x3FlpCc20uQ-2BYE7aXnFsrB-ALHZNgdKXhzIUcrRnDoL"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testBizLicense2() throws Exception { + InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg"); + File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), TestConstants.FILE_JPG); + final WxMpOcrBizLicenseResult result = this.mpService.getOcrService().bizLicense(tempFile); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testComm() throws WxErrorException { + final WxMpOcrCommResult result = this.mpService.getOcrService().comm("https://res.wx.qq.com/op_res/apCy0YbnEdjYsa_cjW6x3FlpCc20uQ-2BYE7aXnFsrB-ALHZNgdKXhzIUcrRnDoL"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testComm2() throws Exception { + InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg"); + File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), TestConstants.FILE_JPG); + final WxMpOcrCommResult result = this.mpService.getOcrService().comm(tempFile); + assertThat(result).isNotNull(); + System.out.println(result); + } + + private InputStream getImageStream(String url) { + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setReadTimeout(5000); + connection.setConnectTimeout(5000); + connection.setRequestMethod("GET"); + if (HttpURLConnection.HTTP_OK == connection.getResponseCode()) { + return connection.getInputStream(); + } + } catch (IOException e) { + System.out.println("获取网络图片出现异常,图片路径为:" + url); + } + return null; + } + public static class MockTest { private WxMpService wxService = mock(WxMpService.class); @@ -46,7 +162,231 @@ public class WxMpOcrServiceImplTest { when(wxService.get(anyString(), anyString())).thenReturn(returnJson); final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); - final WxMpOcrIdCardResult result = wxMpOcrService.idCard(WxMpOcrService.ImageType.PHOTO, "abc"); + final WxMpOcrIdCardResult result = wxMpOcrService.idCard("abc"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testBankCard() throws Exception { + String returnJson = "{\"number\":\"24234234345234\"}"; + + when(wxService.get(anyString(), anyString())).thenReturn(returnJson); + final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); + + final WxMpOcrBankCardResult result = wxMpOcrService.bankCard("abc"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testDriving() throws Exception { + String returnJson = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"plate_num\": \"粤xxxxx\", //车牌号码\n" + + " \"vehicle_type\": \"小型普通客车\", //车辆类型\n" + + " \"owner\": \"东莞市xxxxx机械厂\", //所有人\n" + + " \"addr\": \"广东省东莞市xxxxx号\", //住址\n" + + " \"use_character\": \"非营运\", //使用性质\n" + + " \"model\": \"江淮牌HFCxxxxxxx\", //品牌型号\n" + + " \"vin\": \"LJ166xxxxxxxx51\", //车辆识别代号\n" + + " \"engine_num\": \"J3xxxxx3\", //发动机号码\n" + + " \"register_date\": \"2018-07-06\", //注册日期\n" + + " \"issue_date\": \"2018-07-01\", //发证日期\n" + + " \"plate_num_b\": \"粤xxxxx\", //车牌号码\n" + + " \"record\": \"441xxxxxx3\", //号牌\n" + + " \"passengers_num\": \"7人\", //核定载人数\n" + + " \"total_quality\": \"2700kg\", //总质量\n" + + " \"prepare_quality\": \"1995kg\", //整备质量\n" + + " \"overall_size\": \"4582x1795x1458mm\", //外廓尺寸\n" + + " \"card_position_front\": {//卡片正面位置(检测到卡片正面才会返回)\n" + + " \"pos\": {\n" + + " \"left_top\": {\n" + + " \"x\": 119, \n" + + " \"y\": 2925\n" + + " }, \n" + + " \"right_top\": {\n" + + " \"x\": 1435, \n" + + " \"y\": 2887\n" + + " }, \n" + + " \"right_bottom\": {\n" + + " \"x\": 1435, \n" + + " \"y\": 3793\n" + + " }, \n" + + " \"left_bottom\": {\n" + + " \"x\": 119, \n" + + " \"y\": 3831\n" + + " }\n" + + " }\n" + + " }, \n" + + " \"card_position_back\": {//卡片反面位置(检测到卡片反面才会返回)\n" + + " \"pos\": {\n" + + " \"left_top\": {\n" + + " \"x\": 1523, \n" + + " \"y\": 2849\n" + + " }, \n" + + " \"right_top\": {\n" + + " \"x\": 2898, \n" + + " \"y\": 2887\n" + + " }, \n" + + " \"right_bottom\": {\n" + + " \"x\": 2927, \n" + + " \"y\": 3831\n" + + " }, \n" + + " \"left_bottom\": {\n" + + " \"x\": 1523, \n" + + " \"y\": 3831\n" + + " }\n" + + " }\n" + + " }, \n" + + " \"img_size\": {//图片大小\n" + + " \"w\": 3120, \n" + + " \"h\": 4208\n" + + " }\n" + + "}"; + + when(wxService.get(anyString(), anyString())).thenReturn(returnJson); + final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); + + final WxMpOcrDrivingResult result = wxMpOcrService.driving("abc"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testDrivingLicense() throws Exception { + String returnJson = "{\n" + + " \"errcode\": 0,\n" + + " \"errmsg\": \"ok\",\n" + + " \"id_num\": \"660601xxxxxxxx1234\", //证号\n" + + " \"name\": \"张三\", //姓名\n" + + " \"sex\": \"男\", //性别\n" + + " \"nationality\": \"中国\", //国籍\n" + + " \"address\": \"广东省东莞市xxxxx号\", //住址\n" + + " \"birth_date\": \"1990-12-21\", //出生日期\n" + + " \"issue_date\": \"2012-12-21\", //初次领证日期\n" + + " \"car_class\": \"C1\", //准驾车型\n" + + " \"valid_from\": \"2018-07-06\", //有效期限起始日\n" + + " \"valid_to\": \"2020-07-01\", //有效期限终止日\n" + + " \"official_seal\": \"xx市公安局公安交通管理局\" //印章文字\n" + + "}"; + when(wxService.get(anyString(), anyString())).thenReturn(returnJson); + final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); + + final WxMpOcrDrivingLicenseResult result = wxMpOcrService.drivingLicense("abc"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testBizLicense() throws Exception { + String returnJson = "{\n" + + " \"errcode\": 0, \n" + + " \"errmsg\": \"ok\", \n" + + " \"reg_num\": \"123123\",//注册号\n" + + " \"serial\": \"123123\",//编号\n" + + " \"legal_representative\": \"张三\", //法定代表人姓名\n" + + " \"enterprise_name\": \"XX饮食店\", //企业名称\n" + + " \"type_of_organization\": \"个人经营\", //组成形式\n" + + " \"address\": \"XX市XX区XX路XX号\", //经营场所/企业住所\n" + + " \"type_of_enterprise\": \"xxx\", //公司类型\n" + + " \"business_scope\": \"中型餐馆(不含凉菜、不含裱花蛋糕,不含生食海产品)。\", //经营范围\n" + + " \"registered_capital\": \"200万\", //注册资本\n" + + " \"paid_in_capital\": \"200万\", //实收资本\n" + + " \"valid_period\": \"2019年1月1日\", //营业期限\n" + + " \"registered_date\": \"2018年1月1日\", //注册日期/成立日期\n" + + " \"cert_position\": { //营业执照位置\n" + + " \"pos\": {\n" + + " \"left_top\": {\n" + + " \"x\": 155, \n" + + " \"y\": 191\n" + + " }, \n" + + " \"right_top\": {\n" + + " \"x\": 725, \n" + + " \"y\": 157\n" + + " }, \n" + + " \"right_bottom\": {\n" + + " \"x\": 743, \n" + + " \"y\": 512\n" + + " }, \n" + + " \"left_bottom\": {\n" + + " \"x\": 164, \n" + + " \"y\": 525\n" + + " }\n" + + " }\n" + + " }, \n" + + " \"img_size\": { //图片大小\n" + + " \"w\": 966, \n" + + " \"h\": 728\n" + + " }\n" + + "}"; + when(wxService.get(anyString(), anyString())).thenReturn(returnJson); + final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); + + final WxMpOcrBizLicenseResult result = wxMpOcrService.bizLicense("abc"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + @Test + public void testComm() throws Exception { + String returnJson = "{\n" + + " \"errcode\": 0, \n" + + " \"errmsg\": \"ok\", \n" + + " \"items\": [ //识别结果\n" + + " {\n" + + " \"text\": \"腾讯\", \n" + + " \"pos\": {\n" + + " \"left_top\": {\n" + + " \"x\": 575, \n" + + " \"y\": 519\n" + + " }, \n" + + " \"right_top\": {\n" + + " \"x\": 744, \n" + + " \"y\": 519\n" + + " }, \n" + + " \"right_bottom\": {\n" + + " \"x\": 744, \n" + + " \"y\": 532\n" + + " }, \n" + + " \"left_bottom\": {\n" + + " \"x\": 573, \n" + + " \"y\": 532\n" + + " }\n" + + " }\n" + + " }, \n" + + " {\n" + + " \"text\": \"微信团队\", \n" + + " \"pos\": {\n" + + " \"left_top\": {\n" + + " \"x\": 670, \n" + + " \"y\": 516\n" + + " }, \n" + + " \"right_top\": {\n" + + " \"x\": 762, \n" + + " \"y\": 517\n" + + " }, \n" + + " \"right_bottom\": {\n" + + " \"x\": 762, \n" + + " \"y\": 532\n" + + " }, \n" + + " \"left_bottom\": {\n" + + " \"x\": 670, \n" + + " \"y\": 531\n" + + " }\n" + + " }\n" + + " }\n" + + " ], \n" + + " \"img_size\": { //图片大小\n" + + " \"w\": 1280, \n" + + " \"h\": 720\n" + + " }\n" + + "}"; + when(wxService.get(anyString(), anyString())).thenReturn(returnJson); + final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); + + final WxMpOcrCommResult result = wxMpOcrService.comm("abc"); assertThat(result).isNotNull(); System.out.println(result); }