草庐IT

调用阿里云身份证识别服务识别本地图片,很详细,附工具类

Percep_gan 2024-01-27 原文

调用阿里云身份证识别服务识别本地图片

一、先购买阿里云的身份证识别服务,拿到对应的AccessKey ID 和 AccessKey Secret

二、在项目中添加阿里云的相关依赖,找到对应的工具类,这里用的是新版依赖

1、引入阿里云图片识别的依赖

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>ocr20191230</artifactId>
    <version>${aliyun.ocr.version}</version>
</dependency>

这是对应的依赖版本号查询地址,新版和旧版的依赖都可以在这里查

https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-ocr

接入步骤中的依赖我只添加了这个,json处理的依赖包项目本身就有,看自己情况,没有缺少对应的依赖就不需要添加了。

这是阿里云的示例地址

https://help.aliyun.com/document_detail/153132.htm?spm=a2c4g.11186623.0.0.65296d04gaIiFP#task-2406409

2、查询引入依赖,看是否导入成功

但是在调用过程发现引入依赖后与示例有点不一样!!!
我并没有看到com.aliyun:ocr:0.0.3这个依赖,以为是版本的问题,但看了一下也没有0.0.3这个版本

这是阿里云示例地址中的截图

这是我引入的阿里云依赖后,找到最像示例中的依赖包

RecognizeBankCardAdvanceRequest和RecognizeBankCardRequest这两个类倒是有,可是我的models包下面没有Config这个类,当时就想,示例代码中是需要这个类的,就算是高版本的jar包也不应该删了啊,保留疑问继续往下走。

既然和示例中的jar包有些出入,就先看看识别身份证的相关类吧,阿里云示例中提到

对于同一个接口,如果 SDK 中包含类似 xxxAdvanceRequest 的结构,那么这个接口支持本地文件上传,否则不支持。

示例截图中框的是识别银行卡的,我需要的是识别身份证的,那就找相关的工具类吧。

3、这是我找工具类的过程,可以跳过

(1)、识别身份证的类

识别身份证的是RecognizeIdentityCardAdvanceRequest和RecognizeIdentityCardRequest,其中RecognizeIdentityCardAdvanceRequest支持本地上传,那么就用这个。

识别本地图片的话,就将本地图片的输入流赋值给RecognizeIdentityCardAdvanceRequest实例的imageURLObject属性,示例代码中也有提到。

(2)、调用服务的类

调用身份证识别的服务需要Client这个类,通过在Client实例的recognizeIdentityCardAdvance方法中传入RecognizeIdentityCardAdvanceRequest实例进行图片识别,阿里云示例中没有明说Client这个是那个包中,引入的依赖和示例截图中(不同依赖)都有这个类,当时就想着先使用已经引入的依赖中的Client类,不行再换。

(3)、调用服务的类需要的Config实例,也是前面提到的没有看到的Config类

在实例化Client这个类中需要传入Config类的示例,因为modules中没有Config,进入Client源码,发现使用的是com.aliyun.teaopenapi.models这个包下的Config,行,那就用这个吧。

(4)、Config实例传参

一开始还不知道Config实例如何传参,后面看到阿里云身份证识别产品体验的示例代码(示例代码是旧版依赖的调用方式)中传了regionId、AccessKey ID 和 AccessKey Secret,加上Config确实有对应的变量,那就传这三个参数试试吧。

这是阿里云产品体验中心的代码:

三、示例代码

Config实例中的regionId沿用示例代码中的cn-shanghai。

运行测试一下

识别成功!

完整代码如下:

import com.aliyun.ocr20191230.Client;
import com.aliyun.ocr20191230.models.RecognizeIdentityCardAdvanceRequest;
import com.aliyun.ocr20191230.models.RecognizeIdentityCardResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.google.gson.Gson;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * TODO
 *
 * @author:user
 * @date: 2022-08-08 14:21
 */
public class IdCardIdentifyUtil {

    public static void main(String[] args) throws Exception {
        Config config = new Config();
        config.setAccessKeyId("你的accessKeyId");
        config.setAccessKeySecret("你的accessKeySecret");
        config.setRegionId("cn-shanghai");

        Client client = new Client(config);

        InputStream inputStream = new FileInputStream(new File("D:\\opt\\jeecg-boot\\upload\\temp\\upload_1644998658029.jpg"));

        //这是上传本地图片的
        RecognizeIdentityCardAdvanceRequest request = new RecognizeIdentityCardAdvanceRequest();
        request.setSide("face");
        request.imageURLObject = inputStream;

        //识别本地图片才要上传,但只是new一个实例进行传参,也没做什么
        RuntimeOptions runtimeOptions = new RuntimeOptions();

        RecognizeIdentityCardResponse response = null;
        try {
            response = client.recognizeIdentityCardAdvance(request, runtimeOptions);
        } catch (ServerException e) {
            e.printStackTrace();

            throw new RuntimeException(e.getMessage());
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());

            throw new RuntimeException("ErrCode:" + e.getErrCode() + ",ErrMsg:" + e.getErrMsg());
        }

        System.out.println("response::" + new Gson().toJson(response));
    }

}

四、工具类

这是我改造后的工具类,个人觉得比较适合在项目中使用。

1、身份证识别服务的请求参数

import lombok.Data;

/**
 * 身份证识别接口的参数
 *
 * @author:user
 * @date: 2022-08-08 15:28
 */
@Data
public class IdCardRequestParam {

    //阿里云accessKeyId
    private String accessKeyId;

    //阿里云accessSecret
    private String accessSecret;

    //阿里云识别身份证的regionId,设置请求参数的方法有横线,似乎废弃了
    private String regionId;

