From 7ac670b2873e43070456b059cddff6bdca163e45 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sun, 30 Jun 2019 22:59:58 +0800 Subject: [PATCH] =?UTF-8?q?#1002=20=E5=A2=9E=E5=8A=A0=E5=BE=AE=E4=BF=A1OCR?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E8=AF=81=E8=AF=86=E5=88=AB=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/mp/api/WxMpOcrService.java | 50 +++++++++++++++++ .../me/chanjar/weixin/mp/api/WxMpService.java | 9 ++++ .../mp/api/impl/BaseWxMpServiceImpl.java | 11 ++++ .../mp/api/impl/WxMpOcrServiceImpl.java | 43 +++++++++++++++ .../mp/bean/ocr/WxMpOcrIdCardResult.java | 33 ++++++++++++ .../chanjar/weixin/mp/enums/WxMpApiUrl.java | 20 +++++++ .../mp/api/impl/WxMpOcrServiceImplTest.java | 54 +++++++++++++++++++ 7 files changed, 220 insertions(+) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpOcrService.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImpl.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrIdCardResult.java create mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java 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 new file mode 100644 index 00000000..1748b553 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpOcrService.java @@ -0,0 +1,50 @@ +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.WxMpOcrIdCardResult; + +import java.io.File; + +/** + * 基于小程序或 H5 的身份证、银行卡、行驶证 OCR 识别. + * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=21516712284rHWMX + * + * @author Binary Wang + * @date 2019-06-22 + */ +public interface WxMpOcrService { + @AllArgsConstructor + @Getter + enum ImageType { + /** + * 拍照模型,带背景的图片. + */ + PHOTO("photo"), + /** + * 扫描模式,不带背景的图片. + */ + SCAN("scan"); + + private String type; + } + + /** + * 身份证OCR识别接口. + * + * @param imgType 图片类型 + * @param imgUrl 图片url地址 + * @throws WxErrorException . + */ + WxMpOcrIdCardResult idCard(ImageType imgType, String imgUrl) throws WxErrorException; + + /** + * 身份证OCR识别接口. + * + * @param imgType 图片类型 + * @param imgFile 图片文件对象 + * @throws WxErrorException . + */ + WxMpOcrIdCardResult idCard(ImageType imgType, File imgFile) throws WxErrorException; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 35debff5..f9d4399a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -493,6 +493,13 @@ public interface WxMpService { */ WxMpWifiService getWifiService(); + /** + * 返回WIFI接口方法的实现类对象,以方便调用其各个接口. + * + * @return WxMpWifiService + */ + WxMpOcrService getOcrService(); + void setKefuService(WxMpKefuService kefuService); void setMaterialService(WxMpMaterialService materialService); @@ -527,6 +534,8 @@ public interface WxMpService { void setMarketingService(WxMpMarketingService marketingService); + void setOcrService(WxMpOcrService ocrService); + /** * 返回评论数据管理接口方法的实现类对象,以方便调用其各个接口. * diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java index 98220cd9..0c7a70cd 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java @@ -63,6 +63,7 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH private WxMpWifiService wifiService = new WxMpWifiServiceImpl(this); private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this); private WxMpCommentService commentService = new WxMpCommentServiceImpl(this); + private WxMpOcrService ocrService = new WxMpOcrServiceImpl(this); private Map configStorageMap; @@ -600,6 +601,11 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH return this.wifiService; } + @Override + public WxMpOcrService getOcrService() { + return this.ocrService; + } + @Override public WxMpMarketingService getMarketingService() { return this.marketingService; @@ -610,6 +616,11 @@ public abstract class BaseWxMpServiceImpl implements WxMpService, RequestH this.marketingService = marketingService; } + @Override + public void setOcrService(WxMpOcrService ocrService) { + this.ocrService = ocrService; + } + @Override public WxMpCommentService getCommentService() { return this.commentService; 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 new file mode 100644 index 00000000..4d3c434e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImpl.java @@ -0,0 +1,43 @@ +package me.chanjar.weixin.mp.api.impl; + +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.WxMpOcrIdCardResult; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import static me.chanjar.weixin.mp.enums.WxMpApiUrl.Ocr.IDCARD; + +/** + * ocr 接口实现. + * + * @author Binary Wang + * @date 2019-06-22 + */ +@RequiredArgsConstructor +public class WxMpOcrServiceImpl implements WxMpOcrService { + private final WxMpService wxMpService; + + @Override + public WxMpOcrIdCardResult idCard(ImageType imgType, 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(IDCARD.getUrl(this.wxMpService.getWxMpConfigStorage()), + imgType.getType(), imgUrl), null); + return WxMpOcrIdCardResult.fromJson(result); + } + + @Override + public WxMpOcrIdCardResult idCard(ImageType imgType, File imgFile) { + return null; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrIdCardResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrIdCardResult.java new file mode 100644 index 00000000..fb174968 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/ocr/WxMpOcrIdCardResult.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.mp.bean.ocr; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.Serializable; + +/** + * OCR身份证识别结果. + * + * @author Binary Wang + * @date 2019-06-23 + */ +@Data +public class WxMpOcrIdCardResult implements Serializable { + private static final long serialVersionUID = 8184352486986729980L; + + @SerializedName("type") + private String type; + @SerializedName("name") + private String name; + @SerializedName("id") + private String id; + @SerializedName("valid_date") + private String validDate; + + public static WxMpOcrIdCardResult fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpOcrIdCardResult.class); + } + +} 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 276c1c9e..e6f529d2 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 @@ -426,6 +426,26 @@ public interface WxMpApiUrl { } } + @AllArgsConstructor + enum Ocr implements WxMpApiUrl { + /** + * 身份证识别. + */ + IDCARD(API_DEFAULT_HOST_URL, "/cv/ocr/idcard?type=%s&img_url=%s"); + + private String prefix; + private String path; + + @Override + public String getUrl(WxMpConfigStorage config) { + if (config == null) { + return buildUrl(null, prefix, path); + } + + return buildUrl(config.getHostConfig(), prefix, path); + } + } + @AllArgsConstructor enum Card implements WxMpApiUrl { /** 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 new file mode 100644 index 00000000..01706065 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpOcrServiceImplTest.java @@ -0,0 +1,54 @@ +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.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.test.ApiTestModule; +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 static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * 测试类. + * + * @author Binary Wang + * @date 2019-06-22 + */ +@Test +@Guice(modules = ApiTestModule.class) +public class WxMpOcrServiceImplTest { + @Inject + private WxMpService mpService; + + @Test + public void testIdCard() throws WxErrorException { + final WxMpOcrIdCardResult result = this.mpService.getOcrService().idCard(WxMpOcrService.ImageType.PHOTO, + "http://www.baidu.com"); + assertThat(result).isNotNull(); + System.out.println(result); + } + + public static class MockTest { + private WxMpService wxService = mock(WxMpService.class); + + @Test + public void testIdCard() throws Exception { + String returnJson = "{\"type\":\"Back\",\"name\":\"张三\",\"id\":\"110101199909090099\",\"valid_date\":\"20110101-20210201\"}"; + + when(wxService.get(anyString(), anyString())).thenReturn(returnJson); + final WxMpOcrServiceImpl wxMpOcrService = new WxMpOcrServiceImpl(wxService); + + final WxMpOcrIdCardResult result = wxMpOcrService.idCard(WxMpOcrService.ImageType.PHOTO, "abc"); + assertThat(result).isNotNull(); + System.out.println(result); + } + } +}