浏览代码

#1002 增加微信OCR身份证识别接口

Binary Wang 5 年之前
父节点
当前提交
7ac670b287

+ 50 - 0
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 <a href="https://github.com/binarywang">Binary Wang</a>
+ * @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;
+}

+ 9 - 0
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);
+
   /**
    * 返回评论数据管理接口方法的实现类对象,以方便调用其各个接口.
    *

+ 11 - 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java

@@ -63,6 +63,7 @@ public abstract class BaseWxMpServiceImpl<H, P> 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<String, WxMpConfigStorage> configStorageMap;
 
@@ -601,6 +602,11 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
   }
 
   @Override
+  public WxMpOcrService getOcrService() {
+    return this.ocrService;
+  }
+
+  @Override
   public WxMpMarketingService getMarketingService() {
     return this.marketingService;
   }
@@ -611,6 +617,11 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
   }
 
   @Override
+  public void setOcrService(WxMpOcrService ocrService) {
+    this.ocrService = ocrService;
+  }
+
+  @Override
   public WxMpCommentService getCommentService() {
     return this.commentService;
   }

+ 43 - 0
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 <a href="https://github.com/binarywang">Binary Wang</a>
+ * @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;
+  }
+}

+ 33 - 0
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 <a href="https://github.com/binarywang">Binary Wang</a>
+ * @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);
+  }
+
+}

+ 20 - 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/enums/WxMpApiUrl.java

@@ -427,6 +427,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 {
     /**
      * create.

+ 54 - 0
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 <a href="https://github.com/binarywang">Binary Wang</a>
+ * @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);
+    }
+  }
+}