    //身份证正反面
    private String side;

    //上传图片路径
    private String imageURL;
}

2、身份证正面识别的接收dto

import lombok.Data;

/**
 * 身份证正面dto
 *
 * @author:user
 * @date: 2022-08-08 14:59
 */
@Data
public class IdCardFrontDto {

    //地址
    private String Address;

    //出生日期
    private String BirthDate;

    //性别
    private String Gender;

    //身份证号码
    private String IDNumber;

    //姓名
    private String Name;

    //民族
    private String Nationality;

    //身份证位置,目前没有用到
    private String CardAreas;
}

3、身份证反面识别的接收dto

import lombok.Data;

/**
 * 身份证反面dto
 *
 * @author:user
 * @date: 2022-08-08 15:09
 */
@Data
public class IdCardBackDto {

    //开始日期
    private String StartDate;

    //结束日期
    private String EndDate;

    //发证机关
    private String Issue;
}

4、身份证正反面枚举类

/**
 * 身份证正反面枚举类
 *
 * @author:user
 * @date: 2022-08-08 16:09
 */
public enum IdCardSideEnum {
    FACE("face", "人像面"),
    BACK("back", "国徽面");

    private String code;
    private String desc;

    IdCardSideEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public static String getDesc(String code) {
        for (IdCardSideEnum value : IdCardSideEnum.values()) {
            if (value.code.equals(code))
                return value.desc;
        }
        throw new RuntimeException("未知状态:" + code);
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

5、身份证识别工具类

import com.alibaba.fastjson.JSONObject;
import com.aliyun.ocr20191230.Client;
import com.aliyun.ocr20191230.models.RecognizeIdentityCardAdvanceRequest;
import com.aliyun.ocr20191230.models.RecognizeIdentityCardResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.google.gson.Gson;

import org.jeecg.common.util.VerifyUtil;
import org.jeecg.modules.aliyun.enums.IdCardSideEnum;
import org.jeecg.modules.aliyun.dto.IdCardBackDto;
import org.jeecg.modules.aliyun.dto.IdCardFrontDto;
import org.jeecg.modules.aliyun.dto.IdCardRequestParam;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * TODO
 *
 * @author:user
 * @date: 2022-08-08 14:21
 */
public class IdCardIdentifyUtil {

    /**
     * 识别身份证,泛型方法
     * @param param 识别身份证需要的参数
     * @param c 识别身份证正面传IdCardFrontDto.class;识别身份证反面传IdCardBackDto.class
     * @param <T>
     * @return
     */
    public static <T> T getIdCardInfo(IdCardRequestParam param, Class<T> c) throws Exception {
        VerifyUtil.checkBean(param); //这是之前写的一个校验方法,可以用自己的方式校验空值,之前的博客中也有该方法的代码

        //校验传入身份证正反面码是否合法
        String side = param.getSide();
        IdCardSideEnum.getDesc(side);

        if (IdCardSideEnum.FACE.getCode().equals(side) && !IdCardFrontDto.class.equals(c))
            throw new RuntimeException("识别身份证正面,应传入【IdCardFrontDto.class】");

        if (IdCardSideEnum.BACK.getCode().equals(side) && !IdCardBackDto.class.equals(c))
            throw new RuntimeException("识别身份证反面,应传入【IdCardBackDto.class】");

        String regionId = param.getRegionId();

        //这是阿里云身份证识别案例代码中拿过来的
        Config config = new Config();
        config.setAccessKeyId(param.getAccessKeyId());
        config.setAccessKeySecret(param.getAccessSecret());
        config.setRegionId(regionId);

        Client client = new Client(config);

        //这是识别网络路径的,需要开通oss服务
//        RecognizeIdentityCardRequest request = new RecognizeIdentityCardRequest();
        request.setRegionId(param.getRegionId());
//        request.setSide(side);
//        request.setImageURL(param.getImageURL());

        InputStream inputStream = new FileInputStream(new File(param.getImageURL()));

        //这是上传本地图片的
        RecognizeIdentityCardAdvanceRequest request = new RecognizeIdentityCardAdvanceRequest();
        request.setSide(side);
        request.imageURLObject = inputStream;

        //识别本地图片才要上传,但只是new一个实例进行传参,也没做什么
        RuntimeOptions runtimeOptions = new RuntimeOptions();

        RecognizeIdentityCardResponse response = null;
        try {
            response = client.recognizeIdentityCardAdvance(request, runtimeOptions);
        } catch (ServerException e) {
            e.printStackTrace();

            throw new RuntimeException(e.getMessage());
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());

            throw new RuntimeException("ErrCode:" + e.getErrCode() + ",ErrMsg:" + e.getErrMsg());
        }

        System.out.println("response::" + response);

        //将返回的json转化成JSONObject
        JSONObject responseJsonObject = JSONObject.parseObject(new Gson().toJson(response));

        //返回结果中嵌套了data,不能写错,data就是身份证的信息,
        //身份证正反面的返回键不一样,需要单独处理
        JSONObject idCardJsonObject = responseJsonObject.getJSONObject("body").getJSONObject("data");

        String idCardDataStr = null;
        if (IdCardSideEnum.FACE.getCode().equals(side)) {
            idCardDataStr = idCardJsonObject.getString("frontResult");
        } else if (IdCardSideEnum.BACK.getCode().equals(side)) {
            idCardDataStr = idCardJsonObject.getString("backResult");
        }

        return JSONObject.parseObject(idCardDataStr, c);
    }

}

有关调用阿里云身份证识别服务识别本地图片,很详细,附工具类的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  7. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